[automerger skipped] Merge "Import translations. DO NOT MERGE ANYWHERE" into udc-dev am: a9ca289869 -s ours am: 0a1cf46bde -s ours
am skip reason: subject contains skip directive
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/24836996
Change-Id: Icca59d244457ca8db706a9739eaae32adb0d6942
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index a7edf2a..28eee94 100644
--- a/Android.bp
+++ b/Android.bp
@@ -153,7 +153,8 @@
"androidx.cardview_cardview",
"com.google.android.material_material",
"iconloader_base",
- "view_capture"
+ "view_capture",
+ "animationlib"
],
manifest: "AndroidManifest-common.xml",
sdk_version: "current",
@@ -172,6 +173,8 @@
static_libs: [
"Launcher3ResLib",
"launcher-testing-shared",
+ "animationlib",
+ "com_android_launcher3_flags_lib",
],
sdk_version: "current",
min_sdk_version: min_launcher3_sdk_version,
@@ -273,7 +276,7 @@
"androidx.room_room-runtime",
],
plugins: ["androidx.room_room-compiler-plugin"],
- manifest: "quickstep/AndroidManifest-launcher.xml",
+ manifest: "quickstep/AndroidManifest.xml",
additional_manifests: [
"go/AndroidManifest.xml",
"AndroidManifest-common.xml",
diff --git a/OWNERS b/OWNERS
index b684460..7834396 100644
--- a/OWNERS
+++ b/OWNERS
@@ -13,6 +13,8 @@
winsonc@google.com
jonmiranda@google.com
alexchau@google.com
+patmanning@google.com
+tsuharesu@google.com
per-file FeatureFlags.java, globs = set noparent
per-file FeatureFlags.java = sunnygoyal@google.com, winsonc@google.com, adamcohen@google.com, hyunyoungs@google.com, captaincole@google.com
diff --git a/aconfig/Android.bp b/aconfig/Android.bp
new file mode 100644
index 0000000..dc30a35
--- /dev/null
+++ b/aconfig/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+aconfig_declarations {
+ name: "com_android_launcher3_flags",
+ package: "com.android.launcher3",
+ srcs: ["**/*.aconfig"],
+}
+
+java_aconfig_library {
+ name: "com_android_launcher3_flags_lib",
+ aconfig_declarations: "com_android_launcher3_flags",
+}
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
new file mode 100644
index 0000000..b4132e4
--- /dev/null
+++ b/aconfig/launcher.aconfig
@@ -0,0 +1,29 @@
+package: "com.android.launcher3"
+
+flag {
+ name: "enable_expanding_pause_work_button"
+ namespace: "launcher"
+ description: "Expand and collapse pause work button while scrolling."
+ bug: "270390779"
+}
+
+flag {
+ name: "enable_twoline_allapps"
+ namespace: "launcher"
+ description: "Enables two line label inside all apps."
+ bug: "270390937"
+}
+
+flag {
+ name: "enable_grid_only_overview"
+ namespace: "launcher"
+ description: "Enable a grid-only overview without a focused task."
+ bug: "257950105"
+}
+
+flag {
+ name: "enable_cursor_hover_states"
+ namespace: "launcher"
+ description: "Enables cursor hover states for certain elements."
+ bug: "243191650"
+}
diff --git a/build.gradle b/build.gradle
index 090bafe..f4d7261 100644
--- a/build.gradle
+++ b/build.gradle
@@ -157,6 +157,8 @@
withoutQuickstepImplementation fileTree(dir: "${FRAMEWORK_PREBUILTS_DIR}/libs", include: 'plugin_core.jar')
testImplementation 'junit:junit:4.12'
+ testImplementation libs.mockitoInlineExtended
+ androidTestImplementation libs.mockitoInlineExtended
androidTestImplementation "org.mockito:mockito-core:1.9.5"
androidTestImplementation 'com.google.dexmaker:dexmaker:1.2'
androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2'
diff --git a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
index e5b2c67..29b24b7 100644
--- a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
+++ b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
@@ -25,14 +25,13 @@
import android.os.Binder;
import android.os.Bundle;
import android.system.Os;
-import android.util.Log;
import androidx.annotation.Keep;
import androidx.annotation.Nullable;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.LauncherModel;
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.testing.shared.TestProtocol;
@@ -62,7 +61,6 @@
public void onActivityCreated(Activity activity, Bundle bundle) {
sActivities.put(activity, true);
++sActivitiesCreatedCount;
- Log.d(TestProtocol.FLAKY_ACTIVITY_COUNT, "onActivityCreated", new Exception());
}
@Override
@@ -188,13 +186,29 @@
return response;
}
+ case TestProtocol.REQUEST_REINITIALIZE_DATA: {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ MODEL_EXECUTOR.execute(() -> {
+ LauncherModel model = LauncherAppState.getInstance(mContext).getModel();
+ model.getModelDbController().createEmptyDB();
+ MAIN_EXECUTOR.execute(model::forceReload);
+ });
+ return response;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
case TestProtocol.REQUEST_CLEAR_DATA: {
final long identity = Binder.clearCallingIdentity();
try {
- LauncherSettings.Settings.call(mContext.getContentResolver(),
- LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
- MAIN_EXECUTOR.submit(() ->
- LauncherAppState.getInstance(mContext).getModel().forceReload());
+ MODEL_EXECUTOR.execute(() -> {
+ LauncherModel model = LauncherAppState.getInstance(mContext).getModel();
+ model.getModelDbController().createEmptyDB();
+ model.getModelDbController().clearEmptyDbFlag();
+ MAIN_EXECUTOR.execute(model::forceReload);
+ });
return response;
} finally {
Binder.restoreCallingIdentity(identity);
diff --git a/go/quickstep/res/values-am/strings.xml b/go/quickstep/res/values-am/strings.xml
index ed34797..ffc59d9 100644
--- a/go/quickstep/res/values-am/strings.xml
+++ b/go/quickstep/res/values-am/strings.xml
@@ -9,12 +9,12 @@
<string name="dialog_cancel" msgid="6464336969134856366">"ይቅር"</string>
<string name="dialog_settings" msgid="6564397136021186148">"ቅንብሮች"</string>
<string name="niu_actions_confirmation_title" msgid="3863451714863526143">"በማያ ገጹ ላይ ጽሑፍን ይተረጉሙ ወይም ያዳምጡ"</string>
- <string name="niu_actions_confirmation_text" msgid="2105271481950866089">"እንደ በማያ ገጽዎ ላይ ያለ ጽሁፍ፣ የድር አድራሻዎች እና ቅጽበታዊ ገጽ እይታዎች ያሉ መረጃዎች ለGoogle ሊጋሩ ይችላሉ።\n\nምን መረጃ እንደሚያጋሩ ለመቀየር ወደ "<b>"ቅንብሮች > መተግበሪያዎች > ነባሪ መተግበሪያዎች > ዲጂታል ረዳት መተግበሪያ"</b>" ይሂዱ።"</string>
+ <string name="niu_actions_confirmation_text" msgid="2105271481950866089">"እንደ በማያ ገፅዎ ላይ ያለ ጽሁፍ፣ የድር አድራሻዎች እና ቅጽበታዊ ገፅ እይታዎች ያሉ መረጃዎች ለGoogle ሊጋሩ ይችላሉ።\n\nምን መረጃ እንደሚያጋሩ ለመቀየር ወደ "<b>"ቅንብሮች > መተግበሪያዎች > ነባሪ መተግበሪያዎች > ዲጂታል ረዳት መተግበሪያ"</b>" ይሂዱ።"</string>
<string name="assistant_not_selected_title" msgid="5017072974603345228">"ይህንን ባህሪ ለመጠቀም ረዳት ይምረጡ"</string>
<string name="assistant_not_selected_text" msgid="3244613673884359276">"በማያ ገጽዎ ላይ ጽሑፍን ለማዳመጥ ወይም ለመተርጎም በቅንብሮች ውስጥ የዲጂታል ረዳት መተግበሪያን ይምረጡ"</string>
<string name="assistant_not_supported_title" msgid="1675788067597484142">"ይህንን ባህሪ ለመጠቀም ረዳትዎን ይቀይሩ"</string>
<string name="assistant_not_supported_text" msgid="1708031078549268884">"በማያ ገጽዎ ላይ ጽሑፍን ለማዳመጥ ወይም ለመተርጎም በቅንብሮች ውስጥ የዲጂታል ረዳት መተግበሪያዎን ይቀይሩ"</string>
- <string name="tooltip_listen" msgid="7634466447860989102">"በዚህ ማያ ገጽ ላይ ጽሁፍ ለማዳመጥ እዚህ መታ ያድርጉ"</string>
- <string name="tooltip_translate" msgid="4184845868901542567">"በዚህ ማያ ገጽ ላይ ጽሁፍ ለመተርጎም እዚህ መታ ያድርጉ"</string>
+ <string name="tooltip_listen" msgid="7634466447860989102">"በዚህ ማያ ገፅ ላይ ጽሁፍ ለማዳመጥ እዚህ መታ ያድርጉ"</string>
+ <string name="tooltip_translate" msgid="4184845868901542567">"በዚህ ማያ ገፅ ላይ ጽሁፍ ለመተርጎም እዚህ መታ ያድርጉ"</string>
<string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"ይህ መተግበሪያ ሊጋራ አይችልም"</string>
</resources>
diff --git a/go/quickstep/res/values-el/strings.xml b/go/quickstep/res/values-el/strings.xml
index 9a67420..7038c11 100644
--- a/go/quickstep/res/values-el/strings.xml
+++ b/go/quickstep/res/values-el/strings.xml
@@ -14,7 +14,7 @@
<string name="assistant_not_selected_text" msgid="3244613673884359276">"Για να ακούσετε ή να μεταφράσετε κείμενο στην οθόνη σας, επιλέξτε μια εφαρμογή ψηφιακού βοηθού στις Ρυθμίσεις."</string>
<string name="assistant_not_supported_title" msgid="1675788067597484142">"Αλλάξτε τον βοηθό σας για να χρησιμοποιήσετε αυτήν τη λειτουργία"</string>
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Για να ακούσετε ή να μεταφράσετε κείμενο στην οθόνη σας, αλλάξτε την εφαρμογή ψηφιακού βοηθού στις Ρυθμίσεις."</string>
- <string name="tooltip_listen" msgid="7634466447860989102">"Πατήστε εδώ για να ακούσετε το κείμενο σε αυτήν την οθόνη"</string>
- <string name="tooltip_translate" msgid="4184845868901542567">"Πατήστε εδώ για να μεταφράσετε το κείμενο σε αυτήν την οθόνη"</string>
+ <string name="tooltip_listen" msgid="7634466447860989102">"Πατήστε εδώ για να ακούσετε το κείμενο σε αυτή την οθόνη"</string>
+ <string name="tooltip_translate" msgid="4184845868901542567">"Πατήστε εδώ για να μεταφράσετε το κείμενο σε αυτή την οθόνη"</string>
<string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Δεν είναι δυνατή η κοινή χρήση της εφαρμογής"</string>
</resources>
diff --git a/go/quickstep/res/values-ky/strings.xml b/go/quickstep/res/values-ky/strings.xml
index 55e70c8..dcc1e4e 100644
--- a/go/quickstep/res/values-ky/strings.xml
+++ b/go/quickstep/res/values-ky/strings.xml
@@ -11,9 +11,9 @@
<string name="niu_actions_confirmation_title" msgid="3863451714863526143">"Экрандагы текстти которуу же угуу"</string>
<string name="niu_actions_confirmation_text" msgid="2105271481950866089">"Экрандагы текст, веб-даректер жана скриншоттор сыяктуу маалымат Google менен бөлүшүлүшү мүмкүн.\n\nБөлүшүлгөн маалыматты өзгөртүү үчүн"<b>"Параметрлер > Колдонмолор > Демейки колдонмолор > Санариптик жардамчы колдонмосуна өтүңүз"</b>"."</string>
<string name="assistant_not_selected_title" msgid="5017072974603345228">"Бул функцияны колдонуу үчүн жардамчыны тандаңыз"</string>
- <string name="assistant_not_selected_text" msgid="3244613673884359276">"Экраныңыздагы текстти угуу же которуу үчүн Жөндөөлөрдөн санариптик жардамчы колдонмосун тандаңыз"</string>
+ <string name="assistant_not_selected_text" msgid="3244613673884359276">"Экраныңыздагы текстти угуу же которуу үчүн Параметрлерден санариптик жардамчы колдонмосун тандаңыз"</string>
<string name="assistant_not_supported_title" msgid="1675788067597484142">"Бул функцияны колдонуу үчүн жардамчыңызды өзгөртүңүз"</string>
- <string name="assistant_not_supported_text" msgid="1708031078549268884">"Экраныңыздагы текстти угуу же которуу үчүн Жөндөөлөрдөн санариптик жардамчы колдонмосун өзгөртүңүз"</string>
+ <string name="assistant_not_supported_text" msgid="1708031078549268884">"Экраныңыздагы текстти угуу же которуу үчүн Параметрлерден санариптик жардамчы колдонмосун өзгөртүңүз"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Бул экрандагы текстти угуу үчүн бул жерди басыңыз"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Бул экрандагы текстти которуу үчүн бул жерди басыңыз"</string>
<string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Бул колдонмону бөлүшүүгө болбойт"</string>
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index 63ea20c..f8b08f8 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -135,7 +135,7 @@
}
}
-// Next value 51
+// Next value 52
enum Attribute {
option allow_alias = true;
@@ -187,6 +187,7 @@
ALL_APPS_SEARCH_RESULT_SYSTEM_POINTER = 42;
ALL_APPS_SEARCH_RESULT_EDUCARD = 43;
ALL_APPS_SEARCH_RESULT_LOCATION = 50;
+ ALL_APPS_SEARCH_RESULT_TEXT_HEADER = 51;
// Result sources
DATA_SOURCE_APPSEARCH_APP_PREVIEW = 45;
diff --git a/quickstep/Android.bp b/quickstep/Android.bp
index f5a8253..638ce27 100644
--- a/quickstep/Android.bp
+++ b/quickstep/Android.bp
@@ -42,5 +42,6 @@
"tests/src/com/android/quickstep/NavigationModeSwitchRule.java",
"tests/src/com/android/quickstep/AbstractQuickStepTest.java",
"tests/src/com/android/quickstep/TaplTestsQuickstep.java",
+ "tests/src/com/android/quickstep/TaplTestsSplitscreen.java",
]
}
diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml
index 7d7054f..c6e2d8c 100644
--- a/quickstep/AndroidManifest-launcher.xml
+++ b/quickstep/AndroidManifest-launcher.xml
@@ -20,7 +20,6 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher3">
- <uses-sdk android:targetSdkVersion="33" android:minSdkVersion="26"/>
<!--
Manifest entries specific to Launcher3. This is merged with AndroidManifest-common.xml.
Refer comments around specific entries on how to extend individual components.
diff --git a/quickstep/protos_overrides/launcher_atom_extension.proto b/quickstep/protos_overrides/launcher_atom_extension.proto
index f5a277b..b3df353 100644
--- a/quickstep/protos_overrides/launcher_atom_extension.proto
+++ b/quickstep/protos_overrides/launcher_atom_extension.proto
@@ -61,6 +61,9 @@
// User entered by tapping on QSB bar on homescreen.
QSB = 2;
+
+ // User entered by swiping up from overview (using Rocket Gesture).
+ OVERVIEW = 3;
}
}
}
diff --git a/res/interpolator/standard_decelerate.xml b/quickstep/res/drawable/bg_bubble_dismiss_circle.xml
similarity index 65%
rename from res/interpolator/standard_decelerate.xml
rename to quickstep/res/drawable/bg_bubble_dismiss_circle.xml
index 579f4f5..b793eec 100644
--- a/res/interpolator/standard_decelerate.xml
+++ b/quickstep/res/drawable/bg_bubble_dismiss_circle.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2022 The Android Open Source Project
+ ~ Copyright (C) 2023 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -15,8 +15,13 @@
~ limitations under the License.
-->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:controlX1="0"
- android:controlY1="0"
- android:controlX2="0"
- android:controlY2="1"/>
\ No newline at end of file
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+
+ <stroke
+ android:width="2dp"
+ android:color="@android:color/system_accent1_600" />
+
+ <solid android:color="@android:color/system_accent1_600" />
+</shape>
\ No newline at end of file
diff --git a/quickstep/res/drawable/bg_floating_desktop_select.xml b/quickstep/res/drawable/bg_floating_desktop_select.xml
new file mode 100644
index 0000000..d7df338
--- /dev/null
+++ b/quickstep/res/drawable/bg_floating_desktop_select.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="rectangle">
+
+ <corners android:radius="@dimen/rounded_button_radius" />
+ <solid android:color="?androidprv:attr/materialColorPrimaryContainer" />
+</shape>
\ No newline at end of file
diff --git a/quickstep/res/drawable/ic_bubble_dismiss_white.xml b/quickstep/res/drawable/ic_bubble_dismiss_white.xml
new file mode 100644
index 0000000..b15111b
--- /dev/null
+++ b/quickstep/res/drawable/ic_bubble_dismiss_white.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="20dp"
+ android:height="20dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M19.000000,6.400000l-1.400000,-1.400000 -5.600000,5.600000 -5.600000,-5.600000 -1.400000,1.400000 5.600000,5.600000 -5.600000,5.600000 1.400000,1.400000 5.600000,-5.600000 5.600000,5.600000 1.400000,-1.400000 -5.600000,-5.600000z"
+ android:fillColor="@android:color/system_neutral1_50"/>
+</vector>
diff --git a/quickstep/res/drawable/taskbar_divider_bg.xml b/quickstep/res/drawable/taskbar_divider_bg.xml
deleted file mode 100644
index 52e230d..0000000
--- a/quickstep/res/drawable/taskbar_divider_bg.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle" >
- <solid android:color="@color/taskbar_divider_background"/>
- <corners android:radius="1dp" />
-</shape>
diff --git a/quickstep/res/drawable/taskbar_divider_button.xml b/quickstep/res/drawable/taskbar_divider_button.xml
new file mode 100644
index 0000000..cb116cf
--- /dev/null
+++ b/quickstep/res/drawable/taskbar_divider_button.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="52dp"
+ android:height="52dp"
+ android:viewportHeight="52"
+ android:viewportWidth="52">
+ <group>
+ <path
+ android:fillColor="@color/taskbar_divider_background"
+ android:pathData="M26,11L26,41"
+ android:strokeColor="@color/taskbar_divider_background"
+ android:strokeLineCap="round"
+ android:strokeWidth="2" />
+ </group>
+</vector>
\ No newline at end of file
diff --git a/quickstep/res/interpolator/three_point_fast_out_extra_slow_in.xml b/quickstep/res/interpolator/three_point_fast_out_extra_slow_in.xml
deleted file mode 100644
index 70c4231..0000000
--- a/quickstep/res/interpolator/three_point_fast_out_extra_slow_in.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2021, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0,0 C 0.05, 0, 0.133333, 0.06, 0.166666, 0.4 C 0.208333, 0.82, 0.25, 1, 1, 1"/>
diff --git a/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml b/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml
index 4e67629..69e1574 100644
--- a/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml
+++ b/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml
@@ -23,7 +23,7 @@
android:importantForAccessibility="yes"
android:background="@drawable/keyboard_quick_switch_task_view_background"
android:clipToOutline="true"
- launcher:borderColor="?androidprv:attr/materialColorOutline">
+ launcher:focusBorderColor="?androidprv:attr/materialColorOutline">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/content"
diff --git a/quickstep/res/layout-sw600dp-land/gesture_tutorial_step_menu.xml b/quickstep/res/layout-sw600dp-land/gesture_tutorial_step_menu.xml
index 225b4cd..672440f 100644
--- a/quickstep/res/layout-sw600dp-land/gesture_tutorial_step_menu.xml
+++ b/quickstep/res/layout-sw600dp-land/gesture_tutorial_step_menu.xml
@@ -13,155 +13,163 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<androidx.constraintlayout.widget.ConstraintLayout
+<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:theme="@style/GestureTutorialActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingTop="@dimen/gesture_tutorial_menu_padding_top"
- android:paddingBottom="@dimen/gesture_tutorial_menu_padding_bottom"
- android:paddingHorizontal="@dimen/gesture_tutorial_menu_padding_horizontal"
- android:background="?androidprv:attr/materialColorSurfaceContainer">
+ android:background="?androidprv:attr/materialColorSurfaceContainer"
+ android:fitsSystemWindows="true">
<androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/gesture_tutorial_menu_home_button"
- android:layout_width="0dp"
- android:layout_height="@dimen/gesture_tutorial_menu_button_height"
- android:layout_marginEnd="@dimen/gesture_tutorial_menu_button_spacing"
- android:layout_marginBottom="24dp"
- android:background="@drawable/gesture_tutorial_menu_home_button_background"
- android:clipToOutline="true"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingTop="@dimen/gesture_tutorial_menu_padding_top"
+ android:paddingBottom="@dimen/gesture_tutorial_menu_padding_bottom"
+ android:paddingHorizontal="@dimen/gesture_tutorial_menu_padding_horizontal"
+ android:clipToPadding="false">
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/guideline"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toStartOf="@id/gesture_tutorial_menu_back_button">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/gesture_tutorial_home_step_shape"
- android:scaleType="fitXY"
- android:adjustViewBounds="true"
-
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
-
- <TextView
- style="@style/TextAppearance.GestureTutorial.MenuButton.Home"
- android:id="@+id/gesture_tutorial_menu_home_button_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/home_gesture_tutorial_title"
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/gesture_tutorial_menu_home_button"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/gesture_tutorial_menu_button_height"
+ android:layout_marginEnd="@dimen/gesture_tutorial_menu_button_spacing"
+ android:layout_marginBottom="24dp"
+ android:background="@drawable/gesture_tutorial_menu_home_button_background"
+ android:clipToOutline="true"
app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/guideline"
app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/gesture_tutorial_menu_back_button">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/gesture_tutorial_home_step_shape"
+ android:scaleType="fitXY"
+ android:adjustViewBounds="true"
+
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ <TextView
+ style="@style/TextAppearance.GestureTutorial.MenuButton.Home"
+ android:id="@+id/gesture_tutorial_menu_home_button_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/home_gesture_tutorial_title"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/gesture_tutorial_menu_back_button"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/gesture_tutorial_menu_button_height"
+ android:layout_marginEnd="@dimen/gesture_tutorial_menu_button_spacing"
+ android:layout_marginBottom="24dp"
+ android:background="@drawable/gesture_tutorial_menu_back_button_background"
+ android:clipToOutline="true"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/guideline"
+ app:layout_constraintStart_toEndOf="@id/gesture_tutorial_menu_home_button"
+ app:layout_constraintEnd_toStartOf="@id/gesture_tutorial_menu_overview_button">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/gesture_tutorial_back_step_shape"
+ android:layout_marginBottom="@dimen/gesture_tutorial_menu_back_shape_bottom_margin"
+ android:scaleType="fitXY"
+ android:adjustViewBounds="true"
+
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"/>
+
+ <TextView
+ style="@style/TextAppearance.GestureTutorial.MenuButton.Back"
+ android:id="@+id/gesture_tutorial_menu_back_button_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/back_gesture_tutorial_title"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/gesture_tutorial_menu_overview_button"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/gesture_tutorial_menu_button_height"
+ android:layout_marginBottom="24dp"
+ android:background="@drawable/gesture_tutorial_menu_overview_button_background"
+ android:clipToOutline="true"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/guideline"
+ app:layout_constraintStart_toEndOf="@id/gesture_tutorial_menu_back_button"
+ app:layout_constraintEnd_toEndOf="parent">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/gesture_tutorial_overview_step_shape"
+ android:scaleType="fitXY"
+ android:adjustViewBounds="true"
+
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ <TextView
+ style="@style/TextAppearance.GestureTutorial.MenuButton.Overview"
+ android:id="@+id/gesture_tutorial_menu_overview_button_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/overview_gesture_tutorial_title"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+ <androidx.constraintlayout.widget.Guideline
+ android:id="@+id/guideline"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+
+ app:layout_constraintGuide_end="@dimen/gesture_tutorial_menu_done_button_spacing"/>
+
+ <Button
+ style="@style/TextAppearance.GestureTutorial.ButtonLabel"
+ android:id="@+id/gesture_tutorial_menu_done_button"
+ android:layout_width="wrap_content"
+ android:layout_height="40dp"
+ android:layout_marginVertical="16dp"
+ android:text="@string/gesture_tutorial_action_button_label"
+ android:background="@drawable/gesture_tutorial_action_button_background"
+ android:backgroundTint="?androidprv:attr/materialColorPrimary"
+ android:stateListAnimator="@null"
+
+ app:layout_constraintTop_toBottomOf="@id/guideline"
+ app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
- <androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/gesture_tutorial_menu_back_button"
- android:layout_width="0dp"
- android:layout_height="@dimen/gesture_tutorial_menu_button_height"
- android:layout_marginEnd="@dimen/gesture_tutorial_menu_button_spacing"
- android:layout_marginBottom="24dp"
- android:background="@drawable/gesture_tutorial_menu_back_button_background"
- android:clipToOutline="true"
-
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/guideline"
- app:layout_constraintStart_toEndOf="@id/gesture_tutorial_menu_home_button"
- app:layout_constraintEnd_toStartOf="@id/gesture_tutorial_menu_overview_button">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/gesture_tutorial_back_step_shape"
- android:layout_marginBottom="@dimen/gesture_tutorial_menu_back_shape_bottom_margin"
- android:scaleType="fitXY"
- android:adjustViewBounds="true"
-
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"/>
-
- <TextView
- style="@style/TextAppearance.GestureTutorial.MenuButton.Back"
- android:id="@+id/gesture_tutorial_menu_back_button_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/back_gesture_tutorial_title"
-
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
-
- </androidx.constraintlayout.widget.ConstraintLayout>
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/gesture_tutorial_menu_overview_button"
- android:layout_width="0dp"
- android:layout_height="@dimen/gesture_tutorial_menu_button_height"
- android:layout_marginBottom="24dp"
- android:background="@drawable/gesture_tutorial_menu_overview_button_background"
- android:clipToOutline="true"
-
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/guideline"
- app:layout_constraintStart_toEndOf="@id/gesture_tutorial_menu_back_button"
- app:layout_constraintEnd_toEndOf="parent">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/gesture_tutorial_overview_step_shape"
- android:scaleType="fitXY"
- android:adjustViewBounds="true"
-
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
-
- <TextView
- style="@style/TextAppearance.GestureTutorial.MenuButton.Overview"
- android:id="@+id/gesture_tutorial_menu_overview_button_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/overview_gesture_tutorial_title"
-
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
-
- </androidx.constraintlayout.widget.ConstraintLayout>
-
- <androidx.constraintlayout.widget.Guideline
- android:id="@+id/guideline"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
-
- app:layout_constraintGuide_end="@dimen/gesture_tutorial_menu_done_button_spacing"/>
-
- <Button
- style="@style/TextAppearance.GestureTutorial.ButtonLabel"
- android:id="@+id/gesture_tutorial_menu_done_button"
- android:layout_width="wrap_content"
- android:layout_height="40dp"
- android:layout_marginVertical="16dp"
- android:text="@string/gesture_tutorial_action_button_label"
- android:background="@drawable/gesture_tutorial_action_button_background"
- android:backgroundTint="?androidprv:attr/materialColorPrimary"
- android:stateListAnimator="@null"
-
- app:layout_constraintTop_toBottomOf="@id/guideline"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
-
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
+</FrameLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/activity_allset.xml b/quickstep/res/layout/activity_allset.xml
index 2c312a7..685a151 100644
--- a/quickstep/res/layout/activity_allset.xml
+++ b/quickstep/res/layout/activity_allset.xml
@@ -41,6 +41,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
+ android:fitsSystemWindows="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
@@ -95,7 +96,6 @@
style="@style/TextAppearance.GestureTutorial.Feedback.Subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginBottom="24dp"
android:text="@string/allset_hint"
android:textSize="@dimen/allset_page_swipe_up_text_size"
android:gravity="center_horizontal"
diff --git a/quickstep/res/layout/fallback_recents_activity.xml b/quickstep/res/layout/fallback_recents_activity.xml
index bfeb82d..f0ea09c 100644
--- a/quickstep/res/layout/fallback_recents_activity.xml
+++ b/quickstep/res/layout/fallback_recents_activity.xml
@@ -15,6 +15,7 @@
-->
<com.android.launcher3.LauncherRootView
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/launcher"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
diff --git a/quickstep/res/layout/floating_desktop_app_select.xml b/quickstep/res/layout/floating_desktop_app_select.xml
new file mode 100644
index 0000000..375fc44
--- /dev/null
+++ b/quickstep/res/layout/floating_desktop_app_select.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<com.android.quickstep.views.DesktopAppSelectView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/desktop_mode_floating_app_select_height"
+ android:layout_gravity="top|center_horizontal"
+ android:background="@drawable/bg_floating_desktop_select"
+ android:elevation="@dimen/desktop_mode_floating_app_select_elevation"
+ android:gravity="center_vertical"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/desktop_app_select_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/desktop_mode_floating_app_select_text_margin"
+ android:layout_marginStart="@dimen/desktop_mode_floating_app_select_margin"
+ android:drawablePadding="@dimen/desktop_mode_floating_app_select_text_margin"
+ android:drawableStart="@drawable/ic_desktop"
+ android:drawableTint="?androidprv:attr/materialColorOnPrimaryContainer"
+ android:fontFamily="google-sans-medium"
+ android:gravity="center_vertical"
+ android:text="@string/desktop_select_app_toast"
+ android:textColor="?androidprv:attr/materialColorOnPrimaryContainer"
+ android:textSize="@dimen/desktop_mode_floating_app_select_text_size" />
+
+ <Button
+ android:id="@+id/close_button"
+ style="@android:style/Widget.DeviceDefault.Button.Borderless"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/desktop_mode_floating_app_select_margin"
+ android:minWidth="0dp"
+ android:fontFamily="google-sans-medium"
+ android:text="@string/desktop_button_close_app_toast"
+ android:textAllCaps="false"
+ android:textColor="?androidprv:attr/materialColorPrimary"
+ android:textSize="@dimen/desktop_mode_floating_app_select_text_size" />
+
+</com.android.quickstep.views.DesktopAppSelectView>
diff --git a/quickstep/res/layout/gesture_tutorial_activity.xml b/quickstep/res/layout/gesture_tutorial_activity.xml
index 0e763ec..82caedf 100644
--- a/quickstep/res/layout/gesture_tutorial_activity.xml
+++ b/quickstep/res/layout/gesture_tutorial_activity.xml
@@ -13,80 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<androidx.constraintlayout.widget.ConstraintLayout
+<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/gesture_tutorial_fragment_container"
android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <FrameLayout
- android:id="@+id/gesture_tutorial_fragment_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
-
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent" />
-
- <RelativeLayout
- android:id="@+id/rotation_prompt"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="?attr/surfaceHome"
- android:visibility="gone"
-
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent">
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/background"
- android:layout_width="300dp"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:layout_centerVertical="true"
- android:background="@drawable/rotate_prompt_bg"
- android:padding="24dp">
-
- <ImageView
- android:id="@+id/icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/rotate_tutorial_warning"
-
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintEnd_toEndOf="parent" />
-
- <TextView
- android:id="@+id/rotate_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="20dp"
- android:lineSpacingExtra="2sp"
- android:text="@string/gesture_tutorial_rotation_prompt_title"
- android:textAppearance="@style/rotate_prompt_title"
-
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@id/icon"
- app:layout_constraintEnd_toEndOf="parent" />
-
- <TextView
- android:id="@+id/rotate_screen_subtitle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:gravity="center"
- android:text="@string/gesture_tutorial_rotation_prompt"
- android:textAppearance="@style/rotate_prompt_subtitle"
-
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@id/rotate_title"
- app:layout_constraintEnd_toEndOf="parent" />
-
- </androidx.constraintlayout.widget.ConstraintLayout>
- </RelativeLayout>
-
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
+ android:layout_height="match_parent"/>
\ No newline at end of file
diff --git a/quickstep/res/layout/gesture_tutorial_rotation_prompt.xml b/quickstep/res/layout/gesture_tutorial_rotation_prompt.xml
new file mode 100644
index 0000000..b41a96d
--- /dev/null
+++ b/quickstep/res/layout/gesture_tutorial_rotation_prompt.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="?attr/surfaceHome">
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/background"
+ android:layout_width="300dp"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:background="@drawable/rotate_prompt_bg"
+ android:padding="24dp"
+
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent">
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/rotate_tutorial_warning"
+
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintEnd_toEndOf="parent" />
+
+ <TextView
+ android:id="@+id/rotate_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dp"
+ android:lineSpacingExtra="2sp"
+ android:text="@string/gesture_tutorial_rotation_prompt_title"
+ android:textAppearance="@style/rotate_prompt_title"
+
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/icon"
+ app:layout_constraintEnd_toEndOf="parent" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:gravity="center"
+ android:text="@string/gesture_tutorial_rotation_prompt"
+ android:textAppearance="@style/rotate_prompt_subtitle"
+
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/rotate_title"
+ app:layout_constraintEnd_toEndOf="parent" />
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/gesture_tutorial_step_menu.xml b/quickstep/res/layout/gesture_tutorial_step_menu.xml
index cf78b1b..c8ee6e9 100644
--- a/quickstep/res/layout/gesture_tutorial_step_menu.xml
+++ b/quickstep/res/layout/gesture_tutorial_step_menu.xml
@@ -13,154 +13,161 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<androidx.constraintlayout.widget.ConstraintLayout
+<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:theme="@style/GestureTutorialActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingTop="@dimen/gesture_tutorial_menu_padding_top"
- android:paddingBottom="@dimen/gesture_tutorial_menu_padding_bottom"
- android:paddingHorizontal="@dimen/gesture_tutorial_menu_padding_horizontal"
android:background="?androidprv:attr/materialColorSurfaceContainer"
- android:clipToPadding="false">
+ android:fitsSystemWindows="true">
<androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/gesture_tutorial_menu_home_button"
android:layout_width="match_parent"
- android:layout_height="@dimen/gesture_tutorial_menu_button_height"
- android:background="@drawable/gesture_tutorial_menu_home_button_background"
- android:clipToOutline="true"
- app:layout_constraintVertical_chainStyle="packed"
+ android:layout_height="match_parent"
+ android:paddingTop="@dimen/gesture_tutorial_menu_padding_top"
+ android:paddingBottom="@dimen/gesture_tutorial_menu_padding_bottom"
+ android:paddingHorizontal="@dimen/gesture_tutorial_menu_padding_horizontal"
+ android:clipToPadding="false">
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/gesture_tutorial_menu_back_button"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/gesture_tutorial_home_step_shape"
- android:scaleType="fitXY"
- android:adjustViewBounds="true"
-
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
-
- <TextView
- style="@style/TextAppearance.GestureTutorial.MenuButton.Home"
- android:id="@+id/gesture_tutorial_menu_home_button_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/home_gesture_tutorial_title"
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/gesture_tutorial_menu_home_button"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/gesture_tutorial_menu_button_height"
+ android:background="@drawable/gesture_tutorial_menu_home_button_background"
+ android:clipToOutline="true"
+ app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/gesture_tutorial_menu_back_button"
app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/gesture_tutorial_home_step_shape"
+ android:scaleType="fitXY"
+ android:adjustViewBounds="true"
+
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ <TextView
+ style="@style/TextAppearance.GestureTutorial.MenuButton.Home"
+ android:id="@+id/gesture_tutorial_menu_home_button_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/home_gesture_tutorial_title"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/gesture_tutorial_menu_back_button"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/gesture_tutorial_menu_button_height"
+ android:layout_marginTop="@dimen/gesture_tutorial_menu_button_spacing"
+ android:background="@drawable/gesture_tutorial_menu_back_button_background"
+ android:clipToOutline="true"
+
+ app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_menu_home_button"
+ app:layout_constraintBottom_toTopOf="@id/gesture_tutorial_menu_overview_button"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/gesture_tutorial_back_step_shape"
+ android:scaleType="fitXY"
+ android:adjustViewBounds="true"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"/>
+
+ <TextView
+ style="@style/TextAppearance.GestureTutorial.MenuButton.Back"
+ android:id="@+id/gesture_tutorial_menu_back_button_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/back_gesture_tutorial_title"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/gesture_tutorial_menu_overview_button"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/gesture_tutorial_menu_button_height"
+ android:layout_marginTop="@dimen/gesture_tutorial_menu_button_spacing"
+ android:background="@drawable/gesture_tutorial_menu_overview_button_background"
+ android:clipToOutline="true"
+
+ app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_menu_back_button"
+ app:layout_constraintBottom_toTopOf="@id/guideline"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/gesture_tutorial_overview_step_shape"
+ android:scaleType="fitXY"
+ android:adjustViewBounds="true"
+
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ <TextView
+ style="@style/TextAppearance.GestureTutorial.MenuButton.Overview"
+ android:id="@+id/gesture_tutorial_menu_overview_button_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/overview_gesture_tutorial_title"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+ <androidx.constraintlayout.widget.Guideline
+ android:id="@+id/guideline"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+
+ app:layout_constraintGuide_end="@dimen/gesture_tutorial_menu_done_button_spacing"/>
+
+ <Button
+ style="@style/TextAppearance.GestureTutorial.ButtonLabel"
+ android:id="@+id/gesture_tutorial_menu_done_button"
+ android:layout_width="wrap_content"
+ android:layout_height="40dp"
+ android:layout_marginVertical="16dp"
+ android:text="@string/gesture_tutorial_action_button_label"
+ android:background="@drawable/gesture_tutorial_action_button_background"
+ android:backgroundTint="?androidprv:attr/materialColorPrimary"
+ android:stateListAnimator="@null"
+
+ app:layout_constraintTop_toBottomOf="@id/guideline"
+ app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
- <androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/gesture_tutorial_menu_back_button"
- android:layout_width="match_parent"
- android:layout_height="@dimen/gesture_tutorial_menu_button_height"
- android:layout_marginTop="@dimen/gesture_tutorial_menu_button_spacing"
- android:background="@drawable/gesture_tutorial_menu_back_button_background"
- android:clipToOutline="true"
-
- app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_menu_home_button"
- app:layout_constraintBottom_toTopOf="@id/gesture_tutorial_menu_overview_button"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/gesture_tutorial_back_step_shape"
- android:scaleType="fitXY"
- android:adjustViewBounds="true"
-
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"/>
-
- <TextView
- style="@style/TextAppearance.GestureTutorial.MenuButton.Back"
- android:id="@+id/gesture_tutorial_menu_back_button_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/back_gesture_tutorial_title"
-
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
-
- </androidx.constraintlayout.widget.ConstraintLayout>
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/gesture_tutorial_menu_overview_button"
- android:layout_width="match_parent"
- android:layout_height="@dimen/gesture_tutorial_menu_button_height"
- android:layout_marginTop="@dimen/gesture_tutorial_menu_button_spacing"
- android:background="@drawable/gesture_tutorial_menu_overview_button_background"
- android:clipToOutline="true"
-
- app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_menu_back_button"
- app:layout_constraintBottom_toTopOf="@id/guideline"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/gesture_tutorial_overview_step_shape"
- android:scaleType="fitXY"
- android:adjustViewBounds="true"
-
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
-
- <TextView
- style="@style/TextAppearance.GestureTutorial.MenuButton.Overview"
- android:id="@+id/gesture_tutorial_menu_overview_button_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/overview_gesture_tutorial_title"
-
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
-
- </androidx.constraintlayout.widget.ConstraintLayout>
-
- <androidx.constraintlayout.widget.Guideline
- android:id="@+id/guideline"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
-
- app:layout_constraintGuide_end="@dimen/gesture_tutorial_menu_done_button_spacing"/>
-
- <Button
- style="@style/TextAppearance.GestureTutorial.ButtonLabel"
- android:id="@+id/gesture_tutorial_menu_done_button"
- android:layout_width="wrap_content"
- android:layout_height="40dp"
- android:layout_marginVertical="16dp"
- android:text="@string/gesture_tutorial_action_button_label"
- android:background="@drawable/gesture_tutorial_action_button_background"
- android:backgroundTint="?androidprv:attr/materialColorPrimary"
- android:stateListAnimator="@null"
-
- app:layout_constraintTop_toBottomOf="@id/guideline"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
-
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
+</FrameLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/keyboard_quick_switch_overview.xml b/quickstep/res/layout/keyboard_quick_switch_overview.xml
index e7b1f23..4a9b023 100644
--- a/quickstep/res/layout/keyboard_quick_switch_overview.xml
+++ b/quickstep/res/layout/keyboard_quick_switch_overview.xml
@@ -22,7 +22,7 @@
android:layout_height="@dimen/keyboard_quick_switch_taskview_height"
android:clipToOutline="true"
android:importantForAccessibility="yes"
- launcher:borderColor="?androidprv:attr/materialColorOutline">
+ launcher:focusBorderColor="?androidprv:attr/materialColorOutline">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/content"
diff --git a/quickstep/res/layout/keyboard_quick_switch_taskview.xml b/quickstep/res/layout/keyboard_quick_switch_taskview.xml
index 4d213fa..6ed3c6e 100644
--- a/quickstep/res/layout/keyboard_quick_switch_taskview.xml
+++ b/quickstep/res/layout/keyboard_quick_switch_taskview.xml
@@ -23,7 +23,7 @@
android:importantForAccessibility="yes"
android:background="@drawable/keyboard_quick_switch_task_view_background"
android:clipToOutline="true"
- launcher:borderColor="?androidprv:attr/materialColorOutline">
+ launcher:focusBorderColor="?androidprv:attr/materialColorOutline">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/content"
diff --git a/quickstep/res/layout/keyboard_quick_switch_view.xml b/quickstep/res/layout/keyboard_quick_switch_view.xml
index 16abdee..5af8d51 100644
--- a/quickstep/res/layout/keyboard_quick_switch_view.xml
+++ b/quickstep/res/layout/keyboard_quick_switch_view.xml
@@ -17,6 +17,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/keyboard_quick_switch_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/keyboard_quick_switch_margin_top"
diff --git a/quickstep/res/layout/split_instructions_view.xml b/quickstep/res/layout/split_instructions_view.xml
index 91fb05c..c663bf4 100644
--- a/quickstep/res/layout/split_instructions_view.xml
+++ b/quickstep/res/layout/split_instructions_view.xml
@@ -24,12 +24,15 @@
android:paddingTop="@dimen/split_instructions_vertical_padding"
android:paddingBottom="@dimen/split_instructions_vertical_padding"
android:elevation="@dimen/split_instructions_elevation"
- android:visibility="gone">
+ android:visibility="gone"
+ android:importantForAccessibility="yes">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/split_instructions_text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:gravity="center"
android:textColor="?androidprv:attr/textColorOnAccent"
+ android:drawableEnd="@drawable/ic_split_exit"
+ android:drawablePadding="@dimen/split_instructions_drawable_padding"
android:text="@string/toast_split_select_app" />
</com.android.quickstep.views.SplitInstructionsView>
\ No newline at end of file
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index 4865aef..29c9992 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -24,7 +24,8 @@
android:clipChildren="false"
android:defaultFocusHighlightEnabled="false"
android:focusable="true"
- launcher:borderColor="?androidprv:attr/materialColorOutline">
+ launcher:focusBorderColor="?androidprv:attr/materialColorOutline"
+ launcher:hoverBorderColor="?androidprv:attr/materialColorPrimary">
<com.android.quickstep.views.TaskThumbnailView
android:id="@+id/snapshot"
diff --git a/quickstep/res/layout/task_desktop.xml b/quickstep/res/layout/task_desktop.xml
index fd82c66..06f4d06 100644
--- a/quickstep/res/layout/task_desktop.xml
+++ b/quickstep/res/layout/task_desktop.xml
@@ -25,7 +25,8 @@
android:clipToOutline="true"
android:defaultFocusHighlightEnabled="false"
android:focusable="true"
- launcher:borderColor="?androidprv:attr/materialColorOutline">
+ launcher:focusBorderColor="?androidprv:attr/materialColorOutline"
+ launcher:hoverBorderColor="?androidprv:attr/materialColorPrimary">
<View
android:id="@+id/background"
diff --git a/quickstep/res/layout/task_grouped.xml b/quickstep/res/layout/task_grouped.xml
index c9fa9c0..75ff626 100644
--- a/quickstep/res/layout/task_grouped.xml
+++ b/quickstep/res/layout/task_grouped.xml
@@ -29,7 +29,8 @@
android:clipChildren="false"
android:defaultFocusHighlightEnabled="false"
android:focusable="true"
- launcher:borderColor="?androidprv:attr/materialColorOutline">
+ launcher:focusBorderColor="?androidprv:attr/materialColorOutline"
+ launcher:hoverBorderColor="?androidprv:attr/materialColorPrimary">
<com.android.quickstep.views.TaskThumbnailView
android:id="@+id/snapshot"
diff --git a/quickstep/res/layout/taskbar_all_apps.xml b/quickstep/res/layout/taskbar_all_apps.xml
index 976cd9e..e234165 100644
--- a/quickstep/res/layout/taskbar_all_apps.xml
+++ b/quickstep/res/layout/taskbar_all_apps.xml
@@ -14,18 +14,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView
+<com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:accessibilityPaneTitle="@string/all_apps_label">
-
- <com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView
- android:id="@+id/apps_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:clipChildren="true"
- android:clipToPadding="false"
- android:focusable="false"
- android:saveEnabled="false" />
-</com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView>
+ android:clipChildren="true"
+ android:clipToPadding="false"
+ android:focusable="false"
+ android:saveEnabled="false" />
diff --git a/res/layout/system_shortcut_icons_container_material_u.xml b/quickstep/res/layout/taskbar_all_apps_sheet.xml
similarity index 61%
rename from res/layout/system_shortcut_icons_container_material_u.xml
rename to quickstep/res/layout/taskbar_all_apps_sheet.xml
index fbf18af..a1d5fa6 100644
--- a/res/layout/system_shortcut_icons_container_material_u.xml
+++ b/quickstep/res/layout/taskbar_all_apps_sheet.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
+<!--
+ Copyright (C) 2023 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,14 +14,13 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<LinearLayout
+<com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/system_shortcuts_container"
- android:tag="@string/popup_container_iterate_children"
android:layout_width="match_parent"
- android:layout_height="@dimen/system_shortcut_header_height"
- android:orientation="horizontal"
- android:gravity="end|center_vertical"
- android:background="@drawable/popup_background_material_u"
- android:elevation="@dimen/deep_shortcuts_elevation"/>
+ android:layout_height="match_parent"
+ android:accessibilityPaneTitle="@string/all_apps_label">
+
+ <include
+ android:id="@+id/apps_view"
+ layout="@layout/taskbar_all_apps" />
+</com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView>
diff --git a/quickstep/res/layout/taskbar_divider.xml b/quickstep/res/layout/taskbar_divider.xml
index 73f3811..0a92fa9 100644
--- a/quickstep/res/layout/taskbar_divider.xml
+++ b/quickstep/res/layout/taskbar_divider.xml
@@ -13,16 +13,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<FrameLayout
+<com.android.launcher3.views.IconButtonView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/taskbar_icon_min_touch_size"
android:layout_height="@dimen/taskbar_icon_min_touch_size"
android:contentDescription="@string/taskbar_divider_a11y_title"
- android:backgroundTint="@android:color/transparent">
-
- <View
- android:layout_height="32dp"
- android:layout_width="2dp"
- android:layout_gravity="center"
- android:background="@drawable/taskbar_divider_bg" />
-</FrameLayout>
\ No newline at end of file
+ android:backgroundTint="@android:color/transparent" />
\ No newline at end of file
diff --git a/quickstep/res/layout/taskbar_divider_popup_menu.xml b/quickstep/res/layout/taskbar_divider_popup_menu.xml
index 195443e..4348a47 100644
--- a/quickstep/res/layout/taskbar_divider_popup_menu.xml
+++ b/quickstep/res/layout/taskbar_divider_popup_menu.xml
@@ -19,7 +19,7 @@
android:layout_width="@dimen/taskbar_pinning_popup_menu_width"
android:layout_height="wrap_content"
android:focusable="true"
- android:background="@drawable/popup_background_material_u"
+ android:background="@drawable/popup_background"
android:orientation="vertical">
<LinearLayout
@@ -32,7 +32,7 @@
android:clickable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
- android:background="@drawable/top_rounded_popup_ripple"
+ android:background="@drawable/rounded_popup_ripple"
android:paddingEnd="10dp"
android:paddingStart="10dp"
android:theme="@style/PopupItem">
@@ -59,40 +59,4 @@
android:text="@string/always_show_taskbar" />
</LinearLayout>
-
- <LinearLayout
- android:id="@+id/navigation_mode_switch_option"
- android:layout_width="match_parent"
- android:layout_height="52dp"
- android:layout_gravity="center_vertical"
- android:elevation="2dp"
- android:clickable="true"
- android:focusable="true"
- android:background="@drawable/bottom_rounded_popup_ripple"
- android:gravity="center_vertical"
- android:orientation="horizontal"
- android:paddingEnd="10dp"
- android:paddingStart="10dp"
- android:theme="@style/PopupItem">
-
- <View
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_margin="4dp"
- android:background="@drawable/ic_touch"
- android:backgroundTint="?android:attr/textColorPrimary" />
-
- <com.android.launcher3.BubbleTextView
- style="@style/BaseIcon"
- android:id="@+id/change_navigation_mode_text"
- android:gravity="start|center_vertical"
- android:textAlignment="viewStart"
- android:paddingStart="12dp"
- android:singleLine="true"
- android:ellipsize="end"
- android:textSize="14sp"
- android:textColor="?android:attr/textColorPrimary"
- android:text="@string/change_navigation_mode" />
-
- </LinearLayout>
</com.android.launcher3.taskbar.TaskbarDividerPopupView>
\ No newline at end of file
diff --git a/quickstep/res/layout/transient_taskbar.xml b/quickstep/res/layout/transient_taskbar.xml
index bf4b811..0890a4e 100644
--- a/quickstep/res/layout/transient_taskbar.xml
+++ b/quickstep/res/layout/transient_taskbar.xml
@@ -44,12 +44,12 @@
android:layout_height="@dimen/bubblebar_size"
android:layout_gravity="bottom|end"
android:layout_marginEnd="@dimen/transient_taskbar_bottom_margin"
- android:layout_marginBottom="@dimen/transient_taskbar_bottom_margin"
android:paddingEnd="@dimen/taskbar_icon_spacing"
android:paddingStart="@dimen/taskbar_icon_spacing"
android:visibility="gone"
android:gravity="center"
android:clipChildren="false"
+ android:elevation="@dimen/bubblebar_elevation"
/>
<FrameLayout
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index 2811a3d..b589e32 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Programvoorstelle is geaktiveer"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Programvoorstelle is gedeaktiveer"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Voorspelde program: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Maak seker dat jy van die rand heel regs of heel links af swiep."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Maak seker dat jy van die regter- of linkerrand na die middel van die skerm swiep en laat los."</string>
- <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Jy het geleer hoe om van regs af te swiep om terug te gaan. Nou kan jy leer hoe om tussen programme te wissel."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Jy het die \"gaan terug\"-gebaar voltooi."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Maak seker dat jy nie te naby aan die onderkant van die skerm swiep nie."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Draai jou toestel"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Draai asseblief jou toestel om die tutoriaal oor gebaarnavigasie te voltooi"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Maak seker dat jy van die rand heel regs of heel links af swiep"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Maak seker dat jy van die regter- of linkerrand af na die middel van die skerm toe swiep en laat los"</string>
+ <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Jy het geleer hoe om van regs af te swiep om terug te gaan. Nou kan jy leer hoe om tussen apps te wissel."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Jy het die Gaan Terug-gebaar voltooi"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Maak seker dat jy nie te naby aan die onderkant van die skerm swiep nie"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Gaan na Instellings om sensitiwiteit van teruggebaar te verander"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Swiep om terug te gaan"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Swiep van die linker- of regterrand na die middel van die skerm om na die vorige skerm terug te gaan."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Swiep met 2 vingers van die linker- of regterkant van die skerm af na die middel toe om terug te keer na die vorige skerm."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Maak seker dat jy van die onderrand van die skerm af opswiep."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Maak seker jy onderbreek nie voordat jy laat los nie."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Maak seker jy swiep reguit op."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Jy het die \"gaan na tuisskerm\"-gebaar voltooi. Nou kan jy leer hoe om terug te gaan."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Jy het die \"gaan na tuisskerm\"-gebaar voltooi."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Gaan terug"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Swiep van die linker- of regterrand af na die middel van die skerm toe"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Maak seker dat jy van die onderrand van die skerm af opswiep"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Maak seker jy hou nie stil voordat jy laat los nie"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Maak seker jy swiep reguit op"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Jy het die Gaan na Tuisskerm-gebaar voltooi. Nou kan jy leer hoe om terug te gaan."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Jy het die Gaan na Tuisskerm-gebaar voltooi"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Swiep om na tuisskerm toe te gaan"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Swiep op van die onderkant van jou skerm af. Hierdie gebaar neem jou altyd na die tuisskerm toe."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Swiep met 2 vingers op van die onderkant van die skerm af. Dié gebaar neem jou altyd na die tuisskerm toe."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Gaan na tuisskerm"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Swiep enige tyd van die onderkant van jou skerm af op om na jou tuisskerm toe te gaan"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Maak seker dat jy van die onderrand van die skerm af opswiep."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Probeer om die venster langer te hou voordat jy laat los."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Maak seker dat jy reguit opswiep en dan onderbreek."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Swiep van die onderkant van jou skerm af op"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Knap gedaan!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Maak seker dat jy van die onderrand van die skerm af opswiep"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Probeer om die venster langer te hou voordat jy laat los"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Maak seker dat jy reguit opswiep en dan stilhou"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Jy het geleer hoe om gebare te gebruik. Gaan na Instellings om gebare af te skakel."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Jy het die \"wissel tussen programme\"-gebaar voltooi."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Jy het die Wissel Apps-gebaar voltooi"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Swiep om tussen programme te wissel"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Swiep van die onderkant van jou skerm af op, hou en laat los dan om tussen programme te wissel."</string>
- <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Swiep met 2 vingers op van die onderkant van jou skerm af, hou en laat los dan om tussen programme te wissel."</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Swiep van die onderkant van jou skerm af op, hou en laat los dan om tussen apps te wissel."</string>
+ <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Swiep met 2 vingers op van die onderkant van jou skerm af, hou en laat los dan om tussen apps te wissel."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Wissel apps"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Swiep van die onderkant van jou skerm af op, hou, en los dan"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Welgedaan!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Gereed"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Klaar"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Instellings"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skermkiekie"</string>
<string name="action_split" msgid="2098009717623550676">"Verdeel"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tik op ’n ander app om verdeelde skerm te gebruik"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Verlaat verdeeldeskermkeuse"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Kies nog ’n app as jy verdeelde skerm wil gebruik"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Jou organisasie laat nie hierdie program toe nie"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Slaan navigasietutoriaal oor?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Slaan oor"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Draai skerm"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Taakbalkopvoeding"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Taakbalkopvoeding het verskyn"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Taakbalkopvoeding is toegemaak"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Sleep ’n app na die kant toe om 2 apps tegelyk te gebruik"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Stadigswiep op om die Taakbalk te wys"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Kry appvoorstelle op grond van jou roetine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Skakel gebaarnavigasie in Instellings aan om die Taakbalk outomaties te versteek"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Doen meer met die Taakbalk"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Volgende"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Terug"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Maak toe"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Klaar"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Tuis"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Kennisgewings"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Kitsinstellings"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Taakbalk"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taakbalk word gewys"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taakbalk is versteek"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigasiebalk"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Wys Taakbalk altyd"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Verander navigasiemodus"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Taakbalkverdeler"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Skuif na links bo"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Skuif na regs onder"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Wys nog # app.}other{Wys nog # apps.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> en <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Voeg nou app by werkskerm"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Kanselleer"</string>
</resources>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index 1ab183a..a678b3f 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -33,44 +33,52 @@
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"የእርስዎ የሚገመቱ መተግበሪያዎች"</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"በመነሻ ገጽዎ ታችኛው ረድፍ ላይ የመተግበሪያ አስተያየት ጥቆማዎችን ያግኙ"</string>
<string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"በመነሻ ማያ ገጽዎ የተወዳጆች ረድፍ ላይ የመተግበሪያ አስተያየት ጥቆማዎችን ያግኙ"</string>
- <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"በጣም ስራ ላይ የዋሉ መተግበሪያዎችዎን በቀላሉ ከመነሻ ገጹ ሆነው ይድረሱባቸው። የአስተያየት ጥቆማዎች በእርስዎ ዕለት ተዕለት ተግባራት ላይ በመመስረት ይቀየራሉ። በታችኛው ረድፍ ላይ ያሉ መተግበሪያዎች ወደ መነሻ ገጽዎ ይወሰዳሉ።"</string>
- <string name="hotseat_edu_message_migrate_landscape" msgid="4248943380443387697">"በጣም ሥራ ላይ የዋሉ መተግበሪያዎችዎን በቀላሉ ከመነሻ ገጹ ሆነው ይድረሱባቸው። የአስተያየት ጥቆማዎች በእርስዎ ዕለት ተዕለት ተግባራት ላይ በመመሥረት ይቀየራሉ። በተወዳጆች ረድፍ ውስጥ ያሉ መተግበሪያዎች ወደ የእርስዎ መነሻ ማያ ገጽ ይንቀሳቀሳሉ።"</string>
+ <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"በጣም ሥራ ላይ የዋሉ መተግበሪያዎችዎን በቀላሉ ከመነሻ ገጹ ሆነው ይድረሱባቸው። የአስተያየት ጥቆማዎች በእርስዎ ዕለት ተዕለት ተግባራት ላይ በመመስረት ይቀየራሉ። በታችኛው ረድፍ ላይ ያሉ መተግበሪያዎች ወደ መነሻ ገጽዎ ይወሰዳሉ።"</string>
+ <string name="hotseat_edu_message_migrate_landscape" msgid="4248943380443387697">"በጣም ሥራ ላይ የዋሉ መተግበሪያዎችዎን በቀላሉ ከመነሻ ገጹ ሆነው ይድረሱባቸው። የአስተያየት ጥቆማዎች በእርስዎ ዕለት ተዕለት ተግባራት ላይ በመመሥረት ይቀየራሉ። በተወዳጆች ረድፍ ውስጥ ያሉ መተግበሪያዎች ወደ የእርስዎ መነሻ ማያ ገፅ ይንቀሳቀሳሉ።"</string>
<string name="hotseat_edu_accept" msgid="1611544083278999837">"የመተግበሪያ አስተያየት ጥቆማዎችን አግኝ"</string>
<string name="hotseat_edu_dismiss" msgid="2781161822780201689">"አይ፣ አመሰግናለሁ"</string>
<string name="hotseat_prediction_settings" msgid="6246554993566070818">"ቅንብሮች"</string>
- <string name="hotseat_auto_enrolled" msgid="522100018967146807">"በብዛት ስራ ላይ የዋሉ መተግበሪያዎች እዚህ ይመጣሉ፣ እና በዕለት ተዕለት ተግባራት ላይ በመመስረት ይቀየራሉ"</string>
+ <string name="hotseat_auto_enrolled" msgid="522100018967146807">"በብዛት ሥራ ላይ የዋሉ መተግበሪያዎች እዚህ ይመጣሉ፣ እና በዕለት ተዕለት ተግባራት ላይ በመመስረት ይቀየራሉ"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"የመተግበሪያ ጥቆማዎችን ለማግኘት መተግበሪያዎችን ከታችኛው ረድፍ ይጎትቱ"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"የመተግበሪያ አስተያየት ጥቆማዎች ወደ ባዶ ቦታ ታክለዋል"</string>
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"የመተግበሪያ አስተያየት ጥቆማዎች ነቅቷል"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"የመተግበሪያ አስተያየቶች ቦዝነዋል"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"የተገመተው መተግበሪያ፦ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"ከቀኝ ጠርዝ ወይም ከግራ ጠርዝ ጥግ ጀምሮ ማንሸራተትዎን ያረጋግጡ።"</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"ከቀኝ ወይም ከግራ ጠርዝ ወደ ማያ ገጹ መሃል ማንሸራተትዎን እና መልቀቅዎን ያረጋግጡ።"</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"መሣሪያዎን ያሽከርክሩ"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"የእጅ ምልክት ዳሰሳ አጋዥ ሥልጠናን ለማጠናቀቅ እባክዎ መሣሪያዎን ያሽከርክሩ"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ከቀኝ ጥግ ወይም ከግራ ጥግ ጠርዝ ጀምሮ ማንሸራተትዎን ያረጋግጡ"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"ከቀኝ ወይም ከግራ ጠርዝ ወደ ማያ ገጹ መሃል ማንሸራተትዎን እና መልቀቅዎን ያረጋግጡ"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"ወደ ኋላ ለመመለስ ከቀኝ ጀምሮ እንዴት ማንሸራተት እንደሚችሉ አውቀዋል። ቀጥለው መተግበሪያዎችን እንዴት መቀየር እንደሚችሉ ይወቁ።"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"ወደኋላ የመመለስ ምልክትን አጠናቀዋል።"</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"ከማያ ገጹ ታችኛው ክፍል ጋር በጣም ጠጋ ብለው አለማንሸራተትዎን ያረጋግጡ።"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"ወደኋላ የመመለስ ምልክትን አጠናቅቀዋል"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"ከማያ ገጹ ታችኛው ክፍል ጋር በጣም ጠጋ ብለው አለማንሸራተትዎን ያረጋግጡ"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"ከኋላ ስሜት ሰጭነት ደረጃ ለመለወጥ ወደ ቅንብሮች ይመለሱ"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"ወደኋላ ለመመለስ ያንሸራትቱ"</string>
- <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"ወደ መጨረሻው ማያ ገጽ ለመመለስ ከግራ ወይም ከቀኝ ጠርዝ ወደ ማያ ገጹ መሃል ያንሸራትቱ።"</string>
- <string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"ወደ መጨረሻው ማያ ገጽ ለመመለስ በ2 ጣቶች ከግራ ወይም ከቀኝ ጠርዝ ወደ ማያ ገጹ መሃል ያንሸራትቱ።"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"ከማያ ገጹ የታችኛው ጫፍ ወደ ላይ ማንሸራተትዎን ያረጋግጡ።"</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"ከመልቀቅዎ በፊት ለአፍታ እንዳልቆሙ ያረጋግጡ።"</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"በቀጥታ ወደ ላይ ማንሸራተትዎን ያረጋግጡ።"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"የወደ መነሻ ሂድ ምልክትን አጠናቀዋል። ቀጥሎም ወደ ኋላ እንዴት መሄድ እንደሚችሉ ይወቁ።"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"የወደ መነሻ ሂድ ምልክትን አጠናቀዋል።"</string>
+ <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"ወደ መጨረሻው ማያ ገፅ ለመመለስ ከግራ ወይም ከቀኝ ጠርዝ ወደ ማያ ገጹ መሃል ያንሸራትቱ።"</string>
+ <string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"ወደ መጨረሻው ማያ ገፅ ለመመለስ በ2 ጣቶች ከግራ ወይም ከቀኝ ጠርዝ ወደ ማያ ገጹ መሃል ያንሸራትቱ።"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"ተመለስ"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"ከግራ ወይም ከቀኝ ጠርዝ ወደ ማያ ገጹ መካከል ያንሸራትቱ"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"ከማያ ገጹ የታችኛው ጠርዝ ወደ ላይ ማንሸራተትዎን ያረጋግጡ"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"ከመልቀቅዎ በፊት ባሉበት እንዳልቆሙ ያረጋግጡ"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"በቀጥታ ወደ ላይ ማንሸራተትዎን ያረጋግጡ"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"ወደ መነሻ ሂድ ምልክትን አጠናቅቀዋል። ቀጥሎ ደግሞ እንዴት ወደ ኋላ መመለስ እንደሚቻል ይማሩ።"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"ወደ መነሻ ሂድ ምልክትን አጠናቅቀዋል"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"ወደ መነሻ ለመሄድ ያንሸራትቱ"</string>
- <string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"ከእርስዎ ማያ ገጽ ግርጌ ላይ ወደ ላይ በጣት ጠረግ ያድርጉ። ይህ የእጅ ውዝዋዜ ሁልጊዜ ወደ መነሻ ማያ ገጽ ይወስድዎታል።"</string>
- <string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"በ2 ጣቶች ከማያ ገጹ ግርጌ ወደ ላይ ያንሸራትቱ። ይህ የእጅ ምልክት ሁልጊዜ ወደ መነሻ ማያ ገጽ ይወስደዎታል።"</string>
+ <string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"ከእርስዎ ማያ ገፅ ግርጌ ላይ ወደ ላይ በጣት ጠረግ ያድርጉ። ይህ የእጅ ውዝዋዜ ሁልጊዜ ወደ መነሻ ማያ ገፅ ይወስድዎታል።"</string>
+ <string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"በ2 ጣቶች ከማያ ገጹ ግርጌ ወደ ላይ ያንሸራትቱ። ይህ የእጅ ምልክት ሁልጊዜ ወደ መነሻ ማያ ገፅ ይወስደዎታል።"</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"ወደ መነሻ ይሂዱ"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"በማንኛውም ጊዜ ወደ መነሻ ማያ ገጽዎ ለመሄድ ከማያ ገጽዎ የታችኛው ክፍል ወደ ላይ ያንሸራትቱ"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"ከማያ ገጹ የታችኛው ጫፍ ወደ ላይ ማንሸራተትዎን ያረጋግጡ።"</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"ከመልቀቅዎ በፊት መስኮቱን ረዘም ላለ ጊዜ ለመያዝ ይሞክሩ።"</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"በቀጥታ ወደ ላይ ማንሸራተትዎን ያረጋግጡ፣ ከዚያ ለአፍታ ያቁሙ።"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"ከማያ ገጽዎ የታችኛው ክፍል ወደ ላይ ያንሸራትቱ"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"ጥሩ ሠርተዋል!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"ከማያ ገጹ የታችኛው ጠርዝ ወደ ላይ ማንሸራተትዎን ያረጋግጡ"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"ከመልቀቅዎ በፊት መስኮቱን ረዘም ላለ ጊዜ ለመያዝ ይሞክሩ"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"በቀጥታ ወደ ላይ ማንሸራተትዎን ያረጋግጡ፣ ከዚያ ባለበት ያቁሙ"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"የእጅ ምልክቶችን እንዴት እንደሚጠቀሙ ተምረዋል። የእጅ ምልክቶችን ለማጥፋት ወደ ቅንብሮች ይሂዱ።"</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"መተግበሪያዎችን የመቀያየር ምልክትን አጠናቀዋል።"</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"መተግበሪያዎችን ቀይር ምልክትን አጠናቅቀዋል"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"መተግበሪያዎችን ለመቀየር ያንሸራትቱ"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"በመተግበሪያዎች መካከል ለመቀያየር ከማያ ገጽዎ ግርጌ ወደ ላይ ያንሸራትቱ፣ ይያዙ፣ ከዚያ ይለቀቁ።"</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"በመተግበሪያዎች መካከል ለመቀያየር ከማያ ገጽዎ ግርጌ ላይ በ2 ጣቶች ያንሸራትቱ፣ ይያዙ፣ ከዚያ ይለቀቁ።"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"መተግበሪያዎችን ይቀያይሩ"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"ከማያ ገጽዎ የታችኛው ክፍል ወደ ላይ ያንሸራትቱ፣ ይያዙ፣ ከዚያ ይልቀቁ"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"ጥሩ ሰርተዋል!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"ሁሉም ዝግጁ"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"ተጠናቋል"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"ቅንብሮች"</string>
@@ -84,9 +92,10 @@
<string name="default_device_name" msgid="6660656727127422487">"መሣሪያ"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"የስርዓት አሰሳ ቅንብሮች"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"አጋራ"</string>
- <string name="action_screenshot" msgid="8171125848358142917">"ቅጽበታዊ ገጽ እይታ"</string>
+ <string name="action_screenshot" msgid="8171125848358142917">"ቅጽበታዊ ገፅ ዕይታ"</string>
<string name="action_split" msgid="2098009717623550676">"ክፈል"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"የተከፈለ ማያ ገጽን ለመጠቀም ሌላ መተግበሪያ መታ ያድርጉ"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ከተከፈለ ማያ ገፅ ምርጫ ይውጡ"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"የተከፈለ ማያ ገጽን ለመቀበል ሌላ መተግበሪያ ይምረጡ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ይህ ድርጊት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"የአሰሳ አጋዥ ሥልጠናን ይዝለሉ?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ዝለል"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"ማያ ገጹን አዙር"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"የተግባር አሞሌ ትምህርት"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"የተግባር አሞሌ ትምህርት ይታያል"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"የተግባር አሞሌ ትምህርት ተዘግቷል"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"በአንድ ጊዜ 2 መተግበሪያዎችን ለመጠቀም አንድ መተግበሪያን ወደ ጎን ይጎትቱ"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"የተግባር አሞሌውን ለማሳየት ቀስ ብለው ወደ ላይ ያንሸራትቱ"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"በዕለት ተዕለት ተግባርዎ መሠረት የመተግበሪያ አስተያየቶችን ያግኙ"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"የተግባር አሞሌን በራስ ሰር ለመደበቅ የእጅ ምልክት ዳሰሳን በቅንብሮች ውስጥ ያብሩት"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"በተግባር አሞሌው ተጨማሪ ነገር ያድርጉ"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"ቀጣይ"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"ተመለስ"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"ዝጋ"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"ተጠናቅቋል"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"መነሻ"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"ማሳወቂያዎች"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"ፈጣን ቅንብሮች"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"የተግባር አሞሌ"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"የተግባር አሞሌ ይታያል"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"የተግባር አሞሌ ተደብቋል"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"የአሰሳ አሞሌ"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ሁልጊዜ የተግባር አሞሌ ያሳዩ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"የአሰሳ ሁነታን ይለውጡ"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"የተግባር አሞሌ አካፋይ"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ወደ ላይ/ግራ ይውሰዱ"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ወደ ታች/ቀኝ ይውሰዱ"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ተጨማሪ # መተግበሪያ አሳይ።}one{ተጨማሪ # መተግበሪያ አሳይ።}other{ተጨማሪ # መተግበሪያዎች አሳይ።}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> እና <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"መተግበሪያን ወደ ዴስክቶፕ በማከል ላይ"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ይቅር"</string>
</resources>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index cfe7894..6d7effc 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"تم تفعيل ميزة \"التطبيقات المقترحة\"."</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ميزة \"التطبيقات المقترحة\" غير مفعّلة."</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"التطبيق المتوقع: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"تأكّد من التمرير سريعًا من أقصى الحافة اليسرى أو اليمنى."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"تأكّد من التمرير سريعًا من الحافة اليسرى أو اليمنى إلى وسط الشاشة ثم ارفع إصبعك."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"يُرجى تدوير الجهاز"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"يُرجى تدوير جهازك لإكمال الدليل التوجيهي للتنقُّل بالإيماءات."</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"تأكَّد من التمرير سريعًا من أقصى الحافة اليسرى أو اليمنى."</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"تأكَّد من التمرير سريعًا من الحافة اليسرى أو اليمنى إلى وسط الشاشة ثم ارفع إصبعك."</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"لقد تعلمت كيفية التمرير سريعًا من اليسار للرجوع. تعرّف بعد ذلك على كيفية التبديل بين التطبيقات."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"لقد أكملت التدريب على إيماءة الرجوع."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"تأكّد من عدم التمرير بالقرب من أسفل الشاشة."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"لقد أكملت التدريب على إيماءة الرجوع."</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"تأكَّد من عدم التمرير سريعًا بالقرب من أسفل الشاشة."</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"لتغيير مستوى حساسية إيماءة الرجوع، انتقِل إلى \"الإعدادات\""</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"مرِّر سريعًا للرجوع."</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"للرجوع إلى الشاشة السابقة، مرِّر سريعًا من الحافة اليسرى أو الحافة اليمنى إلى وسط الشاشة."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"للرجوع إلى الشاشة السابقة، عليك التمرير سريعًا بإصبعين من الحافة اليسرى أو اليمنى نحو وسط الشاشة."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"تأكّد من التمرير سريعًا من الحافة السفلى للشاشة إلى أعلاها."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"تأكّد من عدم التوقّف قليلاً قبل رفع إصبعك."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"تأكّد من التمرير إلى الأعلى مباشرةً."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"لقد أكملت التدريب على إيماءة الانتقال إلى الشاشة الرئيسية. تعرّف بعد ذلك على كيفية الرجوع."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"أكملت التدريب على إيماءة الانتقال إلى الشاشة الرئيسية."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"الرجوع"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"مرِّر سريعًا من الحافة اليمنى أو اليسرى إلى منتصف الشاشة."</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"تأكَّد من التمرير سريعًا من الحافة السفلية للشاشة إلى أعلاها."</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"تأكَّد من عدم التوقّف مؤقتًا قبل رفع إصبعك."</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"تأكَّد من التمرير للأعلى مباشرةً."</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"لقد أكملت التدريب على إيماءة الانتقال إلى الشاشة الرئيسية. تعرَّف بعد ذلك على كيفية الرجوع."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"لقد أكملت التدريب على إيماءة الانتقال إلى الشاشة الرئيسية."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"مرِّر سريعًا للانتقال إلى الشاشة الرئيسية"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"مرِّر سريعًا من أسفل الشاشة إلى أعلاها. تنقلك هذه الإيماءة دائمًا إلى الشاشة الرئيسية."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"مرِّر سريعًا بإصبعين من أسفل الشاشة إلى أعلاها. تنقلك هذه الإيماءة دائمًا إلى الشاشة الرئيسية."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"الانتقال إلى الشاشة الرئيسية"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"للانتقال إلى شاشتك الرئيسية في أي وقت، اسحب لأعلى الشاشة من أسفلها."</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"تأكّد من التمرير سريعًا من الحافة السفلى للشاشة إلى أعلاها."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"حاوِل إبقاء إصبعك على النافذة لمدة أطول قبل رفعه."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"تأكّد من التمرير سريعًا للأعلى مباشرةً ثم التوقّف قليلاً."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"مرِّر سريعًا من أسفل الشاشة إلى أعلاها."</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"أحسنت صنعًا."</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"تأكَّد من التمرير سريعًا من الحافة السفلية للشاشة إلى أعلاها."</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"حاوِل إبقاء إصبعك على النافذة لمدة أطول قبل رفعه."</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"تأكَّد من التمرير سريعًا للأعلى مباشرةً ثم التوقّف مؤقتًا."</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"لقد تعرّفت على كيفية استخدام الإيماءات. لإيقاف الإيماءات، انتقِل إلى \"الإعدادات\"."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"أكملت التدريب على إيماءة التبديل بين التطبيقات."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"لقد أكملت التدريب على إيماءة التبديل بين التطبيقات."</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"التمرير سريعًا للتبديل بين التطبيقات"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"للتبديل بين التطبيقات، مرِّر سريعًا من أسفل الشاشة لأعلاها مع تثبيت إصبعك ثم ارفعه."</string>
- <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"للتبديل بين التطبيقات، مرِّر سريعًا من أسفل الشاشة إلى أعلاها بإصبعين مع تثبيتهما، ثم ارفعهما."</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"للتبديل بين التطبيقات، مرِّر سريعًا من أسفل الشاشة إلى الأعلى ثمّ ثبِّت إصبعك قليلاً قبل رفعه."</string>
+ <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"للتبديل بين التطبيقات، مرِّر سريعًا من أسفل الشاشة إلى أعلاها بإصبعين، ثمّ ثبّتهما قليلاً قبل رفعهما."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"تبديل التطبيقات"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"مرِّر سريعًا من أسفل الشاشة إلى أعلاها، وأبقِ إصبعك على الشاشة قليلاً ثم ارفعه."</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"أحسنت."</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"اكتمل التدريب على الإيماءة"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"تم"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"الإعدادات"</string>
@@ -87,23 +95,20 @@
<string name="action_screenshot" msgid="8171125848358142917">"لقطة شاشة"</string>
<string name="action_split" msgid="2098009717623550676">"تقسيم"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"انقر على تطبيق آخر لاستخدام وضع تقسيم الشاشة."</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"الخروج من وضع تقسيم الشاشة"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"اختَر تطبيقًا آخر لاستخدام وضع تقسيم الشاشة."</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"لا يسمح التطبيق أو لا تسمح مؤسستك بهذا الإجراء."</string>
- <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"هل تريد تخطي الدليل التوجيهي؟"</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>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"إلغاء"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"التخطي"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"تدوير الشاشة"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"التعريف بشريط التطبيقات"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"ظهرت لوحة تعليم استخدام شريط المهام."</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"تم إغلاق لوحة تعليم استخدام شريط المهام."</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"اسحب تطبيقًا إلى جانب الشاشة لاستخدام تطبيقََين في آنٍ واحد."</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"مرِّر ببطء للأعلى لإظهار شريط التطبيقات."</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"مرِّر ببطء للأعلى لإظهار شريط التطبيقات"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"احصل على اقتراحات التطبيقات بناءً على سلسلة إجراءاتك."</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"فعِّل خيار \"التنقُّل بالإيماءات\" في \"الإعدادات\" لإخفاء شريط التطبيقات تلقائيًا."</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"إنجاز المزيد باستخدام شريط التطبيقات"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"الشاشة التالية"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"رجوع"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"إغلاق"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"تم"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"الرئيسية"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"الإشعارات"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"إعدادات سريعة"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"شريط التطبيقات"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"تم إظهار شريط التطبيقات"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"تم إخفاء شريط التطبيقات"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"شريط التنقل"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"إظهار شريط التطبيقات دائمًا"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"تغيير وضع التنقل"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"مقسِّم شريط التطبيقات"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"الانتقال إلى يمين الشاشة أو أعلاها"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"الانتقال إلى يسار الشاشة أو أسفلها"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{إظهار تطبيق واحد آخر}zero{إظهار # تطبيق آخر}two{إظهار تطبيقَين آخرَين}few{إظهار # تطبيقات أخرى}many{إظهار # تطبيقًا آخر}other{إظهار # تطبيق آخر}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"\"<xliff:g id="APP_NAME_1">%1$s</xliff:g>\" و\"<xliff:g id="APP_NAME_2">%2$s</xliff:g>\""</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"إضافة تطبيق إلى سطح المكتب"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"إلغاء"</string>
</resources>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index f37bcbb..a68aee5 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -24,7 +24,7 @@
<string name="recents_empty_message" msgid="7040467240571714191">"কোনো শেহতীয়া বস্তু নাই"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"এপে ব্যৱহাৰ কৰা ডেটাৰ ছেটিং"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"আটাইবোৰ মচক"</string>
- <string name="accessibility_recent_apps" msgid="4058661986695117371">"শেহতীয়া এপসমূহ"</string>
+ <string name="accessibility_recent_apps" msgid="4058661986695117371">"শেহতীয়া এপ্সমূহ"</string>
<string name="task_view_closed" msgid="9170038230110856166">"কাৰ্য বন্ধ কৰা হ’ল"</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">"< ১ মিনিট"</string>
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"এপৰ পৰামৰ্শসমূহ সক্ষম কৰা আছে"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"এপৰ পৰামৰ্শসমূহ অক্ষম কৰা আছে"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"পূৰ্বানুমান কৰা এপ্: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"আপুনি সোঁ অথবা বাওঁ প্ৰান্তৰৰ একেবাৰে সীমাৰ পৰা ছোৱাইপ কৰাটো নিশ্চিত কৰক।"</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"আপুনি স্ক্ৰীনৰ সোঁ অথবা বাওঁ প্ৰান্তৰৰ পৰা মধ্যভাগলৈকে ছোৱাইপ কৰি এৰি দিয়াটো নিশ্চিত কৰক।"</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"আপোনাৰ ডিভাইচটো ঘূৰাওক"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"আঙুলিৰ স্পৰ্শৰ নিৰ্দেশেৰে কৰা নেভিগেশ্বনৰ টিউট’ৰিয়েল শেষ কৰিবলৈ অনুগ্ৰহ কৰি আপোনাৰ ডিভাইচটো ঘূৰাওক"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"আপুনি সোঁ অথবা বাওঁ কাষৰ একেবাৰে সীমাৰ পৰা ছোৱাইপ কৰাটো নিশ্চিত কৰক"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"আপুনি স্ক্ৰীনৰ সোঁ অথবা বাওঁ কাষৰ পৰা মধ্যভাগলৈকে ছোৱাইপ কৰি এৰি দিয়াটো নিশ্চিত কৰক"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"সোঁফালৰ পৰা ছোৱাইপ কৰি কেনেকৈ উভতি যাব লাগে, সেইটো আপুনি জানিলে। ইয়াৰ পাছত, এপ্ কেনেকৈ সলনি কৰিব সেয়া জানক।"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"আপুনি উভতি যাওক নিৰ্দেশটো সম্পূৰ্ণ কৰিলে।"</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"আপুনি স্ক্ৰীনৰ তলৰ অংশৰ বেছি ওচৰলৈ ছোৱাইপ নকৰাটো নিশ্চিত কৰক।"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"আপুনি উভতি যাওক নিৰ্দেশটো সম্পূৰ্ণ কৰিলে"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"আপুনি স্ক্ৰীনৰ তলৰ অংশৰ বেছি ওচৰলৈ ছোৱাইপ নকৰাটো নিশ্চিত কৰক"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"উভতি যোৱাৰ নির্দেশটোৰ সংবেদনশীলতা সলনি কৰিবলৈ ছেটিঙলৈ যাওক"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"উভতি যাবলৈ ছোৱাইপ কৰক"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"অন্তিম স্ক্ৰীনখনলৈ উভতি যাবলৈ বাওঁ অথবা সোঁ প্ৰান্তৰৰ পৰা মাজলৈ ছোৱাইপ কৰক।"</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"অন্তিম স্ক্ৰীনখনলৈ উভতি যাবলৈ ২ টা আঙুলিৰে স্ক্ৰীনখনৰ বাওঁ অথবা সোঁ প্ৰান্তৰৰ পৰা মাজলৈ ছোৱাইপ কৰক।"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"আপুনি স্ক্ৰীনৰ তলৰ প্ৰান্তৰ পৰা ওপৰলৈ ছোৱাইপ কৰাটো নিশ্চিত কৰক।"</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"আপুনি এৰি দিয়াৰ পূৰ্বে অলপো নোৰোৱাটো নিশ্চিত কৰক।"</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"আপুনি পোনকৈ ওপৰলৈ ছোৱাইপ কৰাটো নিশ্চিত কৰক।"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"আপুনি গৃহ স্ক্ৰীনলৈ যোৱাৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে। ইয়াৰ পাছত, গৃহ স্ক্ৰীনলৈ কেনেকৈ যাব সেয়া জানক।"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"আপুনি গৃহ স্ক্ৰীনলৈ যোৱাৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে।"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"উভতি যাওক"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"স্ক্ৰীনখনৰ বাওঁ অথবা সোঁ প্ৰান্তৰৰ পৰা মধ্যভাগলৈ ছোৱাইপ কৰক"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"আপুনি স্ক্ৰীনৰ তলৰ প্ৰান্তৰ পৰা ওপৰলৈ ছোৱাইপ কৰাটো নিশ্চিত কৰক"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"আপুনি এৰি দিয়াৰ পূৰ্বে অলপো নোৰোৱাটো নিশ্চিত কৰক"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"আপুনি পোনকৈ ওপৰলৈ ছোৱাইপ কৰাটো নিশ্চিত কৰক"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"আপুনি গৃহ স্ক্ৰীনলৈ যোৱাৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে। ইয়াৰ পাছত, কেনেকৈ উভতি যাব সেয়া জানক।"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"আপুনি গৃহ স্ক্ৰীনলৈ যোৱাৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"গৃহ স্ক্ৰীনলৈ যাবলৈ ছোৱাইপ কৰক"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"আপোনাৰ স্ক্ৰীনৰ তলৰ অংশৰ পৰা ওপৰলৈ ছোৱাইপ কৰক। এই নিৰ্দেশটোৱে আপোনাক সদায় গৃহ স্ক্ৰীনলৈ লৈ যায়।"</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"স্ক্ৰীনখনৰ একেবাৰে তলৰ পৰা ২ টা আঙুলিৰে ওপৰলৈ ছোৱাইপ কৰক। এই নিৰ্দেশটোৱে আপোনাক সদায় গৃহ স্ক্ৰীনলৈ লৈ যায়।"</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"গৃহ পৃষ্ঠালৈ যাওক"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"আপোনাৰ গৃহ স্ক্ৰীনলৈ যিকোনো সময়তে যাবলৈ, আপোনাৰ স্ক্ৰীনখনৰ একেবাৰে তলৰ পৰা ওপৰলৈ ছোৱাইপ কৰক"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"আপুনি স্ক্ৰীনৰ তলৰ প্ৰান্তৰ পৰা ওপৰলৈ ছোৱাইপ কৰাটো নিশ্চিত কৰক।"</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"এৰি দিয়াৰ পূৰ্বে ৱিণ্ডখন দীৰ্ঘ সময়ৰ বাবে ধৰি ৰাখিবলৈ চেষ্টা কৰক।"</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"আপুনি স্ক্ৰীনৰ ওপৰলৈ পোনকৈ ছোৱাইপ কৰি তাৰ পাছত ৰোৱাটো নিশ্চিত কৰক।"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"আপোনাৰ স্ক্ৰীনৰ একেবাৰে তলৰ অংশৰ পৰা ওপৰলৈ ছোৱাইপ কৰক"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"বঢ়িয়া!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"আপুনি স্ক্ৰীনৰ তলৰ প্ৰান্তৰ পৰা ওপৰলৈ ছোৱাইপ কৰাটো নিশ্চিত কৰক"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"এৰি দিয়াৰ পূৰ্বে ৱিণ্ডখন দীৰ্ঘ সময়ৰ বাবে ধৰি ৰাখিবলৈ চেষ্টা কৰক"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"আপুনি স্ক্ৰীনৰ ওপৰলৈ পোনকৈ ছোৱাইপ কৰি তাৰ পাছত ৰোৱাটো নিশ্চিত কৰক"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"আপুনি নিৰ্দেশসমূহ কেনেকৈ ব্যৱহাৰ কৰিব লাগে সেয়া জানিলে। নিৰ্দেশসমূহ অফ কৰিবলৈ, ছেটিঙলৈ যাওক।"</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"আপুনি এপ্ সলনি কৰাৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে।"</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"আপুনি এপ্ সলনি কৰাৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"এপ্ সলনি কৰিবলৈ ছোৱাইপ কৰক"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"এপ্সমূহ সালসলনিকৈ ব্যৱহাৰ কৰিবলৈ আপোনাৰ স্ক্ৰীনৰ একেবাৰে তলৰ অংশৰ পৰা ওপৰলৈ ছোৱাইপ কৰি ধৰি ৰাখক আৰু তাৰ পাছত এৰি দিয়ক।"</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"এপ্সমূহ সালসলনিকৈ ব্যৱহাৰ কৰিবলৈ ২ টা আঙুলিৰে আপোনাৰ স্ক্ৰীনৰ একেবাৰে তলৰ অংশৰ পৰা ওপৰলৈ ছোৱাইপ কৰি ধৰি ৰাখক আৰু তাৰ পাছত এৰি দিয়ক।"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"এপ্ সলনি কৰক"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"আপোনাৰ স্ক্ৰীনৰ তলৰ অংশৰ পৰা ওপৰলৈ ছোৱাইপ কৰক, ধৰি ৰাখক, তাৰ পাছত এৰি দিয়ক"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"বঢ়িয়া!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"সম্পূৰ্ণ সাজু"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"হ’ল"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"ছেটিং"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"স্ক্ৰীনশ্বট"</string>
<string name="action_split" msgid="2098009717623550676">"বিভাজন কৰক"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰিবলৈ অন্য এটা এপত টিপক"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"বিভাজিত স্ক্ৰীনৰ বাছনিৰ পৰা বাহিৰ হওক"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰিবলৈ অন্য এটা এপ্ বাছক"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"এপ্টোৱে অথবা আপোনাৰ প্ৰতিষ্ঠানে এই কাৰ্যটোৰ অনুমতি নিদিয়ে"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"নেভিগেশ্বনৰ টিউট’ৰিয়েল এৰিব বিচাৰে নেকি?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"এৰি যাওক"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"স্ক্ৰীনখন ঘূৰাওক"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"টাস্কবাৰৰ শিক্ষা"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"টাস্কবাৰৰ শিক্ষাৰ পেনেলটো প্ৰদর্শিত হৈছে"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"টাস্কবাৰৰ শিক্ষাৰ পেনেলটো বন্ধ হৈছে"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"এবাৰতে ২ টা এপ্ ব্যৱহাৰ কৰিবলৈ কোনো এপ্ কাষলৈ টানি আনি এৰক"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"টাস্কবাৰ দেখুৱাবলৈ লাহেকৈ ওপৰলৈ ছোৱাইপ কৰক"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"আপোনাৰ ৰুটিনৰ ওপৰত আধাৰিত এপৰ পৰামৰ্শ পাওক"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"টাস্কবাৰ স্বয়ংক্ৰিয়ভাৱে লুকুৱাবলৈ ছেটিঙত আঙুলিৰ স্পৰ্শৰ নিৰ্দেশেৰে কৰা নেভিগেশ্বন অন কৰক"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"টাস্কবাৰৰ জৰিয়তে অধিক কাৰ্য সম্পাদন কৰক"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"পৰৱৰ্তী"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"উভতি যাওক"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"বন্ধ কৰক"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"হ’ল"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"গৃহপৃষ্ঠা"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"জাননী"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"ক্ষিপ্ৰ ছেটিং"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"টাস্কবাৰ"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"টাস্কবাৰ দেখুওৱা হৈছে"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"টাস্কবাৰ লুকুৱাই থোৱা হৈছে"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"নেভিগেশ্বনৰ দণ্ড"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"টাস্কবাৰ সদায় দেখুৱাওক"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"নেভিগেশ্বন ম’ড সলনি কৰক"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"টাস্কবাৰ বিভাজক"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ওপৰৰ বাঁওফাললৈ নিয়ক"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"তলৰ সোঁফাললৈ নিয়ক"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{আৰু # টা এপ্ দেখুৱাওক।}one{আৰু # টা এপ্ দেখুৱাওক।}other{আৰু # টা এপ্ দেখুৱাওক।}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> আৰু <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"ডেস্কটপত এপ্ যোগ দি থকা হৈছে"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"বাতিল কৰক"</string>
</resources>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index 4764bfd..9fff2d8 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Tətbiq təklifləri aktivdir"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Tətbiq təklifləri deaktivdir"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Proqnozlaşdırılan tətbiq: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Ekranın ən sağ və ya sol kənarından sürüşdürün."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Ekranın sağ və ya sol kənarından ortasına sürüşdürüb buraxın."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Cihazı fırladın"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Jest naviqasiyası təlimatını tamamlamaq üçün cihazı fırladın"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Ən sağ və ya sol kənardan sürüşdürün"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Sağ və ya sol kənardan ekranın ortasına sürüşdürüb, buraxın"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Geri qayıtmaq üçün sağdan sürüşdürmək qaydasını öyrəndiniz. Sonra tətbiqləri keçirməyi öyrənin."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Geri getmə jestini tamamladınız."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Ekranın altına çox yaxın sürüşdürmədiyinizə əmin olun."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Geri qayıtma jestini tamamladınız"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Barmağınızı ekranın aşağı kənarına çox yaxınlaşdırmayın"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Geri qayıtma jestinin həssaslığını dəyişmək üçün Ayarlara keçin"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Geri qayıtmaq üçün sürüşdürün"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Sonuncu ekrana qayıtmaq üçün ekranın sol, yaxud sağ kənarından mərkəzinə doğru sürüşdürün."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Sonuncu ekrana qayıtmaq üçün 2 barmaqla ekranın sol, yaxud sağ kənarından mərkəzinə doğru sürüşdürün."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Ekranın ən kənar aşağısından yuxarı sürüşdürün."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Buraxmazdan əvvəl durdurmadığınıza əmin olun."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Birbaşa yuxarı sürüşdürün."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Əsas səhifəyə keçmə jestini tamamladınız. Sonra geri qayıtmağı öyrənin."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Əsas səhifəyə keçmə jestini tamamladınız."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Geri qayıdın"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Sol və ya sağ kənardan ekranın ortasına sürüşdürün"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Ekranın aşağı kənarından yuxarı sürüşdürün"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Buraxmazdan əvvəl durdurmayın"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Düz yuxarı sürüşdürün"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Əsas ekrana keçid jestini tamamladınız. Geri qayıtmağı öyrənin."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Əsas ekrana keçid jestini tamamladınız"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Əsas səhifəyə keçmək üçün sürüşdürün"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Ekranın aşağısından yuxarısına sürüşdürün. Bu jest həmişə Əsas səhifəyə aparır."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"2 barmaqla ekranın aşağısından yuxarısına sürüşdürün. Bu jest həmişə Əsas səhifəyə aparır."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Əsas səhifəyə qayıdın"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"İstənilən vaxt əsas ekranınıza getmək üçün ekranın aşağısından yuxarı sürüşdürün"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Ekranın ən kənar aşağısından yuxarı sürüşdürün."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Barmağı buraxmadan öncə displeydə bir müddət saxlayın."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Sürüşdürüb ekranın yuxarı kənarında saxlayın."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Ekranın aşağısından yuxarı sürüşdürün"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Əla!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Ekranın aşağı kənarından yuxarı sürüşdürün"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Buraxmazdan öncə pəncərəni bir müddət saxlayın"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Düz yuxarı sürüşdürüb, durdurun"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Jestlərdən istifadə qaydasını öyrəndiniz. Jestləri deaktiv etmək üçün Ayarlara keçin."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Tətbiqləri keçirmə jestini tamamladınız."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Tətbiqlər arasında keçid jestini tamamladınız"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Tətbiqi keçirmək üçün sürüşdürün"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Tətbiqlər arasında keçid üçün ekranın aşağısından yuxarı doğru sürüşdürüb saxlayın, sonra buraxın."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Tətbiqlər arasında keçid üçün 2 barmaqla ekranın aşağısından yuxarı doğru sürüşdürüb saxlayın, sonra buraxın."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Tətbiqləri dəyişin"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Ekranın aşağısından yuxarı sürüşdürüb saxlayın, sonra buraxın"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Afərin!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Tam hazır"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Oldu"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Ayarlar"</string>
@@ -87,6 +95,7 @@
<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="8464310533320556058">"Bölünmüş ekran üçün başqa tətbiqə toxunun"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Bölünmüş ekran seçimindən çıxın"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Bölünmüş ekrandan istifadə üçün başqa tətbiq seçin"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Bu əməliyyata tətbiq və ya təşkilatınız tərəfindən icazə verilmir"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Naviqasiya dərsliyi ötürülsün?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Ötürün"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Ekranı fırladın"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Tapşırıq panelində təhsil"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Tapşırıq panelindəki təlim bölməsi görünür"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Tapşırıq panelindəki təlim bölməsi bağlanıb"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Eyni anda 2 tətbiqi istifadə etmək üçün bir tətbiqi yan tərəfə çəkin"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Tapşırıq panelini göstərmək üçün astaca yuxarı sürüşdürün"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Rejiminizə əsasən tətbiq təklifləri alın"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Tapşırıq panelini avtomatik gizlətmək üçün Ayarlarda jest naviqasiyasını aktiv edin"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Tapşırıq paneli ilə daha çox şey edin"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Sonra"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Geri"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Bağlayın"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Hazırdır"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Ev"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Bildirişlər"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Sürətli Ayarlar"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Tapşırıq paneli"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"İşləmə paneli göstərilir"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"İşləmə paneli gizlədilib"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Naviqasiya paneli"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"İşləmə paneli həmişə görünsün"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Naviqasiya rejimini dəyişin"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"İşləmə paneli ayırıcısı"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Yuxarı/sola köçürün"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Aşağı/sağa köçürün"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Daha # tətbiqi göstərin.}other{Daha # tətbiqi göstərin.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> və <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Tətbiqin masaüstünə əlavə edilməsi"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Ləğv edin"</string>
</resources>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index d2c535c..9a7aa4b 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Predlozi aplikacija su omogućeni"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Predlozi aplikacija su onemogućeni"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predviđamo aplikaciju: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Obavezno prevucite od same desne ili leve ivice."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Obavezno prevucite od desne ili leve ivice do sredine ekrana i otpustite."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotirajte uređaj"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rotirajte uređaj da biste dovršili vodič za navigaciju pomoću pokreta"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Obavezno prevucite od same desne ili leve ivice"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Obavezno prevucite od desne ili leve ivice do sredine ekrana i otpustite"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Naučili ste kako da prevlačite zdesna da biste se vratili unazad. Sada naučite da zamenite aplikacije."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Dovršili ste pokret za povratak."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Nikako ne prevlačite previše blizu dna ekrana."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Dovršili ste pokret za povratak"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Nikako ne prevlačite previše blizu dna ekrana"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Osetljivost pok. za nazad možete da promenite u Podešavanjima"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Prevucite da biste se vratili unazad"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Da biste se vratili na poslednji ekran, prevucite od leve ili desne ivice do sredine ekrana."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Da biste se vratili na poslednji ekran, prevucite pomoću dva prsta od leve ili desne ivice do sredine ekrana."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Obavezno prevucite nagore od donje ivice ekrana."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Nikako ne stajte pre otpuštanja."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Obavezno prevucite pravo nagore."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Dovršili ste pokret za povratak na početnu stranicu. Sada saznajte kako da se vratite."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Dovršili ste pokret za povratak na početnu stranicu."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Nazad"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Prevucite od leve ili desne ivice do sredine ekrana"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Obavezno prevucite nagore od donje ivice ekrana"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Nikako ne stajte pre otpuštanja"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Obavezno prevucite pravo nagore"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Dovršili ste pokret za povratak na početnu stranicu. Sada saznajte kako da se vratite."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Dovršili ste pokret za povratak na početnu stranicu."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Prevucite da biste otišli na početnu stranicu"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Prevucite nagore od dna ekrana. Ovaj pokret vas uvek vodi na početni ekran."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Prevucite pomoću dva prsta nagore od dna ekrana. Ovim pokretom uvek otvarate početni ekran."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Idite na početni ekran"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Da biste otišli na početni ekran u bilo kom trenutku, prevucite nagore od dna ekrana."</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Obavezno prevucite nagore od donje ivice ekrana."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Probajte da držite prozor duže pre otpuštanja."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Obavezno prevucite pravo nagore, pa zastanite."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Prevucite nagore sa donjeg dela ekrana"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Odlično!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Obavezno prevucite nagore od donje ivice ekrana"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Probajte da držite prozor duže pre otpuštanja"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Obavezno prevucite pravo nagore, pa zastanite"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Naučili ste kako da koristite pokrete. Da biste isključili pokrete, idite na podešavanja."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Dovršili ste pokret za promenu aplikacija."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Dovršili ste pokret za promenu aplikacija"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Prevucite da biste zamenili aplikacije"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Za prelazak sa jedne aplikacije na drugu prevucite nagore od dna ekrana, zadržite, pa pustite."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Za prelazak između aplikacija prevucite pomoću dva prsta nagore od dna ekrana, zadržite, pa pustite."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Pređite na drugu aplikaciju"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Prevucite nagore od dna ekrana, zadržite, pa pustite"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Odlično!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"To je to"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Gotovo"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Podešavanja"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snimak ekrana"</string>
<string name="action_split" msgid="2098009717623550676">"Podeli"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Dodirnite drugu aplikaciju za podeljeni ekran"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Izlazak iz biranja podeljenog ekrana"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Odaberite drugu aplikaciju za podeljeni ekran"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikacija ili organizacija ne dozvoljavaju ovu radnju"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Želite da preskočite vodič za kretanje?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Preskoči"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Rotirajte ekran"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Uputstva na traci zadataka"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Edukativno okno iz trake zadataka se pojavilo"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Edukativno okno iz trake zadataka je zatvoreno"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Prevucite na stranu da biste koristili 2 aplikacije odjednom"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Nakratko prevucite nagore da biste prikazali traku zadataka"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Sporo prevucite nagore da biste prikazali traku zadataka"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Dobijajte predloge aplikacija na osnovu rutine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Uključite navigaciju pomoću pokreta u Podešavanjima radi automatskog skrivanja trake zadataka"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Uradite više pomoću trake zadataka"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Dalje"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Nazad"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Zatvori"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Gotovo"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Početna"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Obaveštenja"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Brza podešavanja"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Traka zadataka"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Traka zadataka je prikazana"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Traka zadataka je skrivena"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Traka za navigaciju"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Uvek prikazuj traku zadataka"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Promeni režim navigacije"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Razdelnik trake zadataka"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premesti gore levo"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premesti dole desno"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodaje se aplikacija na radnu povrršinu"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Otkaži"</string>
</resources>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index a3bd17c..ca62108 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Прапановы праграм уключаны"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Прапановы праграм выключаны"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Праграма з падказкі: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Пераканайцеся, што вы праводзіце пальцам ад самага вугла (правага ці левага) экрана."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Пераканайцеся, што праводзіце пальцам з правага ці левага вугла ў цэнтр экрана, а потым адпускаеце."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Павярніце прыладу"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Каб пачаць азнаямленне з дапаможнікам па навігацыі жэстамі, павярніце прыладу"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Правядзіце пальцам справа налева ці злева направа ад самага краю экрана"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Правядзіце пальцам ад правага або левага краю экрана ў цэнтр і адпусціце палец"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Вы даведаліся, як гартаць справа для вяртання. Цяпер даведайцеся, як пераключацца паміж праграмамі."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Вы навучыліся рабіць жэст вяртання."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Пераканайцеся, што вы не праводзіце пальцам занадта блізка да ніжняга краю экрана."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Вы навучыліся рабіць жэст для пераходу назад"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Не праводзьце пальцам занадта блізка да ніжняга краю экрана"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Каб змяніць адчувальнасць жэста вяртання, адкрыйце налады"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Правядзіце пальцам, каб вярнуцца"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Каб вярнуцца на папярэдні экран, правядзіце пальцам ад левага ці правага краю да цэнтра экрана."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Каб вярнуцца на папярэдні экран, правядзіце двума пальцамі ад левага ці правага краю ў цэнтр экрана."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Пераканайцеся, што праводзіце пальцам па экране знізу ўверх."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Пераканайцеся, што не затрымліваецеся перад адпусканнем."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Пераканайцеся, што праводзіце пальцам вертыкальна."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Вы навучыліся рабіць жэст пераходу на галоўны экран. А зараз даведайцеся, як вярнуцца назад."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Вы навучыліся рабіць жэст пераходу на галоўны экран."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Назад"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Правядзіце пальцам па экране злева направа ці справа налева ў цэнтр экрана"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Правядзіце пальцам знізу ўверх з ніжняга краю экрана"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Перш чым адпусціць палец, не затрымлівайце яго на адным месцы"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Правядзіце пальцам па экране роўна ўверх"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Вы навучыліся рабіць жэст для пераходу на галоўны экран. Зараз вы даведаецеся, як пераходзіць назад."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Вы навучыліся рабіць жэст для пераходу на галоўны экран"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Правядзіце пальцам для пераходу на галоўны экран"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Правядзіце пальцам па экране знізу ўверх. Гэты жэст дазваляе вярнуцца на Галоўны экран."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Правядзіце двума пальцамі па экране знізу ўверх. Гэты жэст дазваляе вярнуцца на Галоўны экран."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Перайсці на галоўны экран"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Каб у любы час адкрыць галоўны экран, правядзіце пальцам па экране знізу ўверх"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Пераканайцеся, што праводзіце пальцам па экране знізу ўверх."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Перш чым адпусціць палец, паспрабуйце даўжэй утрымліваць акно націснутым."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Пераканайцеся, што праводзіце пальцам вертыкальна, а потым затрымліваеце яго."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Пераход на галоўны экран"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Правядзіце пальцам па экране знізу ўверх"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"У вас добра атрымліваецца!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Правядзіце пальцам знізу ўверх з ніжняга краю экрана"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Перш чым адпусціць палец, паспрабуйце даўжэй утрымліваць акно націснутым"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Правядзіце пальцам па экране роўна ўверх, а потым затрымайце палец"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Вы навучыліся выкарыстоўваць жэсты. Каб выключыць жэсты, адкрыйце Налады."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Вы навучыліся рабіць жэст пераключэння паміж праграмамі."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Вы навучыліся рабіць жэст для пераключэння паміж праграмамі"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Правядзіце пальцам для пераключэння паміж праграмамі"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Каб пераключыцца на іншую праграму, правядзіце па экране знізу ўверх, патрымайце палец і адпусціце."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Каб пераключыцца на іншую праграму, правядзіце двума пальцамі знізу ўверх, патрымайце і адпусціце."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Пераключэнне праграм"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Правядзіце пальцам уверх ад ніжняга краю экрана, затрымайце палец, а потым адпусціце"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Выдатна!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Гатова"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Гатова"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Налады"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Здымак экрана"</string>
<string name="action_split" msgid="2098009717623550676">"Падзелены экран"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Каб падзяліць экран, націсніце на іншую праграму"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Выйсці з рэжыму падзеленага экрана"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Каб падзяліць экран, выберыце іншую праграму"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Гэта дзеянне не дазволена праграмай ці вашай арганізацыяй"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Прапусціць дапаможнік па навігацыі?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Прапусціць"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Павярнуць экран"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Інфармацыя пра панэль задач"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"З\'явілася панэль навучання на панэлі задач"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Панэль навучання на панэлі задач закрыта"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Каб карыстацца 2 праграмамі, перацягніце адну з іх убок"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Каб паказаць панэль задач, павольна правядзіце пальцам уверх"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Атрымлівайце прапановы праграм з улікам вашых дзеянняў"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Каб аўтаматычна схаваць панэль задач, уключыце ў Наладах навігацыю жэстамі"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Выкарыстоўвайце магчымасці панэлі задач"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Далей"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Назад"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Закрыць"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Гатова"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Галоўны экран"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Апавяшчэнні"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Хуткія налады"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Панэль задач"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Панэль задач паказана"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Панэль задач схавана"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Панэль навігацыі"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Заўсёды паказваць панэль задач"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Змяніць рэжым навігацыі"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Раздзяляльнік панэлі задач"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Перамясціць уверх/улева"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Перамясціць уніз/управа"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Паказаць ячшэ # праграму.}one{Паказаць ячшэ # праграму.}few{Паказаць ячшэ # праграмы.}many{Паказаць ячшэ # праграм.}other{Паказаць ячшэ # праграмы.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> і <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Дадаванне праграмы на камп\'ютар"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Скасаваць"</string>
</resources>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index ad63d38..72e731a 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Предложенията за приложения са активирани"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Функцията „Предложения за приложения“ е деактивирана"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Предвидено приложение: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Трябва да прекарате пръст от най-дясната или най-лявата част на екрана."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Трябва да прекарате пръст от десния или левия край на екрана до средата, след което да освободите."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Завъртете устройството си"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Моля, завъртете устройството си, за да завършите урока за навигиране с жестове"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Трябва да плъзнете пръст от най-дясната или най-лявата част на екрана"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Трябва да плъзнете пръст от десния или левия край до средата на екрана, след което да го отпуснете"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Научихте жеста за връщане с плъзгане от дясно. Сега научете как се превключва между приложения."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Изпълнихте жеста за връщане назад."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Не прекарвайте пръст твърде близо до долната част на екрана."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Изпълнихте жеста за връщане назад"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Не плъзвайте пръста си твърде близо до долната част на екрана"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Променете чувств. на жеста за връщане назад от настройките"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Жест за връщане назад"</string>
- <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"За да се върнете на предишния екран, прекарайте пръст от левия или десния край на екрана до средата."</string>
+ <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"За да се върнете на предишния екран, плъзнете пръст от левия или десния край на екрана до средата."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"За да се върнете към последния екран, прекарайте два пръста от левия или десния край на екрана до средата."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Трябва да прекарате пръст нагоре от долния край на екрана."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Не задържайте, преди да вдигнете пръста си."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Трябва да прекарате пръст право нагоре."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Изпълнихте жеста за преминаване към началния екран. В следващия урок ще научите как да се върнете назад."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Изпълнихте жеста за преминаване към началния екран."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Връщане назад"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Плъзнете пръст от левия или десния край до средата на екрана"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Трябва да плъзнете пръст нагоре от долния край на екрана"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Не задържайте, преди да вдигнете пръста си"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Трябва да плъзнете пръст право нагоре"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Изпълнихте жеста за преминаване към началния екран. В следващия урок ще научите как се връща назад."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Изпълнихте жеста за преминаване към началния екран"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Жест за преминаване към началния екран"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Прекарайте пръст нагоре от долната част на екрана. Този жест винаги ще ви отвежда до началния екран."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Прекарайте два пръста нагоре от долната част на екрана. Този жест винаги води до началния екран."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Отваряне на началния екран"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"За да отворите началния си екран по всяко време, прекарайте пръст нагоре от долната част на екрана"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Трябва да прекарате пръст нагоре от долния край на екрана."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Задръжте прозореца по-дълго, преди да вдигнете пръста си."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Прекарайте пръст право нагоре, след което задръжте."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Плъзнете пръст нагоре от долната част на екрана"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Отлично!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Трябва да плъзнете пръст нагоре от долния край на екрана"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Задръжте прозореца по-дълго, преди да вдигнете пръста си"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Плъзнете пръст право нагоре, след което задръжте"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Научихте как да използвате жестовете. За да ги изключите, отворете настройките."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Изпълнихте жеста за превключване между приложения."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Изпълнихте жеста за превключване между приложения"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Жест за превключване между приложенията"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"За превключване прекарайте пръст нагоре от долната част на екрана, задръжте и освободете"</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"За превключване плъзнете пръст нагоре от долната част на екрана, задръжте и освободете."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"За превключване на прил. плъзнете 2 пръста нагоре от долната част на екрана, задръжте и освободете."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Превключване на приложенията"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Плъзнете пръст нагоре от долната част на екрана, задръжте и след това го вдигнете"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Браво!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Готово"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Готово"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Настройки"</string>
@@ -78,7 +86,7 @@
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Чудесно!"</string>
<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="459504134589971527">"Прекарайте пръст нагоре, за да отворите началния екран"</string>
+ <string name="allset_hint" msgid="459504134589971527">"Плъзнете пръст нагоре, за да отворите началния екран"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Докоснете бутона „Начало“, за да преминете към началния екран"</string>
<string name="allset_description_generic" msgid="5385500062202019855">"Можете да започнете да използвате <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="default_device_name" msgid="6660656727127422487">"устройството"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Екранна снимка"</string>
<string name="action_split" msgid="2098009717623550676">"Разделяне на екрана"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Докоснете друго прил., за да ползвате разд. екран"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Изход от избора на разделен екран"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"За разделен екран изберете още едно приложение"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Това действие не е разрешено от приложението или организацията ви"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Пропускане на урока за навигиране?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Пропускане"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Завъртане на екрана"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Урок за лентата на задачите"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Показва се урокът за лентата на задачите"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Урокът за лентата на задачите бе затворен"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Плъзнете приложение встрани, за да използвате едновременно 2"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Плъзнете бавно нагоре, за да видите лентата на задачите"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Получавайте предложения за приложения според навиците си"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Включете навигирането с жестове от настройките с цел авт. скриване на лентата на задачите"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Правете повече неща с лентата на задачите"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Напред"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Назад"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Затваряне"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Начало"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Известия"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Бързи настройки"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Лента на задачите"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Лентата на задачите се показва"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Лентата на задачите е скрита"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Лента за навигация"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Лентата на задачите винаги да се показва"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Промяна на режима на навигация"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Разделител на лентата на задачите"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Преместване горе/вляво"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Преместване долу/вдясно"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показване на още # приложение.}other{Показване на още # приложения.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Приложението се добавя на настолния компютър"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Отказ"</string>
</resources>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index 2756c47..0973a50 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"অ্যাপ সাজেশন চালু করা আছে"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"অ্যাপ সাজেশন বন্ধ করা আছে"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"আপনার প্রয়োজন হতে পারে এমন অ্যাপ: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"স্ক্রিনের একেবারে ডান বা বাঁদিকের প্রান্ত থেকে সোয়াইপ করেছেন কিনা তা দেখে নিন।"</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"স্ক্রিনের ডান বা বাঁদিকের প্রান্ত থেকে মাঝখান পর্যন্ত সোয়াইপ করে আঙুল তুলে নিয়েছেন কিনা তা দেখে নিন।"</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"আপনার ডিভাইস ঘোরান"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"জেসচার নেভিগেশন টিউটোরিয়াল সম্পূর্ণ করতে আপনার ডিভাইসটি ঘোরান"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"স্ক্রিনের একেবারে ডান বা বাঁদিকের প্রান্ত থেকে সোয়াইপ করেছেন কিনা তা দেখে নিন"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"স্ক্রিনের ডান বা বাঁদিকের প্রান্ত থেকে মাঝখান পর্যন্ত সোয়াইপ করেছেন কিনা দেখে নিয়ে আঙুল তুলে নিন"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"ফিরে যেতে, কীভাবে ডানদিক থেকে সোয়াইপ করতে হয় তা আপনি শিখেছেন। এরপর, একটি অ্যাপ থেকে অন্য অ্যাপে কীভাবে যাবেন জেনে নিন।"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"আপনি ফিরে যাওয়ার জেসচার সম্পর্কে জেনেছেন।"</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"স্ক্রিনের নিচের প্রান্তের খুব কাছে পর্যন্ত যাতে সোয়াইপ না করেন সেটি ভাল করে দেখে নিন।"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"আপনি জেনেছেন হাতের জেসচার ব্যবহার করে আগের স্ক্রিনে কীভাবে ফিরে যাওয়া যায়"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"স্ক্রিনের নিচের প্রান্তের খুব কাছে পর্যন্ত যাতে সোয়াইপ না করেন সেটি ভাল করে দেখে নিন"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"ফিরে যাওয়ার জেসচারের সেন্সিটিভিটি পরিবর্তন করতে, সেটিংসে যান"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"ফিরে যেতে সোয়াইপ করুন"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"শেষের স্ক্রিনে ফিরে যেতে, ডান বা বাঁ প্রান্ত থেকে স্ক্রিনের মাঝখান পর্যন্ত সোয়াইপ করুন।"</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"শেষ স্ক্রিনে ফিরতে, বাম বা ডান প্রান্ত থেকে স্ক্রিনের মাঝামাঝি পর্যন্ত ২টি আঙুল দিয়ে সোয়াইপ করুন।"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"স্ক্রিনের নিচের প্রান্ত থেকে আপনি সোয়াইপ করেছেন কিনা ভাল করে দেখে নিন।"</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"আঙুল তুলে নেওয়ার আগে আপনি যাতে পজ না করেন সেটি ভাল করে দেখে নিন।"</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"আপনি উপরের দিকে সোজাসুজি সোয়াইপ করেছেন কিনা ভাল করে দেখে নিন।"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"আপনি হোম স্ক্রিনে যাওয়ার জেসচার সম্পর্কে জেনেছেন। এরপর, ফিরে কীভাবে যাবেন তা জেনে নিন।"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"আপনি হোম স্ক্রিনে যাওয়ার জেসচার সম্পর্কে জেনেছেন।"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"ফিরে যান"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"স্ক্রিনের বাঁদিক বা ডানদিক থেকে মাঝখানে সোয়াইপ করুন"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"স্ক্রিনের নিচের প্রান্ত থেকে আপনি সোয়াইপ করেছেন কিনা ভাল করে দেখে নিন"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"আঙুল তুলে নেওয়ার আগে আপনি যাতে পজ না করেন সেটি ভাল করে দেখে নিন"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"আপনি উপরের দিকে সোজাসুজি সোয়াইপ করেছেন কিনা ভাল করে দেখে নিন"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"আপনি জেনেছেন হাতের জেসচার ব্যবহার করে হোম স্ক্রিনে কীভাবে যাওয়া যায়। এরপর, ফিরে কীভাবে যাবেন তা জেনে নিন।"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"আপনি জেনেছেন হাতের জেসচার ব্যবহার করে হোম স্ক্রিনে কীভাবে যাওয়া যায়"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"হোম স্ক্রিনে যেতে সোয়াইপ করুন"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"স্ক্রিনের নিচের প্রান্ত থেকে উপরের দিকে সোয়াইপ করুন। এটি করলে, আপনি সবসময় হোম স্ক্রিনে যেতে পারবেন।"</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"স্ক্রিনের নিচ থেকে ২টি আঙুল দিয়ে উপরে সোয়াইপ করুন। এই জেসচার সবসময় আপনাকে হোম স্ক্রিনে নিয়ে যায়।"</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"হোমে যান"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"যেকোনও সময় আপনার হোম স্ক্রিনে যেতে, স্ক্রিনের নিচ থেকে উপরের দিকে সোয়াইপ করুন"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"স্ক্রিনের নিচের প্রান্ত থেকে আপনি সোয়াইপ করেছেন কিনা ভাল করে দেখে নিন।"</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"চেষ্টা করুন যাতে আঙুল সরিয়ে নেওয়ার আগে উইন্ডো কিছুক্ষণ প্রেস করে রাখা যায়।"</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"আপনি উপরের দিকে সোজাসুজি সোয়াইপ করেছেন কিনা ভাল করে দেখে নিয়ে তারপর পজ করুন।"</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"হোম স্ক্রিনে যান"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"আপনার স্ক্রিনের একেবারে নিচ থেকে সোয়াইপ করুন"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"অসাধারণ!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"স্ক্রিনের নিচের প্রান্ত থেকে আপনি সোয়াইপ করেছেন কিনা ভাল করে দেখে নিন"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"চেষ্টা করুন যাতে আঙুল সরিয়ে নেওয়ার আগে উইন্ডো বেশ কিছুক্ষণ প্রেস করে রাখা যায়"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"আপনি উপরের দিকে সোজাসুজি সোয়াইপ করেছেন কিনা ভাল করে দেখে নিয়ে তারপর পজ করুন"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"জেসচার কীভাবে ব্যবহার করতে হয় আপনি তা শিখে ফেলেছেন। জেসচার বন্ধ করতে, সেটিংসে যান।"</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"আপনি একটি অ্যাপ থেকে অন্য অ্যাপে যাওয়ার জেসচার সম্পর্কে জেনেছেন।"</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"আপনি জেনেছেন যে হাতের জেসচার ব্যবহার করে একটি অ্যাপ থেকে অন্য অ্যাপে কীভাবে যাওয়া যায়"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"একটি অ্যাপ থেকে অন্য অ্যাপে যেতে সোয়াইপ করুন"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"একটি অ্যাপ থেকে অন্যটিতে পাল্টাতে, স্ক্রিনের নিচ থেকে উপরে সোয়াইপ করে ধরে রাখুন, তারপরে ছেড়ে দিন।"</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"একটি থেকে অন্য অ্যাপে পাল্টাতে, ২টি আঙুল দিয়ে স্ক্রিনের নিচ থেকে উপরে সোয়াইপ করে ধরে রেখে ছেড়ে দিন।"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"অ্যাপ পরিবর্তন করুন"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"স্ক্রিনের নিচের থেকে উপরের দিকে সোয়াইপ করে ধরে থাকুন, তারপরে ছেড়ে দিন"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"শাবাশ!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"সব প্রস্তুত"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"সম্পূর্ণ হয়েছে"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"সেটিংস"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"স্ক্রিনশট নিন"</string>
<string name="action_split" msgid="2098009717623550676">"স্প্লিট"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"স্প্লিট স্ক্রিন ব্যবহারের জন্য অ্যাপে ট্যাপ করুন"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"স্প্লিট স্ক্রিন বেছে নেওয়ার বিকল্প থেকে বেরিয়ে আসুন"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"স্প্লিট স্ক্রিন ব্যবহার করতে অন্য অ্যাপ বেছে নিন"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"এই অ্যাপ বা আপনার প্রতিষ্ঠান এই অ্যাকশনটি পারফর্ম করার অনুমতি দেয়নি"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"নেভিগেশন টিউটোরিয়াল এড়িয়ে যেতে চান?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"এড়িয়ে যান"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"স্ক্রিন ঘোরান"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"টাস্কবার এডুকেশন"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"টাস্কবার এডুকেশন দেখানো হয়েছে"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"টাস্কবার এডুকেশন বন্ধ করা আছে"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"একসাথে ২টি অ্যাপ ব্যবহার করতে একটি অ্যাপ পাশে টেনে আনুন"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"\'টাস্কবার\' দেখানোর জন্য উপরের দিকে আস্তে সোয়াইপ করুন"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"আপনার রুটিন অনুযায়ী অ্যাপ থেকে সাজেশন পান"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"\'টাস্কবার\' অটোমেটিক লুকানোর জন্য, সেটিংসে জেসচার নেভিগেশন চালু করুন"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"\'টাস্কবার\' ফিচারের সাহায্যে আরও অনেক কিছু করুন"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"পরবর্তী"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"ফিরুন"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"বন্ধ করুন"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"হয়ে গেছে"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"হোম"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"বিজ্ঞপ্তি"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"দ্রুত সেটিংস"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"টাস্কবার"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"\'টাস্কবার\' দেখানো হয়েছে"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"\'টাস্কবার\' লুকানো রয়েছে"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"নেভিগেশন বার"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"সবসময় টাস্কবার দেখুন"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"\'নেভিগেশন\' মোড পরিবর্তন করুন"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"টাস্কবার ডিভাইডার"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"উপরে/বাঁদিকে সরান"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"নিচে/ডানদিকে সরান"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{আরও #টি অ্যাপ দেখুন।}one{আরও #টি অ্যাপ দেখুন।}other{আরও #টি অ্যাপ দেখুন।}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ও <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"ডেস্কটপে অ্যাপ যোগ করা হচ্ছে"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"বাতিল করুন"</string>
</resources>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index 872fcfe..a2e4e33 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Prijedlozi aplikacija su omogućeni"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Prijedlozi aplikacija su onemogućeni"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predviđena aplikacija: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Vodite računa da prevučete s krajnjeg desnog ili krajnjeg lijevog ruba."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Vodite računa da prevučete s desnog ili lijevog ruba prema sredini ekrana i pustite."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotirajte uređaj"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rotirajte uređaj da završite vodič za navigaciju pokretima"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Prevucite s krajnjeg desnog ili krajnjeg lijevog ruba"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Prevucite s desnog ili lijevog ruba prema sredini ekrana i pustite"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Naučili ste kako prevući zdesna da se vratite. Sljedeće naučite kako prebacivati između aplikacija."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Savladali ste pokret za vraćanje."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Obratite pažnju da ne prevučete preblizu donjem dijelu ekrana."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Savladali ste pokret za vraćanje"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Pazite da ne prevučete preblizu donjem dijelu ekrana"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Promijenite osjetljivost pokreta za povratak u Postavkama"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Prevucite da se vratite"</string>
- <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Da se vratite na posljednji ekran, prevucite s lijevog ili desnog ruba prema sredini ekrana."</string>
+ <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Da se vratite na prethodni ekran, prevucite s lijevog ili desnog ruba prema sredini ekrana."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Da se vratite na posljednji ekran, prevucite s 2 prsta od lijevog ili desnog ruba do sredine ekrana."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Trebate prevući prema gore s donjeg ruba ekrana."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Obratite pažnju da ne zastanete prije puštanja."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Trebate prevući ravno prema gore."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Savladali ste pokret za otvaranje početnog ekrana. Sljedeće naučite kako se vratiti."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Savladali ste pokret za otvaranje početnog ekrana."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Vratite se nazad"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Prevucite s lijevog ili desnog ruba prema sredini ekrana"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Prevucite prema gore s donjeg ruba ekrana"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Pazite da ne zastanete prije puštanja"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Prevucite ravno nagore"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Savladali ste pokret za otvaranje početnog ekrana. Sljedeće naučite kako se vratiti."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Savladali ste pokret za otvaranje početnog ekrana"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Prevucite da odete na početni ekran"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Prevucite s dna ekrana prema gore. Tim pokretom uvijek idete na početni ekran."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Prevucite s 2 prsta od dna ekrana. Tim pokretom uvijek idete na početni ekran"</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Odlazak na početni ekran"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Idite na početni ekran u bilo kojem trenutku, prevucite s donjeg dijela ekrana nagore"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Trebate prevući prema gore s donjeg ruba ekrana."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Pokušajte zadržati prozor duže prije puštanja."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Trebate prevući ravno prema gore, a zatim zastati."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Idite na početni ekran"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Prevucite s dna ekrana prema gore"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Sjajno!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Vodite računa da prevučete s donjeg ruba ekrana prema gore"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Pokušajte zadržati prozor duže prije puštanja"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Prevucite ravno nagore, a zatim zastanite"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Naučili ste kako koristiti pokrete. Idite u Postavke da isključite pokrete."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Savladali ste pokret za prebacivanje između aplikacija."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Savladali ste pokret za prebacivanje između aplikacija"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Prevucite da prebacujete između aplikacija"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Da prebacujete između aplikacija, prevucite s dna ekrana prema gore, zadržite, a zatim pustite."</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Da se prebacujete između aplikacija, prevucite s dna ekrana nagore, zadržite, a zatim pustite."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Da se prebacujete između aplikacija, prevucite s 2 prsta od dna ekrana, zadržite, a zatim pustite."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Prebacujte se između aplikacija"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Prevucite s dna ekrana prema gore, zadržite, a zatim pustite"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Odlično!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Sve je spremno"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Gotovo"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Postavke"</string>
@@ -80,13 +88,14 @@
<string name="allset_title" msgid="5021126669778966707">"Sve je spremno!"</string>
<string name="allset_hint" msgid="459504134589971527">"Prevucite prema gore da odete na početni ekran"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Dodirnite dugme za početni ekran da odete napočetni ekran"</string>
- <string name="allset_description_generic" msgid="5385500062202019855">"Sve je spremno da počnete koristiti uređaj <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="allset_description_generic" msgid="5385500062202019855">"Spremni ste da počnete koristiti <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="default_device_name" msgid="6660656727127422487">"uređaj"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Postavke navigiranja sistemom"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Dijeli"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Snimak ekrana"</string>
<string name="action_split" msgid="2098009717623550676">"Podijeli"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Dodirnite drugu apl. da koristite podijeljeni ekran"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Izlaz iz odabira podijeljenog ekrana"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Odaberite drugu apl. da koristite podijeljeni ekran"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Ovu radnju ne dozvoljava aplikacija ili vaša organizacija"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Preskočiti vodič za navigiranje?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Preskoči"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Rotiranje ekrana"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Edukacija o traci zadataka"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Edukacija o programskoj traci je prikazana"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Edukacija o programskoj traci je zatvorena"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Prevucite aplikaciju ustranu da odjednom koristite 2 aplikacije"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Sporo prevucite nagore da prikažete traku zadataka"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Sporo prevucite nagore da vidite traku zadataka"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Dobijajte prijedloge aplikacija zasnovane na vašoj rutini"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Uključite navigaciju pokretima u Postavkama da automatski sakrijete traku zadataka"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Ostvarite više pomoću trake zadataka"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Naprijed"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Nazad"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Uradite više pomoću trake zadataka"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Zatvori"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Gotovo"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Dom"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Obavještenja"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Brze postavke"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Traka zadataka"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Traka zadataka je prikazana"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Traka zadataka je sakrivena"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigaciona traka"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Uvijek prikaži traku zadataka"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Promijeni način navigacije"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Razdjelnik trake zadataka"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premjesti gore lijevo"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premjesti dolje desno"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodavanje aplikacije na radnu površinu"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Otkaži"</string>
</resources>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index 00ee4c1..0cfe820 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Els suggeriments d\'aplicacions estan activats"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Els suggeriments d\'aplicacions estan desactivats"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predicció d\'aplicació: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Assegura\'t de lliscar des de l\'extrem dret o esquerre de la pantalla."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Assegura\'t de lliscar des de la vora dreta o esquerra cap al centre de la pantalla i deixar anar."</string>
- <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Has après com pots lliscar des de la dreta per tornar enrere. Ara, descobreix com pots canviar d\'app."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Has completat el gest per tornar enrere."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Assegura\'t de no lliscar massa a prop de la part inferior de la pantalla."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Gira el dispositiu"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Gira el dispositiu per completar el tutorial de navegació amb gestos"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Assegura\'t de lliscar des de l\'extrem dret o esquerre de la pantalla."</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Assegura\'t de lliscar des de la vora dreta o esquerra cap al centre de la pantalla i deixar anar"</string>
+ <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Has après a lliscar des de la dreta per tornar enrere. Ara, descobreix com pots canviar d\'aplicació."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Has completat el gest per tornar enrere"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Assegura\'t de no lliscar massa a prop de la part inferior de la pantalla."</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Per canviar la sensibilitat del gest, ves a Configuració"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Llisca per anar enrere"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Per tornar a la darrera pantalla, llisca des de la vora esquerra o dreta cap al centre de la pantalla."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Per tornar a la pantalla anterior, llisca amb dos dits des de l\'extrem esquerre o dret cap al centre de la pantalla."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Assegura\'t de lliscar des de la vora inferior de la pantalla."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Assegura\'t de no aturar-te abans de deixar anar."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Assegura\'t de lliscar directament cap amunt."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Has completat el gest per anar a la pantalla d\'inici. Ara, descobreix com pots tornar enrere."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Has completat el gest per anar a la pantalla d\'inici."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Torna enrere"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Llisca des de la vora esquerra o dreta cap al centre de la pantalla."</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Assegura\'t de lliscar cap amunt des de la part inferior de la pantalla"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Assegura\'t de no aturar-te abans de deixar anar."</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Assegura\'t de lliscar recte cap amunt."</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Has completat el gest per anar a la pantalla d\'inici. Ara, descobreix com pots tornar enrere."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Has completat el gest per anar a la pantalla d\'inici"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Llisca per anar a la pantalla d\'inici"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Llisca cap amunt des de la part inferior de la pantalla. Aquest gest et porta a la pantalla d\'inici."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Llisca amb dos dits cap amunt des de la part inferior. Aquest gest sempre porta a la pantalla d\'inici."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Ves a la pàgina d\'inici"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Per anar a la pantalla d\'inici en qualsevol moment, llisca cap amunt des la part inferior"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Assegura\'t de lliscar des de la vora inferior de la pantalla."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Prova de mantenir premuda la finestra durant més temps abans de deixar-la anar."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Assegura\'t de lliscar directament cap amunt i després aturar-te."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Llisca cap amunt des de la part inferior de la pantalla."</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Ben fet!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Assegura\'t de lliscar cap amunt des de la part inferior de la pantalla."</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Prova de mantenir premuda la finestra durant més temps abans de deixar-la anar"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Assegura\'t de lliscar directament cap amunt i després aturar-te"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Has après a utilitzar els gestos. Per desactivar-los, ves a Configuració."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Has completat el gest per canviar d\'aplicació."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Has completat el gest per canviar d\'aplicació"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Llisca per canviar d\'aplicació"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Per canviar entre aplicacions, llisca cap amunt des de la part inferior, mantén premut i deixa anar."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Per canviar entre apps, llisca amb dos dits cap amunt des de la part inferior, mantén i deixa anar."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Canvia d\'aplicació"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Llisca cap amunt des de la part inferior de la pantalla, mantén premut i, a continuació, deixa anar."</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Ben fet!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Tot a punt"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Fet"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Configuració"</string>
@@ -80,13 +88,14 @@
<string name="allset_title" msgid="5021126669778966707">"Tot a punt!"</string>
<string name="allset_hint" msgid="459504134589971527">"Llisca cap amunt per anar a la pàgina d\'inici"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Toca el botó d\'inici per anar a la pantalla d\'inici"</string>
- <string name="allset_description_generic" msgid="5385500062202019855">"Ja pots començar a utilitzar <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="allset_description_generic" msgid="5385500062202019855">"Ja pots començar a utilitzar el <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="default_device_name" msgid="6660656727127422487">"dispositiu"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Configuració de navegació del sistema"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Comparteix"</string>
<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="8464310533320556058">"Toca una altra app per utilitzar pantalla dividida"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Surt de la selecció de pantalla dividida"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Tria una altra app per utilitzar pantalla dividida"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"L\'aplicació o la teva organització no permeten aquesta acció"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vols ometre el tutorial de navegació?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Omet"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Gira la pantalla"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informació sobre Barra de tasques"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Ha aparegut el tauler educatiu de la barra de tasques"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"S\'ha tancat el tauler educatiu de la barra de tasques"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Arrossega una app al costat per utilitzar 2 apps alhora"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Arrossega una aplicació al costat per utilitzar-ne dues alhora"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Llisca lentament cap amunt per mostrar la Barra de tasques"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Obtén suggeriments d\'aplicacions basats en la teva rutina"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"A Configuració, activa la navegació amb gestos per amagar la Barra de tasques automàticament"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Fes més coses amb la Barra de tasques"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Següent"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Enrere"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Treu més partit de la Barra de tasques"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Tanca"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Fet"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Inici"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notificacions"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Config. ràpida"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Barra de tasques"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Es mostra la Barra de tasques"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"S\'ha amagat la Barra de tasques"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegació"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Mostra sempre Barra de tasques"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Canvia el mode de navegació"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Separador de la Barra de tasques"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mou a la part superior o a l\'esquerra"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mou a la part inferior o a la dreta"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostra # aplicació més.}other{Mostra # aplicacions més.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"S\'està afegint l\'aplicació a l\'ordinador"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel·la"</string>
</resources>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index 96dbec7..3582005 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -44,49 +44,58 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Návrhy aplikací jsou povoleny"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Návrhy aplikací jsou zakázány"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Předpokládaná aplikace: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Přejeďte prstem z úplného pravého nebo levého okraje obrazovky."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Přejeďte prstem z pravého nebo levého okraje doprostřed obrazovky a zdvihněte prst."</string>
- <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Naučili jste se, jak se vrátit zpět přejetím prstem zprava. Teď se naučíte přepínat aplikace."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Dokončili jste gesto pro přechod zpět."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Dejte pozor, abyste prstem nepřejížděli moc blízko ke spodnímu okraji obrazovky."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Otočte zařízení"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Pokud chcete dokončit výukový program navigace gesty, otočte zařízení"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Přejeďte prstem z úplného pravého nebo levého okraje obrazovky"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Přejeďte prstem z pravého nebo levého okraje doprostřed obrazovky a zdvihněte prst"</string>
+ <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Naučili jste se, jak se vrátit zpět přejetím prstem zprava. Teď se naučíte přepínat mezi aplikacemi."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Dokončili jste gesto pro přechod zpět"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Dejte pozor, abyste prstem nepřejížděli moc blízko ke spodnímu okraji obrazovky"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Citlivost gesta pro přechod zpět můžete změnit v Nastavení"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Přejetím prstem se vrátíte zpět"</string>
- <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"K návratu na poslední obrazovku přejeďte prstem z levého nebo pravého okraje obrazovky doprostřed."</string>
+ <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Na předchozí obrazovku se vrátíte tak, že přejedete prstem z levého nebo pravého okraje obrazovky doprostřed."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Pokud se chcete vrátit na poslední obrazovku, přejeďte dvěma prsty z levého nebo pravého okraje doprostřed obrazovky."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Přejeďte prstem nahoru z dolního okraje obrazovky."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Před zdvihnutím prstu nedělejte pauzu."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Přejeďte prstem přímo nahoru."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Dokončili jste gesto pro přechod na plochu. Teď se naučíte vrátit se zpět."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Dokončili jste gesto pro přechod na plochu."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Návrat zpět"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Přejeďte prstem z levého nebo pravého okraje do středu obrazovky"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Přejeďte prstem nahoru z dolního okraje obrazovky"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Před zdvihnutím prstu nedělejte pauzu"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Přejeďte prstem přímo nahoru"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Dokončili jste gesto pro přechod na plochu. Teď se naučíte vrátit se zpět."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Dokončili jste gesto pro přechod na plochu"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Přechod na plochu přejetím prstem"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Přejeďte prstem ze spodní části obrazovky nahoru. Tímto gestem se vždy dostanete na plochu."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Přejeďte dvěma prsty z dolního okraje obrazovky nahoru. Tímto gestem se vždy dostanete na plochu."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Přejít na plochu"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Na plochu kdykoli přejdete přejetím prstem ze spodní části obrazovky nahoru"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Přejeďte prstem nahoru z dolního okraje obrazovky."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Zkuste podržet okno delší dobu, než ho uvolníte."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Přejeďte prstem přímo nahoru a pak udělejte pauzu."</string>
- <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Naučili jste se používat gesta. Gesta můžete vypnout v nastavení."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Dokončili jste gesto pro přepínání aplikací."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Přechod na plochu"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Přejeďte prstem ze spodní části obrazovky nahoru"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Výborně!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Přejeďte prstem nahoru z dolního okraje obrazovky"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Zkuste podržet okno delší dobu, než ho uvolníte"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Přejeďte prstem přímo nahoru a pak udělejte pauzu"</string>
+ <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Naučili jste se používat gesta. Vypnout je můžete v nastavení."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Dokončili jste gesto pro přepínání aplikací"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Přepínání aplikací přejetím prstem"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Přepínání mezi aplikacemi: Přejeďte nahoru z dolního okraje obrazovky, podržte obrazovku a uvolněte."</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Přejeďte nahoru z dolního okraje obrazovky, podržte obrazovku a uvolněte."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Přepínání mezi aplikacemi: Přejeďte dvěma prsty nahoru z dolního okraje obrazovky, podržte obrazovku a uvolněte."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Přepínání aplikací"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Přejeďte prstem nahoru z dolního okraje obrazovky, podržte obrazovku a potom prst uvolněte"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Výborně!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Vše je nastaveno"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Hotovo"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Nastavení"</string>
- <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Zkusit znovu"</string>
+ <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Zkuste to znovu"</string>
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Skvělé!"</string>
<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="459504134589971527">"Přejetím nahoru se vrátíte na plochu"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Klepnutím na tlačítko plochy se vrátíte na plochu"</string>
- <string name="allset_description_generic" msgid="5385500062202019855">"Jste připraveni začít používat <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="allset_description_generic" msgid="5385500062202019855">"<xliff:g id="DEVICE">%1$s</xliff:g> můžete začít používat"</string>
<string name="default_device_name" msgid="6660656727127422487">"zařízení"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Nastavení navigace v systému"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Sdílet"</string>
<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="8464310533320556058">"Klepnutím na jinou aplikaci rozdělíte obrazovku"</string>
+ <string name="toast_split_select_app" msgid="8464310533320556058">"Obrazovku rozdělíte klepnutím na jinou aplikaci"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Výběr opuštění rozdělené obrazovky"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Vyberte podporovanou aplikaci"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikace nebo organizace zakazuje tuto akci"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Přeskočit výukový program k navigaci?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Přeskočit"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Otočit obrazovku"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informace o panelu aplikací"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Zobrazila se výuka k hlavnímu panelu"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Výuka k hlavnímu panelu byla zavřena"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Pokud chcete používat 2 aplikace najednou, přetáhněte aplikaci na stranu"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Přetáhněte aplikaci na stranu a používejte tak dvě najednou"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Panel aplikací zobrazíte pomalým přejetím prstem nahoru"</string>
- <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Získejte návrhy aplikací na základě vašeho používání"</string>
+ <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Dostávejte návrhy aplikací podle toho, jaké používáte"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Pokud chcete panel aplikací automaticky skrýt, zapněte v Nastavení navigaci gesty"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Pomocí panelu aplikací můžete dělat více věcí"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Další"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Zpět"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Více možností s panelem aplikací"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Zavřít"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Hotovo"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Domů"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Oznámení"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Rychlé nastavení"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Panel aplikací"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Panel aplikací je zobrazen"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Panel aplikací je skrytý"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigační panel"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Vždy zobrazovat panel aplikací"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Změnit režim navigace"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Rozdělovač panelu aplikací"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Přesunout doleva nahoru"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Přesunout doprava dolů"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Zobrazit # další aplikaci.}few{Zobrazit # další aplikace.}many{Zobrazit # další aplikace.}other{Zobrazit # dalších aplikací.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> a <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Přidání aplikace na plochu"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Zrušit"</string>
</resources>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index 801cb71..1603fac 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -44,39 +44,47 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Appforslag er aktiveret"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Appforslag er deaktiveret"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"App, du forventes at skulle bruge: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Stryg fra kanten yderst til højre eller venstre."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Stryg fra højre eller venstre kant mod midten af skærmen, og løft fingeren."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotér din enhed"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rotér enheden for at gennemgå vejledningen i navigation med bevægelser"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Stryg fra kanten yderst til højre eller venstre"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Stryg fra højre eller venstre kant mod midten af skærmen, og løft fingeren"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Du har lært, hvordan du stryger fra højre for at gå tilbage. Nu skal du se, hvordan du skifter app."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Du har fuldført bevægelsen for Gå tilbage."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Undgå at stryge for tæt på bunden af skærmen."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Du har fuldført bevægelsen for Gå tilbage"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Undgå at stryge for tæt på bunden af skærmen"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Juster følsomheden for bevægelsen Gå tilbage i Indstillinger"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Stryg for at gå tilbage"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Stryg mod midten af skærmen fra venstre eller højre kant for at gå tilbage til den seneste skærm."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Du kan gå tilbage til forrige skærm ved at stryge fra venstre eller højre kant mod midten af skærmen med 2 fingre."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Stryg opad fra bunden af skærmen."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Undlad at holde fingeren stille, indtil du løfter fingeren."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Stryg lige opad."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Du har fuldført bevægelsen for Gå til startskærmen. Som det næste kan du se, hvordan du går tilbage."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Du har fuldført bevægelsen for Gå til startskærmen."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Gå tilbage"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Stryg fra venstre eller højre kant til midten af skærmen"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Stryg opad fra bunden af skærmen"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Undlad at holde fingeren stille, indtil du løfter fingeren"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Stryg lige opad"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Du har fuldført bevægelsen for Gå til startskærmen. Som det næste kan du se, hvordan du går tilbage."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Du har fuldført bevægelsen for Gå til startskærmen"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Stryg for at gå til startskærmen"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Stryg opad fra bunden af skærmen. Denne bevægelse åbner altid startskærmen."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Stryg opad med 2 fingre fra bunden af skærmen. Denne bevægelse åbner altid startskærmen."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Gå til startskærmen"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Du kan altid gå til startskærmen ved at stryge opad fra bunden af skærmen"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Stryg opad fra bunden af skærmen."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Prøv at holde fingeren nede på vinduet i længere tid, inden du løfter den."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Stryg lige opad, og hold derefter fingeren stille."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Stryg opad fra bunden af skærmen"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Flot!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Stryg opad fra bunden af skærmen"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Prøv at holde fingeren nede på vinduet i længere tid, inden du løfter den"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Stryg lige opad, og hold derefter fingeren stille"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Du har lært, hvordan du bruger bevægelser. Du kan aktivere bevægelser i Indstillinger."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Du har fuldført bevægelsen for Skift app."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Du har fuldført bevægelsen for at skifte mellem apps"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Stryg for at skifte app"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Skift mellem apps ved at stryge opad fra bunden af skærmen, holde fingeren stille og løfte den."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Skift mellem apps ved at stryge opad fra bunden af skærmen med 2 fingre, holde dem nede og slippe."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Skift mellem apps"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Stryg opad fra bunden af skærmen, hold fingeren nede, og slip"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Flot!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Så er du klar"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Luk"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Indstillinger"</string>
<string name="gesture_tutorial_try_again" msgid="65962545858556697">"Prøv igen"</string>
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Sådan!"</string>
- <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="gesture_tutorial_step" msgid="1279786122817620968">"Vejledning <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="459504134589971527">"Stryg opad for at gå til startsiden"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Tryk på knappen Hjem for at gå til din startskærm"</string>
@@ -87,23 +95,20 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Opdel"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tryk på en anden app for at bruge opdelt skærm"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Luk valg af opdelt skærm"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Vælg en anden app for at bruge opdelt skærm"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Appen eller din organisation tillader ikke denne handling"</string>
- <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vil du springe selvstudiet for navigation over?"</string>
+ <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vil du springe vejledningen 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>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Annuller"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Spring over"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Roter skærm"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Oplysninger om proceslinjen"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Vejledningen om proceslinjen blev åbnet"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Vejledningen om proceslinjen blev lukket"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Træk en app til siden for at bruge 2 apps på én gang"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Stryg langsomt opad for at se proceslinjen"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Få appforslag baseret på din rutine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Aktivér navigation med bevægelser under Indstillinger for automatisk at skjule proceslinjen"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Få mere fra hånden med proceslinjen"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Næste"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Tilbage"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Luk"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Luk"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Hjem"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifikationer"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Kvikmenu"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Proceslinje"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Proceslinjen vises"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Proceslinjen er skjult"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigationslinje"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Vis altid proceslinjen"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Skift navigationstilstand"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Opdeling af proceslinjen"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Flyt til toppen eller venstre side"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Flyt til bunden eller højre side"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Vis # app mere.}one{Vis # app mere.}other{Vis # apps mere.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> og <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Appen føjes til computeren"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuller"</string>
</resources>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index c25ef66..828b85f 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -44,37 +44,45 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Funktion „App-Vorschläge“ aktiviert"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Funktion \"App-Vorschläge\" deaktiviert"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Vorgeschlagene App: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Wische vom äußersten rechten oder linken Displayrand."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Wische vom rechten oder linken Displayrand zur Displaymitte und lass los."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Gerät drehen"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Bitte drehe dein Gerät, um die Anleitung für die Bedienung über Gesten abzuschließen"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Wische vom äußersten rechten oder linken Displayrand"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Wische vom rechten oder linken Displayrand zur Displaymitte und lass los"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Du hast jetzt gelernt, vom rechten Displayrand aus zu wischen, um zurückzugehen. Gleich erfährst du, wie man zwischen Apps wechselt."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Du hast die „Zurück“-Touch-Geste abgeschlossen."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Wische nicht zu nah am unteren Displayrand."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Du hast den Schritt für die „Zurück“-Touch-Geste abgeschlossen"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Wische nicht zu nah an den unteren Displayrand"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Du kannst die Empfindlichkeit von „Zurück“ in den Einstellungen ändern"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Zum Zurückgehen wischen"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Wenn du zum letzten Bildschirm zurückgehen möchtest, wische vom linken oder rechten Rand zur Mitte."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Wenn du zum letzten Bildschirm zurückgehen möchtest, wische mit zwei Fingern vom linken oder rechten Displayrand zur Mitte."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Wische vom unteren Displayrand nach oben."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Achte darauf, nicht innezuhalten, bevor du loslässt."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Wische gerade nach oben."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Du hast die „Startbildschirm“-Touch-Geste abgeschlossen. Gleich erfährst du, wie du zurückgelangst."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Du hast die „Startbildschirm“-Touch-Geste abgeschlossen."</string>
- <string name="home_gesture_intro_title" msgid="836590312858441830">"Zum Startbildschirm gehen"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Zurück"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Wische vom linken oder rechten Displayrand bis zur Mitte des Displays"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Wische vom unteren Displayrand nach oben"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Achte darauf, nicht innezuhalten, bevor du loslässt"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Wische gerade nach oben"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Du hast den Schritt für die „Zum Startbildschirm“-Geste abgeschlossen. Jetzt lernst du, wie du zurückgehst."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Du hast den Schritt für die „Startbildschirm“-Touch-Geste abgeschlossen"</string>
+ <string name="home_gesture_intro_title" msgid="836590312858441830">"Den Startbildschirm aufrufen"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Wenn du zum Startbildschirm gehen möchtest, wische einfach vom unteren Displayrand nach oben."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Wische mit zwei Fingern vom unteren Displayrand nach oben. So gelangst du immer zum Startbildschirm."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Zum Startbildschirm"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Du kannst jederzeit zum Startbildschirm gehen, indem du vom unteren Displayrand nach oben wischst"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Wische vom unteren Displayrand nach oben."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Versuche, das Fenster länger festzuhalten, bevor du es loslässt."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Wische gerade nach oben und halte dann inne."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Zum StartU+00ADbildschirm"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Wische vom unteren Displayrand nach oben"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Gut gemacht!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Wische vom unteren Displayrand nach oben"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Halte das Fenster länger gedrückt, bevor du es loslässt"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Wische gerade nach oben und halte dann inne"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Nun weißt du, wie Touch-Gesten funktionieren. Du kannst sie in den Einstellungen deaktivieren."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Du hast die „Apps wechseln“-Touch-Geste abgeschlossen."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Du hast den Schritt für die „Apps wechseln“-Touch-Geste abgeschlossen"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Zwischen Apps wechseln"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Wische auf dem Display von unten nach oben, halte den Finger gedrückt und lass dann los, um zwischen Apps zu wechseln."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Wische zum App-Wechseln mit zwei Fingern vom unteren Displayrand nach oben, halte und lass dann los."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Apps wechseln"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Wische auf dem Display von unten nach oben, halte es gedrückt und lass es dann los"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Perfekt!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Fertig"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Fertig"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Einstellungen"</string>
- <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Wiederholen"</string>
+ <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Noch einmal versuchen"</string>
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Sehr gut!"</string>
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Anleitung <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Fertig!"</string>
@@ -86,24 +94,21 @@
<string name="action_share" msgid="2648470652637092375">"Teilen"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Teilen"</string>
- <string name="toast_split_select_app" msgid="8464310533320556058">"Für „Geteilter Bildschirm“ auf weitere App tippen"</string>
- <string name="toast_split_app_unsupported" msgid="2360229567007828914">"Für geteilten Bildschirm andere App auswählen"</string>
+ <string name="toast_split_select_app" msgid="8464310533320556058">"Für Splitscreen auf weitere App tippen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Splitscreen-Auswahl beenden"</string>
+ <string name="toast_split_app_unsupported" msgid="2360229567007828914">"Für Splitscreen andere App auswählen"</string>
<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_title" msgid="2725643161260038458">"Tutorial zur Bedienung ü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>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Abbrechen"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Überspringen"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Bildschirm drehen"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informationen zur Taskleiste"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Anleitung für Taskleiste eingeblendet"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Anleitung für Taskleiste geschlossen"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"App zur Seite ziehen, um zwei Apps gleichzeitig zu nutzen"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Langsam nach oben wischen, um die Taskleiste anzuzeigen"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"App-Vorschläge auf Grundlage deiner Nutzung erhalten"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Taskleiste automatisch ausblenden: Aktiviere in „Einstellungen“ die Bedienung über Gesten."</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Mehr Möglichkeiten mit der Taskleiste"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Weiter"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Zurück"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Schließen"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Fertig"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Startbildschirm"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Benachrichtigungen"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Schnelleinstellungen"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Taskleiste"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskleiste eingeblendet"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskleiste ausgeblendet"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigationsleiste"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Taskleiste immer anzeigen"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Navigationsmodus ändern"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Taskleisten-Teiler"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Nach oben / Nach links verschieben"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Nach unten / Nach rechts verschieben"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# weitere App anzeigen.}other{# weitere Apps anzeigen.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> und <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Hinzufügen einer App zum Desktop"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Abbrechen"</string>
</resources>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index baa0e65..ab9fe6d 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Οι προτεινόμενες εφαρμογές ενεργοποιήθηκαν"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Οι προτεινόμενες εφαρμογές είναι απενεργοποιημένες"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Εφαρμογή από πρόβλεψη: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Φροντίστε να σύρετε από το άκρο της δεξιάς ή της αριστερής πλευράς."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Σύρετε από το δεξί ή αριστερό άκρο προς το μέσο της οθόνης και απομακρύνετε το δάχτυλό σας."</string>
- <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Μάθατε πώς να σύρετε από τα δεξιά για επιστροφή. Στη συνέχεια, μάθετε πώς να κάνετε εναλλαγή εφαρμ."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Ολοκληρώσατε την κίνηση επιστροφής."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Φροντίστε να μην σύρετε υπερβολικά κοντά στο κάτω μέρος της οθόνης."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Περιστρέψτε τη συσκευή σας"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Περιστρέψτε τη συσκευή σας για να ολοκληρώσετε τον οδηγό πλοήγησης με κινήσεις"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Φροντίστε να σύρετε από το άκρο της δεξιάς ή της αριστερής πλευράς."</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Σύρετε από το δεξί ή το αριστερό άκρο προς το κέντρο της οθόνης και απομακρύνετε το δάχτυλό σας"</string>
+ <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Μάθατε πώς να σύρετε από τα δεξιά για επιστροφή. Τώρα, μάθετε πώς να κάνετε εναλλαγή εφαρμογών."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Ολοκληρώσατε την κίνηση επιστροφής"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Φροντίστε να μην σύρετε υπερβολικά κοντά στο κάτω μέρος της οθόνης"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Μεταβείτε στις Ρυθμίσεις για αλλαγή ευαισθ. κίνησης επιστρ."</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Σύρετε για επιστροφή"</string>
- <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Για να επιστρέψετε στην τελευτ. οθόνη, σύρετε από το αριστ. ή το δεξί άκρο προς το μέσο της οθόνης."</string>
+ <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Για να επιστρέψετε στην τελευταία οθόνη, σύρετε από το αριστερό ή το δεξί άκρο προς το μέσο της οθόνης."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Για να επιστρέψετε στην προηγούμενη οθόνη, σύρετε με 2 δάχτυλα από την αριστερή ή δεξιά άκρη προς τη μέση της οθόνης."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Φροντίστε να σύρετε προς τα επάνω από το κάτω άκρο της οθόνης."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Φροντίστε να μην κάνετε παύση προτού απομακρύνετε τα δάχτυλά σας."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Φροντίστε να σύρετε απευθείας προς τα επάνω."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Ολοκληρώσατε την κίνηση μετάβασης στην αρχική οθόνη. Στη συνέχεια, μάθετε πώς να κάνετε επιστροφή."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Ολοκληρώσατε την κίνηση μετάβασης στην αρχική οθόνη."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Επιστροφή"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Σύρετε από το αριστερό ή το δεξί άκρο προς το κέντρο της οθόνης"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Φροντίστε να σύρετε προς τα επάνω από το κάτω άκρο της οθόνης"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Φροντίστε να μην διακόψετε την κίνηση προτού απομακρύνετε τα δάχτυλά σας"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Φροντίστε να σύρετε ευθεία προς τα επάνω"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Ολοκληρώσατε την κίνηση μετάβασης στην αρχική οθόνη Στη συνέχεια, μάθετε την κίνηση επιστροφής."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Ολοκληρώσατε την κίνηση μετάβασης στην αρχική οθόνη"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Σύρετε για μετάβαση στην αρχική οθόνη"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Σύρετε προς τα πάνω από το κάτω μέρος της οθόνης. Αυτή η κίνηση σάς μεταφέρει πάντα στην αρχ. οθόνη."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Σύρετε από το κάτω άκρο προς τα πάνω με 2 δάχτ. Αυτή η κίνηση σάς μεταφέρει πάντα στην αρχική οθόνη."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Αρχική"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Για μετάβαση στην αρχική οθόνη ανά πάσα στιγμή, σύρετε προς τα επάνω από το κάτω μέρος της οθόνης"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Φροντίστε να σύρετε προς τα επάνω από το κάτω άκρο της οθόνης."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Δοκιμάστε να κρατήσετε περισσότερο το παράθυρο προτού απελευθερώσετε."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Φροντίστε να σύρετε απευθείας προς τα επάνω και έπειτα κάντε παύση."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Σύρετε προς τα επάνω από το κάτω μέρος της οθόνης"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Μπράβο!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Φροντίστε να σύρετε προς τα επάνω από το κάτω άκρο της οθόνης"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Δοκιμάστε να κρατήσετε περισσότερο το παράθυρο προτού το αφήσετε."</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Φροντίστε να σύρετε ευθεία προς τα επάνω και έπειτα σταματήστε την κίνηση"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Μάθατε πώς να χρησιμοποιείτε κινήσεις. Μεταβείτε στις Ρυθμίσεις για απενεργοποίηση των κινήσεων."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Ολοκληρώσατε την κίνηση εναλλαγής εφαρμογών."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Ολοκληρώσατε την κίνηση εναλλαγής εφαρμογών"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Σύρετε για εναλλαγή εφαρμογών"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Για εναλλαγή εφαρμογών, σύρετε προς τα πάνω από το κάτω μέρος της οθόνης, πατήστε παρατεταμένα και μετά αφήστε."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Για εναλλαγή μεταξύ εφαρμογών, σύρετε από κάτω προς τα πάνω με 2 δάχτ., κρατήστε και έπειτα αφήστε."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Εναλλαγή μεταξύ εφαρμογών"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Σύρετε προς τα πάνω από το κάτω μέρος της οθόνης, κρατήστε τα δάχτυλα επάνω στην οθόνη και μετά απομακρύνετέ τα"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Μπράβο!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Όλα είναι έτοιμα"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Τέλος"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Ρυθμίσεις"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Στιγμιότυπο οθόνης"</string>
<string name="action_split" msgid="2098009717623550676">"Διαχωρισμός"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Πατήστε άλλη εφαρμογή για διαχωρισμό οθόνης"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Έξοδος από την επιλογή διαχωρισμού οθόνης"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Επιλέξτε άλλη εφαρμογή για διαχωρισμό οθόνης"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Αυτή η ενέργεια δεν επιτρέπεται από την εφαρμογή ή τον οργανισμό σας."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Παράβλεψη οδηγού πλοήγησης;"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Παράβλεψη"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Περιστροφή οθόνης"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Πληροφορίες χρήσης της Γραμμής εργαλείων"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Η εκπαίδευση για τη γραμμή εργασιών εμφανίστηκε"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Η εκπαίδευση για τη γραμμή εργασιών έκλεισε"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Σύρετε μια εφαρμ. στην άκρη για χρήση δύο εφαρμ. ταυτόχρονα"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Σύρετε αργά προς τα πάνω για εμφάνιση της Γραμμής εργαλείων"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Λάβετε προτεινόμενες εφαρμογές με βάση τη ρουτίνα σας"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Ενεργοπ. την πλοήγηση με κινήσεις στις Ρυθμίσεις για αυτόμ. απόκρυψη της Γραμμής εργαλείων"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Κάντε περισσότερα με τη Γραμμή εργαλείων"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Επόμενο"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Πίσω"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Κλείσιμο"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Τέλος"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Αρχική σελίδα"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Ειδοποιήσεις"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Γρήγορες ρυθμ."</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Γραμμή εργαλείων"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Η γραμμή εργαλείων εμφανίζεται"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Η γραμμή εργαλείων είναι κρυφή"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Γραμμή πλοήγησης"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Εμφ. πάντα σε Γραμμή εργαλείων"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Αλλαγή τρόπου πλοήγησης"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Διαχωριστικό Γραμμής εργαλείων"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Μετακίνηση επάνω/αριστερά"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Μετακίνηση κάτω/δεξιά"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Εμφάνιση # ακόμα εφαρμογής.}other{Εμφάνιση # ακόμα εφαρμογών.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> και <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Γίνεται προσθήκη εφαρμογής στον υπολογιστή"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Ακύρωση"</string>
</resources>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index 4afe60e..878c062 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -44,33 +44,41 @@
<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_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="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotate your device"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Please rotate your device to complete the gesture navigation tutorial"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Make sure you swipe from the far-right or far-left edge"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"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\'ve learned how to swipe from the right to go back. Next, learn how to switch apps."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"You completed the go back gesture"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"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 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_tutorial_title" msgid="1944737946101059789">"Go back"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Swipe from the left or right edge to the middle of the screen"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Make sure you swipe up from the bottom edge of the screen"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Make sure you don\'t pause before letting go"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Make sure you swipe straight up"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"You completed the go home gesture. Next up, learn how to go back."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"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="home_gesture_tutorial_title" msgid="3126834347496917376">"Go home"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"To go to your home screen at any time, swipe up from the bottom of your 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="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_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="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Swipe up from the bottom of your screen"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Great work!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Make sure you swipe up from the bottom edge of the screen"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Try holding the window for longer before releasing"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Make sure that you swipe straight up, then pause"</string>
+ <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"You\'ve learned how to use gestures. To turn off gestures, go to Settings."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"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_tutorial_title" msgid="4125835002668708720">"Switch apps"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Swipe up from the bottom of your screen, hold, then release"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Well done!"</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>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tap another app to use split screen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Exit split screen selection"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Choose another app to use split screen"</string>
<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>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Skip"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Rotate screen"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Taskbar education"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Taskbar education appeared"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Taskbar education closed"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Drag an app to the side to use two apps at once"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Slow-swipe up to show the Taskbar"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Get app suggestions based on your routine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Turn on gesture navigation in Settings to auto-hide the Taskbar"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Do more with the taskbar"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Next"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Back"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Do more with the Taskbar"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Done"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifications"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Taskbar"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar hidden"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Always show Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Change navigation mode"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Taskbar divider"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Move to top/left"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to desktop"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
</resources>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index eeef677..eed32b3 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -44,33 +44,41 @@
<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 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="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotate your device"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Please rotate your device to complete the gesture navigation tutorial"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Make sure you swipe from the far-right or far-left edge"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"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 you don\'t swipe too close to the bottom of the screen."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"You completed the go back gesture"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"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 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="back_gesture_tutorial_title" msgid="1944737946101059789">"Go back"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Swipe from the left or right edge to the middle of the screen"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Make sure you swipe up from the bottom edge of the screen"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Make sure you don\'t pause before letting go"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Make sure you swipe straight up"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"You completed the go home gesture. Next up, learn how to go back."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"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 2 fingers from the bottom of the screen. This gesture always takes you to the Home screen."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Go home"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"To go to your home screen at any time, swipe up from the bottom of your 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 you swipe straight up, then pause."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Swipe up from the bottom of your screen"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Great job!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Make sure you swipe up from the bottom edge of the screen"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Try holding the window for longer before releasing"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"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_feedback_complete_without_follow_up" msgid="2903050864432331629">"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 2 fingers from the bottom of your screen, hold, then release."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Switch apps"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Swipe up from the bottom of your screen, hold, then release"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Well done!"</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>
@@ -80,13 +88,14 @@
<string name="allset_title" msgid="5021126669778966707">"All set!"</string>
<string name="allset_hint" msgid="459504134589971527">"Swipe up to go home"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Tap the home button to go to your home screen"</string>
- <string name="allset_description_generic" msgid="5385500062202019855">"You’re ready to start using your <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="allset_description_generic" msgid="5385500062202019855">"You\'re ready to start using your <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="default_device_name" msgid="6660656727127422487">"device"</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="8464310533320556058">"Tap another app to use split screen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Exit split screen selection"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Choose another app to use split screen"</string>
<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>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Skip"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Rotate screen"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Taskbar education"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Taskbar education appeared"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Taskbar education closed"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Drag an app to the side to use 2 apps at once"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Slow-swipe up to show the Taskbar"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Get app suggestions based on your routine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Turn on gesture navigation in Settings to auto-hide the Taskbar"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Do more with the Taskbar"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Next"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Back"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Done"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifications"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Taskbar"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar hidden"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Always show Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Change navigation mode"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Taskbar Divider"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Move to top/left"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to Desktop"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
</resources>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index 4afe60e..878c062 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -44,33 +44,41 @@
<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_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="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotate your device"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Please rotate your device to complete the gesture navigation tutorial"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Make sure you swipe from the far-right or far-left edge"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"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\'ve learned how to swipe from the right to go back. Next, learn how to switch apps."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"You completed the go back gesture"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"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 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_tutorial_title" msgid="1944737946101059789">"Go back"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Swipe from the left or right edge to the middle of the screen"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Make sure you swipe up from the bottom edge of the screen"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Make sure you don\'t pause before letting go"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Make sure you swipe straight up"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"You completed the go home gesture. Next up, learn how to go back."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"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="home_gesture_tutorial_title" msgid="3126834347496917376">"Go home"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"To go to your home screen at any time, swipe up from the bottom of your 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="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_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="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Swipe up from the bottom of your screen"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Great work!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Make sure you swipe up from the bottom edge of the screen"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Try holding the window for longer before releasing"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Make sure that you swipe straight up, then pause"</string>
+ <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"You\'ve learned how to use gestures. To turn off gestures, go to Settings."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"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_tutorial_title" msgid="4125835002668708720">"Switch apps"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Swipe up from the bottom of your screen, hold, then release"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Well done!"</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>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tap another app to use split screen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Exit split screen selection"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Choose another app to use split screen"</string>
<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>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Skip"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Rotate screen"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Taskbar education"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Taskbar education appeared"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Taskbar education closed"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Drag an app to the side to use two apps at once"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Slow-swipe up to show the Taskbar"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Get app suggestions based on your routine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Turn on gesture navigation in Settings to auto-hide the Taskbar"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Do more with the taskbar"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Next"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Back"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Do more with the Taskbar"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Done"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifications"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Taskbar"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar hidden"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Always show Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Change navigation mode"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Taskbar divider"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Move to top/left"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to desktop"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
</resources>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index 4afe60e..878c062 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -44,33 +44,41 @@
<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_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="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotate your device"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Please rotate your device to complete the gesture navigation tutorial"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Make sure you swipe from the far-right or far-left edge"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"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\'ve learned how to swipe from the right to go back. Next, learn how to switch apps."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"You completed the go back gesture"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"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 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_tutorial_title" msgid="1944737946101059789">"Go back"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Swipe from the left or right edge to the middle of the screen"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Make sure you swipe up from the bottom edge of the screen"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Make sure you don\'t pause before letting go"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Make sure you swipe straight up"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"You completed the go home gesture. Next up, learn how to go back."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"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="home_gesture_tutorial_title" msgid="3126834347496917376">"Go home"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"To go to your home screen at any time, swipe up from the bottom of your 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="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_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="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Swipe up from the bottom of your screen"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Great work!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Make sure you swipe up from the bottom edge of the screen"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Try holding the window for longer before releasing"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Make sure that you swipe straight up, then pause"</string>
+ <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"You\'ve learned how to use gestures. To turn off gestures, go to Settings."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"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_tutorial_title" msgid="4125835002668708720">"Switch apps"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Swipe up from the bottom of your screen, hold, then release"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Well done!"</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>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tap another app to use split screen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Exit split screen selection"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Choose another app to use split screen"</string>
<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>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Skip"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Rotate screen"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Taskbar education"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Taskbar education appeared"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Taskbar education closed"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Drag an app to the side to use two apps at once"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Slow-swipe up to show the Taskbar"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Get app suggestions based on your routine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Turn on gesture navigation in Settings to auto-hide the Taskbar"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Do more with the taskbar"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Next"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Back"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Do more with the Taskbar"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Done"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifications"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Taskbar"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar hidden"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Always show Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Change navigation mode"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Taskbar divider"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Move to top/left"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to desktop"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
</resources>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index 6aa8c82..ae825c1 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -44,33 +44,41 @@
<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 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="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotate your device"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Please rotate your device to complete the gesture navigation tutorial"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Make sure you swipe from the far-right or far-left edge"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"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 you don\'t swipe too close to the bottom of the screen."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"You completed the go back gesture"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"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 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="back_gesture_tutorial_title" msgid="1944737946101059789">"Go back"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Swipe from the left or right edge to the middle of the screen"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Make sure you swipe up from the bottom edge of the screen"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Make sure you don\'t pause before letting go"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Make sure you swipe straight up"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"You completed the go home gesture. Next up, learn how to go back."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"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 2 fingers from the bottom of the screen. This gesture always takes you to the Home screen."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Go home"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"To go to your home screen at any time, swipe up from the bottom of your 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 you swipe straight up, then pause."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Swipe up from the bottom of your screen"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Great job!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Make sure you swipe up from the bottom edge of the screen"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Try holding the window for longer before releasing"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"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_feedback_complete_without_follow_up" msgid="2903050864432331629">"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 2 fingers from the bottom of your screen, hold, then release."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Switch apps"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Swipe up from the bottom of your screen, hold, then release"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Well done!"</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>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tap another app to use split screen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Exit split screen selection"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Choose another app to use split screen"</string>
<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>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Skip"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Rotate screen"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Taskbar education"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Taskbar education appeared"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Taskbar education closed"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Drag an app to the side to use 2 apps at once"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Slow-swipe up to show the Taskbar"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Get app suggestions based on your routine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Turn on gesture navigation in Settings to auto-hide the Taskbar"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Do more with the Taskbar"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Next"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Back"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Done"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifications"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Taskbar"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar hidden"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Always show Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Change navigation mode"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Taskbar Divider"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Move to top/left"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to Desktop"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
</resources>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index 9bb4fc6..cf5d6e9 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -23,7 +23,7 @@
<string name="recent_task_option_freeform" msgid="48863056265284071">"Formato libre"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No hay elementos recientes"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configuración de uso de la app"</string>
- <string name="recents_clear_all" msgid="5328176793634888831">"Borrar todo"</string>
+ <string name="recents_clear_all" msgid="5328176793634888831">"Cerrar todo"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Apps recientes"</string>
<string name="task_view_closed" msgid="9170038230110856166">"Se cerró la tarea"</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>
@@ -44,49 +44,58 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Sugerencias de apps habilitadas"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Las sugerencias de aplicaciones están inhabilitadas"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predicción de app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Asegúrate de deslizar desde el extremo derecho o izquierdo."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Asegúrate de deslizar desde borde izquierdo o derecho hacia centro de la pantalla y, luego, soltar."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rota el dispositivo"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rota el dispositivo para completar el instructivo de la navegación por gestos"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Asegúrate de deslizar desde el extremo derecho o izquierdo"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Recuerda deslizar desde el borde izquierdo o derecho hacia el centro de la pantalla y, luego, soltar"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Ya sabes deslizar el dedo desde la derecha para ir atrás. Ahora, descubre cómo cambiar de app."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Completaste el gesto \"Atrás\"."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Asegúrate de no hacerlo muy cerca de la parte inferior de la pantalla."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Completaste el gesto para ir atrás"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Asegúrate de no deslizar muy cerca de la parte inferior de la pantalla"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Cambia sensibilidad de gesto \"Atrás\" en Configuración"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Desliza para ir atrás"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Desliza el dedo desde el borde derecho o izquierdo hasta el centro para volver a la última pantalla."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Para volver la pantalla anterior, desliza 2 dedos desde el borde izquierdo o derecho hacia el centro de la pantalla."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Desliza el dedo hacia arriba desde el borde inferior de la pantalla."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Asegúrate de no detenerte antes de soltarlo."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Desliza el dedo directamente hacia arriba."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Completaste el gesto para ir a la página principal. Ahora, descubre cómo ir hacia atrás."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Completaste el gesto para ir a la página principal."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Volver atrás"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Desliza desde el borde izquierdo o derecho hacia el centro de la pantalla"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Asegúrate de deslizar hacia arriba desde el borde inferior de la pantalla"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Asegúrate de no detenerte antes de soltar"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Asegúrate de deslizar el dedo directamente hacia arriba"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Completaste el gesto para ir a la página principal. A continuación, obtén información para volver."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Completaste el gesto para ir a la página principal"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Desliza para ir a la página principal"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Desliza hacia arriba desde la parte inferior de la pantalla. Este gesto te llevará a la pantalla principal."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Desliza hacia arriba desde la parte inferior. Este gesto te llevará siempre a la pantalla principal."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Ir a la pantalla principal"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Para ir a la pantalla principal en cualquier momento, desliza desde la parte inferior de la pantalla"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Desliza el dedo hacia arriba desde el borde inferior de la pantalla."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Prueba mantener presionada la ventana más tiempo antes de soltarla."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Desliza el dedo directamente hacia arriba y luego detente."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Ve a la pantalla principal"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Desliza hacia arriba desde la parte inferior de la pantalla"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"¡Bien hecho!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Asegúrate de deslizar hacia arriba desde el borde inferior de la pantalla"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Intenta mantener presionada la ventana más tiempo antes de soltarla"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Asegúrate de deslizar directamente hacia arriba y detenerte"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Ya sabes cómo usar los gestos. Para desactivarlos, ve a Configuración."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Completaste el gesto para cambiar de app."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Completaste el gesto para cambiar de app"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Desliza para cambiar de app"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Desliza el dedo hacia arriba desde la parte inferior, mantenlo presionado y suéltalo."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Para alternar entre apps, desliza el dedo hacia arriba, mantén presionado y, luego, suelta."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Cambia de app"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Desliza hacia arriba desde la parte inferior de la pantalla, mantenla presionada y, luego, suelta"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"¡Bien hecho!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Listo"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Listo"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Configuración"</string>
- <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Reintentar"</string>
+ <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Vuelve a intentarlo"</string>
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"¡Genial!"</string>
<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="459504134589971527">"Desliza el dedo hacia arriba para ir a la página principal"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Presiona el botón de inicio para ir a la pantalla principal"</string>
- <string name="allset_description_generic" msgid="5385500062202019855">"Ya puedes comenzar a usar <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="allset_description_generic" msgid="5385500062202019855">"Ya puedes comenzar a usar tu <xliff:g id="DEVICE">%1$s</xliff:g>."</string>
<string name="default_device_name" msgid="6660656727127422487">"dispositivo"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Configuración de navegación del sistema"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Compartir"</string>
<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="8464310533320556058">"Presiona otra app para usar la pantalla dividida"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Salir de la selección de pantalla dividida"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Elige otra app para usar la pantalla dividida"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"La app o tu organización no permiten realizar esta acción"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"¿Omitir el instructivo de navegación?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Omitir"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Girar pantalla"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Información sobre la barra de tareas"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Se abrió la barra de herramientas Educación"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Se cerró la barra de herramientas Educación"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Arrastra una app a un lado para usar 2 apps a la vez"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Desliza despacio hacia arriba para ver la Barra de tareas"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Recibe sugerencias de aplicaciones basadas en tu rutina"</string>
- <string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Activa la navegación por gestos en la conf. para ocultar automát. la Barra de tareas"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Haz más con la Barra de tareas"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Siguiente"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Atrás"</string>
+ <string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Activa la navegación por gestos en la Configuración y la Barra de tareas se ocultará sola"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Aprovecha mejor la Barra de tareas"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Cerrar"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Listo"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Botón de inicio"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notificaciones"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Config. rápida"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Barra de tareas"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tareas visible"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tareas oculta"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegación"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Ver siempre la Barra de tareas"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Cambiar el modo de navegación"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Divisor de la Barra de tareas"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover a la parte superior o izquierda"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover a la parte inferior o derecha"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # app más.}other{Mostrar # apps más.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> y <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Agregando app al escritorio"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
</resources>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 5a95416..d40780c 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Sugerencias de aplicaciones habilitadas"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Las sugerencias de aplicaciones están inhabilitadas"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Aplicación sugerida: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Asegúrate de deslizar el dedo desde el borde derecho o izquierdo de la pantalla."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Asegúrate de deslizar el dedo desde el borde derecho o izquierdo de la pantalla hasta el centro y luego levántalo."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Gira el dispositivo"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Gira el dispositivo para completar el tutorial de navegación por gestos"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Asegúrate de deslizar desde el borde derecho o izquierdo de la pantalla"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Asegúrate de deslizar desde el borde derecho o izquierdo de la pantalla hasta el centro y soltar"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Ya sabes deslizar el dedo desde la derecha para ir atrás. Descubre ahora cómo cambiar de aplicación."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Has completado el gesto para volver."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"No deslices el dedo demasiado cerca de la parte inferior de la pantalla."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Has completado el gesto para volver"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"No deslices demasiado cerca de la parte inferior de la pantalla"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Para cambiar la sensibilidad del gesto, ve a Ajustes"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Desliza para ir atrás"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Para volver a la última pantalla, desliza el dedo desde un lateral de la pantalla hasta el centro."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Para volver a la pantalla anterior, desliza dos dedos desde el borde izquierdo o derecho hacia el centro de la pantalla."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Asegúrate de deslizar el dedo hacia arriba desde el borde inferior de la pantalla."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"No hagas ninguna pausa antes de levantar el dedo."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Asegúrate de deslizar el dedo hacia arriba."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Has completado el gesto para ir a la pantalla de inicio. Ahora, descubre cómo ir hacia atrás."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Has completado el gesto para ir a la pantalla de inicio."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Volver"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Desliza desde el borde izquierdo o derecho de la pantalla hasta el centro"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Asegúrate de deslizar hacia arriba desde el borde inferior de la pantalla"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Asegúrate de no hacer ninguna pausa antes de soltar"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Asegúrate de deslizar hacia arriba"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Has completado el gesto para ir a la pantalla de inicio. Ahora, descubre cómo volver."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Has completado el gesto para ir a la pantalla de inicio"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Desliza para ir a la pantalla de inicio"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Desliza hacia arriba desde la parte inferior de la pantalla. Este gesto siempre te lleva a la pantalla de inicio."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Desliza dos dedos hacia arriba desde la parte inferior de la pantalla. Si haces este gesto, siempre irás a la pantalla de inicio."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Ir a Inicio"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Para ir a la pantalla de inicio, desliza el dedo hacia arriba desde la parte inferior de la pantalla"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Asegúrate de deslizar el dedo hacia arriba desde el borde inferior de la pantalla."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Prueba a mantener pulsada la ventana durante más tiempo antes de soltarla."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Asegúrate de deslizar el dedo directamente hacia arriba y luego mantenlo pulsado."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Ir a inicio"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Desliza hacia arriba desde la parte inferior de la pantalla"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"¡Bien hecho!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Asegúrate de deslizar hacia arriba desde el borde inferior de la pantalla"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Prueba a mantener pulsada la ventana durante más tiempo antes de soltarla"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Asegúrate de deslizar directamente hacia arriba y luego detenerte"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Ya sabes cómo utilizar gestos. Para desactivarlos, ve a Ajustes."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Has completado el gesto para cambiar de aplicación."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Has completado el gesto para cambiar de aplicación"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Desliza el dedo para cambiar de aplicación"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Para cambiar de aplicación, desliza el dedo hacia arriba desde el borde inferior, mantenlo pulsado y suéltalo"</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Para cambiar de aplicación, desliza el dedo hacia arriba desde el borde inferior, mantenlo pulsado y suéltalo."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Para cambiar de app, desliza dos dedos hacia arriba desde el borde inferior, mantén pulsada la pantalla y, luego, suelta."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Cambiar de aplicación"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Desliza hacia arriba desde la parte inferior de la pantalla, mantenla pulsada y suelta el dedo."</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"¡Muy bien!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Todo listo"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Hecho"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Ajustes"</string>
@@ -86,7 +94,8 @@
<string name="action_share" msgid="2648470652637092375">"Compartir"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Hacer captura"</string>
<string name="action_split" msgid="2098009717623550676">"Dividir"</string>
- <string name="toast_split_select_app" msgid="8464310533320556058">"Toca otra app para usar la pantalla dividida"</string>
+ <string name="toast_split_select_app" msgid="8464310533320556058">"Toca otra aplicación para usar la pantalla dividida"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Salir de la selección de pantalla dividida"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Elige otra app para usar la pantalla dividida"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"No puedes hacerlo porque la aplicación o tu organización no lo permiten"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"¿Saltar tutorial de navegación?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Saltar"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Girar la pantalla"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Información sobre la barra de tareas"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Ha aparecido una nota sobre la barra de tareas"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Nota sobre la barra de tareas cerrada"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Arrastra una aplicación hacia un lado para usar 2 a la vez"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Desliza hacia arriba lentamente para ver la barra de tareas"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Obtén sugerencias de aplicaciones basadas en tu rutina"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Activa la navegación por gestos en Ajustes para ocultar la barra de tareas automáticamente"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Sácale más partido a la barra de tareas"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Siguiente"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Atrás"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Cerrar"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Hecho"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Inicio"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notificaciones"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Ajustes rápidos"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Barra de tareas"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tareas visible"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tareas oculta"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegación"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Ver siempre Barra de Tareas"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Cambiar el modo de navegación"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Divisor de Barra de Tareas"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover arriba/a la izquierda"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover abajo/a la derecha"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # aplicación más.}other{Mostrar # aplicaciones más.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> y <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Añadiendo aplicación al ordenador"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
</resources>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 1c14660..176741a 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Rakenduste soovitused on lubatud"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Rakenduste soovitused on keelatud"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Ennustatud rakendus: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Pühkige kindlasti parem- või vasakpoolsest servast."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Pühkige ekraanikuva paremast või vasakust servast keskele ja eemaldage sõrm."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Pöörake seadet"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Pöörake seadet, et liigutustega navigeerimise õpetused lõpetada"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Pühkige kindlasti parem- või vasakpoolsest servast"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Pühkige ekraani paremast või vasakust servast keskele ja eemaldage sõrm"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Õppisite, kuidas tagasiliikumiseks paremalt pühkida. Nüüd vaadake, kuidas rakenduste vahel vahetada."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Tegite tagasiliikumise liigutuse."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Veenduge, et te ei pühiks liiga ekraanikuva allosa lähedalt."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Tegite tagasiliikumise liigutuse"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Veenduge, et te ei pühiks liiga ekraani allosa lähedalt."</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Tagasiliigutuse tundlikkuse muutmiseks avage menüü Seaded"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Tagasiliikumiseks pühkige"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Eelmisele ekraanikuvale naasmiseks pühkige vasakust või paremast servast ekraanikuva keskele."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Eelmisele ekraanikuvale naasmiseks pühkige vasakust või paremast servast kahe sõrmega ekraanikuva keskele."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Pühkige kindlasti ekraanikuva alumisest servast üles."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Veenduge, et te enne vabastamist liigutust ei peataks."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Pühkige kindlasti otse üles."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Tegite avakuvale minemise liigutuse. Järgmisena vaadake, kuidas minna tagasi."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Tegite avakuvale minemise liigutuse."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Tagasiliikumine"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Pühkige ekraani paremast või vasakust servast keskele."</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Pühkige kindlasti ekraani alumisest servast üles."</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Veenduge, et te enne vabastamist liigutust ei peataks."</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Pühkige kindlasti otse üles."</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Tegite avakuvale minemise liigutuse. Järgmisena vaadake, kuidas minna tagasi."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Tegite avakuvale minemise liigutuse"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Pühkige avakuvale minemiseks"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Pühkige ekraani alaosast üles. See liigutus viib teid alati tagasi avakuvale."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Pühkige ekraanikuva alumisest servast 2 sõrmega üles. See liigutus viib teid alati tagasi avakuvale."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Avalehele"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Mis tahes ajal avakuvale liikumiseks pühkige ekraanikuva allosast üles"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Pühkige kindlasti ekraanikuva alumisest servast üles."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Hoidke sõrme aknal pisut kauem, enne kui vabastate."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Pühkige kindlasti otse üles, seejärel peatuge."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Avakuvale"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Pühkige ekraani allosast üles."</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Väga hea!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Pühkige kindlasti ekraani alumisest servast üles."</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Hoidke sõrme aknal pisut kauem, enne kui vabastate"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Pühkige kindlasti otse üles, seejärel peatuge"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Õppisite liigutusi kasutama. Liigutuste väljalülitamiseks avage seaded."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Tegite rakenduste vahel vahetamise liigutuse."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Tegite rakenduste vahel vahetamise liigutuse"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Pühkige rakenduste vahetamiseks"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Rakenduste vahel vahetamiseks pühkige ekraanikuva alaosast üles, hoidke ja seejärel vabastage."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Rakenduste vahel vahetamiseks pühkige kuva alaosast kahe sõrmega üles, hoidke ja seejärel vabastage."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Rakenduste vahetamine"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Pühkige ekraani allosast üles, hoidke ja seejärel vabastage."</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Hästi tehtud!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Valmis"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Valmis"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Seaded"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Ekraanipilt"</string>
<string name="action_split" msgid="2098009717623550676">"Eralda"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Jagatud ekraanikuva kasutamiseks puudutage muud rakendust"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Jagatud ekraanikuva valikust väljumine"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Valige jagatud ekraanikuva jaoks muu rakendus"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Rakendus või teie organisatsioon on selle toimingu keelanud"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Kas jätta navigeerimise õpetused vahele?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Jäta vahele"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Pöörake ekraani"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Tegumiriba tutvustus"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Tegumiriba juhised kuvati"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Tegumiriba juhised on suletud"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"2 rakenduse korraga kasutamiseks lohistage rakendus kõrvale"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Tegumiriba kuvamiseks pühkige aeglaselt üles"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Hankige oma rutiini põhjal rakenduste soovitusi"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Tegumiriba automaatseks peitmiseks lülitage seadetes sisse liigutustega navigeerimine"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Tehke tegumiriba abil enamat"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Järgmine"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Tagasi"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Sule"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Valmis"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Avaleht"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Märguanded"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Kiirseaded"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Tegumiriba"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Tegumiriba on kuvatud"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Tegumiriba on peidetud"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigeerimisriba"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Kuva tööriistariba alati"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Navigeerimisrežiimi muutmine"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Tegumiriba jagaja"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Teisalda üles/vasakule"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Teisalda alla/paremale"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Kuva veel # rakendus.}other{Kuva veel # rakendust.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ja <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Rakenduse lisamine arvutisse"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Tühista"</string>
</resources>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index a920ba5..0d6c664 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Gaituta daude aplikazioen iradokizunak"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Desgaituta daude aplikazioen iradokizunak"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Iragarritako aplikazioa: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Ziurtatu hatza pantailaren eskuineko edo ezkerreko ertzetik hasten zarela pasatzen."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Ziurtatu hatza pantailaren eskuineko edo ezkerreko ertzetik erdialdera pasatzen eta altxatzen duzula."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Biratu gailua"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Keinu bidezko nabigazioaren tutoriala osatzeko, biratu gailua"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Ziurtatu hatza pantailaren eskuineko edo ezkerreko ertzetik hasten zarela pasatzen"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Ziurtatu hatza pantailaren eskuineko edo ezkerreko ertzetik erdialdera pasatzen duzula eta ondoren hatza jasotzen duzula"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Hatza eskuinetik pasatuta atzera egiten ikasi duzu. Jarraian, ikasi aplikazioa aldatzen."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Ikasi duzu atzera egiteko keinua."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Ziurtatu hatza ez duzula pantailaren behealdetik gertuegi pasatzen."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Ikasi duzu atzera egiteko keinua"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Ziurtatu hatza ez duzula pasatzen pantailaren behealdetik gertuegi"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Keinuaren sentikortasuna aldatzeko, joan ezarpenetara"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Pasatu hatza atzera egiteko"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Aurreko pantailara itzultzeko, pasatu hatza pantailaren ezkerreko edo eskuineko ertzetik erdialdera."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Aurreko pantailara itzultzeko, pasatu bi hatz pantailaren ezkerreko edo eskuineko ertzetik erdialdera."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Ziurtatu hatza pantailaren beheko ertzetik gora pasatzen duzula."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Ziurtatu askatu aurretik ez duzula hatza gelditzen."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Ziurtatu hatza zuzen pasatzen duzula gora."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Ikasi duzu hasierako pantailara joateko keinua. Jarraian, ikasi atzera egiten."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Ikasi duzu hasierako pantailara joateko keinua."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Egin atzera"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Pasatu hatza pantailaren eskuineko edo ezkerreko ertzetik erdialdera"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Ziurtatu hatza pantailaren beheko ertzetik gora pasatzen duzula"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Ziurtatu ez duzula mugimendua gelditzen askatu arte"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Ziurtatu hatza zuzen pasatzen duzula gora"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Ikasi duzu hasierako pantailara joateko keinua. Orain, ikasi atzera egiten."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Ikasi duzu hasierako pantailara joateko keinua"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Pasatu hatza hasierako pantailara joateko"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Pasatu hatza pantailaren behealdetik gora. Keinu horrek hasierako pantailara eramango zaitu beti."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Pasatu bi hatz pantailaren behealdetik gora. Hasierako pantailara eramango zaitu beti keinu horrek."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Joan hasierako pantailara"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Hasierako pantailara joateko, pasatu hatza pantailaren behealdetik gora"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Ziurtatu hatza pantailaren beheko ertzetik gora pasatzen duzula."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Eduki sakatuta leihoa luzaroago hatza altxatu aurretik."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Ziurtatu hatza zuzen pasatzen duzula gora; ondoren, gelditu."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Pasatu hatza pantailaren behealdetik gora"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Bikain!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Ziurtatu hatza pantailaren beheko ertzetik gora pasatzen duzula"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Eduki sakatuta leihoa luzaroago hatza jaso aurretik"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Ziurtatu hatza zuzen pasatzen duzula gora; ondoren, gelditu"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Ikasi duzu keinuak erabiltzen. Keinuak desaktibatzeko, joan ezarpenetara."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Ikasi duzu aplikazioa aldatzeko keinua."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Ikasi duzu aplikazioz aldatzeko keinua"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Pasatu hatza aplikazioa aldatzeko"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Aplikazio batetik bestera joateko, pasatu hatza pantailaren behealdetik gora, eduki pantaila sakatuta eta altxatu hatza."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Aplikazio batetik bestera joateko, pasatu bi hatz pantailaren behealdetik gora, eduki pantaila sakatuta eta altxatu hatza."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Aldatu aplikazioa"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Pasatu hatza pantailaren behealdetik gora, eduki sakatuta une batez, eta jaso hatza"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Oso ongi!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Dena prest"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Eginda"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Ezarpenak"</string>
@@ -87,6 +95,7 @@
<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="8464310533320556058">"Sakatu beste aplikazio bat pantaila zatitzeko"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Irten Pantaila zatitzea eginbidearen hautapenetik"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Pantaila zatitua ikusteko, aukeratu beste aplikazio bat"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikazioak edo erakundeak ez du eman ekintza hori gauzatzeko baimena"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Nabigazio-tutoriala saltatu nahi duzu?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Saltatu"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Biratu pantaila"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Zereginen barra erabiltzeko argibideak"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Agertu egin da zereginen barraren tutoriala"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Itxi egin da zereginen barraren tutoriala"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Bi aplikazio batera erabiltzeko, arrastatu bat albo batera"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Zereginen barra ikusteko, pasatu hatza motel gora"</string>
- <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Jaso erabileran oinarritutako aplikazioen iradokizunak"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Zereginen barra ikusteko, pasatu hatza gora poliki"</string>
+ <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Jaso aplikazioen iradokizunak erabileran oinarrituta"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Zereginen barra automatikoki ezkutatzeko, aktibatu keinu bidezko nabigazioa ezarpenetan"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Egin gauza gehiago zereginen barrarekin"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Hurrengoa"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Atzera"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Itxi"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Eginda"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Hasiera"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Jakinarazpenak"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Ezarpen bizkorrak"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Zereginen barra"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Zereginen barra ikusgai dago"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Zereginen barra itxita dago"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Nabigazio-barra"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Erakutsi beti zereginen barra"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Aldatu nabigazio modua"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Zereginen barraren zatitzailea"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Eraman gora, ezkerretara"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Eraman behera, eskuinetara"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Erakutsi beste # aplikazio.}other{Erakutsi beste # aplikazio.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> eta <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Aplikazioa mahaigainean gehitzen"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Utzi"</string>
</resources>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index c074720..85b4862 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"«پیشنهاد برنامه» فعال است"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"«پیشنهاد برنامه» غیرفعال است"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"برنامه پیشبینیشده: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"دقت کنید که از انتهای لبه سمت راست یا سمت چپ تند بکشید."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"دقت کنید که از لبه سمت راست یا سمت چپ تند به وسط صفحه بکشید و رها کنید."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"دستگاهتان را بچرخانید"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"لطفاً برای تکمیل آموزش گامبهگام پیمایش اشارهای، دستگاهتان را بچرخانید"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"دقت کنید که از انتهای لبه سمت راست یا سمت چپ تند بکشید"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"دقت کنید که از لبه سمت راست یا سمت چپ تند به وسط صفحه بکشید و رها کنید"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"یاد گرفتید چگونه برای رفتن به عقب از سمت راست تند بکشید. مورد بعدی، با نحوه جابهجا شدن بین برنامهها آشنا شوید."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"اشاره برگشتن را تکمیل کردید."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"دقت کنید که موقع تند کشیدن بیشاز حد به پایین صفحه نزدیک نشوید."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"اشاره برگشتن را تکمیل کردید"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"دقت کنید که موقع تند کشیدن، بیشاز حد به پایین صفحه نزدیک نشوید"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"برای تغییر حساسیت اشاره برگشت، به «تنظیمات» بروید"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"تند بکشید تا بهعقب برگردید"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"برای برگشتن به صفحه آخر، از لبه سمت چپ یا راست تند به وسط صفحه بکشید."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"برای برگشتن به صفحه قبلی، با ۲ انگشت از لبه سمت چپ یا راست تند بهوسط صفحه بکشید."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"دقت کنید که از لبه پایینی صفحه تند به بالا بکشید."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"دقت کنید که تا قبلاز رها کردن، کشیدن را متوقف نکنید."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"دقت کنید که مستقیماً تند به بالا بکشید."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"اشاره رفتن به «صفحه اصلی» را تکمیل کردید. مورد بعدی، با نحوه برگشتن به عقب آشنا شوید."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"اشاره رفتن به «صفحه اصلی» را تکمیل کردید."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"برگشتن"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"از لبه سمت راست یا سمت چپ تند به وسط صفحه بکشید"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"دقت کنید که از لبه پایینی صفحه تند به بالا بکشید"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"دقت کنید که قبلاز رها کردن مکث نکنید"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"دقت کنید که مستقیماً تند به بالا بکشید"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"اشاره رفتن به صفحه اصلی را تکمیل کردید. مورد بعدی، با نحوه برگشتن به عقب آشنا شوید."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"اشاره رفتن به صفحه اصلی را تکمیل کردید"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"تند کشیدن برای رفتن به صفحه اصلی"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"از پایین صفحه، تند بهسمت بالا بکشید. این اشاره همیشه شما را به صفحه اصلی میبرد."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"با ۲ انگشت از پایین صفحه تند بهبالا بکشید. این اشاره همیشه شما را به صفحه اصلی میبرد."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"رفتن به صفحه اصلی"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"برای رفتن به صفحه اصلی در هر زمانی، از پایین صفحه تند بهبالا بکشید"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"دقت کنید که از لبه پایینی صفحه تند به بالا بکشید."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"سعی کنید قبلاز رها کردن، پنجره را برای مدت طولانیتری نگه دارید."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"دقت کنید که مستقیماً تند به بالا بکشید و سپس توقف کنید."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"از پایین صفحه تند به بالا بکشید"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"عالی است!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"دقت کنید که از لبه پایینی صفحه تند به بالا بکشید"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"قبلاز رها کردن پنجره، آن را برای مدت طولانیتری نگه دارید"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"دقت کنید که مستقیماً تند به بالا بکشید و سپس توقف کنید"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"با نحوه استفاده از اشارهها آشنا شدید. برای خاموش کردن اشارهها، به «تنظیمات» بروید."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"اشاره جابهجا شدن بین برنامهها را تکمیل کردید."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"اشاره جابهجایی بین برنامهها را تکمیل کردید"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"برای جابهجا شدن بین برنامهها، تند بهبالا بکشید"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"برای جابهجا شدن بین برنامهها، از پایین صفحه تند بهبالا بکشید، نگه دارید، و سپس رها کنید."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"برای جابهجایی بین برنامهها، با ۲ انگشت از پایین صفحه تند بهبالا بکشید، نگه دارید، و سپس رها کنید."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"جابهجایی بین برنامهها"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"از پایین صفحه تند بهبالا بکشید، نگه دارید، سپس رها کنید"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"آفرین!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"همه چیز آماده است"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"تمام"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"تنظیمات"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"نماگرفت"</string>
<string name="action_split" msgid="2098009717623550676">"دونیمه"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"زدن روی برنامهای دیگر برای استفاده از صفحه دونیمه"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"خروج از انتخاب صفحهٔ دونیمه"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"انتخاب برنامهای دیگر برای استفاده از صفحه دونیمه"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"برنامه یا سازمان شما اجازه نمیدهد این کنش انجام شود."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"آموزش گامبهگام پیمایش رد شود؟"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"رد شدن"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"چرخاندن صفحه"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"آموزش نوار وظیفه"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"پانل آموزشی نوار وظیفه نمایان شد"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"پانل آموزشی نوار وظیفه بسته شد"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"برای استفاده همزمان از ۲ برنامه، برنامهای را بهکنار بکشید"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"برای استفاده همزمان از ۲ برنامه، یک برنامه را به کناری بکشید"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"برای نمایش «نوار وظیفه»، انگشتتان را آهسته بهبالا بکشید"</string>
- <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"دریافت «پیشنهادهای برنامه» براساس روال همیشگی"</string>
+ <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"براساس روالهایتان، پیشنهاد برنامه دریافت کنید"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"برای پنهانسازی خودکار «نوار وظیفه»، پیمایش اشارهای را در «تنظیمات» روشن کنید"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"کارهای بیشتر با «نوار وظیفه» انجام دهید"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"بعدی"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"برگشت"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"با «نوار وظیفه» میتوانید کارهای بیشتر انجام دهید"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"بستن"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"تمام"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"صفحه اصلی"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"اعلانها"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"تنظیمات فوری"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"نوار وظیفه"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"نوار وظیفه نمایان است"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"نوار وظیفه پنهان است"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"نوار پیمایش"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"نوار وظیفه همیشه نشان داده شود"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"تغییر حالت پیمایش"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"جداکننده نوار وظیفه"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"انتقال به بالا/ چپ"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"انتقال به پایین/ راست"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{نمایش # برنامه دیگر.}one{نمایش # برنامه دیگر.}other{نمایش # برنامه دیگر.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> و <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"درحال افزودن برنامه به رایانه"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"لغو"</string>
</resources>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index 3b6d0e5..60d6618 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Sovellusehdotukset käytössä"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Sovellusehdotukset on poistettu käytöstä"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Ennakoitu sovellus: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Muista pyyhkäistä aivan oikeasta tai vasemmasta reunasta."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Pyyhkäise näytön oikeasta tai vasemmasta reunasta keskelle ja päästä irti."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Käännä laite"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Käännä laite, niin voit katsoa esittelyn eleillä navigoinnista"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Pyyhkäise aivan oikeasta tai vasemmasta reunasta"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Pyyhkäise näytön oikeasta tai vasemmasta reunasta keskelle ja päästä irti"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Osaat palata takaisin pyyhkäisemällä oikeasta reunasta. Opettele seuraavaksi vaihtamaan sovellusta."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Olet oppinut Takaisin-eleen."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Varo, ettet pyyhkäise liian lähellä alareunaa."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Olet oppinut takaisin-eleen"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Varo, ettet pyyhkäise liian lähellä alareunaa"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Voit muuttaa Takaisin-eleen herkkyyttä asetuksista"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Siirry takaisin pyyhkäisemällä"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Voit palata edelliseen näkymään pyyhkäisemällä näytön vasemmasta tai oikeasta reunasta keskelle."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Palaa takaisin edelliselle näytölle pyyhkäisemällä kahdella sormella vasemmasta tai oikeasta reunasta näytön keskikohtaan."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Pyyhkäise ylös näytön alareunasta."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Varo keskeyttämästä ennen kuin päästät irti."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Muista pyyhkäistä suoraan ylöspäin."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Olet oppinut aloitusnäytölle palaamisen eleen. Opettele seuraavaksi siirtymään takaisin."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Olet oppinut aloitusnäytölle palaamisen eleen."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Edelliseen siirtyminen"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Pyyhkäise vasemmasta tai oikeasta reunasta näytön keskelle"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Pyyhkäise ylös näytön alareunasta"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Varo pysähtymästä ennen kuin päästät irti"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Pyyhkäise suoraan ylöspäin"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Olet oppinut aloitusnäytölle palaamiseleen. Opettele seuraavaksi siirtymään takaisin."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Olet oppinut aloitusnäytölle palaamiseleen"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Siirry aloitusnäytölle pyyhkäisemällä"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Pyyhkäise ylös näytön alareunasta. Tämä ele vie sinut aina aloitusnäytölle."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Pyyhkäise näytön alareunasta ylöspäin kahdella sormella. Tämä ele vie sinut aina aloitusnäytölle."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Aloitusnäytölle siirtyminen"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Voit siirtyä aloitusnäytölle milloin tahansa pyyhkäisemällä ylös näytön alareunasta"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Pyyhkäise ylös näytön alareunasta."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Kokeile pitää ikkunaa painettuna pidempään ennen kuin päästät irti."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Muista pyyhkäistä suoraan ylöspäin ja keskeytä sitten."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Pyyhkäise ylös näytön alareunasta"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Hienoa!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Pyyhkäise ylös näytön alareunasta"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Kokeile pitää ikkunaa painettuna pidempään ennen kuin päästät irti"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Muista pyyhkäistä suoraan ylöspäin ja pysähdy sitten"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Olet oppinut käyttämään eleitä. Jos haluat laittaa eleet pois päältä, avaa Asetukset."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Olet oppinut sovellusten vaihtamiseleen."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Olet oppinut sovellusten vaihtamiseleen"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Vaihda sovellusta pyyhkäisemällä"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Voit vaihtaa sovelluksesta toiseen pyyhkäisemällä ylöspäin näytön alareunasta ja päästämällä sitten irti."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Vaihda sovelluksia pyyhkäisemällä ylös näytön alareunasta kahdella sormella ja päästä sitten irti."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Sovelluksen vaihtaminen"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Pyyhkäise ylöspäin näytön alareunasta ja päästä irti"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Hienoa!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Valmista"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Valmis"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Asetukset"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Kuvakaappaus"</string>
<string name="action_split" msgid="2098009717623550676">"Jaa"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Avaa jaettu näyttö napauttamalla toista sovellusta"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Poistu jaetun näytön valinnasta"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Käytä jaettua näyttöä valitsemalla toinen sovellus"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Sovellus tai organisaatio ei salli tätä toimintoa"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ohitetaanko navigointiohje?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Ohita"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Käännä näyttö"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Tehtäväpalkin ohje"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Tehtäväpalkin ohje näkyvissä"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Tehtäväpalkin ohje suljettu"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Vedä sovellus sivuun, niin voit käyttää samalla 2 sellaista"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Vedä sovellus sivuun, ja voit käyttää kahta sovellusta"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Näytä tehtäväpalkki pyyhkäisemällä ylös hitaasti"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Sovellussuosituksia käytön perusteella"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Laita eleillä navigointi päälle Asetuksista Tehtäväpalkin piilottamiseksi automaattisesti"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Vinkkejä tehtäväpalkin tehokkaampaan käyttöön"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Seuraava"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Takaisin"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Sulje"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Valmis"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Etusivu"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Ilmoitukset"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Pika-asetukset"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Tehtäväpalkki"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Tehtäväpalkki näkyvissä"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Tehtäväpalkki piilotettu"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigointipalkki"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Näytä tehtäväpalkki aina"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Vaihda navigointitilaa"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Tehtäväpalkin jakaja"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Siirrä ylös tai vasemmalle"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Siirrä alas tai oikealle"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Näytä # muu sovellus.}other{Näytä # muuta sovellusta.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ja <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Sovelluksen lisääminen työpöydälle"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Peru"</string>
</resources>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 2aee419..a98e9c5 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -44,37 +44,45 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Les suggestions d\'applications sont activées"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Les suggestions d\'applications sont désactivées"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Application prédite : <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Assurez-vous de balayer l\'écran à partir de l\'extrémité droite ou gauche."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Balayez l\'écran de l\'extrémité droite ou gauche jusqu\'au centre de l\'écran, puis levez le doigt."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Faites pivoter votre appareil"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Veuillez faire pivoter votre appareil pour terminer le tutoriel de navigation par gestes"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Assurez-vous de balayer l\'écran à partir de l\'extrémité droite ou gauche"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Assurez-vous de balayer l\'écran à partir de l\'extrémité droite ou gauche vers le centre, puis allons-y"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Vous avez appris à balayer de la droite pour revenir en arrière. Apprenez comment changer d\'appli."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Vous avez appris le geste de retour en arrière."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Assurez-vous de ne pas balayer trop près du bas de l\'écran."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Vous avez appris le geste de retour en arrière"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Assurez-vous de ne pas balayer trop près du bas de l\'écran"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Modifiez la sensibilité du geste de retour dans Paramètres"</string>
- <string name="back_gesture_intro_title" msgid="19551256430224428">"Balayer l\'écran pour revenir en arrière"</string>
+ <string name="back_gesture_intro_title" msgid="19551256430224428">"Balayez l\'écran pour revenir en arrière"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Pour revenir à l\'écran précédent, balayez l\'écran de l\'extrémité gauche ou droite vers le centre."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Pour revenir à l\'écran précédent, balayez l\'écran avec deux doigts du bord gauche ou droit jusqu\'au centre."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Assurez-vous de balayer l\'écran à partir de l\'extrémité inférieure vers le haut."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Assurez-vous de ne pas interrompre le geste avant de lever le doigt."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Assurez-vous de balayer l\'écran en ligne droite vers le haut."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Vous avez appris le geste de retour à l\'écran d\'accueil. Maintenant, apprenez à revenir en arrière."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Vous avez appris le geste de retour à l\'écran d\'accueil."</string>
- <string name="home_gesture_intro_title" msgid="836590312858441830">"Balayer pour revenir à l\'écran d\'accueil"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Retour"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Balayez l\'écran à partir du bord gauche ou droit de l\'écran vers le centre"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Assurez-vous de balayer l\'écran à partir de l\'extrémité inférieure vers le haut"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Assurez-vous de ne pas interrompre le geste avant de lever le doigt"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Assurez-vous de balayer l\'écran en ligne droite vers le haut"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Vous avez appris le geste de retour à l\'écran d\'accueil. Maintenant, apprenez à revenir en arrière."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Vous avez appris le geste de retour à l\'écran d\'accueil"</string>
+ <string name="home_gesture_intro_title" msgid="836590312858441830">"Balayez pour revenir à l\'écran d\'accueil"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Balayez l\'écran du bas vers le haut. Ce geste vous ramène toujours à l\'écran d\'accueil."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Balayez l\'écran de bas en haut avec deux doigts. Ce geste vous ramène toujours à l\'écran d\'accueil."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Retour à la page d\'accueil"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Pour accéder à votre écran d\'accueil à tout moment, balayez l\'écran du bas vers le haut"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Assurez-vous de balayer l\'écran à partir de l\'extrémité inférieure vers le haut."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Essayez de tenir la fenêtre plus longtemps avant de relâcher."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Assurez-vous de balayer l\'écran vers le haut, puis de faire une pause."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Balayez votre écran du bas vers le haut"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Super!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Assurez-vous de balayer l\'écran à partir de l\'extrémité inférieure vers le haut"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Essayez de tenir la fenêtre plus longtemps avant de relâcher"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Assurez-vous de balayer l\'écran vers le haut, puis de faire une pause"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Vous avez appris à utiliser les gestes. Pour les désactiver, accédez au menu Paramètres."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Vous avez appris le geste de changement d\'application."</string>
- <string name="overview_gesture_intro_title" msgid="2902054412868489378">"Balayer pour basculer entre les applications"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Pour passer d\'une application à l\'autre, balayez l\'écran de bas en haut, maintenez la pression, puis relâchez."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Vous avez appris le geste de changement d\'application"</string>
+ <string name="overview_gesture_intro_title" msgid="2902054412868489378">"Balayez pour basculer entre les applications"</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Pour changer d\'application, balayez l\'écran de bas en haut, maintenez le doigt dessus, puis relâchez-le."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Pour changer d\'appli, balayez l\'écran de bas en haut avec deux doigts, maintenez-les et relâchez-les."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Changer d\'application"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Balayez l\'écran de bas en haut, maintenez le doigt en place, puis relâchez-le"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Bien joué!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Terminé"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"OK"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Paramètres"</string>
- <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Réessayer"</string>
+ <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Réessayez"</string>
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Bien!"</string>
<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>
@@ -85,8 +93,9 @@
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Paramètres de navigation du système"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Partager"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Capture d\'écran"</string>
- <string name="action_split" msgid="2098009717623550676">"Séparé"</string>
+ <string name="action_split" msgid="2098009717623550676">"Partager"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Toucher une autre appli pour partager l\'écran"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Quitter la sélection d\'écran divisé"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Choisir une autre application pour utiliser l\'écran partagé"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"L\'application ou votre organisation n\'autorise pas cette action"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ignorer le tutoriel sur la navigation?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Ignorer"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Faire pivoter l\'écran"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informations sur la barre des tâches"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"La barre des tâches éducatives s\'est affichée"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"La barre des tâches éducatives est fermée"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Pour utiliser deux applis, faites-les glisser vers le côté"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Balayez lent. vers le haut pour afficher la barre des tâches"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Obtenez des suggestions d\'applis en fonction de vos routines"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Activez la navigation par gestes dans Paramètres pour masquer auto. la barre des tâches"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Faites-en plus avec la barre des tâches"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Suivant"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Retour"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Fermer"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"OK"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Accueil"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifications"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Paramètres rapides"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Barre des tâches"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barre des tâches affichée"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barre des tâches masquée"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barre de navigation"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Touj. afficher barre des tâches"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Changer de mode de navigation"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Séparateur de la barre des tâches"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Déplacer vers le coin supérieur gauche de l\'écran"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Déplacer vers le coin inférieur droit de l\'écran"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afficher # autre application.}one{Afficher # autre application.}other{Afficher # autres applications.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> et <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Ajout de l\'application au bureau en cours…"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuler"</string>
</resources>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index b67266c..2e2e0f1 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Suggestions d\'applications activées"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Les suggestions d\'applications sont désactivées"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Application prédite : <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Veillez à bien balayer l\'écran depuis le bord gauche ou droit."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Balayez bien l\'écran depuis le bord gauche ou droit jusqu\'au centre avant de relever le doigt."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Faire pivoter l\'appareil"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Veuillez faire pivoter votre appareil pour effectuer le tutoriel de navigation par gestes"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Veillez à bien balayer l\'écran depuis le bord gauche ou droit"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Balayez bien l\'écran depuis le bord gauche ou droit jusqu\'au centre avant de relever le doigt"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Vous savez revenir en arrière en balayant depuis la droite. Apprenez à passer d\'une appli à l\'autre."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Vous avez appris le geste pour revenir en arrière."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Veillez à ne pas balayer l\'écran trop près du bas."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Vous avez appris le geste pour revenir en arrière"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Veillez à ne pas balayer l\'écran trop près du bas"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Modifiez la sensibilité du geste retour dans les paramètres"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Balayez l\'écran pour revenir en arrière"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Pour revenir à l\'écran précédent, balayez l\'écran depuis le bord droit ou gauche jusqu\'au centre."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Pour revenir au dernier écran, balayez l\'écran avec deux doigts en partant du bord gauche ou droit vers le milieu."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Veillez à balayer l\'écran de bas en haut."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Veillez à ne pas marquer de pause dans votre geste avant de relever le doigt."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Veillez à balayer l\'écran vers le haut."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Vous savez désormais revenir à l\'écran d\'accueil. Apprenez maintenant à revenir en arrière."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Vous avez appris le geste pour revenir à l\'écran d\'accueil."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Retour"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Balayez l\'écran à partir du bord gauche ou droit jusqu\'au centre"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Veillez à balayer vers le haut depuis le bord inférieur de l\'écran"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Veillez à ne pas marquer de pause dans votre geste avant de relever le doigt"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Veillez à balayer l\'écran vers le haut en ligne droite"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Vous avez appris le geste pour revenir à l\'écran d\'accueil. Apprenez ensuite à revenir en arrière."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Vous avez appris le geste pour revenir à l\'écran d\'accueil"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Balayez pour revenir à l\'écran d\'accueil"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Balayez l\'écran de bas en haut. Ce geste vous ramènera toujours à l\'écran d\'accueil."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Balayez l\'écran de bas en haut avec 2 doigts. Ce geste vous ramènera toujours à l\'écran d\'accueil."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Retour à l\'accueil"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Pour accéder à l\'écran d\'accueil à tout moment, balayez l\'écran du bas vers le haut"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Veillez à balayer l\'écran de bas en haut."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Essayez d\'appuyer plus longtemps sur la fenêtre avant de relever le doigt."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Veillez à balayer l\'écran vers le haut, puis à marquer une pause."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Balayez l\'écran de bas en haut"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Bravo !"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Veillez à balayer vers le haut depuis le bord inférieur de l\'écran"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Essayez d\'appuyer plus longtemps sur la fenêtre avant de relever le doigt"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Veillez à balayer l\'écran vers le haut, puis à marquer une pause"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Vous avez appris à utiliser les gestes. Pour les désactiver, accédez aux paramètres."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Vous avez appris le geste pour passer d\'une appli à l\'autre."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Vous avez appris le geste pour passer d\'une appli à l\'autre"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Balayez pour passer d\'une appli à l\'autre"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Pour changer d\'appli, balayez l\'écran de bas en haut, appuyez de manière prolongée et relâchez."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Pour changer d\'appli, balayez l\'écran de bas en haut avec deux doigts, maintenez appuyé et relâchez."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Changer d\'appli"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Balayez l\'écran de bas en haut, appuyez de manière prolongée, puis relâchez"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Bravo !"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Vous avez terminé"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"OK"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Paramètres"</string>
@@ -86,7 +94,8 @@
<string name="action_share" msgid="2648470652637092375">"Partager"</string>
<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="8464310533320556058">"Appuyez sur autre appli pour utiliser écran partagé"</string>
+ <string name="toast_split_select_app" msgid="8464310533320556058">"Appuyez sur autre appli pour l\'écran partagé"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Quitter la sélection de l\'écran partagé"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Sélect. autre appli pour utiliser l\'écran partagé"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Cette action n\'est pas autorisée par l\'application ou par votre organisation"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ignorer le tutoriel de navigation ?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Passer"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Faire pivoter l\'écran"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Fonctionnement de la barre des tâches"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Infos sur la barre des tâches affichées"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Infos sur la barre des tâches fermées"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Faites glisser une appli sur le côté pour utiliser 2 applis"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Faites glisser une appli sur le côté pour en utiliser 2 à la fois"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Balayez lentement vers haut pour afficher barre des tâches"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Obtenez des suggestions d\'applis basées sur vos habitudes"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Activez la navigation par gestes dans paramètres pour masquage auto de la barre des tâches"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Exploitez les possibilités de la barre des tâches"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Suivant"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Retour"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Faites-en plus avec la barre des tâches"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Fermer"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"OK"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Accueil"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifications"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Réglages rapides"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Barre des tâches"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barre des tâches affichée"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barre des tâches masquée"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barre de navigation"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Toujours voir barre des tâches"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Modifier le mode de navigation"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Séparateur de barre des tâches"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Déplacer en haut ou à gauche"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Déplacer en bas ou à droite"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afficher # autre appli.}one{Afficher # autre appli.}other{Afficher # autre applis.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> et <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Ajout de l\'appli au bureau"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuler"</string>
</resources>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index e4f5de2..11479e1 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"As suxestións de aplicacións están activadas"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"As suxestións de aplicacións están desactivadas"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Aplicación predita: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Asegúrate de pasar o dedo desde o bordo dereito ou esquerdo."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Asegúrate de pasar o dedo desde o bordo dereito ou esquerdo ata o medio da pantalla e avanza."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Xira o dispositivo"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Xira o dispositivo para completar o titorial de navegación con xestos"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Asegúrate de pasar o dedo desde o bordo dereito ou esquerdo"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Asegúrate de pasar o dedo desde o bordo dereito ou esquerdo ata o medio da pantalla e levantalo"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Aprendiches a pasar o dedo desde a dereita para volver. Agora, aprende a cambiar de aplicación."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Completaches o xesto de volver á última pantalla."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Asegúrate de non pasar o dedo demasiado preto da parte inferior da pantalla."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Completaches o xesto de volver á última pantalla"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Asegúrate de non pasar o dedo demasiado preto da parte inferior da pantalla"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Podes cambiar a sensibilidade do xesto en Configuración"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Pasa o dedo para volver"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Para volver á última pantalla, pasa o dedo cara ao medio desde o bordo dereito ou esquerdo."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Para volver á última pantalla, pasa 2 dedos desde o bordo esquerdo ou o dereito ata a metade da pantalla."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Asegúrate de pasar o dedo cara arriba desde o bordo inferior da pantalla."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Asegúrate de non facer unha pausa antes de avanzar."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Asegúrate de pasar o dedo cara arriba cun movemento vertical."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Completaches o xesto de ir ao inicio. O próximo é aprender a volver á última pantalla."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Completaches o xesto de ir ao inicio."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Volver atrás"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Pasa o dedo desde o bordo esquerdo ou dereito ata o medio da pantalla"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Asegúrate de pasar o dedo cara arriba desde o bordo inferior da pantalla"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Asegúrate de non facer unha pausa antes de levantar o dedo"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Asegúrate de pasar o dedo cara arriba cun movemento vertical"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Completaches o xesto de ir ao inicio. O próximo é aprender a volver á última pantalla."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Completaches o xesto de ir ao inicio"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Pasa o dedo para ir ao inicio"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Pasa o dedo cara arriba desde a parte inferior da pantalla. Ao facelo, irás á pantalla de inicio."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Pasa 2 dedos desde a parte inferior da pantalla. Ao facelo, sempre irás á pantalla de inicio."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Ir á pantalla de inicio"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Para ir á pantalla de inicio, pasa o dedo cara arriba desde a parte inferior da pantalla"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Asegúrate de pasar o dedo cara arriba desde o bordo inferior da pantalla."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Proba a manter premida a pantalla máis tempo antes de soltala."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Asegúrate de pasar o dedo cara arriba cun movemento vertical. Despois, fai unha pausa."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Pasa o dedo cara arriba desde a parte inferior da pantalla"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Moi ben!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Asegúrate de pasar o dedo cara arriba desde o bordo inferior da pantalla"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Proba a manter premida a ventá máis tempo antes de levantar o dedo"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Asegúrate de pasar o dedo cara arriba cun movemento vertical. Despois, fai unha pausa"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Aprendiches a usar os xestos. Para desactivalos, vai a Configuración."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Completaches o xesto para cambiar de aplicación."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Completaches o xesto para cambiar de aplicación"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Pasa o dedo para cambiar de aplicación"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Para cambiar de aplicación, pasa o dedo cara arriba desde a parte inferior da pantalla, mantén premido e levanta o dedo."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Para cambiar de app, pasa 2 dedos cara arriba desde abaixo, mantén premida a pantalla e levántaos."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Pasar dunha aplicación a outra"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Pasa o dedo cara arriba desde a parte inferior da pantalla, mantena premida e sepárao"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Ben feito!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Todo listo"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Feito"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Configuración"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Facer captura"</string>
<string name="action_split" msgid="2098009717623550676">"Dividir"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Para usar a pantalla dividida, toca outra app"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Saír da selección de pantalla dividida"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Escolle outra app para usar a pantalla dividida"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"A aplicación ou a túa organización non permite realizar esta acción"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Queres omitir o titorial de navegación?"</string>
@@ -95,17 +104,13 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Omitir"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Xira a pantalla"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Información sobre a función Barra de tarefas"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Panel de información de barra de tarefas aberto"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Panel de información de barra de tarefas pechado"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Arrastra unha aplicación cara a un lado para usar dúas á vez"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Pasa o dedo amodo cara arriba para ver a barra de tarefas"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Obtén suxestións de aplicacións en función da túa rutina"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Activa navegación con xestos en Configuración e oculta automaticamente a barra de tarefas"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Tira máis proveito da barra de tarefas"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Seguinte"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Atrás"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Pechar"</string>
- <string name="taskbar_edu_done" msgid="6880178093977704569">"Feito"</string>
+ <string name="taskbar_edu_done" msgid="6880178093977704569">"Listo"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Inicio"</string>
<string name="taskbar_button_a11y" msgid="5241161324875094465">"Accesibilidade"</string>
<string name="taskbar_button_back" msgid="8558862226461164514">"Atrás"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notificacións"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Configuración rápida"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Barra de tarefas"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Estase mostrando a barra de tarefas"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Non se está mostrando a barra de tarefas"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegación"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Manter Barra de tarefas"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Cambiar modo de navegación"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Divisor da Barra de tarefas"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover á parte superior ou á esquerda"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover á parte inferior ou á dereita"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # aplicación máis.}other{Mostrar # aplicacións máis.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Engadindo aplicación ao ordenador"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
</resources>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 03bbfe9..ef44fb9 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ઍપના સુઝાવો ચાલુ છે"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ઍપના સુઝાવો બંધ છે"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"પૂર્વાનુમાનિત ઍપ: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"ખાતરી કરો કે તમે એકદમ દૂરની જમણી કે ડાબી કિનારીએથી સ્વાઇપ કરો છો."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"ખાતરી કરો કે તમે જમણી કે ડાબી કિનારીએથી સ્ક્રીનના મધ્ય ભાગ સુધી સ્વાઇપ કરો છો અને આંગળી ઊંચકી લો છો."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"તમારા ડિવાઇસને ફેરવો"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"સંકેતથી નૅવિગેશન ટ્યૂટૉરિઅલ પૂર્ણ કરવા માટે કૃપા કરીને તમારા ડિવાઇસને ફેરવો"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ખાતરી કરો કે તમે એકદમ દૂરની જમણી કે ડાબી કિનારીએથી સ્વાઇપ કરો છો"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"ખાતરી કરો કે તમે જમણી કે ડાબી કિનારીએથી સ્ક્રીનના મધ્ય ભાગ સુધી સ્વાઇપ કરો છો અને આંગળી ઊંચકી લો છો"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"પાછળ જવા જમણેથી કેવી રીતે સ્વાઇપ કરવું એ તમે શીખી લીધું છે. હવે પછી, ઍપ સ્વિચ કરવાની રીત જાણો."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"તમે પાછા જવાનો સંકેત પૂર્ણ કર્યો છે."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"ખાતરી કરો કે તમારાથી સ્ક્રીનની એકદમ નીચેની કિનારીની ખૂબ નજીક સુધી સ્વાઇપ ન થઈ જાય."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"તમે પાછા જવાનો સંકેત પૂર્ણ કર્યો છે"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"ખાતરી કરો કે તમારાથી સ્ક્રીનની એકદમ નીચેની કિનારીની ખૂબ નજીક સુધી સ્વાઇપ ન થઈ જાય"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"પાછા જવાના સંકેતની સંવેદિતા બદલવા માટે, સેટિંગમાં જાઓ"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"પાછળ જવા માટે સ્વાઇપ કરો"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"છેલ્લી સ્ક્રીન પર પાછા જવા, ડાબી કે જમણી કિનારીએથી સ્ક્રીનના મધ્ય ભાગ સુધી સ્વાઇપ કરો."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"છેલ્લી સ્ક્રીન પર પાછા જવા માટે, 2 આંગળી વડે ડાબી કે જમણી કિનારીએથી સ્ક્રીનના મધ્ય ભાગ સુધી સ્વાઇપ કરો."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"ખાતરી કરો કે તમે સ્ક્રીનની નીચેની કિનારીએથી ઉપરની તરફ સ્વાઇપ કરો છો."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"ખાતરી કરો કે તમે આંગળી ઊંચકી લેતા પહેલાં સ્વાઇપ કરવાનું થોભાવતા નથી."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"ખાતરી કરો કે તમે સીધું ઉપરની તરફ સ્વાઇપ કરો છો."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"તમે હોમ સ્ક્રીન પર પાછા જવાનો સંકેત પૂર્ણ કર્યો છે. હવે પછી, પાછા જવાની રીત વિશે જાણો."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"તમે હોમ સ્ક્રીન પર પાછા જવાનો સંકેત પૂર્ણ કર્યો છે."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"પાછા જાઓ"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"જમણી કે ડાબી કિનારીએથી સ્ક્રીનના મધ્ય ભાગ સુધી સ્વાઇપ કરો"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"ખાતરી કરો કે તમે સ્ક્રીનની નીચેની કિનારીએથી ઉપરની તરફ સ્વાઇપ કરો છો"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"ખાતરી કરો કે તમે આંગળી ઊંચકી લેતા પહેલાં સ્વાઇપ કરવાનું થોભાવતા નથી"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"ખાતરી કરો કે તમે સીધું ઉપરની તરફ સ્વાઇપ કરો છો"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"તમે હોમ સ્ક્રીન પર જવાનો સંકેત પૂર્ણ કર્યો. હવે પછી, પાછા જવાની રીત વિશે જાણો."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"તમે હોમ સ્ક્રીન પર જવાનો સંકેત પૂર્ણ કર્યો"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"હોમ સ્ક્રીન પર જવા માટે સ્વાઇપ કરો"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"તમારી સ્ક્રીનના નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરો. આ સંકેત તમને હંમેશાં હોમ સ્ક્રીન પર લઈ જાય છે."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"2 આંગળી વડે સ્ક્રીનના સૌથી નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરો. આ સંકેત તમને હંમેશાં હોમ સ્ક્રીન પર લઈ જાય છે."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"હોમ પર જાઓ"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"કોઈપણ સમયે તમારી હોમ સ્ક્રીન પર જવા માટે, તમારી સ્ક્રીનની સૌથી નીચેની બાજુએથી ઉપરની તરફ સ્વાઇપ કરો"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"ખાતરી કરો કે તમે સ્ક્રીનની નીચેની કિનારીએથી ઉપરની તરફ સ્વાઇપ કરો છો."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"તમારી આંગળી ઊંચકતા પહેલાં તેને વિન્ડો પર થોડી વધારે વાર માટે દબાવી રાખવાનો પ્રયાસ કરો."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"ખાતરી કરો કે તમે સીધું ઉપર સ્વાઇપ કરો છો, પછી થોભી જાઓ છો."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"તમારી સ્ક્રીનની સૌથી નીચેથી ઉપરની તરફ સ્વાઇપ કરો"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"ખૂબ સરસ કામ!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"ખાતરી કરો કે તમે સ્ક્રીનની નીચેની કિનારીએથી ઉપરની તરફ સ્વાઇપ કરો છો"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"તમારી આંગળી ઊંચકતા પહેલાં તેને વિન્ડો પર થોડી વધારે વાર માટે દબાવી રાખવાનો પ્રયાસ કરો"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"ખાતરી કરો કે તમે સીધું ઉપર સ્વાઇપ કરો છો, પછી થોભી જાઓ છો"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"સંકેતોનો ઉપયોગ કરવાની રીત વિશે તમે જાણ્યું. સંકેતો બંધ કરવા, સેટિંગમાં જાઓ."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"તમે ઍપ સ્વિચ કરવાનો સંકેત પૂર્ણ કર્યો છે."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"તમે ઍપ સ્વિચ કરવાનો સંકેત પૂર્ણ કર્યો."</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"ઍપ સ્વિચ કરવા સ્વાઇપ કરો"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"એક ઍપ પરથી બીજી ઍપ પર સ્વિચ કરવા માટે, તમારી સ્ક્રીનના નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરીને, થોડીવાર દબાવી રાખો, પછી છોડી દો."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"એક ઍપ પરથી બીજી ઍપ પર સ્વિચ કરવા માટે, 2 આંગળી વડે તમારી સ્ક્રીનના સૌથી નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરીને, થોડીવાર દબાવી રાખો, પછી છોડી દો."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"ઍપ સ્વિચ કરો"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"તમારી સ્ક્રીનના નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરીને થોડીવાર દબાવી રાખો પછી છોડી દો"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"વાહ!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"બધું સેટ થઈ ગયું"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"થઈ ગયું"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"સેટિંગ"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"સ્ક્રીનશૉટ"</string>
<string name="action_split" msgid="2098009717623550676">"વિભાજિત કરો"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"વિભાજિત સ્ક્રીન વાપરવા, કોઈ અન્ય ઍપ પર ટૅપ કરો"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"\'સ્ક્રીનને વિભાજિત કરો\' પસંદગીમાંથી બહાર નીકળો"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"સ્ક્રીન વિભાજનનો ઉપયોગ કરવા કોઈ અન્ય ઍપ પસંદ કરો"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ઍપ કે તમારી સંસ્થા દ્વારા આ ક્રિયા કરવાની મંજૂરી નથી"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"નૅવિગેશન ટ્યૂટૉરિઅલ છોડી દઈએ?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"છોડો"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"સ્ક્રીન ફેરવો"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ટાસ્કબાર વિશે શિક્ષણ"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"ટાસ્કબારનું શિક્ષણ આપતી પૅનલ દેખાય છે"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"ટાસ્કબારનું શિક્ષણ આપતી પૅનલ બંધ થઈ છે"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"એક સાથે 2 ઍપનો ઉપયોગ કરવા માટે, ઍપને ખેંચીને બાજુ પર લઈ જાઓ"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"ટાસ્કબાર બતાવવા માટે ઉપરની તરફ ધીમેથી સ્વાઇપ કરો"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"તમારા રૂટિનના આધારે ઍપના સુઝાવો મેળવો"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"ટાસ્કબારને ઑટોમૅટિક રીતે છુપાવવા માટે સેટિંગમાં સંકેતથી નૅવિગેશનની સુવિધા ચાલુ કરો"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"ટાસ્કબાર વડે બીજું ઘણું કરો"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"આગળ"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"પાછળ"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"બંધ કરો"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"થઈ ગયું"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"હોમ"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"નોટિફિકેશન"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"ઝડપી સેટિંગ"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"ટાસ્કબાર"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ટાસ્કબાર બતાવવામાં આવ્યો"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ટાસ્કબાર છુપાવવામાં આવ્યો"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"નૅવિગેશન બાર"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"હંમેશાં ટાસ્કબાર બતાવો"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"નૅવિગેશન મોડ બદલો"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ટાસ્કબાર વિભાજક"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"સૌથી ઉપર ડાબી બાજુએ ખસેડો"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"સૌથી નીચે જમણી બાજુએ ખસેડો"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{વધુ # ઍપ બતાવો.}one{વધુ # ઍપ બતાવો.}other{વધુ # ઍપ બતાવો.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> અને <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"ડેસ્કટૉપ પર ઍપ ઉમેરી રહ્યાં છીએ"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"રદ કરો"</string>
</resources>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index c13b7e5..28551ad 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="recent_task_option_pin" msgid="7929860679018978258">"पिन करना"</string>
+ <string name="recent_task_option_pin" msgid="7929860679018978258">"पिन करें"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"फ़्रीफ़ॉर्म"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"हाल ही में इस्तेमाल किया गया कोई ऐप्लिकेशन नहीं है"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ऐप्लिकेशन इस्तेमाल की सेटिंग"</string>
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"सुझाए गए ऐप्लिकेशन की सुविधा चालू है"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"सुझाए गए ऐप्लिकेशन की सुविधा बंद है"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"सुझाया गया ऐप्लिकेशन: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"पक्का करें कि आप स्क्रीन की दाईं या बाईं ओर के बिलकुल किनारे से स्वाइप कर रहे हों."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"स्क्रीन के दाएं या बाएं किनारे से स्क्रीन के बीच तक स्वाइप करें और अपनी उंगली उठा लें."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"अपना डिवाइस घुमाएं"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"जेस्चर वाले नेविगेशन से जुड़े ट्यूटोरियल को पूरा करने के लिए अपने डिवाइस को घुमाएं"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"स्क्रीन पर बिलकुल दाएं या बाएं किनारे से स्वाइप करें"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"स्क्रीन पर दाएं या बाएं किनारे से बीच तक स्वाइप करें और फिर अपनी उंगली को स्क्रीन से हटा दें"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"आपने स्क्रीन के दाएं किनारे से स्वाइप करके, पिछली स्क्रीन पर वापस जाने का तरीका सीख लिया है. अब, एक ऐप से दूसरे ऐप पर जाने का तरीका सीखें."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"आपने पेज पर पीछे ले जाने वाले हाथ के जेस्चर (हाव-भाव) के बारे में जान लिया है."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"देख लें कि आप स्क्रीन पर बिलकुल नीचे तक स्वाइप न कर रहे हों."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"आपने जान लिया है कि हाथ का जेस्चर इस्तेमाल करके पिछली स्क्रीन पर वापस कैसे जाएं"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"स्क्रीन पर बिलकुल नीचे तक स्वाइप न करें"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"\'सेटिंग\' में जाकर, पीछे जाने के लिए इस्तेमाल होने वाले हाथ के जेस्चर (हाव-भाव) की संवेदनशीलता बदलें"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"पिछली स्क्रीन पर वापस जाने के लिए स्वाइप करें"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"पिछली स्क्रीन पर वापस जाने के लिए, स्क्रीन के बाएं या दाएं किनारे से बीचों-बीच तक स्वाइप करें."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"पिछली स्क्रीन पर वापस जाने के लिए, स्क्रीन के बाएं या दाएं किनारे से स्क्रीन के बीच तक दो उंगलियों से स्वाइप करें."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"देख लें कि आप स्क्रीन के निचले किनारे से ऊपर की ओर स्वाइप कर रहे हों."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"देख लें कि आप स्क्रीन से अपनी उंगली उठाने से पहले, इसे कहीं न रोक रहे हों."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"देख लें कि आप ऊपर की ओर बिलकुल सीधे स्वाइप कर रहे हों."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"आपने होम स्क्रीन पर ले जाने वाले हाथ के जेस्चर के बारे में जान लिया है. अब, वापस जाने का तरीका जानें."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"आपने होम स्क्रीन पर ले जाने वाले हाथ के जेस्चर (हाव-भाव) के बारे में जान लिया है."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"पिछली स्क्रीन पर वापस जाना"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"स्क्रीन पर बाएं या दाएं किनारे से बीच तक स्वाइप करें"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"स्क्रीन पर निचले किनारे से ऊपर की ओर स्वाइप करें"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"उंगली हटाने से पहले उसे स्क्रीन पर कहीं न रोकें"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"स्क्रीन पर सीधे ऊपर की ओर स्वाइप करें"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"आपने जान लिया कि हाथ का जेस्चर इस्तेमाल करके होम स्क्रीन पर कैसे जाएं. अब वापस जाने का तरीका जानें."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"आपने जान लिया है कि हाथ का जेस्चर इस्तेमाल करके होम स्क्रीन पर कैसे जाएं"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"होम स्क्रीन पर जाने के लिए स्वाइप करें"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"स्क्रीन पर नीचे से ऊपर की ओर स्वाइप करें. हाथ का यह जेस्चर आपको हमेशा होम स्क्रीन पर ले जाता है."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"स्क्रीन के सबसे नीचे से ऊपर की ओर 2 उंगलियों से स्वाइप करें. जेस्चर हमेशा होम स्क्रीन पर ले जाता है."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"होम स्क्रीन पर जाएं"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"किसी भी समय फ़ोन की होम स्क्रीन पर जाने के लिए, फ़ोन पर सबसे नीचे से ऊपर की ओर स्वाइप करें"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"देख लें कि आप स्क्रीन के निचले किनारे से ऊपर की ओर स्वाइप कर रहे हों."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"कोशिश करें कि स्क्रीन से उंगली उठाने से पहले, इसे कुछ देर स्क्रीन पर दबाकर रखें."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"देख लें कि आप स्क्रीन पर ऊपर की तरफ़, बिलकुल सीधे स्वाइप कर रहे हों और फिर रुकें."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"होम स्क्रीन पर जाना"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"स्क्रीन पर सबसे नीचे से ऊपर की ओर स्वाइप करें"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"बहुत बढ़िया!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"स्क्रीन पर निचले किनारे से ऊपर की ओर स्वाइप करें"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"उंगली हटाने से पहले स्क्रीन को देर तक दबाकर रखें"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"स्क्रीन पर सीधे ऊपर की ओर स्वाइप करें और फिर रुकें"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"आपने हाथ के जेस्चर इस्तेमाल करने सीख लिए हैं. जेस्चर बंद करने के लिए, सेटिंग में जाएं."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"आपने एक ऐप्लिकेशन से दूसरे पर जाने के लिए इस्तेमाल होने वाले हाथ के जेस्चर के बारे में जान लिया है."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"आपने जान लिया है कि हाथ का जेस्चर इस्तेमाल करके ऐप्लिकेशन के बीच स्विच कैसे करें"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"एक ऐप्लिकेशन से दूसरे पर जाने के लिए स्वाइप करें"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"एक ऐप से दूसरे पर जाने के लिए, स्क्रीन पर नीचे से ऊपर की ओर स्वाइप करें, दबाकर रखें, और फिर छोड़ दें."</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"एक ऐप से दूसरे पर जाने के लिए स्क्रीन पर नीचे से ऊपर की ओर स्वाइप करें, दबाकर रखें, और फिर छोड़ दें."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"इन ऐप के बीच स्विच करने के लिए, दो उंगलियों से नीचे से ऊपर स्वाइप करें, होल्ड करें, और फिर छोड़ें."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"ऐप्लिकेशन के बीच स्विच करना"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"अपनी स्क्रीन पर सबसे नीचे से ऊपर की ओर स्वाइप करें, स्क्रीन को दबाकर रखें, और फिर छोड़ दें"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"बहुत खूब!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"आप पूरी तरह तैयार हैं"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"हो गया"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"सेटिंग"</string>
@@ -80,30 +88,27 @@
<string name="allset_title" msgid="5021126669778966707">"हो गया!"</string>
<string name="allset_hint" msgid="459504134589971527">"होम पेज पर जाने के लिए, ऊपर की ओर स्वाइप करें"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"होम स्क्रीन पर जाने के लिए, होम बटन पर टैप करें"</string>
- <string name="allset_description_generic" msgid="5385500062202019855">"आप <xliff:g id="DEVICE">%1$s</xliff:g> को इस्तेमाल करने के लिए तैयार हैं"</string>
+ <string name="allset_description_generic" msgid="5385500062202019855">"अब <xliff:g id="DEVICE">%1$s</xliff:g> इस्तेमाल के लिए तैयार है"</string>
<string name="default_device_name" msgid="6660656727127422487">"डिवाइस"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"सिस्टम नेविगेशन सेटिंग"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"शेयर करें"</string>
<string name="action_screenshot" msgid="8171125848358142917">"स्क्रीनशॉट लें"</string>
<string name="action_split" msgid="2098009717623550676">"स्प्लिट स्क्रीन मोड"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"स्प्लिट स्क्रीन के लिए दूसरे ऐप्लिकेशन पर टैप करें"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"स्प्लिट स्क्रीन मोड से बाहर निकलें"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"स्प्लिट स्क्रीन के लिए, दूसरा ऐप्लिकेशन चुनें"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ऐप्लिकेशन या आपका संगठन इस कार्रवाई की अनुमति नहीं देता"</string>
- <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"क्या आपको नेविगेशन ट्यूटोरियल छोड़ना है?"</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>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"रद्द करें"</string>
- <string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"छोड़ें"</string>
+ <string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"अभी नहीं"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"स्क्रीन घुमाएं"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"टास्कबार का ट्यूटोरियल"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"टास्कबार ट्यूटोरियल दिखाया गया"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"टास्कबार ट्यूटोरियल बंद किया गया"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"किसी ऐप को किनारे की ओर ड्रैग करके, दो ऐप एक साथ यूज़ करें"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"किसी ऐप को किनारे की ओर ड्रैग करके 2 ऐप एक साथ इस्तेमाल करें"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"टास्कबार दिखाने के लिए, ऊपर की ओर धीरे से स्वाइप करें"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"डिवाइस के इस्तेमाल के आधार पर ऐप्लिकेशन के सुझाव पाएं"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"टास्कबार अपने-आप छिपाने वाली सुविधा के लिए, सेटिंग में जाकर जेस्चर वाला नेविगेशन चालू करें"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"टास्कबार की मदद से कई और काम करें"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"आगे बढ़ें"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"वापस जाएं"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"बंद करें"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"हो गया"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"होम"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"सूचनाएं"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"फटाफट सेटिंग"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"टास्कबार"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"टास्कबार दिखाया गया"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"टास्कबार छिपाया गया"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"नेविगेशन बार"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"टास्कबार हमेशा दिखाएं"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"नेविगेशन का मोड बदलें"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"टास्कबार डिवाइडर"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ऊपर/बाईं तरफ़ ले जाएं"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"नीचे/दाईं तरफ़ ले जाएं"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# और ऐप्लिकेशन दिखाएं.}one{# और ऐप्लिकेशन दिखाएं.}other{# और ऐप्लिकेशन दिखाएं.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> और <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"डेस्कटॉप पर ऐप्लिकेशन जोड़ा जा रहा है"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"रद्द करें"</string>
</resources>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index 203a998..abad768 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Predlaganje apl. omogućeno"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Predlaganje apl. onemogućeno"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predviđena aplikacija: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Pazite da prijeđete prstom od krajnjeg desnog ili krajnjeg lijevog ruba."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Pazite da prijeđete prstom od desnog ili lijevog ruba do sredine zaslona i podignite prst."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Zakrenite uređaj"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Zakrenite uređaj da biste dovršili vodič o navigaciji pokretima"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Pazite da prijeđete prstom od krajnjeg desnog ili krajnjeg lijevog ruba"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Pazite da prijeđete prstom od desnog ili lijevog ruba do sredine zaslona i podignite prst"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Naučili ste kako prijeći prstom zdesna da biste se vratili. Sad saznajte kako promijeniti aplikaciju."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Izvršili ste pokret za povratak."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Pazite da ne prijeđete prstom preblizu dnu zaslona."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Izvršili ste pokret za povratak"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Pazite da ne prijeđete prstom preblizu dnu zaslona"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Osjetljivost pokreta povratka promijenite u postavkama"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Prijeđite prstom da biste se vratili"</string>
- <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Za povratak na zadnji zaslon prijeđite prstom od lijevog ili desnog ruba do sredine zaslona."</string>
+ <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Da biste se vratili na prethodni zaslon, prijeđite prstom od lijevog ili desnog ruba do sredine zaslona."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Da biste se vratili na posljednji zaslon, prijeđite s dva prsta od lijevog ili desnog ruba do sredine zaslona."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Pazite da prijeđete prstom prema gore od donjeg ruba zaslona."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Pazite da ne zastanete prije podizanja prsta."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Pazite da prijeđete prstom ravno prema gore."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Izvršili ste pokret za otvaranje početnog zaslona. Sad saznajte kako se vratiti."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Izvršili ste pokret za otvaranje početnog zaslona."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Povratak"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Prijeđite prstom od lijevog ili desnog ruba do sredine zaslona"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Pazite da prijeđete prstom prema gore od donjeg ruba zaslona"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Pazite da ne zastanete prije podizanja prsta"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Pazite da prijeđete prstom ravno prema gore"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Izvršili ste pokret za otvaranje početnog zaslona. Sad saznajte kako se vratiti."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Izvršili ste pokret za otvaranje početnog zaslona"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Prijeđite prstom da biste otvorili početni zaslon"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Prijeđite prstom od dna zaslona prema gore. Tim pokretom uvijek će se otvoriti početni zaslon."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Prijeđite s dva prsta od dna zaslona prema gore. Tim pokretom uvijek će se otvoriti početni zaslon."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Otvaranje početnog zaslona"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Da biste otvorili početni zaslon, prijeđite prstom od dna zaslona prema gore"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Pazite da prijeđete prstom prema gore od donjeg ruba zaslona."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Pokušajte zadržati prozor dulje prije podizanja prsta."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Pazite da prijeđete prstom ravno prema gore, a zatim zastanete."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Prijeđite prstom od dna zaslona prema gore"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Sjajno!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Pazite da prijeđete prstom prema gore od donjeg ruba zaslona"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Pokušajte zadržati prozor dulje prije podizanja prsta"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Pazite da prijeđete prstom ravno prema gore, a zatim zastanete"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Naučili ste koristiti pokrete. Pokrete možete isključiti u postavkama."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Izvršili ste pokret za promjenu aplikacije."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Izvršili ste pokret za promjenu aplikacije"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Povlačenje prstom za promjenu aplikacije"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Za promjenu aplikacije prijeđite prstom od dna zaslona prema gore, zadržite pritisak pa pustite."</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Da biste promijenili aplikaciju, prijeđite prstom od dna zaslona prema gore, zadržite pritisak pa pustite."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Za promjenu aplikacije prijeđite s dva prsta od dna zaslona prema gore, zadržite pritisak i pustite."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Promjena aplikacije"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Prijeđite prstom od dna zaslona prema gore, zadržite pritisak pa pustite"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Odlično!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Sve je spremno"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Gotovo"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Postavke"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snimka zaslona"</string>
<string name="action_split" msgid="2098009717623550676">"Podijeli"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Dodirnite drugu aplikaciju za podijeljeni zaslon"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Zatvori odabir podijeljenog zaslona"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Odaberite drugu aplikaciju za upotrebu podijeljenog zaslona"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikacija ili vaša organizacija ne dopuštaju ovu radnju"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Želite li preskočiti vodič za kretanje?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Preskoči"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Zakretanje zaslona"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Upute za traku sa zadacima"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Upute za programsku traku su se pojavile"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Upute za programsku traku su zatvorene"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Povucite apl. u stranu radi istodobne upotrebe 2 aplikacije"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Spori pokret prema gore za prikaz trake sa zadacima"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Povucite aplikaciju u stranu radi istodobne upotrebe dviju aplikacija"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Polako prijeđite prstom prema gore za prikaz trake sa zadacima"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Primajte prijedloge aplikacija na temelju svoje rutine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Uključite navigaciju pokretima u postavkama da bi se traka sa zadacima automatski sakrila"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Učinite više uz pomoć trake sa zadacima"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Dalje"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Natrag"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Učinite više pomoću trake sa zadacima"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Zatvori"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Gotovo"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Početna"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Obavijesti"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Brze postavke"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Traka sa zadacima"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Traka sa zadacima prikazana"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Traka sa zadacima skrivena"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigacijska traka"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Uvijek prikaži traku zadataka"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Promijeni način navigacije"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Razdjelnik trake sa zadacima"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premjesti gore/lijevo"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premjesti dolje/desno"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Prikaži više aplikacija (još #).}one{Prikaži više aplikacija (još #).}few{Prikaži više aplikacija (još #).}other{Prikaži više aplikacija (još #).}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodavanje aplikacije na radnu površinu"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Odustani"</string>
</resources>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 0e5e4f0..16cd5f5 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Alkalmazásjavaslatok engedélyezve"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Alkalmazásjavaslatok letiltva"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Várható alkalmazás: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Csúsztasson a képernyő jobb vagy bal széléről."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Csúsztassa ujját a képernyő jobb vagy bal széléről a képernyő közepéig, majd emelje fel."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Forgassa el eszközét"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Forgassa el eszközét a kézmozdulatokkal való navigáció útmutatójának befejezéséhez"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Csúsztasson a képernyő jobb vagy bal széléről."</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Csúsztassa ujját a képernyő jobb vagy bal széléről a képernyő közepéig, majd emelje fel."</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Megtanulta, hogyan léphet vissza jobbról csúsztatva. A következő az appok közötti váltás."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Teljesítette a visszalépési kézmozdulatot."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Ne csúsztasson túl közel a képernyő aljához."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Teljesítette a visszalépési kézmozdulatot."</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Ne csúsztasson túl közel a képernyő aljához."</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"A vissza mozdulat érzékenysége a Beállításokban módosítható"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Csúsztasson a visszalépéshez"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Ha visszatérne a legutóbbi képernyőre, csúsztasson a képernyő közepére a bal vagy a jobb széléről."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Ha vissza szeretne térni a legutóbbi képernyőre, csúsztasson gyorsan két ujjal a képernyő bal vagy jobb széléről a közepe felé."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Csúsztasson felfelé a képernyő aljától."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Ne álljon meg, mielőtt elengedi a képernyőt."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Csúsztasson egyenesen felfelé."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Teljesítette a kezdőképernyőre lépés kézmozdulatát. Most megtanulhatja, hogyan léphet vissza."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Teljesítette a kezdőképernyőre lépés kézmozdulatát."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Vissza"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Csúsztasson bal vagy jobb szélről a képernyő közepe felé."</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Csúsztasson felfelé a képernyő aljától."</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Ne álljon meg, mielőtt elengedi a képernyőt."</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Csúsztasson egyenesen felfelé."</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Teljesítette a kezdőképernyőre lépés kézmozdulatát. Most megtanulhatja, hogyan léphet vissza."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Teljesítette a kezdőképernyőre lépés kézmozdulatát."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Csúsztatás a kezdőképernyőre lépéshez"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Csúsztassa ujját felfelé a képernyő aljától. Ez a mozdulat mindig a kezdőképernyőre visz."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Csúsztasson felfelé két ujjal a képernyő aljáról. Ez a kézmozdulat mindig a kezdőképernyőre viszi."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Ugrás a kezdőképernyőre"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Ha vissza szeretne térni a kezdőképernyőre, bármikor felfelé csúsztathat ujjával a képernyő aljáról"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Csúsztasson felfelé a képernyő aljától."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Próbálja tovább lenyomva tartani az ablakot, mielőtt elengedi a képernyőt."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Csúsztasson egyenesen felfelé, majd várjon egy kicsit."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Húzza ujját felfelé a képernyő aljától."</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Kiváló!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Csúsztasson felfelé a képernyő aljától."</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Próbálja tovább lenyomva tartani az ablakot, mielőtt elengedi a képernyőt."</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Csúsztasson egyenesen felfelé, majd várjon egy kicsit"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Eddig megismerhette a kézmozdulatok használatát. A kézmozdulatokat a Beállításokban kapcsolhatja ki."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Teljesítette az alkalmazásváltás kézmozdulatát."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Teljesítette az alkalmazásváltás kézmozdulatát."</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Alkalmazásváltás csúsztatással"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Appok közti váltáshoz csúsztasson felfelé a kép aljáról, tartsa lenyomva az ujját, majd emelje fel."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Appváltáshoz csúsztasson fel két ujjal a kép aljáról, tartsa lenyomva ujjait, majd emelje fel őket."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Váltás az alkalmazások között"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Csúsztasson felfelé a képernyő aljáról, tartsa lenyomva ujját, majd emelje fel"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Szép munka!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Minden kész"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Kész"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Beállítások"</string>
@@ -80,13 +88,14 @@
<string name="allset_title" msgid="5021126669778966707">"Kész is!"</string>
<string name="allset_hint" msgid="459504134589971527">"Felfelé csúsztatva megjelenik a kezdőképernyő"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"A kezdőképernyőre való lépéshez koppintson a kezdőképernyő gombra"</string>
- <string name="allset_description_generic" msgid="5385500062202019855">"Készen áll a(z) <xliff:g id="DEVICE">%1$s</xliff:g> használatára"</string>
+ <string name="allset_description_generic" msgid="5385500062202019855">"Készen áll az <xliff:g id="DEVICE">%1$s</xliff:g> használatára"</string>
<string name="default_device_name" msgid="6660656727127422487">"eszköz"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Rendszer-navigációs beállítások"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Megosztás"</string>
<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="8464310533320556058">"Koppintson másik appra az osztott képernyőhöz"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Kilépés az osztott képernyő elemeinek kiválasztásából"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Válasszon másik appot a képernyő felosztásához"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Az alkalmazás vagy az Ön szervezete nem engedélyezi ezt a műveletet"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Kihagyja a navigáció bemutatóját?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Kihagyás"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Képernyő elforgatása"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Tálca használatának ismertetése"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Az eszköztár használatát ismertető panel megjelent"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Az eszköztár használatát ismertető panel bezárult"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Húzzon egy appot oldalra, ha kettőt használna egyidejűleg"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Csúsztassa ujját lassan fel a Feladatsáv megjelenítéséhez"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Lassan csúsztassa fel az ujját a Feladatsáv megjelenítéséhez"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Alkalmazásjavaslatokat kaphat a rutinja alapján"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"A Feladatsáv automatikus elrejtéséhez aktiválja a navigációs kézmozdulatokat a beállításokban"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Jobban kihasználhatja a Feladatsávot"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Tovább"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Vissza"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Bezárás"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Kész"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Kezdőlap"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Értesítések"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Gyorsbeállítások"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Tálca"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Feladatsáv megjelenítve"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Feladatsáv elrejtve"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigációs sáv"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Mindig megjelenő feladatsáv"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Navigációs mód módosítása"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Feladatsáv-elválasztó"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mozgatás felülre vagy a bal oldalra"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mozgatás alulra vagy a jobb oldalra"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# további alkalmazás megjelenítése.}other{# további alkalmazás megjelenítése.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> és <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Alkalmazás hozzáadása az asztalhoz"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Mégse"</string>
</resources>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index 662a36f..48eecd6 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -24,7 +24,7 @@
<string name="recents_empty_message" msgid="7040467240571714191">"Վերջին տարրեր չկան"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Հավելվածի օգտագործման կարգավորումներ"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Փակել բոլորը"</string>
- <string name="accessibility_recent_apps" msgid="4058661986695117371">"Վերջին օգտագործած հավելվածները"</string>
+ <string name="accessibility_recent_apps" msgid="4058661986695117371">"Վերջին հավելվածներ"</string>
<string name="task_view_closed" msgid="9170038230110856166">"Առաջադրանքը փակված է"</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 ր"</string>
@@ -44,35 +44,43 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"«Առաջարկվող հավելվածներ» գործառույթը միացված է"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"«Առաջարկվող հավելվածներ» գործառույթն անջատված է"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Առաջարկվող հավելված՝ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Համոզվեք, որ մատը սահեցնում եք էկրանի աջ կամ ձախ եզրից։"</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Մատը սահեցրեք էկրանի աջ կամ ձախ եզրից դեպի կենտրոն և բաց թողեք։"</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Պտտեք սարքը"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Պտտեք սարքը՝ ժեստերով նավիգացիայի ուղեցույցն ավարտելու համար"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Համոզվեք, որ մատը սահեցնում եք էկրանի աջ կամ ձախ եզրից"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Մատը սահեցրեք էկրանի աջ կամ ձախ եզրից դեպի կենտրոն և բաց թողեք"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Դուք սովորեցիք՝ ինչպես մատը աջից սահեցնելով հետ գնալ։ Այժմ սովորենք՝ ինչպես անցնել մի հավելվածից մյուսը։"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Դուք սովորեցիք հետ գնալու ժեստը։"</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Համոզվեք, որ մատը չափազանց մոտ չեք սահեցնում էկրանին ներքևի հատվածին։"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Դուք սովորեցիք հետ գնալու ժեստը"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Համոզվեք, որ մատը չափազանց մոտ չեք սահեցնում էկրանի ներքևի հատվածին"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Հետ գնալու ժեստի զգայունությունը փոփոխեք կարգավորումներում"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Սահեցրեք մատը՝ հետ գնալու համար"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Վերջին էկրանին վերադառնալու համար էկրանի աջ կամ ձախ եզրից մատը սահեցրեք դեպի կենտրոն։"</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Վերջին էկրանին վերադառնալու համար 2 մատը սահեցրեք ձախ կամ աջ եզրից դեպի կենտրոն։"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Համոզվեք, որ մատն էկրանի ներքևի եզրից վերև եք սահեցնում։"</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Համոզվեք, որ դադար չեք տալիս նախքան բաց թողնելը։"</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Համոզվեք, որ մատն ուղիղ վերև եք սահեցնում։"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Դուք սովորեցիք հիմնական էկրան անցնելու ժեստը։ Այժմ սովորենք՝ ինչպես հետ գնալ։"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Դուք սովորեցիք հիմնական էկրան անցնելու ժեստը։"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Հետ գնալ"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Էկրանի աջ կամ ձախ եզրից մատը սահեցրեք դեպի կենտրոն"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Համոզվեք, որ մատն էկրանի ներքևի եզրից վերև եք սահեցնում"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Համոզվեք, որ դադար չեք տալիս նախքան բաց թողնելը"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Համոզվեք, որ մատն ուղիղ վերև եք սահեցնում"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Դուք սովորեցիք հիմնական էկրան անցնելու ժեստը։ Այժմ սովորենք՝ ինչպես հետ գնալ։"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Դուք սովորեցիք հիմնական էկրան անցնելու ժեստը"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Սահեցրեք մատը՝ հիմնական էկրան անցնելու համար"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Մատը սահեցրեք էկրանի ներքևից վերև։ Այս ժեստը բացում է հիմնական էկրանը։"</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Երկու մատը էկրանի ներքևից սահեցրեք վերև։ Այս ժեստը բացում է հիմնական էկրանը։"</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Անցնել հիմնական էկրան"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Հիմնական էկրան վերադառնալու համար մատը էկրանի ներքևից սահեցրեք վերև"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Համոզվեք, որ մատն էկրանի ներքևի եզրից վերև եք սահեցնում։"</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Նախքան բաց թողնելը փորձեք հնարավորինս երկար պահել պատուհանը։"</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Համոզվեք, որ մատն ուղիղ վերև եք սահեցնում, այնուհետև դադար տվեք։"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Մատը սահեցրեք էկրանի ներքևից վերև"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Կեցցե՛ք"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Համոզվեք, որ մատն էկրանի ներքևի եզրից վերև եք սահեցնում"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Նախքան բաց թողնելը փորձեք հնարավորինս երկար պահել պատուհանը"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Համոզվեք, որ մատն ուղիղ վերև եք սահեցնում, այնուհետև դադար տվեք"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Դուք սովորեցիք՝ ինչպես օգտագործել ժեստերը։ Ժեստերը կարող եք անջատել կարգավորումներում։"</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Դուք սովորեցիք մի հավելվածից մյուսն անցնելու ժեստը։"</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Դուք սովորեցիք մի հավելվածից մյուսն անցնելու ժեստը"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Մատը սահեցրեք՝ մյուս հավելվածին անցնելու համար"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Մեկ հավելվածից մյուսն անցնելու համար մատը էկրանի ներքևից սահեցրեք վերև, ապա հեռացրեք այն էկրանից։"</string>
- <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Մեկ հավելվածից մյուսն անցնելու համար 2 մատը էկրանի ներքևից սահեցրեք վերև, ապա հեռացրեք այն էկրանից։"</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Մեկ հավելվածից մյուսն անցնելու համար մատը էկրանի ներքևից սահեցրեք վերև, պահեք, ապա բաց թողեք։"</string>
+ <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Մեկ հավելվածից մյուսն անցնելու համար 2 մատը էկրանի ներքևից սահեցրեք վերև, պահեք, ապա բաց թողեք։"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Անցում մեկ հավելվածից մյուսին"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Մատը սահեցրեք էկրանի ներքևից վերև, պահեք և բաց թողեք"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Հիանալի՛ է"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Պատրաստ է"</string>
- <string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Պատրաստ է"</string>
+ <string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Ավարտել"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Կարգավորումներ"</string>
<string name="gesture_tutorial_try_again" msgid="65962545858556697">"Նորից փորձեք"</string>
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Գերազանց է"</string>
@@ -80,13 +88,14 @@
<string name="allset_title" msgid="5021126669778966707">"Պատրաստ է"</string>
<string name="allset_hint" msgid="459504134589971527">"Մատը սահեցրեք վերև՝ հիմնական էկրան անցնելու համար"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Հիմնական էկրան վերադառնալու համար սեղմեք գլխավոր էկրանի կոճակը"</string>
- <string name="allset_description_generic" msgid="5385500062202019855">"Դուք արդեն կարող եք օգտագործել ձեր <xliff:g id="DEVICE">%1$s</xliff:g> սարքը"</string>
+ <string name="allset_description_generic" msgid="5385500062202019855">"Դուք արդեն կարող եք օգտագործել ձեր <xliff:g id="DEVICE">%1$s</xliff:g>ը"</string>
<string name="default_device_name" msgid="6660656727127422487">"սարք"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Նավիգացիայի համակարգային կարգավորումներ"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Կիսվել"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Սքրինշոթ անել"</string>
<string name="action_split" msgid="2098009717623550676">"Տրոհել"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Հպեք այլ հավելվածի՝ տրոհված էկրանից օգտվելու համար"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Դուրս գալ տրոհված էկրանի ռեժիմից"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Ընտրեք այլ հավելված՝ կիսված էկրանից օգտվելու համար"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Այս գործողությունն արգելված է հավելվածի կամ ձեր կազմակերպության կողմից"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Բաց թողնե՞լ նավիգացիայի ուղեցույցը"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Բաց թողնել"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Պտտել էկրանը"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Խնդրագոտու «Կրթություն» պատուհան"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Խնդրագոտու «Կրթություն» վահանակը բացվեց"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Խնդրագոտու «Կրթություն» վահանակը փակվեց"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Միաժամանակ օգտագործեք երկու հավելված՝ մեկը մի կողմ քաշելով"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Հավելվածների վահանակը բացելու համար մատը դանդաղ սահեցրեք վեր"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Ստացեք առաջարկներ ձեր գործողությունների հիման վրա"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Կարգավորումներում միացրեք ժեստերով նավիգացիան՝ հավելվածների վահանակը թաքցնելու համար"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Օգտվեք հավելվածների վահանակի բոլոր հնարավորություններից"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Առաջ"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Հետ"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Փակել"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Պատրաստ է"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Սկիզբ"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Ծանուցումներ"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Արագ կարգավորումներ"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Խնդրագոտի"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Խնդրագոտին ցուցադրվում է"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Խնդրագոտին թաքցված է"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Նավիգացիայի գոտի"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Միշտ ցուցադրել հավելվածները"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Փոխել նավիգացիայի ռեժիմը"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Հավելվածների վահանակի բաժանիչ"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Տեղափոխել վերևի ձախ անկյուն"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Տեղափոխել ներքևի աջ անկյուն"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Ցուցադրել ևս # հավելված։}one{Ցուցադրել ևս # հավելված։}other{Ցուցադրել ևս # հավելված։}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> և <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Հավելվածն ավելացվում է աշխատասեղանին"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Չեղարկել"</string>
</resources>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index 4c67c5d..2852fc0 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -44,41 +44,49 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Saran aplikasi diaktifkan"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Saran aplikasi dinonaktifkan"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Aplikasi yang diprediksi: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Pastikan Anda menggeser dari tepi ujung kanan atau ujung kiri."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Pastikan Anda menggeser dari tepi kanan atau kiri ke tengah layar, lalu lepaskan."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Putar perangkat Anda"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Putar perangkat Anda untuk menyelesaikan tutorial navigasi gestur"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Pastikan Anda menggeser dari tepi ujung kanan atau ujung kiri"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Pastikan Anda menggeser dari tepi kanan atau kiri ke tengah layar, lalu lepaskan"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Anda telah belajar cara geser dari kanan untuk kembali. Berikutnya, pelajari cara beralih aplikasi."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Anda telah menyelesaikan gestur kembali."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Pastikan Anda tidak menggeser terlalu dekat ke bagian bawah layar."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Anda telah menyelesaikan gestur kembali"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Pastikan Anda tidak menggeser terlalu dekat ke bagian bawah layar"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Untuk mengubah sensitivitas gestur kembali, buka Setelan"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Geser untuk kembali"</string>
- <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Untuk kembali ke layar terakhir, geser dari tepi kiri atau kanan ke tengah layar."</string>
+ <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Untuk kembali ke layar yang sebelumnya dibuka, geser dari tepi kiri atau kanan ke tengah layar."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Untuk kembali ke layar terakhir, geser dengan 2 jari dari tepi kiri atau kanan ke tengah layar."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Pastikan Anda menggeser ke atas dari tepi bawah layar."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Pastikan Anda tidak menjeda sebelum melepaskan."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Pastikan Anda menggeser lurus ke atas."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Anda telah menyelesaikan gestur menuju Layar utama. Selanjutnya, pelajari cara beralih kembali."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Anda telah menyelesaikan gestur menuju Layar utama."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Kembali"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Geser dari tepi kiri atau kanan ke tengah layar"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Pastikan Anda menggeser ke atas dari tepi bawah layar"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Pastikan Anda tidak berhenti sebelum melepaskan sentuhan"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Pastikan Anda menggeser lurus ke atas"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Anda telah menyelesaikan gestur buka layar utama. Berikutnya, pelajari cara melakukan gestur kembali."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Anda telah menyelesaikan gestur buka layar utama"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Geser untuk beralih ke layar utama"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Geser ke atas dari bagian bawah layar. Gestur ini akan selalu membawa Anda ke Layar utama."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Geser ke atas dengan 2 jari dari bawah layar. Gestur ini akan selalu membawa Anda ke Layar utama."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Buka layar utama"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Untuk membuka layar utama kapan saja, geser ke atas dari bagian bawah layar"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Pastikan Anda menggeser ke atas dari tepi bawah layar."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Coba tahan jendela lebih lama sebelum melepaskan."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Pastikan Anda menggeser lurus ke atas, lalu menjedanya."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Geser ke atas dari bagian bawah layar"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Bagus."</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Pastikan Anda menggeser ke atas dari tepi bawah layar"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Coba tahan jendela lebih lama sebelum melepaskan"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Pastikan Anda menggeser lurus ke atas, lalu berhenti sejenak"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Anda telah mempelajari cara menggunakan gestur. Untuk menonaktifkan gestur, buka Setelan."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Anda telah menyelesaikan gestur beralih aplikasi."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Anda telah menyelesaikan gestur beralih aplikasi"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Geser untuk beralih aplikasi"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Untuk beralih antar-aplikasi, geser ke atas dari bagian bawah layar, tahan, lalu lepaskan."</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Untuk beralih dari satu aplikasi ke aplikasi lain, geser ke atas dari bagian bawah layar, tahan, lalu lepaskan."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Untuk beralih antar-aplikasi, geser ke atas dengan 2 jari dari bawah layar, tahan, lalu lepaskan."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Beralih aplikasi"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Geser ke atas dari bagian bawah layar, tahan, kemudian lepaskan"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Bagus."</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Semua siap"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Selesai"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Setelan"</string>
<string name="gesture_tutorial_try_again" msgid="65962545858556697">"Coba lagi"</string>
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Bagus!"</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">"Semua siap."</string>
- <string name="allset_hint" msgid="459504134589971527">"Geser ke atas untuk beralih ke layar utama"</string>
+ <string name="allset_title" msgid="5021126669778966707">"Selesai!"</string>
+ <string name="allset_hint" msgid="459504134589971527">"Geser ke atas untuk membuka Layar utama"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Ketuk tombol layar utama untuk membuka layar utama"</string>
<string name="allset_description_generic" msgid="5385500062202019855">"Anda sudah siap untuk mulai menggunakan <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="default_device_name" msgid="6660656727127422487">"perangkat"</string>
@@ -86,7 +94,8 @@
<string name="action_share" msgid="2648470652637092375">"Bagikan"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Pisahkan"</string>
- <string name="toast_split_select_app" msgid="8464310533320556058">"Ketuk apl lain untuk menggunakan layar terpisah"</string>
+ <string name="toast_split_select_app" msgid="8464310533320556058">"Ketuk aplikasi lain untuk memakai layar terpisah"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Keluar dari pemilihan layar terpisah"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Pilih aplikasi lain untuk memakai layar terpisah"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Tindakan ini tidak diizinkan oleh aplikasi atau organisasi Anda"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Lewati tutorial gestur?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Lewati"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Putar layar"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Pengantar Taskbar"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Edukasi taskbar ditampilkan"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Edukasi taskbar ditutup"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Tarik aplikasi ke samping untuk menggunakan 2 aplikasi sekaligus"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Geser perlahan ke atas untuk menampilkan Taskbar"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Dapatkan saran aplikasi berdasarkan rutinitas Anda"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Aktifkan navigasi gestur di Setelan untuk menyembunyikan otomatis Taskbar"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Lakukan banyak hal dengan Taskbar"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Berikutnya"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Kembali"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Lakukan lebih banyak dengan Taskbar"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Tutup"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Selesai"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Layar utama"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifikasi"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Setelan Cepat"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Taskbar"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar ditampilkan"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar disembunyikan"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Menu navigasi"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Selalu tampilkan Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Ubah mode navigasi"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Pemisah Taskbar"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Pindahkan ke atas/kiri"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Pindahkan ke bawah/kanan"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Tampilkan # aplikasi lain.}other{Tampilkan # aplikasi lain.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> dan <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Menambahkan aplikasi ke Desktop"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Batalkan"</string>
</resources>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index d5a04be..998c23f 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Kveikt á tillögum að forritum"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Slökkt er á tillögðum forritum"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Tillaga að forriti: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Passaðu að strjúka frá jaðri hægri eða vinstri brúnar."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Passaðu að strjúka frá jaðri hægri eða vinstri brúnar að miðju skjásins og sleppa síðan."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Snúðu tækinu"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Snúðu tækinu til að ljúka leiðsögn um bendingastjórnun"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Passaðu að strjúka frá jaðri hægri eða vinstri brúnar"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Passaðu að strjúka frá jaðri hægri eða vinstri brúnar að miðju skjásins og sleppa síðan"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Þú lærðir að strjúka frá hægri til að bakka. Næst skaltu læra hvernig þú skiptir á milli forrita."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Þú laukst við að kynna þér bendinguna „til baka“."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Passaðu að strjúka ekki of nálægt neðri brún skjásins."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Þú laukst við að kynna þér bendinguna „til baka“"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Passaðu að strjúka ekki of nálægt neðri brún skjásins"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Til að breyta næmi til baka-bendingar ferðu í stillingar"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Strjúktu til að fara til baka"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Til að fara til baka á síðasta skjá skaltu strjúka frá vinstri eða hægri brún að miðju skjásins."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Strjúktu frá vinstri eða hægri brún að miðju skjásins með 2 fingrum til að fara aftur á síðasta skjá."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Passaðu að strjúka upp frá neðri brún skjásins."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Passaðu að stoppa ekki áður en þú sleppir."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Passaðu að strjúka beint upp."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Þú laukst við að kynna þér bendinguna „heim“. Næst skaltu læra hvernig þú ferð „til baka“."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Þú laukst við að kynna þér bendinguna „heim“."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Til baka"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Strjúktu frá vinstri eða hægri brún að miðju skjásins"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Passaðu að strjúka upp frá neðri brún skjásins"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Passaðu að stoppa ekki áður en þú sleppir"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Passaðu að strjúka beint upp"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Þú laukst við að kynna þér bendinguna „heim“. Næst skaltu læra hvernig þú ferð „til baka“."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Þú laukst við að kynna þér bendinguna „heim“"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Strjúktu til að fara heim"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Strjúktu upp frá neðri hluta skjásins. Þetta flytur þig alltaf á heimaskjáinn."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Strjúktu frá neðri brún skjásins með 2 fingrum. Þessi bending opnar ávallt heimaskjáinn."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Fara á heimaskjá"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Strjúktu upp frá neðsta hluta skjásins til að opna heimskjáinn hvenær sem er"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Passaðu að strjúka upp frá neðri brún skjásins."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Prófaðu að halda fingrinum lengur á glugganum áður en þú sleppir."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Passaðu að strjúka beint upp og stoppa svo."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Strjúktu upp frá neðri hluta skjásins"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Vel gert!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Passaðu að strjúka upp frá neðri brún skjásins"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Prófaðu að halda fingrinum lengur á glugganum áður en þú sleppir"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Passaðu að strjúka beint upp og stoppa svo"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Þú kynntir þér hvernig á að nota bendingar. Opnaðu stillingar til að slökkva á bendingum."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Þú laukst við að kynna þér bendinguna „skipta um forrit“."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Þú laukst við að kynna þér bendinguna „skipta um forrit“"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Strjúktu til að skipta á milli forrita"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Strjúktu upp frá neðri hluta skjásins, haltu og slepptu svo til að skipta á milli forrita."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Strjúktu upp frá neðri brún skjásins með 2 fingrum, haltu og slepptu til að skipta á milli forrita."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Skipta um forrit"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Strjúktu upp frá neðri hluta skjásins, haltu inni og slepptu svo"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Vel gert!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Allt til reiðu"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Lokið"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Stillingar"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skjámynd"</string>
<string name="action_split" msgid="2098009717623550676">"Skipta"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Ýttu á annað forrit til að nota skjáskiptingu"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Loka skjáskiptingu"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Veldu annað forrit til að nota skjáskiptingu"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Forritið eða fyrirtækið leyfir ekki þessa aðgerð"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Sleppa flettileiðsögn?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Sleppa"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Snúa skjánum"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Leiðsögn verkefnastiku"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Leiðsögn verkefnastiku sýnileg"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Leiðsögn verkefnastiku lokað"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Dragðu forrit til hliðar til að nota 2 forrit í einu"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Strjúktu hægt upp til að birta forritastikuna"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Fáðu forritatillögur sem byggjast á rútínunni þinni"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Kveiktu á bendingastjórnun í stillingunum til að fela forritastikuna sjálfkrafa"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Nýttu forritastikuna betur"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Áfram"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Til baka"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Loka"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Lokið"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Heim"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Tilkynningar"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Flýtistillingar"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Verkstika"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Forritastika sýnd"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Forritastika falin"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Yfirlitsstika"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Alltaf sýna forritastiku"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Breyta leiðsagnarstillingu"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Skipting forritastiku"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Færa efst/til vinstri"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Færa neðst/til hægri"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Sýna # forrit í viðbót.}one{Sýna # forrit í viðbót.}other{Sýna # forrit í viðbót.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> og <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Forriti bætt við skjáborð"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Hætta við"</string>
</resources>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index 7587d2c..3755dbb 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"La funzionalità app suggerite è attiva"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"La funzionalità app suggerite è disattivata"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"App prevista: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Assicurati di scorrere dal bordo all\'estrema destra o all\'estrema sinistra."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Assicurati di scorrere dal bordo destro o sinistro verso il centro dello schermo e solleva il dito."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Ruota il dispositivo"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Ruota il dispositivo per completare il tutorial relativo alla navigazione tramite gesti"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Assicurati di scorrere dal bordo all\'estrema destra o all\'estrema sinistra"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Assicurati di scorrere dal bordo destro o sinistro verso il centro dello schermo e solleva il dito"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Hai imparato a scorrere da destra per tornare indietro. Ora impara come passare da un\'app all\'altra."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Hai completato il gesto Indietro."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Assicurati di non scorrere troppo vicino alla parte inferiore dello schermo."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Hai completato il gesto Indietro"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Assicurati di non scorrere troppo vicino alla parte inferiore dello schermo"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Usa Impostazioni per cambiare sensibilità del gesto Indietro"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Scorri per tornare indietro"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Per tornare all\'ultima schermata, scorri dal bordo sinistro o destro verso il centro dello schermo."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Per tornare all\'ultima schermata, scorri con 2 dita dal bordo sinistro o destro verso il centro dello schermo."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Assicurati di scorrere verso l\'alto dal bordo inferiore dello schermo."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Assicurati di non fare pause prima di sollevare il dito."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Assicurati di scorrere verso l\'alto senza fermarti."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Hai completato il gesto per andare alla schermata Home. Ora, impara come tornare indietro."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Hai completato il gesto Vai alla schermata Home."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Vai indietro"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Scorri dal bordo sinistro o destro verso il centro dello schermo"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Assicurati di scorrere verso l\'alto dal bordo inferiore dello schermo"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Assicurati di non fare pause prima di sollevare il dito"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Assicurati di scorrere verso l\'alto senza fermarti"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Hai completato il gesto Vai alla schermata Home. Ora, impara come tornare indietro."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Hai completato il gesto Vai alla schermata Home"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Scorri per andare alla schermata Home"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Scorri verso l\'alto dalla parte inferiore dello schermo. Questo gesto ti porta sempre alla schermata Home."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Scorri verso l\'alto con 2 dita dal basso. Questo gesto ti porta sempre alla schermata Home."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Vai alla schermata Home"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Per andare alla schermata Home in qualsiasi momento, scorri sullo schermo dal basso verso l\'alto"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Assicurati di scorrere verso l\'alto dal bordo inferiore dello schermo."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Prova a tenere premuta la finestra più a lungo prima di rilasciarla."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Assicurati di scorrere verso l\'alto senza fermarti, poi fai una pausa."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Scorri verso l\'alto dalla parte inferiore dello schermo"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Ottimo lavoro!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Assicurati di scorrere verso l\'alto dal bordo inferiore dello schermo"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Prova a tenere premuta la finestra più a lungo prima di rilasciarla"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Assicurati di scorrere verso l\'alto senza fermarti, poi fai una pausa"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Hai imparato a usare i gesti. Per disattivarli, vai alle Impostazioni."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Hai completato il gesto Cambia app."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Hai completato il gesto Cambia app"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Scorri per passare da un\'app all\'altra"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Per spostarti tra le app, scorri verso l\'alto dal fondo dello schermo, tieni premuto e rilascia."</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Per spostarti tra le app, scorri dal basso verso l\'alto sullo schermo, tieni premuto e rilascia."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Per spostarti tra le app, scorri verso l\'alto con 2 dita, tieni premuto e rilascia."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Cambia app"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Scorri verso l\'alto dalla parte inferiore dello schermo, tieni premuto e poi rilascia"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Ben fatto!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Fatto"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Fine"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Impostazioni"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Dividi"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tocca un\'altra app per usare lo schermo diviso"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Esci dalla selezione dello schermo diviso"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Scegli un\'altra app per usare lo schermo diviso"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Questa azione non è consentita dall\'app o dall\'organizzazione"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Saltare il tutorial di navigazione?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Salta"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Ruota lo schermo"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informazioni sulla barra delle applicazioni"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Riquadro Formazione barra delle applicazioni visualizzato"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Riquadro Formazione barra delle applicazioni chiuso"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Trascina un\'app di lato per usare due app contemporaneamente"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Scorri lentamente verso l\'alto per mostrare barra delle app"</string>
- <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Ottieni app suggerite in base alla tua routine"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Scorri lentamente in su per mostrare la barra delle app"</string>
+ <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Visualizza le app suggerite in base alla tua routine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Per nascondere automaticamente la barra delle app, attiva la navigazione tramite gesti"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Fai di più con la barra delle appl"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Avanti"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Indietro"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Fai di più con la barra delle app"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Chiudi"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Fine"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifiche"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Impostazioni rapide"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Barra delle applicazioni"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra delle app visualizzata"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra delle app nascosta"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra di navigazione"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Mostra sempre barra delle app"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Cambia modalità di navigazione"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Divisore barra delle app"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Sposta in alto/a sinistra"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Sposta in basso/a destra"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostra # altra app.}other{Mostra altre # app.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Aggiunta app a desktop in corso…"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annulla"</string>
</resources>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index 2e83482..e07d338 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -44,38 +44,46 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"התכונה \'הצעות לאפליקציות\' מופעלת"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ההצעות לאפליקציות מושבתות"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"האפליקציות החזויות: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"חשוב להקפיד להחליק מהקצה השמאלי או הימני."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"חשוב להקפיד להחליק מהקצה השמאלי או הימני למרכז המסך ואז לשחרר."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"צריך לסובב את המכשיר"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"צריך לסובב את המכשיר כדי להשלים את המדריך לניווט באמצעות תנועות"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"חשוב להחליק מהקצה השמאלי או הימני"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"חשוב להחליק מהקצה השמאלי או הימני למרכז המסך ואז לשחרר"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"למדת איך להחליק מצד ימין כדי לחזור אחורה. בשלב הבא לומדים איך לעבור בין אפליקציות."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"השלמת את תנועת \'הקודם\'."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"חשוב להקפיד שלא להחליק קרוב מדי לתחתית המסך."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"השלמת את התנועה \'חזרה אחורה\'"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"חשוב שלא להחליק קרוב מדי לתחתית המסך"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"כדי לשנות את מידת הרגישות של תנועת החזרה, יש לעבור להגדרות"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"יש להחליק כדי לחזור"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"כדי לחזור למסך הקודם, יש להחליק מהקצה השמאלי או הימני למרכז המסך."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"כדי לחזור למסך הקודם, יש להחליק עם שתי אצבעות מהקצה השמאלי או הימני למרכז המסך."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"חשוב להקפיד להחליק למעלה מהקצה התחתון של המסך."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"חשוב לוודא שלא מחכים לפני שמשחררים."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"חשוב להקפיד להחליק ישר למעלה."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"השלמת את תנועת המעבר למסך הבית. בשלב הבא לומדים איך לחזור למסך הקודם."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"השלמת את תנועת המעבר למסך הבית."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"הקודם"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"מחליקים מהקצה השמאלי או הימני למרכז המסך"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"חשוב להחליק למעלה מהקצה התחתון של המסך"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"חשוב שלא לחכות לפני שחרור האצבע"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"חשוב להחליק ישר למעלה"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"השלמת את תנועת המעבר למסך הבית. בשלב הבא נראה איך לחזור למסך הקודם."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"השלמת את תנועת המעבר למסך הבית"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"יש להחליק כדי לעבור למסך הבית"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"החלקה למעלה מתחתית המסך תמיד תעביר אותך למסך הבית."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"יש להחליק למעלה עם שתי אצבעות מתחתית המסך. התנועה הזו תמיד מעבירה אותך למסך הבית."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"מעבר למסך הבית"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"למעבר למסך הבית בכל שלב, צריך להחליק למעלה מהחלק התחתון של המסך"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"חשוב להקפיד להחליק למעלה מהקצה התחתון של המסך."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"אפשר להחזיק את החלון זמן רב יותר לפני שמשחררים."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"חשוב להקפיד להחליק ישר למעלה ואז להמתין."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"מחליקים כלפי מעלה מהחלק התחתון של המסך"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"מעולה!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"חשוב להחליק למעלה מהקצה התחתון של המסך"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"כדאי לנסות להחזיק את החלון זמן רב יותר לפני שחרור האצבע"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"חשוב להחליק ישר למעלה ואז להמתין"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"למדת איך להשתמש בתנועות. ניתן להשבית את התנועות ב\'הגדרות\'."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"השלמת את תנועת המעבר בין האפליקציות."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"השלמת את תנועת המעבר בין האפליקציות"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"יש להחליק כדי לעבור בין אפליקציות"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"כדי לעבור בין אפלקציות, יש להחליק למעלה מתחתית המסך, להחזיק ולאחר מכן לשחרר."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"כדי לעבור בין אפלקציות, יש להחליק למעלה עם שתי אצבעות מתחתית המסך, להחזיק ולאחר מכן לשחרר."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"מעבר בין אפליקציות"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"מחליקים כלפי מעלה מתחתית המסך, מחזיקים ואז משחררים"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"כל הכבוד!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"הכול מוכן"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"סיום"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"הגדרות"</string>
<string name="gesture_tutorial_try_again" msgid="65962545858556697">"ניסיון חוזר"</string>
- <string name="gesture_tutorial_nice" msgid="2936275692616928280">"איזה יופי!"</string>
+ <string name="gesture_tutorial_nice" msgid="2936275692616928280">"יפה!"</string>
<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="459504134589971527">"כדי לחזור לדף הבית, מחליקים כלפי מעלה"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"צילום מסך"</string>
<string name="action_split" msgid="2098009717623550676">"פיצול"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"צריך להקיש על אפליקציה אחרת כדי להשתמש במסך מפוצל"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"יציאה מתצוגת מסך מפוצל"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"כדי להשתמש במסך מפוצל צריך לבחור אפליקציה אחרת"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"האפליקציה או הארגון שלך אינם מתירים את הפעולה הזאת"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"לדלג על המדריך לניווט?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"דילוג"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"סיבוב המסך"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"הסבר על סרגל האפליקציות"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"חלונית ההסברים על שורת המשימות מופיעה"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"חלונית ההסברים על שורת המשימות נסגרה"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"כדי להשתמש בשתי אפליקציות בו-זמנית, צריך לגרור אפליקציה לצד"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"צריך להחליק לאט כדי להציג את סרגל האפליקציות"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"קבלת הצעות לאפליקציות על סמך השימוש השגרתי שלך"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"אפשר להפעיל את הניווט באמצעות תנועות ב\'הגדרות\' כדי להסתיר אוטומטית את סרגל האפליקציות"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"פעולות נוספות שאפשר לעשות עם סרגל האפליקציות"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"הבא"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"חזרה"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"סגירה"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"סיום"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"בית"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"התראות"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"הגדרות מהירות"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"סרגל האפליקציות"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"סרגל האפליקציות מוצג"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"סרגל האפליקציות מוסתר"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"סרגל הניווט"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"סרגל האפליקציות מוצג תמיד"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"שינוי מצב הניווט"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"המחיצה בסרגל האפליקציות"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"העברה לפינה השמאלית/העליונה"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"העברה לפינה הימנית/התחתונה"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{הצגת אפליקציה אחת (#) נוספת.}one{הצגת # אפליקציות נוספות.}two{הצגת # אפליקציות נוספות.}other{הצגת # אפליקציות נוספות.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ו-<xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"האפליקציה מתווספת לשולחן העבודה"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ביטול"</string>
</resources>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index fb54446..7517f9d 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -44,38 +44,46 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"アプリの候補表示が有効です"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"アプリの候補は無効です"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"予測されたアプリ: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"右端または左端からスワイプしてください。"</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"画面の右端または左端から中央に向かってスワイプし、指を離してください。"</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"デバイスを回転してください"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"ジェスチャー ナビゲーションのチュートリアルを終了するには、デバイスを回転してください"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"右端または左端からスワイプしてください"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"画面の右端または左端から中央に向かってスワイプし、指を離してください"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"右側からスワイプして前の画面に戻る方法を学習しました。次は、アプリを切り替える方法を覚えましょう。"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"「戻る」操作を学習しました。"</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"スワイプする際は画面の下部に近づきすぎないようにしましょう。"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"「戻る」操作を学習しました"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"スワイプする際は画面の下部に近づきすぎないようにしましょう"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"「戻る」操作の感度を変更するには [設定] に移動します"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"スワイプで戻る"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"直前の画面に戻るには、画面の左端または右端から中央に向かってスワイプします。"</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"直前の画面に戻るには、2 本の指で画面の左端または右端から中央に向かってスワイプします。"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"画面の下端から上にスワイプしてください。"</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"指を離す前にいったん止めないでください。"</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"まっすぐ上にスワイプしてください。"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"「ホームに戻る」操作を学習しました。次は、前の画面に戻る方法を覚えましょう。"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"「ホームに戻る」操作を学習しました。"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"戻る"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"画面の左端または右端から中央に向かってスワイプします"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"画面の下端から上にスワイプしてください"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"指を離す前にいったん止めないでください"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"まっすぐ上にスワイプしてください"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"「ホームに移動」操作を学習しました。次は、前の画面に戻る方法を覚えましょう。"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"「ホームに移動」操作を学習しました"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"スワイプでホームに戻る"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"画面を下から上にスワイプします。この操作でいつでもホーム画面に戻れます。"</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"2 本の指で画面下部から上にスワイプします。この操作で常にホーム画面に戻ります。"</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"ホームに移動"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"画面を下から上にスワイプすると、ホーム画面にいつでも移動できます"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"画面の下端から上にスワイプしてください。"</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"ウィンドウをもう少し長く押してから指を離すようにしてみましょう。"</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"まっすぐ上にスワイプしてから、いったん指を止めてください。"</string>
- <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"主な操作方法を覚えました。操作を OFF にするには、設定に移動してください。"</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"「アプリを切り替える」操作を完了しました。"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"画面を下から上にスワイプします"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"よくできました!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"画面の下端から上にスワイプしてください"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"ウィンドウをもう少し長く押してから指を離すようにしてみましょう"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"まっすぐ上にスワイプしてから、いったん指を止めてください"</string>
+ <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"主なジェスチャーについて学びました。ジェスチャーを OFF にするには、設定に移動してください。"</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"「アプリの切り替え」操作を学習しました"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"スワイプでアプリを切り替える"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"アプリを切り替えるには、画面を下から上にスワイプして長押しし、指を離します。"</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"アプリを切り替えるには、2 本の指で画面下部から上にスワイプしたまま長押しし、指を離します。"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"アプリの切り替え"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"画面を下から上にスワイプして長押しし、指を離します"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"完了です!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"設定完了"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"完了"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"設定"</string>
- <string name="gesture_tutorial_try_again" msgid="65962545858556697">"もう一度"</string>
- <string name="gesture_tutorial_nice" msgid="2936275692616928280">"成功しました"</string>
+ <string name="gesture_tutorial_try_again" msgid="65962545858556697">"もう一度行ってください"</string>
+ <string name="gesture_tutorial_nice" msgid="2936275692616928280">"その調子です!"</string>
<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="459504134589971527">"ホームに移動するには上にスワイプします"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"スクリーンショット"</string>
<string name="action_split" msgid="2098009717623550676">"分割"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"分割画面を使用するには、他のアプリをタップします"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"分割画面の選択を終了します"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"分割画面にするには、別のアプリを選択してください"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"この操作はアプリまたは組織で許可されていません"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"操作チュートリアルをスキップしますか?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"スキップ"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"画面を回転"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"タスクバーの説明"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"タスクバーの説明を開きました"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"タスクバーの説明を閉じました"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"アプリを横にドラッグして 2 個のアプリを同時に使用できます"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"タスクバーを表示するには、ゆっくりと上にスワイプします"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"タスクバーを表示するには、上にゆっくりとスワイプします"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"毎日の使用状況に基づいてアプリの候補が表示されます"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"[設定] でジェスチャー ナビゲーションを ON にすると、タスクバーを自動的に非表示にできます"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"タスクバーの各種機能"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"次へ"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"戻る"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"閉じる"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"完了"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"ホーム"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"通知"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"クイック設定"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"タスクバー"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"タスクバー表示"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"タスクバー非表示"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ナビゲーション バー"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"常にタスクバーを表示"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"ナビゲーション モードを変更"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"タスクバーの区切り"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"上 / 左に移動"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"下 / 右に移動"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{他 # 件のアプリを表示できます。}other{他 # 件のアプリを表示できます。}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> と <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"アプリをデスクトップに追加する"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"キャンセル"</string>
</resources>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index 5628a9c..64aa870 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"აპის შეთავაზებები ჩართულია"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"აპის შეთავაზებები გათიშულია"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"ნაწინასწარმეტყველები აპი: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"გადაფურცლეთ უკიდურესი მარჯვენა ან მარცხენა ბოლოდან."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"გადაფურცლეთ მარჯვენა ან მარცხენა კიდიდან ეკრანის ცენტრისკენ და თითი აუშვით."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"შეატრიალეთ მოწყობილობა"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"ჟესტებით ნავიგაციის სახელმძღვანელოს დასასრულებლად შეატრიალეთ თქვენი მოწყობილობა"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"გადაფურცლეთ უკიდურესი მარჯვენა ან მარცხენა ბოლოდან"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"გადაფურცლეთ მარჯვენა ან მარცხენა კიდიდან ეკრანის ცენტრისკენ და თითი აუშვით"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"თქვენ ისწავლეთ მარჯვნიდან გადაფურცვლა უკან დასაბრუნებლად. ახლა კი შეიტყვეთ, როგორ გადართოთ აპები."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"თქვენ შეასრულეთ უკან დაბრუნების ჟესტი."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"არ გადაფურცლოთ ეკრანის ბოლოსთან ახლოს."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"თქვენ შეასრულეთ უკან დაბრუნების ჟესტი"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"არ გადაფურცლოთ ეკრანის ბოლოსთან ახლოს"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"დაბრუნების ჟესტის მგრძნობელობის შესაცვლელად გადადით პარამეტრებზე"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"უკან დასაბრუნებლად გადაფურცლეთ"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"ბოლო ეკრანზე დასაბრუნებლად გადაფურცლეთ მარცხენა ან მარჯვენა კიდიდან ეკრანის ცენტრისკენ."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"ბოლო ეკრანზე დასაბრუნებლად ორი თითით გადაფურცლეთ მარცხენა ან მარჯვენა კიდიდან ეკრანის ცენტრისკენ."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"გადაფურცლეთ ეკრანის ქვედა კიდიდან ზემოთ."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"არ დააპაუზოთ თითის აშვებამდე."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"გადაფურცლეთ ზემოთ."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"თქვენ შეასრულეთ მთავარ ეკრანზე დაბრუნების ჟესტი. ახლა კი შევიტყოთ, თუ როგორ დავბრუნდეთ უკან."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"თქვენ შეასრულეთ მთავარ ეკრანზე დაბრუნების ჟესტი."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"უკან დაბრუნება"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"გადაფურცლეთ მარცხენა ან მარჯვენა ბოლოდან ეკრანის შუისკენ"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"გადაფურცლეთ ეკრანის ქვედა კიდიდან ზემოთ"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"არ დააპაუზოთ თითის აშვებამდე"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"გადაფურცლეთ პირდაპირ ზემოთ"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"თქვენ შეასრულეთ მთავარ ეკრანზე დაბრუნების ჟესტი. ახლა კი შევიტყოთ, თუ როგორ დავბრუნდეთ უკან."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"თქვენ შეასრულეთ მთავარ ეკრანზე დაბრუნების ჟესტი"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"მთავარი გვერდის სანახავად გადაფურცლეთ"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"გადაფურცლეთ ეკრანის ქვედა კიდიდან ზემოთ. ამ ჟესტს ყოველთვის მთავარი გვერდის ეკრანზე გადაყავხართ."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"ორი თითით გადაფურცლეთ ეკრანის ქვედა ნაწილიდან. ეს ჟესტი ყოველთვის მთავარ ეკრანზე გადაგიყვანთ."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"მთავარზე გადასვლა"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"ნებისმიერ დროს მთავარ ეკრანზე გადასასვლელად, გადაფურცლეთ ეკრანის ქვემოდან ზემოთ"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"გადაფურცლეთ ეკრანის ქვედა კიდიდან ზემოთ."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"უფრო ხანგრძლივად დააჭირეთ თითი ფანჯარას, რომ არ დაიხუროს."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"გადაფურცლეთ პირდაპირ ზემოთ და შემდეგ დააპაუზეთ."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"გადაფურცლეთ ზემოთ თქვენი ეკრანის ბოლოდან"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"შესანიშნავია!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"გადაფურცლეთ ეკრანის ქვედა კიდიდან ზემოთ"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"უფრო ხანგრძლივად დააჭირეთ თითი ფანჯარას, შემდეგ აუშვით"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"გადაფურცლეთ პირდაპირ ზემოთ და შემდეგ დააპაუზეთ"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"თქვენ ისწავლეთ ჟესტების გამოყენება. ჟესტების გამოსართავად გადადით პარამეტრებში."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"თქვენ შეასრულეთ აპების გადართვის ჟესტი."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"თქვენ შეასრულეთ აპების გადართვის ჟესტი"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"აპების გადასართავად გადაფურცლეთ"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"აპების გადასართავად, გადაფურცლეთ ეკრანის ქვედა კიდიდან ზემოთ, დააყოვნეთ, შემდეგ თითი აუშვით."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"აპებს შორის გადასართავად ეკრანის ქვედა კიდიდან ორი თითით გადაფურცლეთ, დააყოვნეთ და აუშვით."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"აპების გადართვა"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"გადაფურცლეთ ეკრანის ქვედა კიდიდან ზემოთ, დააყოვნეთ, შემდეგ აუშვით"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"ყოჩაღ!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"მზად არის"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"მზადაა"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"პარამეტრები"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ეკრანის ანაბეჭდი"</string>
<string name="action_split" msgid="2098009717623550676">"გაყოფა"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"შეეხეთ სხვა აპს ეკრანის გასაყოფად"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ეკრანის გაყოფის არჩევანიდან გასვლა"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"აირჩიეთ სხვა აპი ეკრანის გასაყოფად"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ეს მოქმედება არ არის დაშვებული აპის ან თქვენი ორგანიზაციის მიერ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"გსურთ, გამოტოვოთ ნავიგაციის სახელმძღვანელო?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"გამოტოვება"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"ეკრანის შეტრიალება"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ამოცანათა ზოლი: განათლება"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"ამოცანების ზოლის სასწავლო არე გამოჩნდა"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"ამოცანების ზოლის სასწავლო არე დაიხურა"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"2 აპის ერთდროულად გამოსაყენებლად გადაათრიეთ აპი კიდეზე"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"მოკლედ გადაფურცლეთ ზემოთ, რომ ამოცანათა ზოლი გამოაჩინოთ"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"მიიღეთ აპის შეთავაზებები თქვენი რუტინის მიხედვით"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"ჩართეთ ჟესტებით ნავიგაცია პარამეტრებში, რათა ავტომატურად დაიმალოთ სამუშაო ზოლი"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"გააკეთეთ მეტი ამოცანათა ზოლის მეშვეობით"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"შემდეგი"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"უკან"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"დახურვა"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"მზადაა"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"მთავარი"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"შეტყობინებები"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"სწრაფი პარამეტრები"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"ამოცანათა ზოლი"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ამოცანათა ზოლი ნაჩვენებია"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ამოცანათა ზოლი დამალულია"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ნავიგაციის ზოლი"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ამოცანათა ზოლის მუდამ ჩვენება"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"შეცვალეთ ნავიგაციის რეჟიმი"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ამოცანათა ზოლის გამყოფი"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ზემოთ/მარცხნივ გადატანა"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ქვემოთ/მარჯვნივ გადატანა"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{#-ით მეტი აპის ჩენება}other{#-ით მეტი აპის ჩვენება.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> და <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"მიმდინარეობს აპის დესკტოპზე დამატება"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"გაუქმება"</string>
</resources>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index f5a59bc..cde0dfd 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -24,7 +24,7 @@
<string name="recents_empty_message" msgid="7040467240571714191">"Соңғы элементтер жоқ"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Қолданбаны пайдалану параметрлері"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Барлығын өшіру"</string>
- <string name="accessibility_recent_apps" msgid="4058661986695117371">"Соңғы пайдаланылған қолданбалар"</string>
+ <string name="accessibility_recent_apps" msgid="4058661986695117371">"Соңғы қолданбалар"</string>
<string name="task_view_closed" msgid="9170038230110856166">"Тапсырма жабылды."</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 мин"</string>
@@ -44,49 +44,58 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"\"Қолданба ұсыныстары\" функциясы қосылды."</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"\"Қолданба ұсыныстары\" функциясы өшірулі."</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Болжалды қолданба: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Экранның оң немесе сол жиегінен сырғытыңыз."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Экранның оң немесе сол жиегінен ортасына қарай сырғытып, саусағыңызды жіберіңіз."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Құрылғыны бұрыңыз"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Қимылмен басқару нұсқаулығын аяқтау үшін құрылғыны бұрыңыз."</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Экранның оң немесе сол жиегінен сырғытыңыз."</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Экранның оң немесе сол жиегінен ортасына қарай сырғытып, саусағыңызды жіберіңіз."</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Оңнан солға сырғыту арқылы артқа қайтуды үйрендіңіз. Енді қолданбаларды ауыстыруды үйреніңіз."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Артқа қайту қимылын аяқтадыңыз."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Саусағыңызбен сырғыту кезінде экранның төменгі жағына тым жақындамаңыз."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Артқа қайту қимылын аяқтадыңыз."</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Сырғытқанда саусақты экранның төменгі жағына қатты жақындатпаңыз."</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Артқа қайту қимылы сезгіштігін параметрлерден өзгертіңіз."</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Артқа қайту үшін сырғытыңыз"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Соңғы ашылған экранға оралу үшін экранның сол немесе оң жақ шетінен ортасына қарай сырғытыңыз."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Соңғы ашылған экранға оралу үшін екі саусақпен экранның сол не оң жағынан ортасына сырғытыңыз."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Экранның төменгі шетінен жоғары қарай сырғытыңыз."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Жіберер алдында кідіріс жасамаңыз."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Тігінен жоғары қарай сырғытыңыз."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Негізгі экранға қайту қимылын аяқтадыңыз. Енді артқа қайтуды үйреніңіз."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Негізгі экранға қайту қимылын аяқтадыңыз."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Артқа"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Экранның сол немесе оң жақ шетінен ортасына қарай сырғытыңыз."</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Экранның төменгі шетінен жоғары қарай сырғытыңыз."</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Жіберер алдында кідіріс жасамаңыз."</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Тігінен жоғары қарай сырғытыңыз."</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Негізгі экранға қайту қимылын аяқтадыңыз. Енді артқа қайтуды үйреніңіз."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Негізгі экранға қайту қимылын аяқтадыңыз."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Негізгі экранға өту үшін сырғытыңыз"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Экранның төменгі жағынан жоғары қарай сырғытыңыз. Сонда негізгі экран ашылады."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Екі саусақпен экранның төменгі жағынан жоғары сырғытыңыз. Бұл қимыл үнемі негізгі экранды ашады."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Негізгі бетке өту"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Кез келген уақытта негізгі экранға өту үшін экранның астыңғы жағынан жоғары қарай сырғытыңыз."</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Экранның төменгі шетінен жоғары қарай сырғытыңыз."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Жіберер алдында терезені ұзағырақ ұстап тұруға тырысыңыз."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Тігінен жоғары қарай сырғытыңыз да, кідіріңіз."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Негізгі экранға өту"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Экранның төменгі жағынан жоғары қарай сырғытыңыз."</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Жарайсыз!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Экранның төменгі шетінен жоғары қарай сырғытыңыз."</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Жіберер алдында терезені ұзағырақ ұстап тұруға тырысыңыз."</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Тігінен жоғары қарай сырғытыңыз да, кідіріңіз."</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Қимылдарды қолдануды үйрендіңіз. Қимылдарды өшіру үшін \"Параметрлер\" бөліміне өтіңіз."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Қолданбаларды ауыстыру қимылын аяқтадыңыз."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Қолданбаларды ауыстыру қимылын аяқтадыңыз."</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Қолданбаларды ауыстыру үшін сырғытыңыз"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Бір қолданбадан екіншісіне ауысу үшін экранның төменгі жағынан жоғары қарай сырғытып, ұстап тұрып жіберіңіз."</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Бір қолданбадан екіншісіне ауысу үшін экранның төменгі жағынан жоғары қарай сырғытып, ұстап тұрыңыз, кейін жіберіңіз."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Бір қолданбадан екіншісіне ауысу үшін екі саусақпен экранның төменгі жағынан жоғары қарай сырғытып, ұстап тұрып жіберіңіз."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Қолданбалар арасында ауысу"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Экранның төменгі жағынан жоғары қарай сырғытып, ұстап тұрыңыз да, жіберіңіз."</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Жарайсыз!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Бәрі дайын"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Дайын"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Параметрлер"</string>
- <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Қайталау"</string>
+ <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Қайталап көріңіз"</string>
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Жақсы!"</string>
<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="459504134589971527">"Негізгі экранға өту үшін жоғары қарай сырғытыңыз."</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Негізгі экранға өту үшін негізгі экран түймесін түртіңіз."</string>
<string name="allset_description_generic" msgid="5385500062202019855">"<xliff:g id="DEVICE">%1$s</xliff:g> пайдалануға дайын."</string>
- <string name="default_device_name" msgid="6660656727127422487">"құрылғы"</string>
+ <string name="default_device_name" msgid="6660656727127422487">"Құрылғы"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Навигацияның жүйелік параметрлері"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Бөлісу"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
<string name="action_split" msgid="2098009717623550676">"Бөлу"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Экранды бөлу режимін пайдалану үшін басқа қолданбаны түртіңіз."</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Экранды бөлу режимінен шығу"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Экранды бөлу үшін басқа қолданбаны таңдаңыз."</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Бұл әрекетке қолданба не ұйым рұқсат етпейді."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Қимылдар оқулығын өткізіп жіберу керек пе?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Өткізіп жіберу"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Экранды бұру"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Тапсырмалар жолағы: үйрену"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Тапсырмалар тақтасы бойынша нұсқаулық ашылды."</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Тапсырмалар тақтасы бойынша нұсқаулық жабылды."</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"2 қолданбаны бір мезгілде пайдалану үшін қолданбаны шетке сүйреңіз."</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Тапсырмалар жолағын көрсету үшін жоғары қарай ақырын сырғытыңыз."</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Іс-әрекеттеріңізге негізделген қолданба ұсыныстарын алыңыз."</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Тапсырмалар жолағын автоматты түрде жасыру үшін параметрлерден қимылмен басқаруды қосыңыз."</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Тапсырмалар жолағы арқылы көп әрекетті орындаңыз"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Келесі"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Артқа"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Тапсырмалар жолағында мүмкіндік көп"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Жабу"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Дайын"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Негізгі экран"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Хабарландырулар"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Жылдам параметрлер"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Тапсырмалар жолағы"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Тапсырмалар жолағы көрсетілді"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Тапсырмалар жолағы жасырылды"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Навигация жолағы"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Тапсырма жолағын үнемі көрсету"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Навигация режимін өзгерту"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Тапсырмалар жолағын бөлгіш"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Жоғары/солға жылжыту"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Төмен/оңға жылжыту"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Тағы # қолданбаны көрсету.}other{Тағы # қолданбаны көрсету.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> және <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Жұмыс үстеліне қолданба қосу"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Бас тарту"</string>
</resources>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index 8881134..89d8335 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"បានបើកការណែនាំកម្មវិធី"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"បានបិទការណែនាំកម្មវិធី"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"កម្មវិធីដែលបានព្យាករ៖ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"ត្រូវប្រាកដថាអ្នកអូសពីគែមខាងស្ដាំ ឬខាងឆ្វេង។"</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"ត្រូវប្រាកដថាអ្នកអូសពីគែមខាងស្ដាំ ឬខាងឆ្វេងទៅផ្នែកកណ្ដាលនៃអេក្រង់ រួចដកដៃ។"</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"បង្វិលឧបករណ៍របស់អ្នក"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"សូមបង្វិលឧបករណ៍របស់អ្នក ដើម្បីបញ្ចប់មេរៀនអំពីការរុករកដោយប្រើចលនា"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ត្រូវប្រាកដថាអ្នកអូសពីគែមខាងស្ដាំ ឬខាងឆ្វេង"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"ត្រូវប្រាកដថាអ្នកអូសពីគែមខាងស្ដាំ ឬខាងឆ្វេងទៅផ្នែកកណ្ដាលនៃអេក្រង់ រួចដកដៃ"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"អ្នកបានស្វែងយល់ពីរបៀបអូសពីខាងស្ដាំ ដើម្បីថយក្រោយ។ បន្ទាប់ទៀត សូមស្វែងយល់ពីរបៀបប្ដូរកម្មវិធី។"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"អ្នកបានបញ្ចប់ចលនាថយក្រោយហើយ។"</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"ត្រូវប្រាកដថាអ្នកមិនអូសទៅជិតផ្នែកខាងក្រោមនៃអេក្រង់ពេក។"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"អ្នកបានបញ្ចប់ចលនាថយក្រោយហើយ"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"ត្រូវប្រាកដថាអ្នកមិនអូសទៅជិតផ្នែកខាងក្រោមនៃអេក្រង់ពេក"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"ដើម្បីប្ដូរកម្រិតរំញោចនឹងចលនាថយក្រោយ សូមចូលទៅកាន់ការកំណត់"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"អូសដើម្បីថយក្រោយ"</string>
- <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"ដើម្បីត្រឡប់ទៅអេក្រង់ចុងក្រោយវិញ សូមអូសពីគែមខាងឆ្វេង ឬខាងស្ដាំទៅផ្នែកកណ្ដាលនៃអេក្រង់។"</string>
+ <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"ដើម្បីត្រឡប់ទៅអេក្រង់មុនវិញ សូមអូសពីគែមខាងឆ្វេង ឬខាងស្ដាំទៅផ្នែកកណ្ដាលនៃអេក្រង់។"</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"ដើម្បីត្រឡប់ទៅអេក្រង់ចុងក្រោយវិញ អូសដោយប្រើម្រាមដៃពីរពីគែមខាងឆ្វេង ឬខាងស្ដាំទៅផ្នែកកណ្ដាលនៃអេក្រង់។"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"ត្រូវប្រាកដថាអ្នកអូសឡើងលើពីគែមខាងក្រោមនៃអេក្រង់។"</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"ត្រូវប្រាកដថាអ្នកមិនផ្អាក មុនពេលដកដៃ។"</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"ត្រូវប្រាកដថាអ្នកអូសត្រង់ឡើងលើ។"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"អ្នកបានបញ្ចប់ចលនាចូលទៅកាន់ទំព័រដើមហើយ។ បន្ទាប់មកទៀត សូមស្វែងយល់ពីរបៀបថយក្រោយ។"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"អ្នកបានបញ្ចប់ចលនាចូលទៅកាន់ទំព័រដើមហើយ។"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"ថយក្រោយ"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"អូសពីគែមខាងឆ្វេង ឬខាងស្ដាំទៅផ្នែកកណ្ដាលនៃអេក្រង់"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"ត្រូវប្រាកដថាអ្នកអូសឡើងលើពីគែមខាងក្រោមនៃអេក្រង់"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"ត្រូវប្រាកដថាអ្នកមិនផ្អាក មុនពេលដកដៃ"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"ត្រូវប្រាកដថាអ្នកអូសត្រង់ឡើងលើ"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"អ្នកបានបញ្ចប់ចលនាចូលទៅកាន់ទំព័រដើមហើយ។ បន្ទាប់មកទៀត សូមស្វែងយល់ពីរបៀបថយក្រោយ។"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"អ្នកបានបញ្ចប់ចលនាចូលទៅកាន់ទំព័រដើមហើយ"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"អូសដើម្បីចូលទៅកាន់អេក្រង់ដើម"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"អូសឡើងលើពីផ្នែកខាងក្រោមនៃអេក្រង់របស់អ្នក។ ចលនានេះនាំអ្នកទៅអេក្រង់ដើមជានិច្ច។"</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"អូសឡើងលើដោយប្រើម្រាមដៃពីរពីផ្នែកខាងក្រោមនៃអេក្រង់។ ចលនានេះតែងតែនាំអ្នកទៅអេក្រង់ដើមជានិច្ច។"</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"ទៅទំព័រដើម"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"ដើម្បីទៅកាន់អេក្រង់ដើមរបស់អ្នកនៅពេលណាក៏បាន សូមអូសឡើងលើពីផ្នែកខាងក្រោមនៃអេក្រង់របស់អ្នក"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"ត្រូវប្រាកដថាអ្នកអូសឡើងលើពីគែមខាងក្រោមនៃអេក្រង់។"</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"សាកល្បងសង្កត់វិនដូឱ្យបានយូរជាងនេះ មុនពេលដកដៃ។"</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"ត្រូវប្រាកដថាអ្នកអូសត្រង់ឡើងលើ រួចផ្អាក។"</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"ទៅអេក្រង់ដើម"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"អូសឡើងលើពីផ្នែកខាងក្រោមនៃអេក្រង់របស់អ្នក"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"ធ្វើបានល្អ!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"ត្រូវប្រាកដថាអ្នកអូសឡើងលើពីគែមខាងក្រោមនៃអេក្រង់"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"សាកល្បងសង្កត់វិនដូឱ្យបានយូរជាងនេះ មុនពេលដកដៃ"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"ត្រូវប្រាកដថាអ្នកអូសត្រង់ឡើងលើ រួចផ្អាក"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"អ្នកបានស្វែងយល់អំពីរបៀបប្រើចលនាហើយ។ ដើម្បីបិទចលនា សូមចូលទៅកាន់ការកំណត់។"</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"អ្នកបានបញ្ចប់ចលនាប្ដូរកម្មវិធីហើយ។"</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"អ្នកបានបញ្ចប់ចលនាប្ដូរកម្មវិធីហើយ"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"អូសដើម្បីប្ដូរកម្មវិធី"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"ដើម្បីប្ដូររវាងកម្មវិធី សូមអូសឡើងលើពីផ្នែកខាងក្រោមនៃអេក្រង់របស់អ្នក រួចចុចឱ្យជាប់ បន្ទាប់មកដកដៃចេញ។"</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"ដើម្បីប្ដូរកម្មវិធី អូសឡើងលើដោយប្រើម្រាមដៃពីរពីផ្នែកខាងក្រោមនៃអេក្រង់របស់អ្នក សង្កត់ ហើយលែងវិញ។"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"ប្ដូរកម្មវិធី"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"អូសឡើងលើពីផ្នែកខាងក្រោមនៃអេក្រង់របស់អ្នក រួចចុចឱ្យជាប់ បន្ទាប់មកដកដៃចេញ"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"ល្អណាស់!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"រួចហើយ"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"រួចរាល់"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"ការកំណត់"</string>
@@ -80,13 +88,14 @@
<string name="allset_title" msgid="5021126669778966707">"រួចហើយ!"</string>
<string name="allset_hint" msgid="459504134589971527">"អូសឡើងលើ ដើម្បីចូលទៅកាន់អេក្រង់ដើម"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"ចុចប៊ូតុងដើម ដើម្បីចូលទៅកាន់អេក្រង់ដើមរបស់អ្នក"</string>
- <string name="allset_description_generic" msgid="5385500062202019855">"អ្នកអាចចាប់ផ្ដើមប្រើ <xliff:g id="DEVICE">%1$s</xliff:g> របស់អ្នកបានហើយ"</string>
+ <string name="allset_description_generic" msgid="5385500062202019855">"អ្នកអាចចាប់ផ្ដើមប្រើ<xliff:g id="DEVICE">%1$s</xliff:g>របស់អ្នកបានហើយ"</string>
<string name="default_device_name" msgid="6660656727127422487">"ឧបករណ៍"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"ការកំណត់ការរុករកប្រព័ន្ធ"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"ចែករំលែក"</string>
<string name="action_screenshot" msgid="8171125848358142917">"រូបថតអេក្រង់"</string>
<string name="action_split" msgid="2098009717623550676">"បំបែក"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"ចុចកម្មវិធីផ្សេងទៀត ដើម្បីប្រើមុខងារបំបែកអេក្រង់"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ចាកចេញពីការជ្រើសរើសរបស់មុខងារបំបែកអេក្រង់"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"ជ្រើសរើសកម្មវិធីផ្សេងទៀត ដើម្បីប្រើមុខងារបំបែកអេក្រង់"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"សកម្មភាពនេះមិនត្រូវបានអនុញ្ញាតដោយកម្មវិធី ឬស្ថាប័នរបស់អ្នកទេ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"រំលងមេរៀនអំពីការរុករកឬ?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"រំលង"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"បង្វិលអេក្រង់"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ការអប់រំលើរបារកិច្ចការ"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"ការបង្រៀនអំពីរបារកិច្ចការបានបង្ហាញ"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"ការបង្រៀនអំពីរបារកិច្ចការត្រូវបានបិទ"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"អូសកម្មវិធីទៅចំហៀង ដើម្បីប្រើកម្មវិធី 2 ក្នុងពេលតែមួយ"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"អូសឡើងលើយឺតៗ ដើម្បីបង្ហាញរបារកិច្ចការ"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"ទទួលការណែនាំកម្មវិធីដោយផ្អែកលើទម្លាប់របស់អ្នក"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"បើកការរុករកដោយប្រើចលនានៅក្នុងការកំណត់ ដើម្បីលាក់របារកិច្ចការដោយស្វ័យប្រវត្តិ"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"ធ្វើបានកាន់តែច្រើនដោយប្រើរបារកិច្ចការ"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"បន្ទាប់"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"ថយក្រោយ"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"បិទ"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"រួចរាល់"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"ទំព័រដើម"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"ការជូនដំណឹង"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"ការកំណត់រហ័ស"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"របារកិច្ចការ"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"បានបង្ហាញរបារកិច្ចការ"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"បានលាក់របារកិច្ចការ"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"របាររុករក"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"បង្ហាញរបារកិច្ចការជានិច្ច"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"ប្ដូរមុខងាររុករក"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"បន្ទាត់ខណ្ឌចែករបារកិច្ចការ"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ផ្លាស់ទីទៅខាងលើ/ឆ្វេង"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ផ្លាស់ទីទៅខាងក្រោម/ស្ដាំ"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{បង្ហាញកម្មវិធី # ទៀត។}other{បង្ហាញកម្មវិធី # ទៀត។}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> និង <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"កំពុងបញ្ចូលកម្មវិធីទៅកុំព្យូទ័រ"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"បោះបង់"</string>
</resources>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 6e7c8ac..b7cdd15 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -44,42 +44,50 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ಆ್ಯಪ್ ಸಲಹೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ಆ್ಯಪ್ ಸಲಹೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"ಶಿಫಾರಸು ಮಾಡಿದ ಆ್ಯಪ್: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"ನೀವು ಬಲಕೊನೆಯ ಅಂಚಿನಿಂದ ಅಥವಾ ಎಡಕೊನೆಯ ಅಂಚಿನಿಂದ ಸ್ವೈಪ್ ಮಾಡುತ್ತಿದ್ದೀರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"ನೀವು ಬಲ ಅಥವಾ ಎಡ ಅಂಚಿನಿಂದ ಸ್ಕ್ರೀನ್ನ ಮಧ್ಯಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡುತ್ತಿದ್ದೀರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಂಡು ಬಿಟ್ಟುಬಿಡಿ."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"ನಿಮ್ಮ ಸಾಧನವನ್ನು ತಿರುಗಿಸಿ"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"ಗೆಸ್ಚರ್ ನ್ಯಾವಿಗೇಶನ್ ಟುಟೋರಿಯಲ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಲು, ನಿಮ್ಮ ಸಾಧನವನ್ನು ತಿರುಗಿಸಿ"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ನೀವು ಬಲಕೊನೆಯ ಅಂಚಿನಿಂದ ಅಥವಾ ಎಡಕೊನೆಯ ಅಂಚಿನಿಂದ ಸ್ವೈಪ್ ಮಾಡುತ್ತಿದ್ದೀರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"ನೀವು ಬಲ ಅಥವಾ ಎಡ ಅಂಚಿನಿಂದ ಸ್ಕ್ರೀನ್ನ ಮಧ್ಯಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡುತ್ತಿದ್ದೀರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಂಡು ಬಿಟ್ಟುಬಿಡಿ"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"ಹಿಂದೆ ಹೋಗಲು ಬಲದಿಂದ ಸ್ವೈಪ್ ಮಾಡುವುದು ಹೇಗೆಂದು ಕಲಿತಿರಿ. ಮುಂದೆ, ಆ್ಯಪ್ಗಳನ್ನು ಬದಲಿಸುವುದು ಹೇಗೆಂದು ತಿಳಿಯಿರಿ."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"ನೀವು ಗೋ ಬ್ಯಾಕ್ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"ನೀವು ಸ್ಕ್ರೀನ್ನ ಕೆಳಭಾಗಕ್ಕೆ ಹೆಚ್ಚು ಹತ್ತಿರ ಸ್ವೈಪ್ ಮಾಡದಂತೆ ನೋಡಿಕೊಳ್ಳಿ."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"ನೀವು ಗೋ ಬ್ಯಾಕ್ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"ನೀವು ಸ್ಕ್ರೀನ್ನ ಕೆಳಭಾಗಕ್ಕೆ ಹೆಚ್ಚು ಹತ್ತಿರ ಸ್ವೈಪ್ ಮಾಡದಂತೆ ನೋಡಿಕೊಳ್ಳಿ"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"ಬ್ಯಾಕ್ ಗೆಸ್ಚರ್ನ ಸೂಕ್ಷ್ಮತೆ ಬದಲಾಯಿಸಲು, ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಹೋಗಿ"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"ಹಿಂದಕ್ಕೆ ಹೋಗಲು ಸ್ವೈಪ್ ಮಾಡಿ"</string>
- <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"ಕೊನೆಯ ಸ್ಕ್ರೀನ್ಗೆ ಹಿಂತಿರುಗಲು, ಎಡ ಅಥವಾ ಬಲ ಅಂಚಿನಿಂದ ಸ್ಕ್ರೀನ್ ಮಧ್ಯಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ."</string>
+ <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"ಹಿಂದಿನ ಸ್ಕ್ರೀನ್ಗೆ ಮರಳಲು, ಎಡ ಅಥವಾ ಬಲ ಅಂಚಿನಿಂದ ಸ್ಕ್ರೀನ್ ಮಧ್ಯದವರೆಗೆ ಸ್ವೈಪ್ ಮಾಡಿ."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"ಹಿಂದಿನ ಸ್ಕ್ರೀನ್ಗೆ ಹೋಗಲು, 2 ಬೆರಳುಗಳಿಂದ ಎಡ ಅಥವಾ ಬಲ ಅಂಚಿನಿಂದ ಸ್ಕ್ರೀನ್ ಮಧ್ಯಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"ಸ್ಕ್ರೀನ್ನ ಕೆಳಗಿನ ಅಂಚಿನಿಂದ ನೀವು ಸ್ವೈಪ್ ಮಾಡುತ್ತಿದ್ದೀರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"ವಿರಾಮಗೊಳಿಸದೆ ನಿಮ್ಮ ಬೆರಳನ್ನು ಸ್ಕ್ರೀನ್ನಿಂದ ಮೇಲೆತ್ತಿ."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"ನೀವು ನೇರವಾಗಿ ಸ್ವೈಪ್ ಮಾಡುತ್ತಿದ್ದೀರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"ನೀವು ಗೋ ಹೋಮ್ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ. ಮುಂದೆ, ಹಿಂದಕ್ಕೆ ಹೋಗುವುದು ಹೇಗೆ ಎಂದು ತಿಳಿಯಿರಿ."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"ನೀವು ಗೋ ಹೋಮ್ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"ಹಿಂದಿರುಗಿ"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"ಎಡ ಅಥವಾ ಬಲ ಅಂಚಿನಿಂದ ಸ್ಕ್ರೀನ್ನ ಮಧ್ಯಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"ಸ್ಕ್ರೀನ್ನ ಕೆಳಗಿನ ಅಂಚಿನಿಂದ ನೀವು ಸ್ವೈಪ್ ಮಾಡುತ್ತಿದ್ದೀರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"ವಿರಾಮಗೊಳಿಸದೆ ನಿಮ್ಮ ಬೆರಳನ್ನು ಸ್ಕ್ರೀನ್ನಿಂದ ಮೇಲೆತ್ತಿ"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"ನೀವು ನೇರವಾಗಿ ಸ್ವೈಪ್ ಮಾಡುತ್ತಿದ್ದೀರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"ನೀವು ಹೋಮ್ಗೆ ಹೋಗಿ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ. ಮುಂದೆ, ಹಿಂದಕ್ಕೆ ಹೋಗುವುದು ಹೇಗೆ ಎಂದು ತಿಳಿಯಿರಿ."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"ನೀವು ಹೋಮ್ಗೆ ಹೋಗಿ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ಗೆ ಹಿಂತಿರುಗಲು ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"ಸ್ಕ್ರೀನ್ನ ಕೆಳಗಿನಿಂದ ಮೇಲೆ ಸ್ವೈಪ್ ಮಾಡಿ. ಈ ಗೆಸ್ಚರ್ ಯಾವಾಗಲೂ ನಿಮ್ಮನ್ನು ಹೋಮ್ ಸ್ಕ್ರೀನ್ಗೆ ಕರೆದೊಯ್ಯುತ್ತದೆ."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"2 ಬೆರಳುಗಳಿಂದ ಸ್ಕ್ರೀನ್ನ ಕೆಳಗಿನಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ. ಈ ಗೆಸ್ಚರ್ ಯಾವಾಗಲೂ ನಿಮ್ಮನ್ನು ಹೋಮ್ ಸ್ಕ್ರೀನ್ಗೆ ಕರೆದೊಯ್ಯುತ್ತದೆ."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"ಮುಖಪುಟಕ್ಕೆ ಹೋಗಿ"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"ಯಾವುದೇ ಸಮಯದಲ್ಲಿ ನಿಮ್ಮ ಹೋಮ್ ಸ್ಕ್ರೀನ್ಗೆ ಹೋಗಲು, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ನ ಕೆಳಭಾಗದಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"ಸ್ಕ್ರೀನ್ನ ಕೆಳಗಿನ ಅಂಚಿನಿಂದ ನೀವು ಸ್ವೈಪ್ ಮಾಡುತ್ತಿದ್ದೀರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"ಬೆರಳನ್ನು ಮೇಲೆತ್ತುವ ಮೊದಲು ವಿಂಡೋವನ್ನು ಹೆಚ್ಚು ಸಮಯ ಹಿಡಿದಿಡಲು ಪ್ರಯತ್ನಿಸಿ."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"ನೀವು ನೇರವಾಗಿ ಸ್ವೈಪ್ ಮಾಡಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ, ನಂತರ ವಿರಾಮಗೊಳಿಸಿ."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"ಹೋಮ್ಗೆ ಹೋಗಿ"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ನ ಕೆಳಗಿನಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"ಭೇಷ್!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"ಸ್ಕ್ರೀನ್ನ ಕೆಳಗಿನ ಅಂಚಿನಿಂದ ನೀವು ಸ್ವೈಪ್ ಮಾಡುತ್ತಿದ್ದೀರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"ಬೆರಳನ್ನು ಮೇಲೆತ್ತುವ ಮೊದಲು ವಿಂಡೋವನ್ನು ಹೆಚ್ಚು ಸಮಯ ಹಿಡಿದಿಡಲು ಪ್ರಯತ್ನಿಸಿ"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"ನೀವು ನೇರವಾಗಿ ಸ್ವೈಪ್ ಮಾಡಿದ್ದೀರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ, ನಂತರ ವಿರಾಮಗೊಳಿಸಿ"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"ಗೆಶ್ಚರ್ಗಳನ್ನು ಬಳಸುವುದು ಹೇಗೆಂದು ನೀವು ತಿಳಿದುಕೊಂಡಿರುವಿರಿ. ಗೆಶ್ಚರ್ಗಳನ್ನು ಆಫ್ ಮಾಡಲು, ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಹೋಗಿ."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"ನೀವು ಆ್ಯಪ್ಗಳನ್ನು ಬದಲಾಯಿಸುವ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"ನೀವು ಆ್ಯಪ್ಗಳನ್ನು ಬದಲಾಯಿಸುವ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"ಆ್ಯಪ್ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"ಆ್ಯಪ್ಗಳ ನಡುವೆ ಬದಲಿಸಲು, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ನ ಕೆಳಭಾಗದಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ, ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಿ, ನಂತರ ಬಿಟ್ಟುಬಿಡಿ."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"ಆ್ಯಪ್ಗಳ ನಡುವೆ ಬದಲಿಸಲು, 2 ಬೆರಳುಗಳಿಂದ ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ನ ಕೆಳಭಾಗದಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ, ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಿ, ನಂತರ ಬಿಟ್ಟುಬಿಡಿ."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"ಆ್ಯಪ್ಗಳನ್ನು ಬದಲಿಸಿ"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ನ ಕೆಳಭಾಗದಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ, ಹೋಲ್ಡ್ ಮಾಡಿ, ನಂತರ ಬಿಡುಗಡೆ ಮಾಡಿ"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"ಭೇಷ್!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"ಸಂಪೂರ್ಣ ಸಿದ್ಧವಾಗಿದೆ"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"ಮುಗಿದಿದೆ"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="gesture_tutorial_try_again" msgid="65962545858556697">"ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string>
- <string name="gesture_tutorial_nice" msgid="2936275692616928280">"ಚೆನ್ನಾಗಿದೆ!"</string>
+ <string name="gesture_tutorial_nice" msgid="2936275692616928280">"ಭೇಷ್!"</string>
<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="459504134589971527">"ಮುಖಪುಟಕ್ಕೆ ಹೋಗಲು ಮೇಲೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
- <string name="allset_button_hint" msgid="2395219947744706291">"ನಿಮ್ಮ ಮುಖಪುಟದ ಪರದೆಗೆ ಹೋಗಲು ಮುಖಪುಟ ಬಟನ್ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+ <string name="allset_button_hint" msgid="2395219947744706291">"ನಿಮ್ಮ ಹೋಮ್ ಸ್ಕ್ರೀನ್ಗೆ ಹೋಗಲು ಹೋಮ್ ಬಟನ್ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="allset_description_generic" msgid="5385500062202019855">"ನಿಮ್ಮ <xliff:g id="DEVICE">%1$s</xliff:g> ಬಳಸುವುದನ್ನು ಪ್ರಾರಂಭಿಸಲು ನೀವು ಸಿದ್ಧರಾಗಿರುವಿರಿ"</string>
<string name="default_device_name" msgid="6660656727127422487">"ಸಾಧನ"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"ಸಿಸ್ಟಂ ನ್ಯಾವಿಗೇಶನ್ ಸೆಟ್ಟಿಂಗ್ಗಳು"</annotation></string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ಸ್ಕ್ರೀನ್ಶಾಟ್"</string>
<string name="action_split" msgid="2098009717623550676">"ವಿಭಜಿಸಿ"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಬಳಸಲು ಬೇರೆ ಆ್ಯಪ್ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಆಯ್ಕೆಯಿಂದ ನಿರ್ಗಮಿಸಿ"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"\"ಪರದೆ ಬೇರ್ಪಡಿಸಿ\" ಬಳಸಲು ಬೇರೆ ಆ್ಯಪ್ ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ಆ್ಯಪ್ ಅಥವಾ ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಈ ಕ್ರಿಯೆಯನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ನ್ಯಾವಿಗೇಶನ್ ಟ್ಯುಟೋರಿಯಲ್ ಸ್ಕಿಪ್ ಮಾಡಬೇಕೇ?"</string>
@@ -95,26 +104,31 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ಸ್ಕಿಪ್ ಮಾಡಿ"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"ಸ್ಕ್ರೀನ್ ತಿರುಗಿಸಿ"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ಟಾಸ್ಕ್ಬಾರ್ ಶಿಕ್ಷಣ"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"ಟಾಸ್ಕ್ಬಾರ್ ಶಿಕ್ಷಣ ಕಾಣಿಸಿಕೊಂಡಿದೆ"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"ಟಾಸ್ಕ್ಬಾರ್ ಶಿಕ್ಷಣ ಮುಚ್ಚಿದೆ"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ಒಂದೇ ಬಾರಿಗೆ 2 ಆ್ಯಪ್ಗಳನ್ನು ಬಳಸಲು ಆ್ಯಪ್ ಅನ್ನು ಬದಿಗೆ ಎಳೆಯಿರಿ"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"ಟಾಸ್ಕ್ಬಾರ್ ಅನ್ನು ತೋರಿಸಲು ನಿಧಾನವಾಗಿ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"ನಿಮ್ಮ ದಿನಚರಿಯ ಆಧಾರದ ಮೇಲೆ ಆ್ಯಪ್ ಸಲಹೆಗಳನ್ನು ಪಡೆಯಿರಿ"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"ಟಾಸ್ಕ್ಬಾರ್ ಅನ್ನು ಸ್ವಯಂ-ಮರೆಮಾಡಲು ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಗೆಸ್ಚರ್ ನ್ಯಾವಿಗೇಶನ್ ಅನ್ನು ಆನ್ ಮಾಡಿ"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"ಟಾಸ್ಕ್ಬಾರ್ ಮೂಲಕ ಹೆಚ್ಚಿನದನ್ನು ಮಾಡಿ"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"ಮುಂದೆ"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"ಹಿಂದೆ"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"ಮುಚ್ಚಿರಿ"</string>
- <string name="taskbar_edu_done" msgid="6880178093977704569">"ಮುಗಿದಿದೆ"</string>
+ <string name="taskbar_edu_done" msgid="6880178093977704569">"ಆಯಿತು"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"ಮುಖಪುಟ"</string>
- <string name="taskbar_button_a11y" msgid="5241161324875094465">"ಪ್ರವೇಶಿಸುವಿಕೆ"</string>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ"</string>
<string name="taskbar_button_back" msgid="8558862226461164514">"ಹಿಂದೆ"</string>
<string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME ಪರಿವರ್ತಕ"</string>
<string name="taskbar_button_recents" msgid="7273376136216613134">"ಇತ್ತೀಚಿನವು"</string>
- <string name="taskbar_button_notifications" msgid="7471740351507357318">"ಅಧಿಸೂಚನೆಗಳು"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"ನೋಟಿಫಿಕೇಶನ್ಗಳು"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"ಟಾಸ್ಕ್ಬಾರ್"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ಟಾಸ್ಕ್ಬಾರ್ ತೋರಿಸಲಾಗಿದೆ"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ಟಾಸ್ಕ್ಬಾರ್ ಮರೆಮಾಡಲಾಗಿದೆ"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ನ್ಯಾವಿಗೇಷನ್ ಬಾರ್"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ಯಾವಾಗಲೂ ಟಾಸ್ಕ್ಬಾರ್ ತೋರಿಸಿ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"ನ್ಯಾವಿಗೇಶನ್ ಮೋಡ್ ಬದಲಾಯಿಸಿ"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ಟಾಸ್ಕ್ಬಾರ್ ಡಿವೈಡರ್"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ಮೇಲಿನ/ಎಡಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ಕೆಳಗಿನ/ಬಲಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ಇನ್ನೂ # ಆ್ಯಪ್ ಅನ್ನು ತೋರಿಸಿ.}one{ಇನ್ನೂ # ಆ್ಯಪ್ಗಳನ್ನು ತೋರಿಸಿ.}other{ಇನ್ನೂ # ಆ್ಯಪ್ಗಳನ್ನು ತೋರಿಸಿ.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ಮತ್ತು <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"ಡೆಸ್ಕ್ಟಾಪ್ಗೆ ಆ್ಯಪ್ ಅನ್ನು ಸೇರಿಸಲಾಗುತ್ತಿದೆ"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ರದ್ದುಮಾಡಿ"</string>
</resources>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index e6d783a..c00eeed 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"앱 제안이 사용 설정됨"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"앱 제안이 사용 중지됨"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"예상 앱: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"오른쪽 또는 왼쪽 가장자리 끝에서 스와이프하세요."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"오른쪽 또는 왼쪽 가장자리에서 화면 중앙으로 스와이프한 후 손가락을 떼세요."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"기기를 회전시키세요"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"동작 탐색 튜토리얼을 완료하려면 기기를 회전시키세요."</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"오른쪽 또는 왼쪽 가장자리 끝에서 스와이프하세요."</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"오른쪽 또는 왼쪽 가장자리에서 화면 중앙으로 스와이프한 후 손가락을 떼세요."</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"오른쪽에서 스와이프하여 뒤로 돌아가는 방법을 배웠습니다. 이번에는 앱 전환 방법을 알아보겠습니다."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"돌아가기 동작을 완료했습니다."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"화면 하단에 지나치게 가까운 곳에서 스와이프하면 안 됩니다."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"돌아가기 동작을 완료했습니다."</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"화면 하단에 지나치게 가까운 곳에서 스와이프하면 안 됩니다."</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"돌아가기 동작의 민감도를 변경하려면 설정으로 이동하세요"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"스와이프하여 돌아가기"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"이전 화면으로 돌아가려면 왼쪽 또는 오른쪽 가장자리에서 화면 중앙으로 스와이프하세요."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"마지막 화면으로 돌아가려면 두 손가락을 사용해 왼쪽 또는 오른쪽 가장자리에서 화면 중앙으로 스와이프하세요"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"화면 하단 가장자리에서 위로 스와이프하세요."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"손가락을 떼기 전에 멈추지 않아야 합니다."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"위로 곧게 스와이프하세요."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"홈으로 이동 동작을 완료했습니다. 이번에는 뒤로 돌아가는 방법을 알아보겠습니다."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"홈으로 이동 동작을 완료했습니다."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"뒤로"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"왼쪽 또는 오른쪽 가장자리에서 화면 중앙으로 스와이프하세요."</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"화면 하단 가장자리에서 위로 스와이프하세요."</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"손가락을 떼기 전에 멈추지 않아야 합니다."</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"위로 곧게 스와이프하세요."</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"홈으로 이동 동작을 완료했습니다. 이번에는 뒤로 돌아가는 방법을 알아보겠습니다."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"홈으로 이동 동작을 완료했습니다."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"스와이프하여 홈으로 이동"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"화면 하단에서 위로 스와이프합니다. 이 동작을 사용하면 언제든지 홈 화면으로 이동할 수 있습니다."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"두 손가락을 사용해 화면 하단에서 위로 스와이프하세요. 이 동작을 사용하면 언제든지 홈 화면으로 이동할 수 있습니다"</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"홈으로 이동"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"언제든지 화면을 아래에서 위로 스와이프하여 홈 화면으로 이동할 수 있습니다"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"화면 하단 가장자리에서 위로 스와이프하세요."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"창을 더 오래 누르고 있다가 손가락을 떼 보세요."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"위로 곧게 스와이프한 후 잠시 멈추세요."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"화면 하단에서 위로 스와이프하세요."</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"아주 좋습니다"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"화면 하단 가장자리에서 위로 스와이프하세요."</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"창을 더 오래 누르고 있다가 손가락을 떼 보세요."</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"위로 곧게 스와이프한 후 잠시 멈추세요."</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"동작 사용 방법을 알아봤습니다. 동작을 사용 중지하려면 설정으로 이동하세요."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"앱 전환 동작을 완료했습니다."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"앱 전환 동작을 완료했습니다."</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"스와이프하여 앱 전환"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"앱 간에 전환하려면 화면 하단에서 위로 스와이프하고 잠시 멈춘 다음 손가락을 떼세요."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"앱 간에 전환하려면 두 손가락을 사용해 화면 하단에서 위로 스와이프하고 잠시 멈춘 다음 손가락을 떼세요"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"앱 전환"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"화면 하단에서 위로 스와이프하고 잠시 멈춘 다음 손가락을 떼세요."</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"잘하셨습니다"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"설정 완료"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"완료"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"설정"</string>
@@ -80,13 +88,14 @@
<string name="allset_title" msgid="5021126669778966707">"설정 완료"</string>
<string name="allset_hint" msgid="459504134589971527">"위로 스와이프하여 홈으로 이동"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"홈 화면으로 이동하려면 홈 버튼을 탭하세요."</string>
- <string name="allset_description_generic" msgid="5385500062202019855">"<xliff:g id="DEVICE">%1$s</xliff:g> 기기를 사용할 준비가 되었습니다."</string>
+ <string name="allset_description_generic" msgid="5385500062202019855">"<xliff:g id="DEVICE">%1$s</xliff:g>을(를) 사용할 준비가 되었습니다."</string>
<string name="default_device_name" msgid="6660656727127422487">"기기"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"시스템 탐색 설정"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"공유"</string>
<string name="action_screenshot" msgid="8171125848358142917">"스크린샷"</string>
<string name="action_split" msgid="2098009717623550676">"분할"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"다른 앱을 탭하여 화면 분할 사용"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"화면 분할 선택 종료"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"화면 분할을 사용하려면 다른 앱을 선택하세요."</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"이 작업은 앱 또는 조직에서 허용되지 않습니다."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"이동 방법 튜토리얼을 건너뛰시겠습니까?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"건너뛰기"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"화면 회전"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"태스크 바 정보"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"작업 표시줄 튜토리얼 패널 표시됨"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"작업 표시줄 튜토리얼 패널 닫힘"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"앱을 옆으로 드래그하여 앱 2개를 동시에 사용합니다."</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"위로 천천히 스와이프하면 태스크 바가 표시됩니다."</string>
- <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"루틴에 따라 앱 제안을 받습니다."</string>
+ <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"사용 습관에 따라 앱 제안을 받습니다."</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"태스크 바를 자동 숨김하려면 설정에서 동작 탐색을 켜세요."</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"태스크 바 최대한 활용하기"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"다음"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"뒤로"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"닫기"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"완료"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"홈"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"알림"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"빠른 설정"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"태스크 바"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"태스크 바 표시"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"태스크 바 숨김"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"탐색 메뉴"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"태스크 바 항상 표시"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"탐색 모드 변경"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"태스크 바 분할"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"상단/왼쪽으로 이동"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"하단/오른쪽으로 이동"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{앱 #개 더 표시}other{앱 #개 더 표시}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> 및 <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"데스크톱에 앱 추가하기"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"취소"</string>
</resources>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 166e7f4..f5d8782 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Сунушталган колдонмолор функциясы иштетилди"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Сунушталган колдонмолор функциясы өчүрүлгөн"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Божомолдонгон колдонмо: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Экранды эң четинен оңдон солго же солдон оңго карай сүрүңүз."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Экранды оң же сол жагынан ортосуна карай сүрүп, манжаңызды алыңыз."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Түзмөгүңүздү буруңуз"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Жаңсап чабыттоо үйрөткүчүнүн аягына чыгуу үчүн түзмөктү буруңуз"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Экранды эң четинен оңдон солго же солдон оңго карай сүрүңүз"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Экранды оң же сол жагынан ортосуна карай сүрүп, манжаңызды алыңыз"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Артка кайтуу үчүн экранды оңдон солго карай сүрүүнү үйрөндүңүз. Эми колдонмолорду которуштурганды үйрөнүп алыңыз."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"\"Артка\" жаңсоосун үйрөндүңүз."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Манжаңызды экрандын ылдый жагына өтө жакындатпай сүрүңүз."</string>
- <string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"\"Артка\" жаң-нун сезгичтигин өзгөртүү үчүн жөндөөлөргө өтүңүз"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"\"Артка\" жаңсоосун үйрөндүңүз"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Манжаңызды экрандын ылдый жагына өтө жакындатпай сүрүңүз"</string>
+ <string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"\"Артка\" жаң-нун сезгичтигин өзгөртүү үчүн параметрлерге өтүңүз"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Артка кайтуу үчүн сүрүңүз"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Акыркы экранга кайтуу үчүн экранды сол же оң жагынан ортосуна карай сүрүңүз."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Акыркы экранга кайтуу үчүн экранды сол же оң жагынан ортосуна карай 2 манжаңыз менен сүрүңүз."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Экранды ылдыйдан өйдө сүрүңүз."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Манжаңызды алганга чейин токтотпоңуз."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Экранды өйдө сүрүңүз."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"\"Башкы бетке өтүү\" жаңсоосун үйрөндүңүз. Эми артка кайтууну үйрөнүп алыңыз."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"\"Башкы бетке өтүү\" жаңсоосун үйрөндүңүз."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Артка кайтуу"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Экранды сол же оң жагынан ортосуна карай сүрүңүз"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Экранды ылдыйдан өйдө сүрүңүз"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Манжаңызды алганга чейин токтотпоңуз"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Экранды өйдө сүрүңүз"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"\"Башкы бетке өтүү\" жаңсоосун үйрөндүңүз. Эми артка кайтууну үйрөнүп алыңыз."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"\"Башкы бетке өтүү\" жаңсоосун үйрөндүңүз"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Башкы бетке өтүү үчүн сүрүп коюңуз"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Экранды ылдый жагынан өйдө сүрүңүз. Бул жаңсоо сизди ар дайым Башкы экранга алып барат."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Экранды ылдый жагынан өйдө 2 манжаңыз менен сүрүңүз. Бул жаңсоо ар дайым Башкы экранга алып барат."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Башкы бетке өтүү"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Каалаган убакта башкы экранга өтүү үчүн экранды ылдыйдан жогору карай сүрүңүз"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Экранды ылдыйдан өйдө сүрүңүз."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Манжаңызды алуудан мурун экранда узагыраак кармаңыз."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Экранды өйдө карай сүрүп, токтоп туруңуз."</string>
- <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Жаңсоолорду колдонгонду үйрөндүңүз. Жаңсоолорду өчүрүү үчүн жөндөөлөргө өтүңүз."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"\"Колдонмолорду которуштуруу\" жаңсоосун үйрөндүңүз."</string>
- <string name="overview_gesture_intro_title" msgid="2902054412868489378">"Колдонмолорду которуштуруу үчүн сүрүңүз"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Экранды төмөндөн жогору карай сүрүңүз"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Азаматсыз!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Экранды ылдыйдан өйдө сүрүңүз"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Манжаңызды алуудан мурун экранда узагыраак кармаңыз"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Экранды өйдө карай сүрүп, токтоп туруңуз"</string>
+ <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Жаңсоолорду колдонгонду үйрөндүңүз. Жаңсоолорду өчүрүү үчүн параметрлерге өтүңүз."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"\"Колдонмолорду которуштуруу\" жаңсоосун үйрөндүңүз"</string>
+ <string name="overview_gesture_intro_title" msgid="2902054412868489378">"Башка колдонмого которулуу үчүн сүрүңүз"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Бир колдонмодон экинчисине өтүү үчүн экранды ылдыйдан өйдө карай сүрүп, бир аз коё бербей туруңуз."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Бир колдонмодон экинчисине өтүү үчүн экранды 2 манжа менен ылдыйдан өйдө сүрүп, коё бербей туруңуз."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Башка колдонмого которулуу"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Экранды төмөндөн жогору карай сүрүңүз да, бир аз коё бербей кармап туруңуз"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Эң жакшы!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Дапдаяр!"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Бүттү"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Параметрлер"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
<string name="action_split" msgid="2098009717623550676">"Бөлүү"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Экранды бөлүү үчүн башка колдонмону таптап коюңуз"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Тандалган экранды бөлүүдөн чыгуу"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Экранды бөлүү үчүн башка колдонмону тандаңыз"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Бул аракетти аткарууга колдонмо же ишканаңыз тыюу салган"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Жаңсоолор үйрөткүчүн өткөрүп жибересизби?"</string>
@@ -94,16 +103,12 @@
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Жокко чыгаруу"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Өткрп жиберүү"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Экранды буруу"</string>
- <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Тапшырмалар панели жөнүндө маалымат"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Тапшырмалар тактасынын окутуу панели көрсөтүлдү"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Тапшырмалар тактасынын окутуу панели жабылды"</string>
+ <string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Тапшырмалар тактасы жөнүндө маалымат"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"2 колдонмону бир убакта пайдалануу үчүн капталга сүйрөңүз"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Тапшырмалар панелин көрүү үчүн экранды жай өйдө сүрүңүз"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Тапшырмалар тактасын көрүү үчүн экранды жай өйдө сүрүңүз"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Программаңыздын негизинде сунушталган колдонмолорду алуу"</string>
- <string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Тапшырмалар панелин автоматтык түрдө жашыруу үчүн Тууралоодон жаңсап чабыттоону күйгүзүңүз"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Тапшырмалар панели менен көбүрөөк нерселерди аткарыңыз"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Кийинки"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Артка"</string>
+ <string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Тапшырмалар тактасын автоматтык түрдө жашыруу үчүн Тууралоодон жаңсап чабыттоону күйгүзүңүз"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Тапшырмалар тактасы менен көбүрөөк нерселерди аткарыңыз"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Жабуу"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Бүттү"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Башкы бет"</string>
@@ -112,9 +117,18 @@
<string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME которгучу"</string>
<string name="taskbar_button_recents" msgid="7273376136216613134">"Акыркылар"</string>
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Билдирмелер"</string>
- <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Ыкчам жөндөөлөр"</string>
- <string name="taskbar_a11y_title" msgid="6432169809852243110">"Тапшырмалар панели"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Ыкчам параметрлер"</string>
+ <string name="taskbar_a11y_title" msgid="6432169809852243110">"Тапшырмалар тактасы"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Тапшырмалар панели көрсөтүлдү"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Тапшырмалар панели жашырылды"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Чабыттоо тилкеси"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Тапшырмалар панелин ар дайым көрсөтүү"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Өтүү режимин өзгөртүү"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Тапшырмалар панелин бөлгүч"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Жогорку/сол бурчка жылдыруу"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Төмөнкү/оң бурчка жылдыруу"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Дагы # колдонмону көрсөтүү.}other{Дагы # колдонмону көрсөтүү.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> жана <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Колдонмону иш тактага кошуу"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Жокко чыгаруу"</string>
</resources>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index 63c4265..2f67c30 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ເປີດການນຳໃຊ້ການແນະນຳແອັບແລ້ວ"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ປິດການນຳໃຊ້ການແນະນຳແອັບແລ້ວ"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"ແອັບທີ່ຄາດເດົາໄວ້: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"ກະລຸນາກວດສອບວ່າທ່ານປັດຈາກຂອບຂວາສຸດ ຫຼື ຊ້າຍສຸດ."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"ກະລຸນາກວດສອບວ່າທ່ານປັດຈາກຂອບຂວາ ຫຼື ຊ້າຍໄປຫາທາງກາງຂອງໜ້າຈໍແລ້ວປ່ອຍນິ້ວ."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"ໝຸນອຸປະກອນຂອງທ່ານ"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"ກະລຸນາໝຸນອຸປະກອນຂອງທ່ານເພື່ອເຮັດຕາມການສອນການນຳໃຊ້ກ່ຽວກັບການນຳທາງແບບທ່າທາງໃຫ້ສຳເລັດ"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ກະລຸນາກວດສອບວ່າທ່ານປັດຈາກຂອບຂວາສຸດ ຫຼື ຊ້າຍສຸດ"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"ກະລຸນາກວດສອບວ່າທ່ານປັດຈາກຂອບຂວາ ຫຼື ຊ້າຍໄປຫາທາງກາງຂອງໜ້າຈໍແລ້ວປ່ອຍນິ້ວ"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"ທ່ານຮຽນຮູ້ວິທີປັດຈາກຂວາເພື່ອກັບຄືນແລ້ວ. ຕໍ່ໄປ, ມາສຶກສາວິທີສະຫຼັບແອັບ."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"ທ່ານໃຊ້ທ່າທາງກັບຄືນສຳເລັດແລ້ວ."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"ກະລຸນາກວດສອບວ່າທ່ານບໍ່ໄດ້ປັດໃກ້ກັບທາງລຸ່ມຂອງໜ້າຈໍເກີນໄປ."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"ທ່ານໃຊ້ທ່າທາງກັບຄືນສຳເລັດແລ້ວ"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"ກະລຸນາກວດສອບວ່າທ່ານບໍ່ໄດ້ປັດໃກ້ກັບທາງລຸ່ມຂອງໜ້າຈໍເກີນໄປ"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"ເພື່ອປ່ຽນຄວາມລະອຽດອ່ອນຂອງທ່າທາງກັບຄືນ, ໃຫ້ໄປຫາການຕັ້ງຄ່າ"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"ປັດເພື່ອກັບຄືນ"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"ເພື່ອກັບໄປໜ້າຈໍຫຼ້າສຸດ, ໃຫ້ປັດຈາກຂອບຊ້າຍ ຫຼື ຂວາໄປຫາທາງກາງຂອງໜ້າຈໍ."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"ເພື່ອກັບໄປໜ້າຈໍຫຼ້າສຸດ, ໃຫ້ປັດດ້ວຍ 2 ນິ້ວຈາກຂອບຊ້າຍ ຫຼື ຂວາໄປຫາທາງກາງຂອງໜ້າຈໍ."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"ກະລຸນາກວດສອບວ່າທ່ານປັດຂຶ້ນຈາກຂອບລຸ່ມສຸດຂອງໜ້າຈໍ."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"ກະລຸນາກວດສອບວ່າທ່ານບໍ່ຢຸດຊົ່ວຄາວກ່ອນປ່ອຍນິ້ວ."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"ກະລຸນາກວດສອບວ່າທ່ານປັດຂຶ້ນໄປຊື່ໆ."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"ທ່ານໃຊ້ທ່າທາງໄປໜ້າຫຼັກສຳເລັດແລ້ວ. ຕໍ່ໄປ, ມາສຶກສາວິທີກັບຄືນ."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"ທ່ານໃຊ້ທ່າທາງໄປໜ້າຫຼັກສຳເລັດແລ້ວ."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"ກັບຄືນ"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"ປັດຈາກຂອບຊ້າຍ ຫຼື ຂວາໄປຫາກາງໜ້າຈໍ"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"ກະລຸນາກວດສອບວ່າທ່ານປັດຂຶ້ນຈາກຂອບລຸ່ມສຸດຂອງໜ້າຈໍ"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"ກະລຸນາກວດສອບວ່າທ່ານບໍ່ຢຸດຊົ່ວຄາວກ່ອນປ່ອຍນິ້ວ"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"ກະລຸນາກວດສອບວ່າທ່ານປັດຂຶ້ນໄປຊື່ໆ"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"ທ່ານໃຊ້ທ່າທາງໄປໜ້າຫຼັກສຳເລັດແລ້ວ. ຕໍ່ໄປ, ມາສຶກສາວິທີກັບຄືນ."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"ທ່ານໃຊ້ທ່າທາງໄປໜ້າຫຼັກສຳເລັດແລ້ວ"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"ປັດເພື່ອໄປໜ້າຫຼັກ"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"ປັດຂຶ້ນມາຈາກລຸ່ມສຸດຂອງໜ້າຈໍທ່ານ. ທ່າທາງນີ້ຈະພາທ່ານໄປໂຮມສະກຣີນສະເໝີ."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"ປັດຂຶ້ນດ້ວຍ 2 ນິ້ວຈາກລຸ່ມສຸດຂອງໜ້າຈໍ. ທ່າທາງນີ້ຈະພາທ່ານໄປໂຮມສະກຣີນສະເໝີ."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"ໄປໜ້າຫຼັກ"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"ປັດຂຶ້ນຈາກລຸ່ມສຸດຂອງໜ້າຈໍຂອງທ່ານເພື່ອກັບໄປໂຮມສະກຣີນຂອງທ່ານໄດ້ທຸກເວລາ"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"ກະລຸນາກວດສອບວ່າທ່ານປັດຂຶ້ນຈາກຂອບລຸ່ມສຸດຂອງໜ້າຈໍ."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"ລອງກົດໃສ່ໜ້າຈໍຄ້າງໄວ້ດົນຂຶ້ນກ່ອນປ່ອຍນິ້ວ."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"ກະລຸນາກວດສອບວ່າທ່ານປັດຂຶ້ນຊື່ໆ, ຈາກນັ້ນຢຸດຊົ່ວຄາວ."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"ປັດຂຶ້ນຈາກລຸ່ມສຸດຂອງໜ້າຈໍທ່ານ"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"ດີຫຼາຍ!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"ກະລຸນາກວດສອບວ່າທ່ານປັດຂຶ້ນຈາກຂອບລຸ່ມສຸດຂອງໜ້າຈໍ"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"ລອງກົດໃສ່ໜ້າຈໍຄ້າງໄວ້ດົນຂຶ້ນກ່ອນປ່ອຍນິ້ວ"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"ກະລຸນາກວດສອບວ່າທ່ານປັດຂຶ້ນຊື່ໆ, ຈາກນັ້ນຢຸດຊົ່ວຄາວ"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"ທ່ານໄດ້ສຶກສາວິທີໃຊ້ທ່າທາງແລ້ວ. ເພື່ອປິດທ່າທາງຕ່າງໆ, ໃຫ້ເຂົ້າໄປຫາການຕັ້ງຄ່າ."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"ທ່ານໃຊ້ທ່າທາງສະຫຼັບແອັບສຳເລັດແລ້ວ."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"ທ່ານໃຊ້ທ່າທາງສະຫຼັບແອັບສຳເລັດແລ້ວ"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"ປັດເພື່ອສະຫຼັບແອັບ"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"ເພື່ອສະຫຼັບລະຫວ່າງແອັບ, ໃຫ້ປັດຂຶ້ນຈາກລຸ່ມສຸດຂອງໜ້າຈໍທ່ານ, ກົດຄ້າງໄວ້, ຈາກນັ້ນປ່ອຍ."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"ເພື່ອສະຫຼັບລະຫວ່າງແອັບ, ໃຫ້ປັດຂຶ້ນດ້ວຍ 2 ນິ້ວຈາກລຸ່ມສຸດຂອງໜ້າຈໍທ່ານ, ກົດຄ້າງໄວ້ແລ້ວປ່ອຍ."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"ສະຫຼັບແອັບ"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"ປັດຂຶ້ນຈາກລຸ່ມສຸດຂອງໜ້າຈໍຂອງທ່ານຄ້າງໄວ້ແລ້ວປ່ອຍ"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"ດີຫຼາຍ!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"ທຸກຢ່າງພ້ອມແລ້ວ"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"ແລ້ວໆ"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"ການຕັ້ງຄ່າ"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ຮູບໜ້າຈໍ"</string>
<string name="action_split" msgid="2098009717623550676">"ແບ່ງ"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"ແຕະແອັບອື່ນເພື່ອໃຊ້ໜ້າຈໍແຍກ"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ອອກຈາກາກນເລືອກການແບ່ງໜ້າຈໍ"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"ເລືອກແອັບອື່ນເພື່ອໃຊ້ການແບ່ງໜ້າຈໍ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ແອັບ ຫຼື ອົງການຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ໃຊ້ຄຳສັ່ງນີ້"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ຂ້າມການສອນການນຳໃຊ້ການນຳທາງບໍ?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ຂ້າມ"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"ໝຸນໜ້າຈໍ"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ແຖບໜ້າວຽກ Education"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"ສະແດງການສຶກສາແຖບໜ້າວຽກແລ້ວ"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"ປິດການສຶກສາແຖບໜ້າວຽກແລ້ວ"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ລາກແອັບໄປດ້ານຂ້າງເພື່ອໃຊ້ 2 ແອັບໃນເວລາດຽວກັນ"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"ປັດຂຶ້ນຊ້າໆເພື່ອສະແດງແຖບໜ້າວຽກ"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"ຮັບການແນະນຳແອັບໂດຍອີງໃສ່ສິ່ງທີ່ເຮັດປະຈຳຂອງທ່ານ"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"ເປີດການນຳທາງແບບທ່າທາງໃນການຕັ້ງຄ່າເພື່ອເຊື່ອງແຖບໜ້າວຽກໄວ້ໂດຍອັດຕະໂນມັດ"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"ເຮັດສິ່ງຕ່າງໆໄດ້ຫຼາຍຂຶ້ນດ້ວຍແຖບໜ້າວຽກ"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"ຕໍ່ໄປ"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"ກັບຄືນ"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"ປິດ"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"ແລ້ວໆ"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"ໜ້າຫຼັກ"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"ການແຈ້ງເຕືອນ"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"ການຕັ້ງຄ່າດ່ວນ"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"ແຖບໜ້າວຽກ"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ແຖບໜ້າວຽກທີ່ສະແດງຢູ່"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ແຖບໜ້າວຽກທີ່ເຊື່ອງໄວ້ຢູ່"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ແຖບການນຳທາງ"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ສະແດງແຖບໜ້າວຽກສະເໝີ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"ປ່ຽນໂໝດການນຳທາງ"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ເສັ້ນແບ່ງແຖບໜ້າວຽກ"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ຍ້າຍໄປຊ້າຍ/ເທິງ"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ຍ້າຍໄປຂວາ/ລຸ່ມ"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ສະແດງອີກ # ແອັບ.}other{ສະແດງອີກ # ແອັບ.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ແລະ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"ການເພີ່ມແອັບໄປໃສ່ເດັສທັອບ"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ຍົກເລີກ"</string>
</resources>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index 337a046..8bb1252 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Siūlomų programų funkcija įgalinta"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Siūlomų programų funkcija išjungta"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Numatoma programa: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Turite perbraukti nuo dešiniojo ar kairiojo krašto."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Turite perbraukti nuo dešiniojo ar kairiojo krašto link ekrano vidurio ir pakelti pirštą."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Pasukite įrenginį"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Pasukite įrenginį, kad pereitumėte į naršymo gestais mokomąją medžiagą"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Turite perbraukti nuo dešiniojo ar kairiojo krašto"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Turite perbraukti nuo dešiniojo ar kairiojo krašto link ekrano vidurio ir pakelti pirštą"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Išmokote, kaip sugrįžti perbraukiant iš dešinės. Toliau sužinosite, kaip perjungti programas."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Atlikote grįžimo atgal gestą."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Nebraukite per arti ekrano apačios."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Atlikote grįžimo atgal gestą"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Nebraukite per arti ekrano apačios"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Norėd. pak. grįžimo gesto jautr., eikite į sk. „Nustatymai“"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Norėdami grįžti, perbraukite"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Norėdami grįžti į ankstesnį ekraną, perbr. nuo kairiojo arba dešinio krašto link ekrano vidurio."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Jei norite grįžti į ankstesnį ekraną, perbraukite dviem pirštais nuo kairiojo arba dešiniojo krašto link ekrano vidurio."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Turite perbraukti aukštyn nuo apatinio ekrano krašto."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Nepristabdykite prieš pakeldami pirštą."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Turite tiesiai perbraukti aukštyn."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Atlikote perėjimo į pagrindinį ekraną gestą. Toliau sužinosite, kaip grįžti atgal."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Atlikote perėjimo į pagrindinį ekraną gestą."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Grįžti"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Perbraukite nuo kairiojo arba dešiniojo krašto link ekrano vidurio"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Turite perbraukti aukštyn nuo apatinio ekrano krašto"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Nepristabdykite prieš pakeldami pirštą"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Turite tiesiai perbraukti aukštyn"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Atlikote perėjimo į pagrindinį ekraną gestą. Toliau sužinosite, kaip grįžti atgal."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Atlikote perėjimo į pagrindinį ekraną gestą"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Perbraukite, kad pereitumėte į pagrindinį ekraną"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Perbraukite aukštyn nuo ekrano apačios. Atlikus šį gestą, visada nukreipiama į pagrindinį ekraną."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Perbraukite dviem pirštais nuo ekrano apačios. Šis gestas visada nukreipia į pagrindinį ekraną."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Eikite į pagrindinį ekraną"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Jei norite bet kada pasiekti pagrindinį ekraną, perbraukite aukštyn iš ekrano apačios"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Turite perbraukti aukštyn nuo apatinio ekrano krašto."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Pabandykite palaikyti langą ilgiau prieš pakeldami pirštą."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Turite tiesiai perbraukti aukštyn, o tada pristabdyti."</string>
- <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"išmokote naudotis gestais. Gestus galite išjungti nustatymuose."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Atlikote programų perjungimo gestą."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Eiti į pagrindinį ekraną"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Perbraukite aukštyn nuo ekrano apačios"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Puiku!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Turite perbraukti aukštyn nuo apatinio ekrano krašto"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Pabandykite palaikyti langą ilgiau prieš pakeldami pirštą"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Turite tiesiai perbraukti aukštyn, o tada pristabdyti"</string>
+ <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Išmokote naudotis gestais. Gestus galite išjungti nustatymuose."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Atlikote programų perjungimo gestą"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Perbraukite, kad perjungtumėte programas"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Norėdami perjungti programas, perbraukite aukštyn nuo ekrano apačios, palaikykite ir paleiskite."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Perjunkite programas perbraukę dviem pirštais aukštyn nuo ekrano apačios, palaikę ir paleidę."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Perjungti programas"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Perbraukite aukštyn nuo ekrano apačios, palaikykite ir paleiskite"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Puiku!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Viskas nustatyta"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Atlikta"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Nustatymai"</string>
@@ -87,6 +95,7 @@
<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="8464310533320556058">"Išskaidyto ekrano režimas palietus kitą programą"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Išeiti iš išskaidyto ekrano pasirinkimo"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Išskaidyto ekrano režimą naudokite kita programa"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Jūsų organizacijoje arba naudojant šią programą neleidžiama atlikti šio veiksmo"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Praleisti naršymo mokymo programą?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Praleisti"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Pasukti ekraną"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Užduočių juostos mokomoji informacija"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Užduočių juostos patarimai rodomi"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Užduočių juostos patarimai uždaryti"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Nuvilkę programą į šoną vienu metu naudokite dvi programas"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Trumpai perbraukite, kad būtų rodoma Užduočių juosta"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Gaukite programų pasiūlymų pagal savo veiklą"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Įjungę naršymą gestais „Nustatymų“ skiltyje automatiškai paslėpkite Užduočių juostą"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Atlikite daugiau naudodami Užduočių juostą"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Kitas"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Atgal"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Uždaryti"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Atlikta"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Pagrindinis"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Pranešimai"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Spartieji nustatymai"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Užduočių juosta"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Užduočių juosta rodoma"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Užduočių juosta paslėpta"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Naršymo juosta"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Visada rodyti užduočių juostą"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Keisti naršymo režimą"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Užduočių juostos daliklis"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Perkelti aukštyn, kairėn"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Perkelti žemyn, dešinėn"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Rodyti dar # programą.}one{Rodyti dar # programą.}few{Rodyti dar # programas.}many{Rodyti dar # programos.}other{Rodyti dar # programų.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"„<xliff:g id="APP_NAME_1">%1$s</xliff:g>“ ir „<xliff:g id="APP_NAME_2">%2$s</xliff:g>“"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Pridedama programa prie darbalaukio"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Atšaukti"</string>
</resources>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index 8cf5e12..a8bff55 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Ieteicamās lietotnes ir iespējotas"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Ieteicamās lietotnes ir atspējotas"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Prognozētā lietotne: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Velciet no pašas labās vai kreisās malas."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Velciet no ekrāna labās vai kreisās malas uz vidu un atlaidiet."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Pagrieziet ierīci"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Lūdzu, pagrieziet savu ierīci, lai pabeigtu žestu navigācijas apmācību."</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Jāvelk no pašas labās vai kreisās malas."</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Jāvelk no ekrāna labās vai kreisās malas uz vidu un jāatlaiž."</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Jūs esat apguvis, kā vilkt no labās malas, lai pārietu atpakaļ. Tagad mācieties pārslēgt lietotnes."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Jūs sekmīgi veicāt atgriešanās žestu."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Nevelciet pārāk tuvu ekrāna apakšdaļai."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Jūs sekmīgi veicāt atgriešanās žestu."</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Nevelciet pārāk tuvu ekrāna apakšdaļai."</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Atgriešanās žesta jutīguma līmeni varat mainīt iestatījumos."</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Vilkšana, lai atgrieztos"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Lai atgrieztos iepriekšējā ekrānā, velciet no kreisās vai labās malas uz ekrāna vidu."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Lai pārietu uz iepriekšējo ekrānu, ar diviem pirkstiem velciet no kreisās vai labās malas uz ekrāna vidu."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Jāvelk augšup no ekrāna apakšmalas."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Pirms atlaišanas nepārtrauciet kustību."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Jāvelk tieši uz augšu."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Jūs sekmīgi veicāt sākuma ekrāna atvēršanas žestu. Tagad varat iemācīties, kā pāriet atpakaļ."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Jūs sekmīgi veicāt sākuma ekrāna atvēršanas žestu."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Atpakaļ"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Velciet no ekrāna kreisās vai labās malas uz vidu."</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Jāvelk augšup no ekrāna apakšmalas."</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Pirms atlaišanas nepārtrauciet kustību."</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Jāvelk tieši uz augšu."</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Jūs sekmīgi veicāt sākuma ekrāna atvēršanas žestu. Tagad varat iemācīties, kā pāriet atpakaļ."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Jūs sekmīgi veicāt sākuma ekrāna atvēršanas žestu."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Vilkšana, lai pārietu uz sākumu"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Velciet augšup no ekrāna apakšdaļas. Ar šo žestu vienmēr varat atvērt sākuma ekrānu."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Ar 2 pirkstiem velciet augšup no ekrāna apakšdaļas. Ar šo žestu vienmēr varat atvērt sākuma ekrānu."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Došanās uz sākuma ekrānu"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Jebkurā laikā varat doties uz sākuma ekrānu, no ekrāna apakšdaļas velkot augšup."</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Jāvelk augšup no ekrāna apakšmalas."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Mēģiniet ilgāk turēt logu, pirms atlaižat."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Jāvelk tieši uz augšu un pēc tam jāaptur kustība."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Velciet augšup no ekrāna apakšdaļas."</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Lieliski!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Jāvelk augšup no ekrāna apakšmalas."</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Mēģiniet ilgāk turēt logu, pirms atlaižat."</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Jāvelk tieši uz augšu un pēc tam jāaptur kustība."</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Jūs esat apguvis žestu izmantošanu. Lai izslēgtu žestus, pārejiet uz sadaļu Iestatījumi."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Jūs sekmīgi veicāt lietotņu pārslēgšanas žestu."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Jūs sekmīgi veicāt lietotņu pārslēgšanas žestu."</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Vilkšana, lai pārslēgtu lietotnes"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Lai pārslēgtu lietotnes, velciet augšup no ekrāna apakšdaļas, turiet un pēc tam atlaidiet."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Lai pārslēgtu lietotnes, ar 2 pirkstiem velciet no ekrāna apakšdaļas, turiet un pēc tam atlaidiet."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Lietotņu pārslēgšana"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Velciet augšup no ekrāna apakšdaļas, turiet un pēc tam atlaidiet."</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Ļoti labi!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Gatavs"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Gatavs"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Iestatījumi"</string>
@@ -87,6 +95,7 @@
<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="8464310533320556058">"Lai sadalītu ekrānu, pieskarieties citai lietotnei"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Izejiet no ekrāna sadalīšanas režīma atlases."</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Izvēlieties citu lietotni, lai sadalītu ekrānu"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Lietotne vai jūsu organizācija neatļauj veikt šo darbību."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vai izlaist navigācijas mācības?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Izlaist"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Pagriezt ekrānu"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informācija par uzdevumu joslu"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Tika atvērta uzdevumjoslas apmācība"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Tika aizvērta uzdevumjoslas apmācība"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Velciet lietotni sānis, lai izmantotu 2 lietotnes vienlaikus"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Lai skatītu Uzdevumu joslu, lēni velciet augšup."</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Lai skatītu uzdevumu joslu, lēni velciet augšup"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Skatiet ieteiktās lietotnes, balstoties uz jūsu ieradumiem"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Lai Uzdevumu josla tiktu automātiski paslēpta, iestatījumos ieslēdziet žestu navigāciju."</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Plašākas iespējas, izmantojot uzdevumu joslu"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Tālāk"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Atpakaļ"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Aizvērt"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Gatavs"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Sākums"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Paziņojumi"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Ātrie iestatīj."</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Uzdevumu josla"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Uzdevumu josla tiek rādīta"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Uzdevumu josla paslēpta"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigācijas josla"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Vienmēr rādīt uzdevumu joslu"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Mainīt navigācijas režīmu"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Uzdevumu joslas atdalītājs"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Pārvietot uz augšējo/kreiso stūri"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Pārvietot uz apakšējo/labo stūri"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Rādīt vēl # lietotni}zero{Rādīt vēl # lietotnes}one{Rādīt vēl # lietotni}other{Rādīt vēl # lietotnes}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"“<xliff:g id="APP_NAME_1">%1$s</xliff:g>” un “<xliff:g id="APP_NAME_2">%2$s</xliff:g>”"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Notiek lietotnes pievienošana datoram"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Atcelt"</string>
</resources>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index 20c462c..258a544 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -44,41 +44,49 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Предлозите за апликации се овозможени"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Предлозите за апликации се оневозможени"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Предвидена апликација: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Повлечете од крајниот десен или крајниот лев раб."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Повлечете од десниот или левиот раб кон средината на екранот и пуштете."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Ротирајте го уредот"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Ротирајте го уредот за да го завршите упатството за навигација со движење"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Повлечете од крајниот десен или крајниот лев раб"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Повлечете од десниот или левиот раб кон средината на екранот и пуштете"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Научивте како да повлекувате оддесно за враќање назад. Научете и како да се префрлате помеѓу апликациите."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Завршивте со упатството за враќање назад."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Не повлекувајте преблиску до долниот раб на екранот."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Завршивте со упатството за враќање назад"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Не повлекувајте преблиску до дното на екранот"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"За да ја промените чувствителноста, одете во „Поставки“"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Повлечете за да се вратите назад"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"За да се вратите на последниот екран, повлечете од левиот или десниот раб кон средината на екранот."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"За да се вратите на последниот екран на кој бевте, повлечете со два прста од левиот или десниот раб кон средината на екранот."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Повлечете нагоре од долниот раб на екранот."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Не правете пауза пред да пуштите."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Повлечете право нагоре."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Го научивте движењето за отворање на почетниот екран. Научете го и движењето за враќање назад."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Го научивте движењето за отворање на почетниот екран."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Враќање назад"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Повлечете од левиот или десниот раб кон средината на екранот"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Повлечете нагоре од долниот раб на екранот"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Не правете пауза пред да пуштите"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Повлечете право нагоре"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Го научивте движењето за отворање на почетниот екран. Научете го и движењето за враќање назад."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Го научивте движењето за враќање на почетниот екран"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Повлечете за да одите на почетниот екран"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Повлечете нагоре од долниот раб на екранот. Ова движење секогаш ќе ве одведе на почетниот екран."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Повлечете нагоре со два прста од долниот раб на екранот. Движењево секогаш ве носи на почетниот екран."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Одете на почетниот екран"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"За да одите на вашиот почетен екран во кое било време, повлечете нагоре од дното на екранот"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Повлечете нагоре од долниот раб на екранот."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Задржете го прозорецот подолго пред да го пуштите."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Повлечете право нагоре, а потоа застанете."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Отворање на почетниот екран"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Повлечете нагоре од дното на екранот"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Одлично сторено!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Повлечете нагоре од долниот раб на екранот"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Задржете го прозорецот подолго пред да го пуштите"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Повлечете право нагоре, а потоа застанете"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Научивте како се користат движењата. За да ги исклучите движењата, одете во „Поставки“."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Завршивте со упатството за префрлање помеѓу апликации."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Го научивте движењето за префрлање помеѓу апликации"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Повлечете за префрлање помеѓу апликации"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"За да смените апликација, повлечете нагоре од дното на екранот и задржете, па пуштете."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"За да се префрлате помеѓу апликации, повлечете нагоре со два прста од долниот раб на екранот, задржете и потоа отпуштете."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Променете ја апликацијата"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Повлечете нагоре од дното на екранот и задржете, па пуштете"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Браво!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Готово"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Готово"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Поставки"</string>
- <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Обиди се пак"</string>
+ <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Обидете се повторно"</string>
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Одлично!"</string>
<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="459504134589971527">"Повлечете нагоре за да појдете на почетен екран"</string>
+ <string name="allset_hint" msgid="459504134589971527">"Повлечете нагоре за да го отворите почетниот екран"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Допрете го копчето за почетен екран за да одите на почетниот екран"</string>
<string name="allset_description_generic" msgid="5385500062202019855">"Подготвени сте да почнете да го користите вашиот <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="default_device_name" msgid="6660656727127422487">"уред"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Слика од екранот"</string>
<string name="action_split" msgid="2098009717623550676">"Раздели"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Допрете друга аплик. за да користите поделен екран"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Излези од изборот на поделен екран"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Изберете друга апликација за да користите поделен екран"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Апликацијата или вашата организација не го дозволува дејствово"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Да се прескокне упатството за навигација?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Прескокни"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Ротирајте го екранот"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Обука за лентата со задачи"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Се појави лентата за задачи за образование"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Затворена е лентата за задачи за образование"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Повлечете апликација настрана за да користите 2 апликации"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Полека повлечете нагоре за да се прикаже „Лентата со задачи“"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Полека повлечете нагоре за да се прикаже лентата со задачи"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Добивајте предлози за апликации според вашата рутина"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Вклучете навигација со движење во „Поставки“ за автоматско сокривање на „Лентата со задачи“"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Правете повеќе со една лента со задачи"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Следно"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Назад"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Затвори"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Дома"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Известувања"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Брзи поставки"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Лента со задачи"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Лентата со задачи е прикажана"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Лентата со задачи е скриена"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Лента за навигација"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Секогаш прикажувај „Лента“"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Променете режим на навигација"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Разделник на „Лента со задачи“"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Премести горе лево"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Премести долу десно"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Прикажи уште # апликација.}one{Прикажи уште # апликација.}other{Прикажи уште # апликации.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Додавање на апликацијата во „Работна површина“"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Откажи"</string>
</resources>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index d72796a..fffcd54 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ആപ്പ് നിർദ്ദേശങ്ങൾ പ്രവർത്തനക്ഷമമാക്കി"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ആപ്പ് നിർദ്ദേശങ്ങൾ പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"പ്രവചിച്ച ആപ്പ്: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"വലത്തേയറ്റത്തെയോ ഇടത്തേയറ്റത്തെയോ അരികിൽ നിന്ന് സ്വെെപ്പ് ചെയ്യുന്നുണ്ടെന്ന് ഉറപ്പാക്കുക."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"വലതോ ഇടതോ അരികിൽ നിന്ന് സ്ക്രീനിന്റെ മധ്യഭാഗത്തേക്ക് സ്വെെപ്പ് ചെയ്ത് വിടുക."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"നിങ്ങളുടെ ഉപകരണം റൊട്ടേറ്റ് ചെയ്യുക"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"ജെസ്ച്ചർ നാവിഗേഷൻ ട്യൂട്ടോറിയൽ പൂർത്തിയാക്കാൻ നിങ്ങളുടെ ഉപകരണം റൊട്ടേറ്റ് ചെയ്യുക"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"വലത്തേയറ്റത്തെയോ ഇടത്തേയറ്റത്തെയോ അരികിൽ നിന്നാണ് സ്വെെപ്പ് ചെയ്യുന്നതെന്ന് ഉറപ്പാക്കുക"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"വലതോ ഇടതോ അരികിൽ നിന്ന് സ്ക്രീനിന്റെ മധ്യഭാഗത്തേക്കാണ് സ്വെെപ്പ് ചെയ്യുന്നതെന്ന് ഉറപ്പാക്കുക"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"മടങ്ങാൻ വലതുഭാഗത്ത് നിന്ന് സ്വൈപ്പ് ചെയ്യുന്ന രീതി മനസ്സിലായി. ഇനി, ആപ്പുകൾ മാറുന്ന രീതി അറിയുക."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"മടങ്ങുക ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"സ്ക്രീനിന്റെ ഏറ്റവും അടിഭാഗത്തേക്ക് സ്വെെപ്പ് ചെയ്യുന്നില്ലെന്ന് ഉറപ്പാക്കുക."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"മടങ്ങുക ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"സ്ക്രീനിന്റെ ഏറ്റവും അടിഭാഗത്തേക്ക് സ്വെെപ്പ് ചെയ്യുന്നില്ലെന്ന് ഉറപ്പാക്കുക"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"ബാക്ക്ജെസ്റ്ററിന്റെ സെൻസിറ്റിവിറ്റി മാറ്റാൻ ക്രമീകരണത്തിൽ പോകൂ"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"മടങ്ങാൻ സ്വെെപ്പ് ചെയ്യുക"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"മുൻ സ്ക്രീനിലേക്ക് മടങ്ങാൻ, ഇടതോ വലതോ അരികിൽ നിന്ന് സ്ക്രീനിന്റെ നടുവിലേക്ക് സ്വെെപ്പ് ചെയ്യുക."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"മുമ്പത്തെ സ്ക്രീനിലേക്ക് മടങ്ങാൻ, 2 വിരലുകൾ ഉപയോഗിച്ച് ഇടത് അല്ലെങ്കിൽ വലത് മൂലയിൽ നിന്ന് സ്ക്രീനിന്റെ മധ്യഭാഗത്തേക്ക് സ്വൈപ്പ് ചെയ്യുക."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"സ്ക്രീനിന്റെ താഴത്തെ അരികിൽ നിന്ന് മുകളിലേക്ക് സ്വെെപ്പ് ചെയ്യുന്നുണ്ടെന്ന് ഉറപ്പാക്കുക."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"വിടുന്നതിന് മുമ്പ് നിങ്ങൾ താൽക്കാലികമായി നിർത്തുന്നില്ലെന്ന് ഉറപ്പാക്കുക."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"നേരെ മുകളിലേക്ക് സ്വെെപ്പ് ചെയ്യുന്നുണ്ടെന്ന് ഉറപ്പാക്കുക."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"ഹോമിലേക്ക് പോകുക ജെസ്ച്ചർ പൂർത്തിയാക്കി. അടുത്തത്, എങ്ങനെ മടങ്ങാമെന്ന് അറിയുക."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"ഹോമിലേക്ക് പോകുക ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"മടങ്ങുക"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"ഇടതോ വലതോ അരികിൽ നിന്ന് സ്ക്രീനിന്റെ മധ്യഭാഗത്തേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"സ്ക്രീനിന്റെ താഴത്തെ അരികിൽ നിന്ന് മുകളിലേക്കാണ് സ്വെെപ്പ് ചെയ്യുന്നതെന്ന് ഉറപ്പാക്കുക"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"വിടുന്നതിന് മുമ്പ് നിങ്ങൾ താൽക്കാലികമായി നിർത്തുന്നില്ലെന്ന് ഉറപ്പാക്കുക"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"നേരെ മുകളിലേക്കാണ് സ്വെെപ്പ് ചെയ്യുന്നതെന്ന് ഉറപ്പാക്കുക"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"ഹോം ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി. അടുത്തത്, തിരികെ എങ്ങനെ പോകാമെന്ന് മനസ്സിലാക്കുക."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"ഹോം ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"ഹോമിലേക്ക് പോകാൻ സ്വെെപ്പ് ചെയ്യുക"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"സ്ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യൂ. ഈ ജെസ്ച്ചർ എപ്പോഴും ഹോം സ്ക്രീനിലേക്ക് നയിക്കുന്നു."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"സ്ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലേക്ക് 2 വിരലുകൾ കൊണ്ട് സ്വൈപ്പ് ചെയ്യൂ. ഈ ജെസ്ച്ചർ എല്ലായ്പ്പോഴും ഹോം സ്ക്രീനിലേക്ക് നയിക്കുന്നു."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"ഹോമിലേക്ക് പോകൂ"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"ഏതുസമയത്തും ഹോം സ്ക്രീനിലേക്ക് പോകാൻ, സ്ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യൂ"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"സ്ക്രീനിന്റെ താഴത്തെ അരികിൽ നിന്ന് മുകളിലേക്ക് സ്വെെപ്പ് ചെയ്യുന്നുണ്ടെന്ന് ഉറപ്പാക്കുക."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"റിലീസ് ചെയ്യുന്നതിന് മുമ്പ് വിൻഡോ കൂടുതൽ സമയം ഹോൾഡ് ചെയ്യാൻ ശ്രമിക്കുക."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"നേരെ മുകളിലേക്ക് സ്വെെപ്പ് ചെയ്ത് അൽപ്പസമയം പിടിച്ചുനിർത്തുന്നുണ്ടെന്ന് ഉറപ്പാക്കുക."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"സ്ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"കൊള്ളാം!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"സ്ക്രീനിന്റെ താഴത്തെ അരികിൽ നിന്ന് മുകളിലേക്കാണ് സ്വെെപ്പ് ചെയ്യുന്നതെന്ന് ഉറപ്പാക്കുക"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"റിലീസ് ചെയ്യുന്നതിന് മുമ്പ് വിൻഡോ കൂടുതൽ സമയം ഹോൾഡ് ചെയ്യാൻ ശ്രമിക്കുക"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"നേരെ മുകളിലേക്ക് സ്വെെപ്പ് ചെയ്ത് അൽപ്പസമയം പിടിച്ചുനിർത്തുന്നുണ്ടെന്ന് ഉറപ്പാക്കുക"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"ജെസ്ച്ചറുകൾ ഉപയോഗിക്കുന്ന രീതി നിങ്ങൾ മനസ്സിലാക്കി. ജെസ്ച്ചറുകൾ ഓഫാക്കാൻ ക്രമീകരണത്തിലേക്ക് പോകുക."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"ആപ്പുകൾ തമ്മിൽ മാറുക ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"ആപ്പുകൾ തമ്മിൽ മാറുക ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"ആപ്പുകൾ മാറാൻ സ്വെെപ്പ് ചെയ്യുക"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"ആപ്പുകൾക്കിടയിൽ മാറാൻ സ്ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്ത് പിടിച്ച ശേഷം വിടുക."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"ആപ്പുകൾക്കിടയിൽ മാറാൻ സ്ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലേക്ക് 2 വിരലുകൾ കൊണ്ട് സ്വൈപ്പ് ചെയ്ത് പിടിച്ച ശേഷം വിടുക."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"ആപ്പുകൾ മാറുക"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"നിങ്ങളുടെ സ്ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്ത് പിടിച്ച ശേഷം, വിടുക"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"അഭിനന്ദനങ്ങൾ!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"എല്ലാം സജ്ജീകരിച്ചു"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"പൂർത്തിയായി"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"ക്രമീകരണം"</string>
@@ -86,7 +94,8 @@
<string name="action_share" msgid="2648470652637092375">"പങ്കിടുക"</string>
<string name="action_screenshot" msgid="8171125848358142917">"സ്ക്രീൻഷോട്ട്"</string>
<string name="action_split" msgid="2098009717623550676">"വിഭജിക്കുക"</string>
- <string name="toast_split_select_app" msgid="8464310533320556058">"സ്പ്ലിറ്റ് സ്ക്രീനിനായി മറ്റൊരു ആപ്പ് ടാപ്പുചെയ്യൂ"</string>
+ <string name="toast_split_select_app" msgid="8464310533320556058">"സ്പ്ലിറ്റ് സ്ക്രീനിന് മറ്റൊരു ആപ്പിൽ ടാപ്പ് ചെയ്യൂ"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"സ്ക്രീൻ വിഭജന തിരഞ്ഞെടുപ്പിൽ നിന്ന് പുറത്തുകടക്കുക"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"സ്ക്രീൻ വിഭജന മോഡിന് മറ്റൊരു ആപ്പ് തിരഞ്ഞെടുക്കൂ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ഈ നടപടി എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"നാവിഗേഷൻ ട്യൂട്ടോറിയൽ ഒഴിവാക്കണോ?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ഒഴിവാക്കുക"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"സ്ക്രീൻ റൊട്ടേറ്റ് ചെയ്യുക"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ടാസ്ക്ബാർ മാർഗ്ഗനിർദ്ദേശ വിൻഡോ"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"ടാസ്ക്ക്ബാർ വിവര പാനൽ ദൃശ്യമായി"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"ടാസ്ക്ക്ബാർ വിവര പാനൽ അടച്ചു"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ഒരേ സമയം 2 ആപ്പുകൾ ഉപയോഗിക്കാൻ ഒരു ആപ്പ് വശത്തേക്ക് വലിച്ചിടൂ"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"ടാസ്ക്ബാർ ദൃശ്യമാക്കാൻ മുകളിലേക്ക് പതുക്കെ സ്വൈപ്പ് ചെയ്യൂ"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"നിങ്ങളുടെ ദിനചര്യ അനുസരിച്ച് ആപ്പ് നിർദ്ദേശങ്ങൾ നേടുക"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"ടാസ്ക്ബാർ സ്വയമേവ മറയ്ക്കാൻ ക്രമീകരണത്തിൽ ജെസ്ച്ചർ നാവിഗേഷൻ ഓണാക്കുക"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"ടാസ്ക്ബാർ ഉപയോഗിച്ച് കൂടുതൽ ചെയ്യുക"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"അടുത്തത്"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"മടങ്ങുക"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"അടയ്ക്കുക"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"പൂർത്തിയായി"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"ഹോം"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"അറിയിപ്പുകൾ"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"ദ്രുത ക്രമീകരണം"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"ടാസ്ക്ബാർ"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ടാസ്ക്ബാർ കാണിച്ചിരിക്കുന്നു"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ടാസ്ക്ബാർ മറച്ചിരിക്കുന്നു"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"നാവിഗേഷൻ ബാർ"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ടാസ്ക്ബാർ എപ്പോഴും കാണിക്കൂ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"നാവിഗേഷൻ മോഡ് മാറ്റുക"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ടാസ്ക്ബാർ ഡിവൈഡർ"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"മുകളിലേക്കോ ഇടത്തേക്കോ നീക്കുക"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"താഴേക്കോ വലത്തേക്കോ നീക്കുക"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# ആപ്പ് കൂടി കാണിക്കുക.}other{# ആപ്പുകൾ കൂടി കാണിക്കുക.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"ആപ്പ് ഡെസ്ക്ടോപ്പിലേക്ക് ചേർക്കുന്നു"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"റദ്ദാക്കുക"</string>
</resources>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index 47d840a..8c7ae78 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -23,7 +23,7 @@
<string name="recent_task_option_freeform" msgid="48863056265284071">"Чөлөөтэй хувьсах"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Сүүлийн үеийн зүйл алга"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Апп ашиглалтын тохиргоо"</string>
- <string name="recents_clear_all" msgid="5328176793634888831">"Бүгдийг устгах"</string>
+ <string name="recents_clear_all" msgid="5328176793634888831">"Бүгдийг арилгах"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Саяхны аппууд"</string>
<string name="task_view_closed" msgid="9170038230110856166">"Ажлыг хаасан"</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>
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Санал болгож буй аппуудыг идэвхжүүлсэн"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Санал болгож буй аппуудыг идэвхгүй болгосон"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Таамаглаж буй апп: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Та баруун зах эсвэл зүүн захын булангаас шударна уу."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Та баруун эсвэл зүүн булангаас дэлгэцийн дунд хэсэг хүртэл шударч, суллана уу."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Төхөөрөмжөө эргүүлэх"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Зангааны навигацын практик хичээлийг дуусгахын тулд төхөөрөмжөө эргүүлнэ үү"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Та баруун зах эсвэл зүүн захын ирмэгээс шударна уу"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Та баруун эсвэл зүүн ирмэгээс дэлгэцийн дунд хэсэг хүртэл шударч, суллана уу"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Та буцахын тулд баруунаас хэрхэн шудрахыг мэдэж авлаа. Дараа нь аппууд хооронд хэрхэн сэлгэхийг мэдэж аваарай."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Та буцах зангааг гүйцэтгэлээ."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Та дэлгэцийн доод хэсэгтэй хэт ойр бүү шудраарай."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Та буцах зангааг гүйцэтгэлээ"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Та дэлгэцийн доод хэсэгтэй хэт ойр бүү шудраарай"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Буцах зангааны мэдрэгшлийг өөрчлөх бол Тохиргоо руу очно уу"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Буцахын тулд шудрах"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Сүүлийн дэлгэц рүү буцахын тулд дэлгэцийн зүүн эсвэл баруун булангаас дунд хэсэг рүү шударна уу."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Сүүлийн дэлгэц рүү буцахын тулд 2 хуруугаараа дэлгэцийн голоос зүүн эсвэл баруун ирмэг рүү шударна уу."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Та дэлгэцийн доод булангаас дээш шударна уу."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Та суллахаасаа өмнө түр зогсоож болохгүй."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Та чигээрээ шударна уу."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Та Нүүр лүү очих зангааг гүйцэтгэлээ. Дараа нь хэрхэн буцахыг мэдэж авна уу."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Та Нүүр лүү очих зангааг гүйцэтгэлээ."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Буцах"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Зүүн эсвэл баруун ирмэгээс дэлгэцийн дунд хэсэг хүртэл шударна уу"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Та дэлгэцийн доод ирмэгээс дээш шударна уу"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Та суллахаасаа өмнө түр зогсоож болохгүй"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Та дээш чигээрээ шударна уу"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Та үндсэн нүүр лүү очих зангааг гүйцэтгэлээ. Дараа нь хэрхэн буцахыг мэдэж авна уу."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Та үндсэн нүүр лүү очих зангааг гүйцэтгэлээ."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Нүүр лүү очихын тулд шудрах"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Дэлгэцийнхээ доороос дээш шударна уу. Энэ зангаа таныг тогтмол Үндсэн нүүрэнд аваачна."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"2 хуруугаараа дэлгэцийн доороос дээш шударна уу. Энэ зангаа таныг тогтмол Үндсэн нүүрэнд аваачна."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Үндсэн нүүр лүү очих"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Үндсэн нүүр лүүгээ хүссэн үедээ очихын тулд дэлгэцийн доороос дээш шударна уу"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Та дэлгэцийн доод булангаас дээш шударна уу."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Суллахаасаа өмнө цонхыг илүү удаан дарж үзнэ үү."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Та чигээрээ шударч, дараа нь түр зогсооно уу."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Дэлгэцийнхээ доороос дээш шударна уу"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Үнэхээр сайн ажиллалаа!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Та дэлгэцийн доод ирмэгээс дээш шударна уу"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Суллахаасаа өмнө цонхыг илүү удаан дарж үзнэ үү"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Та дээш чигээрээ шударч, дараа нь түр зогсооно уу"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Та зангааг хэрхэн ашиглахыг мэдэж авлаа. Зангааг унтраахын тулд Тохиргоо руу очно уу."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Та аппуудыг сэлгэх зангааг гүйцэтгэлээ."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Та аппуудыг сэлгэх зангааг гүйцэтгэлээ"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Аппуудыг сэлгэхийн тулд шудрах"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Аппуудын хооронд сэлгэхийн тулд дэлгэцийнхээ доод хэсгээс дээш шударч, удаан дараад, суллана уу."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Аппуудын хооронд сэлгэхийн тулд 2 хуруугаараа дэлгэцийнхээ доод хэсгээс дээш шударч, удаан дараад, суллана уу."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Аппуудыг сэлгэх"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Дэлгэцийнхээ доод хэсгээс дээш шударч, удаан дараад суллана уу"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Сайн байна!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Бүгдийг тохируулсан"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Дууссан"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Тохиргоо"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Дэлгэцийн агшин дарах"</string>
<string name="action_split" msgid="2098009717623550676">"Хуваах"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Дэлгэцийг хуваахыг ашиглахын тулд өөр аппыг товш"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Дэлгэцийг хуваах сонголтоос гарах"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Дэлгэцийг хуваах горим ашиглах өөр апп сонгоно уу"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Энэ үйлдлийг апп эсвэл танай байгууллага зөвшөөрдөггүй"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Навигацын практик хичээлийг алгасах уу?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Алгасах"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Дэлгэцийг эргүүлэх"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Ажлын хэсгийн боловсрол"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Боловсролын ажлын талбар гарч ирсэн"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Боловсролын ажлын талбарыг хаасан"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"2 аппыг зэрэг ашиглахын тулд аппыг хажуу тийш чирнэ үү"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Ажлын хэсгийг харуулахын тулд аажмаар дээш шударна уу"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Таны хэвшилд тулгуурлан санал болгож буй аппуудыг аваарай"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Ажлын хэсгийг автоматаар хаахын тулд Тохиргоонд зангааны навигацыг асаана уу"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Ажлын хэсгийн тусламжтай илүү ихийг хийгээрэй"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Дараах"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Буцах"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Хаах"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Дууссан"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Гэр"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Мэдэгдэл"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Шуурхай тохиргоо"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Ажлын хэсэг"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Ажлын хэсгийг харуулсан"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Ажлын хэсгийг нуусан"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Навигацын самбар"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Ажлын хэсгийг үргэлж харуулах"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Навигацын горимыг өөрчлөх"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Ажлын хэсгийг хуваагч"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Зүүн дээд хэсэг рүү зөөх"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Баруун доод хэсэг рүү зөөх"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Өөр # аппыг харуулна уу.}other{Өөр # аппыг харуулна уу.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> болон <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Компьютерт апп нэмж байна"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Цуцлах"</string>
</resources>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index 8d77bd1..5bf47ce 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"अॅप सूचना सुरू केल्या आहेत"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"अॅप सूचना बंद केल्या आहेत"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"पूर्वानुमान केलेले अॅप: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"तुम्ही स्क्रीनच्या अगदी उजव्या किंवा अगदी डाव्या कडेला स्वाइप केल्याची खात्री करा."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"तुम्ही स्क्रीनच्या उजव्या किंवा डाव्या कडेपासून मध्यभागी स्वाइप करून सोडून दिल्याची खात्री करा."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"तुमचे डिव्हाइस फिरवा"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"कृपया जेश्चर नेव्हिगेशन ट्यूटोरियल पूर्ण करण्यासाठी तुमचे डिव्हाइस फिरवा"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"तुम्ही स्क्रीनच्या अगदी उजव्या किंवा अगदी डाव्या कडेपासून स्वाइप करत आहात खात्री करा"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"तुम्ही स्क्रीनच्या उजव्या किंवा डाव्या कडेपासून मध्यभागी स्वाइप करून सोडून देत आहात याची खात्री करा"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"मागे जाण्यासाठी उजवीकडून कसे स्वाइप करावे ते शिकलात. आता पुढे, ॲप्स कशी स्विच करायची ते जाणून घ्या."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"तुम्ही गो बॅक जेश्चर पूर्ण केले."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"तुम्ही स्क्रीनच्या तळाच्या अगदी जवळून स्वाइप करत नाही याची खात्री करा."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"तुम्ही गो बॅक जेश्चर पूर्ण केले आहे"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"तुम्ही स्क्रीनच्या तळाच्या अगदी जवळून स्वाइप करत नाही याची खात्री करा"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"बॅक जेश्चरची संवेदनशीलता बदलण्यासाठी, सेटिंग्ज वर जा"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"परत जाण्यासाठी स्वाइप करा"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"मागील स्क्रीनवर परत जाण्यासाठी, स्क्रीनच्या डाव्या किंवा उजव्या कडेपासून मध्यावर स्वाइप करा."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"मागील स्क्रीनवर परत जाण्यासाठी, दोन बोटांनी डाव्या किंवा उजव्या कडेपासून स्क्रीनच्या मध्यभागी स्वाइप करा."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"तुम्ही स्क्रीनच्या तळाच्या कडेपासून वर स्वाइप करत आहात याची खात्री करा."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"तुम्ही स्क्रीनवरून बोट उचलण्यापूर्वी ते थांबवत नाही याची खात्री करा."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"तुम्ही सरळ वर स्वाइप करत आहात याची खात्री करा."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"तुम्ही गो होम जेश्चर पूर्ण केले. आता, मागे कसे जायचे ते जाणून घ्या."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"तुम्ही गो होम जेश्चर पूर्ण केले."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"मागे जा"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"डाव्या किंवा उजव्या कडेपासून स्क्रीनच्या मध्यभागी स्वाइप करा"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"तुम्ही स्क्रीनच्या तळाच्या कडेपासून वर स्वाइप करत आहात याची खात्री करा"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"तुम्ही स्क्रीनवरून बोट उचलण्यापूर्वी थांबत नाही याची खात्री करा"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"तुम्ही सरळ वर स्वाइप करत आहात याची खात्री करा"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"तुम्ही गो होम जेश्चर पूर्ण केले आहे. आता, मागे कसे जायचे ते जाणून घ्या."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"तुम्ही गो होम जेश्चर पूर्ण केले आहे"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"होमवर जाण्यासाठी स्वाइप करा"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"तुमच्या स्क्रीनच्या तळाकडून वर स्वाइप करा. हे जेश्चर तुम्हाला नेहमी होम स्क्रीनवर घेऊन जाते."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"स्क्रीनच्या तळापासून दोन बोटांनी वर स्वाइप करा. हे जेश्चर तुम्हाला नेहमी होम स्क्रीनवर घेऊन जाते."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"होमवर जा"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"कधीही तुमच्या होम स्क्रीनवर जाण्यासाठी, तुमच्या स्क्रीनच्या तळापासून वर स्वाइप करा"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"तुम्ही स्क्रीनच्या तळाच्या कडेपासून वर स्वाइप करत आहात याची खात्री करा."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"विंडोवरून बोट उचलण्यापूर्वी थोडा वेळ ते तेथेच धरून ठेवा."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"तुम्ही सरळ वर स्वाइप करून, त्यानंतर बोट थांबवत आहात याची खात्री करा."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"तुमच्या स्क्रीनच्या तळापासून वर स्वाइप करा"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"उत्तम कामगिरी!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"तुम्ही स्क्रीनच्या तळाच्या कडेपासून वर स्वाइप करत आहात याची खात्री करा"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"विंडोवरून बोट उचलण्यापूर्वी थोडा वेळ ते तेथेच धरून ठेवा"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"तुम्ही सरळ वर स्वाइप करून थांबत आहात याची खात्री करा"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"तुम्ही जेश्चर कसे वापरायचे हे शिकलात. जेश्चर बंद करण्यासाठी, सेटिंग्ज वर जा."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"तुम्ही ॲप्स स्विच करण्याचे जेश्चर पूर्ण केले."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"तुम्ही स्विच ॲप्स जेश्चर पूर्ण केले आहे"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"अॅप्स स्विच करण्यासाठी स्वाइप करा"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"ॲप्सदरम्यान स्विच करण्यासाठी, स्क्रीनच्या तळापासून वर स्वाइप करा, धरून ठेवा, त्यानंतर सोडून द्या."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"ॲप्सदरम्यान स्विच करण्यासाठी, स्क्रीनच्या तळापासून दोन बोटांनी वर स्वाइप करा, धरून ठेवा नंतर सोडा."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"अॅप्स स्विच करा"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"तुमच्या स्क्रीनच्या तळापासून वर स्वाइप करा, धरून ठेवा, त्यानंतर सोडा"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"छान!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"सर्व तयार आहे"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"पूर्ण झाले"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"सेटिंग्ज"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"स्क्रीनशॉट"</string>
<string name="action_split" msgid="2098009717623550676">"स्प्लिट"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"स्प्लिट स्क्रीन वापरण्यासाठी दुसऱ्या ॲपवर टॅप करा"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"स्प्लिट स्क्रीन निवडीतून बाहेर पडा"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"स्प्लिट स्क्रीन वापरण्यासाठी दुसरे ॲप निवडा"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"अॅप किंवा तुमच्या संस्थेद्वारे ही क्रिया करण्याची अनुमती नाही"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"नेव्हिगेशन ट्यूटोरियल वगळायचे आहे का?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"वगळा"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"स्क्रीन फिरवा"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"टास्कबारशी संबंधित माहिती"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"टास्कबारशी संबंधित माहिती देणारे पॅनल उघडले आहे"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"टास्कबारशी संबंधित माहिती देणारे पॅनल बंद केले आहे"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"दोन ॲप्स एकत्र वापरण्यासाठी एक अॅप बाजूला ड्रॅग करा"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"टास्कबार दाखवण्यासाठी थोडे हळू वरती स्वाइप करा"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"तुमच्या दिनक्रमावर आधारित ॲप सूचना मिळवा"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"टास्कबार ऑटो हाइड करण्यासाठी सेटिंग्ज मधून जेश्चर नेव्हिगेशन सुरू करा"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"टास्कबार चा पुरेपूर वापर करा"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"पुढे"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"मागे जा"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"बंद करा"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"पूर्ण झाले"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"होम"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"सूचना"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"क्विक सेटिंग्ज"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"टास्कबार"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"टास्कबार दाखवलेला आहे"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"टास्कबार लपवलेले आहे"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"नेव्हिगेशन बार"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"नेहमी टास्कबार दाखवा"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"नेव्हिगेशन मोड बदला"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"टास्कबार विभाजक"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"सर्वात वरती/डावीकडे हलवा"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"तळाशी/उजवीकडे हलवा"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{आणखी # अॅप दाखवा.}other{आणखी # अॅप्स दाखवा.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> आणि <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"डेस्कटॉपवर ॲप जोडत आहे"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"रद्द करा"</string>
</resources>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index 3041bc7..5e61b88 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Cadangan apl didayakan"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Cadangan apl dilumpuhkan"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Apl yang diramalkan: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Pastikan anda meleret dari hujung sebelah kanan atau sebelah kiri."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Pastikan anda meleret dari tepi sebelah kanan atau kiri ke tengah skrin dan lepaskan."</string>
- <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Anda belajar cara meleret dari kanan untuk kembali. Seterusnya, ketahui cara menukar apl."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Anda telah melengkapkan gerak isyarat undur."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Pastikan anda tidak meleret terlalu dekat dengan bahagian bawah skrin."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Putarkan peranti anda"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Sila putarkan peranti anda untuk melengkapkan tutorial navigasi gerak isyarat"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Pastikan anda meleret dari hujung sebelah kanan atau hujung sebelah kiri"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Pastikan anda meleret dari tepi sebelah kanan atau kiri ke bahagian tengah skrin dan lepaskan"</string>
+ <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Anda sudah belajar cara meleret dari kanan untuk kembali. Seterusnya, ketahui cara menukar apl."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Anda telah melengkapkan gerak isyarat undur"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Pastikan anda tidak meleret terlalu dekat dengan bahagian bawah skrin"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Utk mengubah kepekaan gerak isyarat undur, pergi ke Tetapan"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Leret untuk kembali"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Untuk kembali ke skrin terakhir, leret dari tepi sebelah kiri atau kanan ke tengah skrin."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Untuk kembali ke skrin terakhir, leret dengan 2 jari dari tepi kiri atau kanan ke tengah skrin."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Pastikan anda meleret ke atas dari tepi sebelah bawah skrin."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Pastikan anda tidak menjeda sebelum melepaskan gerak isyarat tersebut."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Pastikan anda meleret terus ke atas."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Anda telah melengkapkan gerak isyarat pergi ke Laman Utama. Seterusnya, ketahui cara kembali."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Anda telah melengkapkan gerak isyarat pergi ke Laman Utama."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Kembali"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Leret dari sisi kiri atau kanan ke bahagian tengah skrin"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Pastikan anda meleret ke atas dari sisi bahagian bawah skrin"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Pastikan anda tidak menjeda sebelum melepaskan leretan tersebut"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Pastikan anda meleret terus ke atas"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Anda telah melengkapkan gerak isyarat akses laman utama. Seterusnya, ketahui cara kembali."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Anda telah melengkapkan gerak isyarat akses laman utama"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Leret untuk kembali ke laman utama"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Leret ke atas dari bahagian bawah skrin. Gerak isyarat ini sentiasa membawa anda ke Skrin utama."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Leret ke atas dengan 2 jari dari bawah skrin. Gerak isyarat ini sentiasa bawa anda ke Skrin utama."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Pergi ke laman utama"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Untuk pergi ke skrin utama anda pada bila-bila masa, leret ke atas dari bahagian bawah skrin anda"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Pastikan anda meleret ke atas dari tepi sebelah bawah skrin."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Cuba tahan tetingkap untuk tempoh yang lebih lama sebelum melepaskan."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Pastikan anda meleret ke atas, kemudian menjeda."</string>
- <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Anda mempelajari cara menggunakan gerak isyarat. Untuk mematikan gerak isyarat, pergi ke Tetapan."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Anda telah melengkapkan gerak isyarat menukar apl."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Pergi ke skrin utama"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Leret ke atas dari bahagian bawah skrin anda"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Syabas!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Pastikan anda meleret ke atas dari sisi bahagian bawah skrin"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Cuba tahan tetingkap untuk tempoh yang lebih lama sebelum melepaskan"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Pastikan anda meleret terus ke atas, kemudian menjeda"</string>
+ <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Anda sudah belajar cara menggunakan gerak isyarat. Untuk mematikan gerak isyarat, pergi ke Tetapan."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Anda telah melengkapkan gerak isyarat menukar apl"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Leret untuk menukar apl"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Untuk beralih antara apl, leret ke atas dari bahagian bawah skrin anda, tahan, kemudian lepaskan."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Untuk beralih antara apl, leret ke atas dengan 2 jari dari bawah skrin, tahan, kemudian lepaskan."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Beralih antara apl"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Leret ke atas dari bahagian bawah skrin anda, tahan, kemudian lepaskan"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Syabas!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Selesai"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Selesai"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Tetapan"</string>
@@ -78,7 +86,7 @@
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Bagus!"</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">"Siap!"</string>
- <string name="allset_hint" msgid="459504134589971527">"Leret ke atas untuk mencapai laman utama"</string>
+ <string name="allset_hint" msgid="459504134589971527">"Leret ke atas untuk ke laman utama"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Ketik butang skrin utama untuk pergi ke skrin utama anda"</string>
<string name="allset_description_generic" msgid="5385500062202019855">"Anda sudah sedia untuk mula menggunakan <xliff:g id="DEVICE">%1$s</xliff:g> anda"</string>
<string name="default_device_name" msgid="6660656727127422487">"peranti"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Tangkapan skrin"</string>
<string name="action_split" msgid="2098009717623550676">"Pisah"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Ketik apl lain untuk menggunakan skrin pisah"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Keluar daripada pilihan skrin pisah"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Pilih apl lain untuk menggunakan skrin pisah"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Tindakan ini tidak dibenarkan oleh apl atau organisasi anda"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Langkau tutorial navigasi?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Langkau"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Putar skrin"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Pendidikan bar tugas"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Pendidikan bar tugas muncul"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Pendidikan bar tugas ditutup"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Seret apl ke tepi untuk menggunakan 2 apl serentak"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Leret perlahan ke atas untuk menunjukkan Bar Tugas"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Dapatkan cadangan apl berdasarkan rutin anda"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Hidupkan navigasi gerak isyarat dalam Tetapan untuk autosembunyi Bar Tugas"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Lakukan lebih banyak perkara dengan Bar Tugas"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Seterusnya"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Kembali"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Tutup"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Selesai"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Laman Utama"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Pemberitahuan"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Tetapan Pantas"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Bar Tugas"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Bar Tugas dipaparkan"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Bar Tugas disembunyikan"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Bar navigasi"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Sentiasa paparkan Bar Tugas"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Tukar mod navigasi"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Pembahagi Bar Tugas"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Alihkan ke atas/kiri"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Alihkan ke bawah/kanan"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Tunjukkan # lagi apl.}other{Tunjukkan # lagi apl.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> dan <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Menambahkan apl pada Desktop"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Batal"</string>
</resources>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index b5ec599..6f1a276 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -24,7 +24,7 @@
<string name="recents_empty_message" msgid="7040467240571714191">"မကြာမီကဖွင့်ထားသည်များ မရှိပါ"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"အက်ပ်အသုံးပြုမှု ဆက်တင်များ"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"အားလုံးရှင်းရန်"</string>
- <string name="accessibility_recent_apps" msgid="4058661986695117371">"လတ်တလောသုံး အက်ပ်များ"</string>
+ <string name="accessibility_recent_apps" msgid="4058661986695117371">"မကြာသေးမီက အက်ပ်များ"</string>
<string name="task_view_closed" msgid="9170038230110856166">"လုပ်ဆောင်စရာ ပိတ်ထားသည်"</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">"< ၁ မိနစ်"</string>
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"အက်ပ်အကြံပြုချက်များ ဖွင့်ထားသည်"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"အက်ပ်အကြံပြုချက်များကို ပိတ်ထားသည်"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"ကြိုတင်မှန်းဆထားသော အက်ပ်− <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"ညာ သို့မဟုတ် ဘယ်ဘက်အစွန်မှ ပွတ်ဆွဲကြောင်း သေချာပါစေ။"</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"စခရင်၏ ညာ သို့မဟုတ် ဘက်ဘက်အစွန်မှ အလယ်သို့ ပွတ်ဆွဲပြီး လွှတ်လိုက်ကြောင်း သေချာပါစေ။"</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"သင့်စက်ကို လှည့်ပါ"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"လက်ဟန်ဖြင့် လမ်းညွှန်ခြင်း ရှင်းလင်းပို့ချချက်အား အပြီးသတ်ရန် သင့်စက်ကို လှည့်ပါ"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ညာ (သို့) ဘယ်အစွန်း၏ ခပ်လှမ်းလှမ်းမှ ပွတ်ဆွဲကြောင်း သေချာပါစေ"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"ဖန်သားပြင်၏ ညာ (သို့) ဘယ်အစွန်းမှ အလယ်သို့ ပွတ်ဆွဲပြီး လွှတ်လိုက်ကြောင်း သေချာပါစေ"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"နောက်ပြန်သွားရန် ညာဘက်မှပွတ်ဆွဲနည်းကို သိသွားပါပြီ။ နောက်အဆင့်တွင် အက်ပ်များပြောင်းနည်းကို လေ့လာပါ။"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"နောက်ဆုတ်လက်ဟန် ရှင်းလင်းပို့ချချက် ပြီးပါပြီ။"</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"ဖန်သားပြင် အောက်ခြေနှင့် အလွန်နီးကပ်စွာ ပွတ်ဆွဲခြင်းမရှိကြောင်း သေချာပါစေ။"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"နောက်သို့ လက်ဟန် အပြီးသတ်လိုက်ပါပြီ"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"ဖန်သားပြင် အောက်ခြေနှင့် အလွန်နီးကပ်စွာ ပွတ်ဆွဲခြင်းမရှိကြောင်း သေချာပါစေ"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"နောက်ဆုတ်လက်ဟန်၏ အာရုံခံစွမ်းကိုပြောင်းရန် ‘ဆက်တင်များ’ သို့ သွားပါ"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"နောက်ပြန်သွားရန် ပွတ်ဆွဲပါ"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"နောက်ဆုံးဖန်သားပြင်သို့ ပြန်သွားရန် ဘယ်ဘက် (သို့) ညာဘက်အစွန်မှ ဖန်သားပြင်အလယ်သို့ ပွတ်ဆွဲပါ။"</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"ပြီးခဲ့သည့်ဖန်သားပြင်သို့သွားရန် ဘယ်ဘက် (သို့) ညာဘက်အစွန်းမှ ဖန်သားပြင်အလယ်သို့ လက် ၂ ချောင်းဖြင့် ပွတ်ဆွဲပါ။"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"ဖန်သားပြင် အောက်ခြေအစွန်မှ အပေါ်သို့ ပွတ်ဆွဲကြောင်း သေချာပါစေ။"</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"လက်မလွှတ်ခင် ခဏရပ်ခြင်းမရှိကြောင်း သေချာပါစေ။"</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"အပေါ်တည့်တည့်သို့ ပွတ်ဆွဲကြောင်း သေချာပါစေ။"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"ပင်မစာမျက်နှာသို့သွားသည့် လက်ဟန် ရှင်းလင်းပို့ချချက် ပြီးပါပြီ။ နောက်အဆင့်တွင် နောက်သို့ပြန်သွားနည်းကို လေ့လာပါ။"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"ပင်မစာမျက်နှာသို့သွားသည့် လက်ဟန် ရှင်းလင်းပို့ချချက် ပြီးပါပြီ။"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"နောက်သို့"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"ဖန်သားပြင်၏ ဘယ် (သို့) ညာအစွန်းမှ အလယ်သို့ ပွတ်ဆွဲပါ"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"ဖန်သားပြင် အောက်ခြေအစွန်းမှ အပေါ်သို့ ပွတ်ဆွဲကြောင်း သေချာပါစေ"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"လက်မလွှတ်ခင် ခဏရပ်ခြင်းမရှိကြောင်း သေချာပါစေ"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"အပေါ်တည့်တည့်သို့ ပွတ်ဆွဲကြောင်း သေချာပါစေ"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"ပင်မစာမျက်နှာသို့သွားသည့် လက်ဟန် အပြီးသတ်လိုက်ပါပြီ။ နောက်အဆင့်တွင် နောက်သို့ပြန်သွားပုံကို လေ့လာပါ။"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"ပင်မစာမျက်နှာသို့သွားသည့် လက်ဟန် အပြီးသတ်လိုက်ပါပြီ"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"ပင်မစာမျက်နှာသို့သွားရန် ပွတ်ဆွဲပါ"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"သင့်ဖန်သားပြင် အောက်ခြေမှ အပေါ်သို့ပွတ်ဆွဲပါ။ ဤလက်ဟန်ဖြင့် ပင်မစာမျက်နှာသို့ အမြဲပြန်သွားနိုင်သည်။"</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"ဖန်သားပြင်အောက်မှ အပေါ်သို့ လက် ၂ ချောင်းဖြင့် ပွတ်ဆွဲပါ။ ဤလက်ဟန်က ပင်မစာမျက်နှာသို့ အမြဲပို့ပေးမည်။"</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"ပင်မစာမျက်နှာသို့ သွားပါ"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"ပင်မစာမျက်နှာသို့ အချိန်မရွေး ပြန်သွားရန် စခရင်အောက်ခြေမှ အပေါ်သို့ ပွတ်ဆွဲပါ"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"ဖန်သားပြင် အောက်ခြေအစွန်မှ အပေါ်သို့ ပွတ်ဆွဲကြောင်း သေချာပါစေ။"</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"မလွှတ်ခင် ဝင်းဒိုးကို အချိန်ကြာကြာ ဖိထားကြည့်ပါ။"</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"အပေါ်တည့်တည့်သို့ ပွတ်ဆွဲပြီးနောက် ခဏရပ်ကြောင်း သေချာပါစေ။"</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"ပင်မစာမျက်နှာသွားရန်"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"သင့်ဖန်သားပြင် အောက်ခြေမှ အပေါ်သို့ ပွတ်ဆွဲပါ"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"တော်ပါပေသည်။"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"ဖန်သားပြင် အောက်ခြေအစွန်းမှ အပေါ်သို့ ပွတ်ဆွဲကြောင်း သေချာပါစေ"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"မလွှတ်ခင် ဝင်းဒိုးကို အချိန်ကြာကြာ ဖိထားကြည့်ပါ"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"အပေါ်တည့်တည့်သို့ ပွတ်ဆွဲပြီးနောက် ခဏရပ်ကြောင်း သေချာပါစေ"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"လက်ဟန်များသုံးနည်းကို သင်သိသွားပါပြီ။ လက်ဟန်များကို ပိတ်ရန် ဆက်တင်များသို့ သွားပါ။"</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"အက်ပ်များပြောင်းသည့် လက်ဟန် ရှင်းလင်းပို့ချချက် ပြီးပါပြီ။"</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"အက်ပ်များပြောင်းသည့် လက်ဟန် အပြီးသတ်လိုက်ပါပြီ"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"အက်ပ်များပြောင်းရန် ပွတ်ဆွဲပါ"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"အက်ပ်တစ်ခုမှတစ်ခုသို့ ပြောင်းရန် စခရင်အောက်ခြေမှ အပေါ်သို့ ပွတ်ဆွဲ၍ ဖိထားပြီးနောက် လွှတ်ပါ။"</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"အက်ပ်များကြားပြောင်းရန် ဖန်သားပြင်အောက်မှ အပေါ်သို့ လက် ၂ ချောင်းဖြင့်ဆွဲ၍ ထိန်းထားပြီး လွှတ်ပါ။"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"အက်ပ်များ ကူးပြောင်းရန်"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"သင့်ဖန်သားပြင် အောက်ခြေမှ အပေါ်သို့ ပွတ်ဆွဲ၍ ဖိထားပြီးလွှတ်လိုက်ပါ"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"အလွန်ကောင်းပါသည်။"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"အားလုံးအဆင်သင့်ဖြစ်ပါပြီ"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"ပြီးပြီ"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"ဆက်တင်များ"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
<string name="action_split" msgid="2098009717623550676">"ခွဲထုတ်ရန်"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"မျက်နှာပြင် ခွဲ၍ပြသရန် အက်ပ်နောက်တစ်ခုကို တို့ပါ"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"မျက်နှာပြင် ခွဲ၍ပြသခြင်း ရွေးချယ်မှုမှ ထွက်ရန်"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"မျက်နှာပြင်ခွဲ၍ပြသခြင်းသုံးရန် နောက်အက်ပ်တစ်ခုရွေးပါ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ဤလုပ်ဆောင်ချက်ကို အက်ပ် သို့မဟုတ် သင်၏အဖွဲ့အစည်းက ခွင့်မပြုပါ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"လမ်းညွှန်ခြင်း ရှင်းလင်းပို့ချချက်ကို ကျော်မလား။"</string>
@@ -95,26 +104,31 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ကျော်ရန်"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"ဖန်သားပြင်လှည့်ရန်"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"လုပ်ဆောင်စရာဘား ပညာပေး"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"ပညာရေး လုပ်ဆောင်စရာဘား ပြထားသည်"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"ပညာရေး လုပ်ဆောင်စရာဘား ပိတ်ထားသည်"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"အက်ပ် ၂ ခုကို တစ်ပြိုက်တည်းသုံးရန် အက်ပ်ကို ဘေးသို့ ဖိဆွဲပါ"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"အက်ပ် ၂ ခု တစ်ပြိုင်တည်းသုံးရန် အက်ပ်ကို ဘေးသို့ ဖိဆွဲပါ"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Taskbar ပြရန် အပေါ်သို့ ဖြည်းဖြည်းပွတ်ဆွဲပါ"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"ပုံမှန်အစီအစဉ်ပေါ် အခြေခံ၍ အက်ပ်အကြံပြုချက်များကို ရယူပါ"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Taskbar ကို အော်တိုဝှက်ရန် ဆက်တင်များတွင် လက်ဟန်ဖြင့်လမ်းညွှန်ခြင်း ဖွင့်နိုင်သည်"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Taskbar ဖြင့် ပိုမိုလုပ်ဆောင်နိုင်ခြင်း"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"ရှေ့သို့"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"နောက်သို့"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"ပိတ်ရန်"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"ပြီးပြီ"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"ပင်မစာမျက်နှာ"</string>
- <string name="taskbar_button_a11y" msgid="5241161324875094465">"အများသုံးစွဲနိုင်မှု"</string>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"အများသုံးနိုင်မှု"</string>
<string name="taskbar_button_back" msgid="8558862226461164514">"နောက်သို့"</string>
<string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME ပြောင်းစနစ်"</string>
<string name="taskbar_button_recents" msgid="7273376136216613134">"လတ်တလောများ"</string>
<string name="taskbar_button_notifications" msgid="7471740351507357318">"အကြောင်းကြားချက်"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"အမြန်ဆက်တင်များ"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"လုပ်ဆောင်စရာဘား"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar ပြထားသည်"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar ဖျောက်ထားသည်"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"လမ်းညွှန်ဘား"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"‘လုပ်ဆောင်စရာဘား’ အမြဲပြပါ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"ရွှေ့ကြည့်သည့်မုဒ် ပြောင်းရန်"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"လုပ်ဆောင်စရာဘား ပိုင်းခြားစနစ်"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"အပေါ်/ဘယ်ဘက်သို့ ရွှေ့ရန်"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"အောက်ခြေ/ညာဘက်သို့ ရွှေ့ရန်"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{နောက်ထပ်အက်ပ် # ခု ပြပါ။}other{နောက်ထပ်အက်ပ် # ခု ပြပါ။}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> နှင့် <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"‘ဒက်စ်တော့’ တွင် အက်ပ်ကို ထည့်ခြင်း"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"မလုပ်တော့"</string>
</resources>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index f75171f..d4b8de9 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Appforslag er på"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Appforslag er slått av"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Foreslått app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Sørg for at du sveiper fra kanten helt til høyre eller venstre."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Sørg for at du sveiper fra den høyre eller venstre kanten til midten av skjermen og slipper."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Roter enheten"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Roter enheten for å fullføre veiledningen for navigasjon med bevegelser"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Sørg for at du sveiper fra kanten helt til høyre eller venstre"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Sørg for at du sveiper fra den høyre eller venstre kanten til midten av skjermen og slipper"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Du har lært hvordan du sveiper fra høyre for å gå tilbake. I neste trinn lærer du å bytte app."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Du har fullført bevegelsen for å gå tilbake."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Sørg for at du ikke sveiper for nær bunnen av skjermen."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Du har fullført bevegelsen for å gå tilbake"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Sørg for at du ikke sveiper for nær bunnen av skjermen"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Gå til Innstillinger for å endre tilbakebevegelsefølsomheten"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Sveip for å gå tilbake"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"For å gå tilbake til forrige skjerm, sveip fra venstre eller høyre kant til midten av skjermen."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"For å gå tilbake til den forrige skjermen, sveip med to fingre fra den venstre eller høyre kanten til midten av skjermen."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Sørg for at du sveiper opp fra den nederste kanten av skjermen."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Sørg for at du ikke setter på pause før du slipper."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Sørg for at du sveiper rett opp."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Du har fullført bevegelsen for å gå til startskjermen. I neste trinn ser du hvordan du går tilbake."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Du har fullført bevegelsen for å gå til startskjermen."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Gå tilbake"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Sveip fra venstre eller høyre kant til midten av skjermen"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Sørg for at du sveiper opp fra den nederste kanten av skjermen"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Sørg for at du ikke setter på pause før du slipper"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Sørg for at du sveiper rett opp"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Du har fullført bevegelsen for å gå til startskjermen. I neste trinn ser du hvordan du går tilbake."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Du har fullført bevegelsen for å gå til startskjermen"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Sveip for å gå til startskjermen"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Sveip opp fra bunnen av skjermen. Denne bevegelsen tar deg alltid til startskjermen."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Sveip opp med to fingre fra bunnen av skjermen. Denne bevegelsen tar deg alltid til startskjermen."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Gå til startskjermen"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"For å gå til startskjermen, sveip opp fra bunnen av skjermen når som helst"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Sørg for at du sveiper opp fra den nederste kanten av skjermen."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Prøv å holde vinduet lenger før du slipper."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Sørg for at du sveiper rett opp, og så stopper du."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Sveip opp fra bunnen av skjermen"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Bra jobbet!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Sørg for at du sveiper opp fra den nederste kanten av skjermen"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Prøv å holde vinduet lenger før du slipper"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Sørg for at du sveiper rett opp, og så stopper du"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Du har lært hvordan du bruker bevegelser. For å slå av bevegelser, gå til Innstillinger."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Du har fullført bevegelsen for å bytte app."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Du har fullført bevegelsen for å bytte app"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Sveip for å bytte app"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"For å bytte mellom apper, sveip opp fra bunnen av skjermen, hold, og slipp"</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"For å bytte mellom apper, sveip opp med to fingre fra bunnen av skjermen, hold, og slipp."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Bytt app"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Sveip opp fra bunnen av skjermen, hold, og slipp"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Bra!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Ferdig"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Ferdig"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Innstillinger"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skjermdump"</string>
<string name="action_split" msgid="2098009717623550676">"Del opp"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Trykk på en annen app for å bruke delt skjerm"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Avslutt valg av delt skjerm"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Velg en annen app for å bruke delt skjerm"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Appen eller organisasjonen din tillater ikke denne handlingen"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vil du hoppe over navigeringsveiledningen?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Hopp over"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Rotér skjermen"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Veiledning for oppgavelinjen"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Opplæringen for oppgavelinjen vises"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Opplæringen for oppgavelinjen er lukket"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Dra en app til siden for å bruke 2 apper samtidig"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Sveip langsomt opp for å vise oppgavelinjen"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Få appforslag som er basert på rutinene dine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Slå på navigasjon med bevegelser i innstillingene for å skjule oppgavelinjen automatisk"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Gjør mer med oppgavelinjen"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Neste"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Tilbake"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Lukk"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Ferdig"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Hjem"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Varsler"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Hurtiginnst."</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Oppgavelinje"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Oppgavelinjen vises"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Oppgavelinjen er skjult"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigasjonsrad"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Vis alltid oppgavelinjen"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Endre navigasjonsmodus"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Skille for oppgavelinjen"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Flytt til øverst/venstre"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Flytt til nederst/høyre"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Vis # app til.}other{Vis # apper til.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> og <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Legg til apper på datamaskin"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Avbryt"</string>
</resources>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index a2b76ac..b326cb4 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"सिफारिस गरिएका एप देखाउने सुविधा अन गरिएको छ"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"सिफारिस गरिएका एपहरू देखाउने सुविधा असक्षम पारिएको छ"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"पूर्वानुमान गरिएको एप: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"स्क्रिनको सबैभन्दा दायाँ किनारा वा सबैभन्दा बायाँ किनाराबाट स्वाइप गर्नुहोस्।"</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"स्क्रिनको दायाँ वा बायाँ किनाराबाट मध्य भागसम्म स्वाइप गर्नुहोस् अनि औँला उठाउनुहोस्।"</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"आफ्नो डिभाइस रोटेट गर्नुहोस्"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"इसारामार्फत गरिने नेभिगेसनको ट्युटोरियल पूरा गर्न कृपया आफ्नो डिभाइस रोटेट गर्नुहोस्"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"स्क्रिनको सबैभन्दा दायाँ किनारा वा सबैभन्दा बायाँ किनाराबाट स्वाइप गर्नुहोस्"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"स्क्रिनको दायाँ वा बायाँ किनाराबाट मध्य भागसम्म स्वाइप गर्नुहोस् अनि औँला उठाउनुहोस्"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"तपाईंले स्क्रिनको दायाँ किनाराबाट स्वाइप गरेर अघिल्लो स्क्रिनमा फर्कने तरिका सिक्नुभयो। अब एउटा एपबाट अर्को एपमा जाने तरिका सिक्नुहोस्।"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"तपाईंले \'पछाडि जानुहोस्\' नामक इसारा प्रयोग गर्ने तरिका सिक्नुभयो।"</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"स्क्रिनको फेदको धेरै नजिकसम्म स्वाइप नगर्नुहोस्।"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"तपाईंले \"पछाडि जानुहोस्\" नामक इसारा प्रयोग गर्ने तरिका सिक्नुभयो"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"स्क्रिनको फेदको धेरै नजिकसम्म स्वाइप नगर्नुहोस्"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"\'पछाडि\' नामक इसाराको संवेदनशीलता बदल्न सेटिङमा जानुहोस्"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"पछाडि जान स्वाइप गर्नुहोस्"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"यसअघिको स्क्रिनमा फर्कन स्क्रिनको बायाँ वा दायाँ किनाराबाट मध्य भागसम्म स्वाइप गर्नुहोस्।"</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"तपाईं यसअघि जुन स्क्रिनमा हुनुहुन्थ्यो त्यही स्क्रिनमा फर्कन चाहनुहुन्छ भने २ वटा औँला प्रयोग गरी स्क्रिनको बायाँ वा दायाँ किनाराबाट मध्य भागसम्म स्वाइप गर्नुहोस्।"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्।"</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"औँला उठाउनुअघि नरोकिनुहोस्।"</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"सीधै माथितिर स्वाइप गर्नुहोस्।"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"तपाईंले \'होम स्क्रिनमा जानुहोस्\' नामक इसारा प्रयोग गर्ने तरिका सिक्नुभयो। अब पछाडि जाने तरिका सिक्नुहोस्।"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"तपाईंले \'होम स्क्रिनमा जानुहोस्\' नामक इसारा प्रयोग गर्ने तरिका सिक्नुभयो।"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"पछाडि जाने तरिका"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"स्क्रिनको बायाँ वा दायाँ किनाराबाट मध्य भागसम्म स्वाइप गर्नुहोस्"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"औँला उठाउनुअघि नरोकिनुहोस्"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"सीधै माथितिर स्वाइप गर्नुहोस्"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"तपाईंले \"होम स्क्रिनमा जानुहोस्\" नामक इसारा प्रयोग गर्ने तरिका सिक्नुभयो। अब पछाडि जाने तरिका सिक्नुहोस्।"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"तपाईंले \"होम स्क्रिनमा जानुहोस्\" नामक इसारा प्रयोग गर्ने तरिका सिक्नुभयो"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"होम स्क्रिनमा जान स्वाइप गर्नुहोस्"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्। यो इसारा प्रयोग गर्दा सधैँ होम स्क्रिन खुल्छ।"</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"२ वटा औँला प्रयोग गरी स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्। यो जेस्चर प्रयोग गर्दा सधैँ होम स्क्रिन खुल्छ।"</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"होम स्क्रिनमा जाने तरिका"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"जुनसुकै बेला होम स्क्रिनमा जान स्क्रिनको पुछारबाट माथितिर स्वाइप गर्नुहोस्"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्।"</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"स्क्रिनबाट औँला उठाउनुअघि एपको विन्डोमा केही बेर छोइराख्नुहोस्।"</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"सीधै माथितिर स्वाइप गर्नुहोस् अनि रोकिनुहोस्।"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"अद्भुत!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"स्क्रिनबाट औँला उठाउनुअघि एपको विन्डोमा केही बेर छोइराख्नुहोस्"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"सीधै माथितिर स्वाइप गर्नुहोस् अनि रोकिनुहोस्"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"तपाईंले इसाराहरू प्रयोग गर्ने तरिका सिक्नुभयो। इसारा अफ गर्न सेटिङमा जानुहोस्।"</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"तपाईंले \'एउटा एपबाट अर्को एपमा जानुहोस्\' नामक इसारा प्रयोग गर्ने तरिका सिक्नुभयो।"</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"तपाईंले \"एउटा एपबाट अर्को एपमा जानुहोस्\" नामक इसारा प्रयोग गर्ने तरिका सिक्नुभयो"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"एउटा एपबाट अर्को एपमा जान स्वाइप गर्नुहोस्"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"एउटा एपबाट अर्कोमा जान स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्, छोइराख्नुहोस् अनि औँला उठाउनुहोस्।"</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"एउटा एपबाट अर्कोमा जान २ वटा औँला प्रयोग गरी स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्, छोइराख्नुहोस् अनि औँला उठाउनुहोस्।"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"एउटा एपबाट अर्को एपमा जाने तरिका"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्, छोइराख्नुहोस् अनि औँला उठाउनुहोस्"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"स्याबास!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"सबै तयार छ"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"सम्पन्न भयो"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"सेटिङ"</string>
@@ -87,23 +95,20 @@
<string name="action_screenshot" msgid="8171125848358142917">"स्क्रिनसट"</string>
<string name="action_split" msgid="2098009717623550676">"स्प्लिट गर्नुहोस्"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"स्प्लिटस्क्रिन प्रयोग गर्न अर्को एपमा ट्याप गर्नु…"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"स्प्लिट स्क्रिन मोडबाट बाहिरिनुहोस्"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"स्प्लिट स्क्रिन प्रयोग गर्न अर्को एप रोज्नुहोस्"</string>
<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>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"रद्द गर्नुहोस्"</string>
- <string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"स्किप गर्नु…"</string>
+ <string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"स्किप गर्नुहोस्"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"स्क्रिन घुमाउनुहोस्"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"टास्कबार एजुकेसन"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"टास्कबार एजुकेसन देखिएको छ"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"टास्कबार एजुकेसन बन्द गरिएको छ"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"एपलाई छेउतिर ड्र्याग गरेर एकै पटक २ वटा एप चलाउनुहोस्"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"टास्कबार देखाउन माथितिर बिस्तारै स्वाइप गर्नुहोस्"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"आफ्नो रुटिनका आधारमा एपसम्बन्धी सुझावहरू प्राप्त गर्नुहोस्"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"टास्कबार स्वतः लुकाउन सेटिङमा गई इसारामार्फत गरिने नेभिगेसन अन गर्नुहोस्"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"टास्कबार प्रयोग गरेर अझ धेरै कार्य गर्नुहोस्"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"अर्को"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"पछाडि"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"बन्द गर्नुहोस्"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"सम्पन्न भयो"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"होम"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"सूचनाहरू"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"द्रुत सेटिङ"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"टास्कबार"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"टास्कबार देखाइएको छ"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"टास्कबार लुकाइएको छ"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"नेभिगेसन बार"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"टास्कबार सधैँ देखाइयोस्"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"नेभिगेसन मोड बदल्नुहोस्"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"टास्कबार डिभाइडर"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"सिरान/बायाँतिर सार्नुहोस्"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"फेद/दायाँतिर सार्नुहोस्"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{थप # एप देखाइयोस्।}other{थप # वटा एप देखाइयोस्।}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> र <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"डेस्कटपमा एप हालिँदै छ"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"रद्द गर्नुहोस्"</string>
</resources>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index c0ffc6f..6a7efe5 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -44,38 +44,46 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"App-suggesties staan aan"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"App-suggesties staan uit"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Voorspelde app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Swipe helemaal vanaf de rechter- of linkerrand."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Swipe vanaf de rechter- of linkerrand naar het midden van het scherm en laat los."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Het apparaat draaien"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Draai het apparaat om de tutorial voor navigatie met gebaren af te ronden"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Swipe vanaf de rechter- of linkerrand"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Swipe vanaf de rechter- of linkerrand naar het midden van het scherm en laat los"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Je weet nu hoe je vanaf rechts kunt swipen om terug te gaan. Ontdek nu hoe je tussen apps schakelt."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Je weet nu hoe je het gebaar Terug maakt."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Swipe niet te dicht bij de onderkant van het scherm."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Je weet nu hoe je het gebaar Terug maakt"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Swipe niet te dicht bij de onderkant van het scherm"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Open Instellingen om de gevoeligheid van Terug te wijzigen"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Swipe om terug te gaan"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Swipe vanaf de linker- of rechterrand naar het midden om terug te gaan naar het vorige scherm."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Als je wilt teruggaan naar het laatste scherm, swipe je met 2 vingers vanaf de linker- of rechterrand naar het midden van het scherm."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Swipe vanaf de onderrand van het scherm omhoog."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Pauzeer niet voordat je loslaat."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Swipe recht omhoog."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Je hebt geleerd hoe je weer naar het startscherm gaat. Ontdek nu hoe je weer teruggaat."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Je weet nu hoe je teruggaat naar het startscherm."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Terug"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Swipe vanaf de linker- of rechterrand naar het midden van het scherm"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Swipe vanaf de onderrand van het scherm omhoog"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Pauzeer niet voordat je loslaat"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Swipe recht omhoog"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Je weet nu hoe je het gebaar Naar startscherm maakt. Ontdek als volgende hoe je kunt teruggaan."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Je weet nu hoe je teruggaat naar het startscherm"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Swipe om naar het startscherm te gaan"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Swipe omhoog vanaf de onderkant van het scherm. Met dit gebaar ga je altijd naar het startscherm."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Swipe met 2 vingers omhoog vanaf de onderkant van het scherm. Met dit gebaar ga je altijd naar het startscherm."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Naar het startscherm"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Ga op elk moment naar je startscherm door omhoog te swipen vanaf de onderkant van je scherm"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Swipe vanaf de onderrand van het scherm omhoog."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Houd het venster langer vast voordat je loslaat."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Swipe recht omhoog en pauzeer dan."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Swipe omhoog vanaf de onderkant van het scherm"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Goed gedaan"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Swipe vanaf de onderrand van het scherm omhoog"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Houd je vinger langer op het venster voordat je loslaat"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Swipe recht omhoog en pauzeer dan"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Je weet nu hoe je gebaren gebruikt. Als je gebaren wilt uitzetten, kun je dat via Instellingen doen."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Je weet nu hoe je het gebaar Schakelen tussen apps maakt."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Je weet nu hoe je het gebaar Schakelen tussen apps maakt"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Swipe om tussen apps te schakelen"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Swipe omhoog vanaf de onderkant van het scherm, houd vast en laat los om tussen apps te schakelen."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Swipe met 2 vingers omhoog vanaf de onderkant van het scherm, houd vast en laat los om tussen apps te schakelen."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Schakelen tussen apps"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Swipe omhoog vanaf de onderkant van het scherm, houd je vinger op het scherm en laat dan los"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Goed bezig"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Klaar"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Klaar"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Instellingen"</string>
<string name="gesture_tutorial_try_again" msgid="65962545858556697">"Probeer opnieuw"</string>
- <string name="gesture_tutorial_nice" msgid="2936275692616928280">"Dat gaat lekker."</string>
+ <string name="gesture_tutorial_nice" msgid="2936275692616928280">"Dat gaat lekker"</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">"Klaar"</string>
<string name="allset_hint" msgid="459504134589971527">"Swipe omhoog om naar het startscherm te gaan"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Splitsen"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tik op nog een app om je scherm te splitsen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Sluit de selectie voor gesplitst scherm"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Kies andere app om gesplitst scherm te gebruiken"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Deze actie wordt niet toegestaan door de app of je organisatie"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Navigatietutorial overslaan?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Overslaan"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Scherm draaien"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Taakbalk Onderwijs"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Uitleg van taakbalk geopend"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Uitleg van taakbalk gesloten"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Sleep een app naar de zijkant om 2 apps tegelijk te gebruiken"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Swipe kort omhoog om de Taakbalk te bekijken"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Swipe langzaam omhoog om de taakbalk te tonen"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Krijg app-suggesties op basis van je routine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Zet navigatie met gebaren aan bij Instellingen om de Taakbalk automatisch te verbergen"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Doe meer met de Taakbalk"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Volgende"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Terug"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Doe meer met de taakbalk"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Sluiten"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Klaar"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Meldingen"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Snelle instellingen"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Taakbalk"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taakbalk wordt getoond"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taakbalk is verborgen"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigatiebalk"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Taakbalk altijd tonen"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Navigatiemodus wijzigen"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Scheiding voor Taakbalk"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Naar boven/links verplaatsen"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Naar beneden/rechts verplaatsen"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Nog # app tonen.}other{Nog # apps tonen.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> en <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"App toevoegen aan desktop"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuleren"</string>
</resources>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index 1f15b28..f0a5053 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -21,7 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"ପିନ୍"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"ଫ୍ରିଫର୍ମ"</string>
- <string name="recents_empty_message" msgid="7040467240571714191">"କୌଣସି ସାମ୍ପ୍ରତିକ ଆଇଟମ୍ ନାହିଁ"</string>
+ <string name="recents_empty_message" msgid="7040467240571714191">"ବର୍ତ୍ତମାନର କୌଣସି ଆଇଟମ ନାହିଁ"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ଆପ ବ୍ୟବହାର ସେଟିଂସ"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ସବୁ ଖାଲି କରନ୍ତୁ"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"ବର୍ତ୍ତମାନର ଆପ୍"</string>
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ଆପ୍ ପରାମର୍ଶଗୁଡ଼ିକୁ ସକ୍ଷମ କରାଯାଇଛି"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ଆପ୍ ପରାମର୍ଶଗୁଡ଼ିକୁ ଅକ୍ଷମ କରାଯାଇଛି"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"ପୂର୍ବାନୁମାନ କରାଯାଇଥିବା ଆପ୍: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"ଆପଣ ସ୍କ୍ରିନର ଏକଦମ୍-ଡାହାଣ ବା ବାମ ଧାରରୁ ସ୍ୱାଇପ୍ କରୁଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ।"</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"ଆପଣ ସ୍କ୍ରିନର ଡାହାଣ ବା ବାମ ଧାରରୁ ମଝିକୁ ସ୍ୱାଇପ୍ କରି ଛାଡ଼ି ଦେଉଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ।"</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"ଆପଣଙ୍କ ଡିଭାଇସକୁ ରୋଟେଟ କରନ୍ତୁ"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"ଜେଶ୍ଚର ନାଭିଗେସନ ଟ୍ୟୁଟୋରିଆଲ ସମ୍ପୂର୍ଣ୍ଣ କରିବାକୁ ଦୟାକରି ଆପଣଙ୍କ ଡିଭାଇସ ରୋଟେଟ କରନ୍ତୁ"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ଆପଣ ସ୍କ୍ରିନର ଏକଦମ୍-ଡାହାଣ ବା ବାମ ଧାରରୁ ସ୍ୱାଇପ୍ କରୁଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ।"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"ଆପଣ ସ୍କ୍ରିନର ଡାହାଣ ବା ବାମ ଧାରରୁ ମଝିକୁ ସ୍ୱାଇପ କରି ଛାଡ଼ି ଦେଉଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"ଆପଣ ଡାହାଣରୁ ସ୍ୱାଇପ୍ କରି ପଛକୁ କିପରି ଫେରିବେ ତାହା ଜାଣିଲେ। ତା\'ପରେ, ଆପକୁ କିପରି ସ୍ୱିଚ୍ କରିବେ ତାହା ଜାଣନ୍ତୁ।"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"ଆପଣ \'ପଛକୁ ଫେରନ୍ତୁ\' ଜେଶ୍ଚର୍ ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି।"</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"ଆପଣ ସ୍କ୍ରିନର ତଳଭାଗର ଅତି ନିକଟରୁ ସ୍ୱାଇପ୍ କରୁନଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ।"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"ଆପଣ \'ପଛକୁ ଫେରନ୍ତୁ\' ଜେଶ୍ଚର ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"ଆପଣ ସ୍କ୍ରିନର ତଳଭାଗର ଅତି ନିକଟରୁ ସ୍ୱାଇପ କରୁନଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"ପଛକୁ ଫେରିବା ଜେଶ୍ଚରର ସମ୍ବେଦନଶୀଳତା ବଦଳାଇବାକୁ ସେଟିଂସକୁ ଯାଆନ୍ତୁ"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"ପଛକୁ ଫେରିବା ପାଇଁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string>
- <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"ପୂର୍ବବର୍ତ୍ତୀ ସ୍କ୍ରିନକୁ ଫେରିବା ପାଇଁ, ସ୍କ୍ରିନର ବାମ କିମ୍ବା ଡାହାଣ ଧାରରୁ ମଝିକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ।"</string>
+ <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"ପୂର୍ବ ସ୍କ୍ରିନକୁ ଫେରିବା ପାଇଁ, ସ୍କ୍ରିନର ବାମ କିମ୍ବା ଡାହାଣ ଧାରରୁ ମଝିକୁ ସ୍ୱାଇପ କରନ୍ତୁ।"</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"ପୂର୍ବ ସ୍କ୍ରିନକୁ ଫେରିବା ପାଇଁ, ସ୍କ୍ରିନର ବାମ କିମ୍ବା ଡାହାଣ ଧାରରୁ ମଝିକୁ 2ଟି ଆଙ୍ଗୁଠିରେ ସ୍ୱାଇପ କରନ୍ତୁ।"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"ଆପଣ ସ୍କ୍ରିନର ତଳ ଧାରରୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରୁଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ।"</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"ଆପଣ ଛାଡ଼ିବା ପୂର୍ବରୁ ବିରତ କରୁନଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ।"</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"ଆପଣ ସିଧା ଉପରକୁ ସ୍ୱାଇପ୍ କରୁଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ।"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"ଆପଣ ହୋମ ଜେଶ୍ଚର ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି। ତା\'ପରେ, ପଛକୁ କିପରି ଫେରିବେ ତାହା ଜାଣନ୍ତୁ।"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"ଆପଣ ହୋମ ଜେଶ୍ଚର ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି।"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"ପଛକୁ ଫେରନ୍ତୁ"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"ସ୍କ୍ରିନର ବାମ କିମ୍ବା ଡାହାଣ ଧାରରୁ ମଝିକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"ଆପଣ ସ୍କ୍ରିନର ତଳ ଧାରରୁ ଉପରକୁ ସ୍ୱାଇପ କରୁଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"ଆପଣ ଛାଡ଼ିବା ପୂର୍ବରୁ ବିରତ କରୁନଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ।"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"ଆପଣ ସିଧା ଉପରକୁ ସ୍ୱାଇପ କରୁଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"ଆପଣ \'ହୋମକୁ ଯାଆନ୍ତୁ\' ଜେଶ୍ଚର ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି। ତା\'ପରେ, ପଛକୁ କିପରି ଫେରିବେ ତାହା ଜାଣନ୍ତୁ।"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"ଆପଣ \'ମୂଳପୃଷ୍ଠାକୁ ଯାଆନ୍ତୁ\' ଜେଶ୍ଚର୍ ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି।"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"ହୋମକୁ ଯିବା ପାଇଁ ସ୍ୱାଇପ କରନ୍ତୁ"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"ଆପଣଙ୍କ ସ୍କ୍ରିନର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ। ଏହି ଜେଶ୍ଚର ସର୍ବଦା ଆପଣଙ୍କୁ ହୋମ ସ୍କ୍ରିନକୁ ନେଇଥାଏ।"</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"2ଟି ଆଙ୍ଗୁଠିରେ ସ୍କ୍ରିନର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ। ଏହି ଜେଶ୍ଚର ସର୍ବଦା ଆପଣଙ୍କୁ ହୋମ ସ୍କ୍ରିନକୁ ନେଇଥାଏ।"</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"ହୋମକୁ ଯାଆନ୍ତୁ"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"ଯେ କୌଣସି ସମୟରେ ଆପଣଙ୍କ ହୋମ ସ୍କ୍ରିନକୁ ଯିବା ପାଇଁ ଆପଣଙ୍କ ସ୍କିନର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"ଆପଣ ସ୍କ୍ରିନର ତଳ ଧାରରୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରୁଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ।"</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"ୱିଣ୍ଡୋକୁ ରିଲିଜ୍ କରିବା ପୂର୍ବରୁ ଅଧିକ ସମୟ ଧରି ରଖିବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"ଆପଣ ସିଧା ଉପରକୁ ସ୍ୱାଇପ୍ କରି ତା\'ପରେ ବିରତ କରୁଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ।"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"ଆପଣଙ୍କ ସ୍କ୍ରିନର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"ବଢ଼ିଆ କାମ!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"ଆପଣ ସ୍କ୍ରିନର ତଳ ଧାରରୁ ଉପରକୁ ସ୍ୱାଇପ କରୁଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"ୱିଣ୍ଡୋକୁ ରିଲିଜ୍ କରିବା ପୂର୍ବରୁ ଅଧିକ ସମୟ ଧରି ରଖିବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"ଆପଣ ସିଧା ଉପରକୁ ସ୍ୱାଇପ୍ କରି ତା\'ପରେ ବିରତ କରୁଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ।"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"ଜେଶ୍ଚରଗୁଡ଼ିକୁ କିପରି ବ୍ୟବହାର କରାଯିବ ଆପଣ ତାହା ଶିଖିଛନ୍ତି। ଜେଶ୍ଚରଗୁଡ଼ିକୁ ବନ୍ଦ କରିବାକୁ, ସେଟିଂସକୁ ଯାଆନ୍ତୁ।"</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"ଆପଣ \'ଆପଗୁଡ଼ିକୁ ସ୍ୱିଚ୍ କରନ୍ତୁ\' ଜେଶ୍ଚର୍ ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି।"</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"ଆପଣ \'ଆପଗୁଡ଼ିକୁ ସ୍ୱିଚ୍ କରନ୍ତୁ\' ଜେଶ୍ଚର୍ ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି।"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"ଆପଗୁଡ଼ିକୁ ସ୍ୱିଚ୍ କରିବା ପାଇଁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"ଆପଗୁଡ଼ିକ ମଧ୍ୟରେ ସ୍ୱିଚ୍ କରିବାକୁ, ସ୍କ୍ରିନର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ, ଧରି ରଖନ୍ତୁ, ତା\'ପରେ ରିଲିଜ୍ କରନ୍ତୁ।"</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"ଆପ୍ସ ମଧ୍ୟରେ ସୁଇଚ କରିବାକୁ, ସ୍କ୍ରିନର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ, ଧରି ରଖନ୍ତୁ, ତା\'ପରେ ରିଲିଜ କରନ୍ତୁ।"</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"ଆପ୍ସ ମଧ୍ୟରେ ସ୍ୱିଚ କରିବାକୁ, 2ଟି ଆଙ୍ଗୁଠିରେ ସ୍କ୍ରିନର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ କରି ଧରି ରଖନ୍ତୁ, ତା\'ପରେ ରିଲିଜ କର।"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"ଆପ୍ସ ସୁଇଚ କରନ୍ତୁ"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"ଆପଣଙ୍କ ସ୍କ୍ରିନ୍ର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରି ଧରି ରଖନ୍ତୁ, ତା\'ପରେ ରିଲିଜ୍ କରନ୍ତୁ"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"ବହୁତ ବଢ଼ିଆ!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"ସବୁ ପ୍ରସ୍ତୁତ"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"ହୋଇଗଲା"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"ସେଟିଂସ"</string>
@@ -78,7 +86,7 @@
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"ବଢ଼ିଆ!"</string>
<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="459504134589971527">"ମୂଳପୃଷ୍ଠାକୁ ଯିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string>
+ <string name="allset_hint" msgid="459504134589971527">"ହୋମକୁ ଯିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"ଆପଣଙ୍କ ହୋମ ସ୍କ୍ରିନକୁ ଯିବା ପାଇଁ ହୋମ ବଟନରେ ଟାପ କରନ୍ତୁ"</string>
<string name="allset_description_generic" msgid="5385500062202019855">"ଆପଣ ଆପଣଙ୍କ <xliff:g id="DEVICE">%1$s</xliff:g> ବ୍ୟବହାର କରିବା ଆରମ୍ଭ କରିବାକୁ ପ୍ରସ୍ତୁତ ଅଛନ୍ତି"</string>
<string name="default_device_name" msgid="6660656727127422487">"ଡିଭାଇସ"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ସ୍କ୍ରିନସଟ୍"</string>
<string name="action_split" msgid="2098009717623550676">"ସ୍ପ୍ଲିଟ୍"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"ସ୍ପ୍ଲିଟସ୍କ୍ରିନ ବ୍ୟବହାର କରିବାକୁ ଅନ୍ୟ ଏକ ଆପରେ ଟାପ କର"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ଚୟନରୁ ବାହାରି ଯାଆନ୍ତୁ"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ବ୍ୟବହାର କରିବାକୁ ଅନ୍ୟ ଏକ ଆପ ବାଛନ୍ତୁ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ଆପ୍ କିମ୍ବା ଆପଣଙ୍କ ସଂସ୍ଥା ଦ୍ୱାରା ଏହି କାର୍ଯ୍ୟକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ନାଭିଗେସନ୍ ଟ୍ୟୁଟୋରିଆଲକୁ ବାଦ୍ ଦେବେ?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ବାଦ୍ ଦିଅନ୍ତୁ"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"ସ୍କ୍ରିନ ଘୂରାନ୍ତୁ"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ଟାସ୍କବାର ଶିକ୍ଷା"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"ଟାସ୍କବାର୍ ଶିକ୍ଷା ଦେଖାଯାଇଛି"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"ଟାସ୍କବାର୍ ଶିକ୍ଷା ବନ୍ଦ ହୋଇଯାଇଛି"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ଥରକେ 2ଟି ଆପ୍ସ ବ୍ୟବହାର କରିବା ପାଇଁ ଏକ ଆପକୁ ପାର୍ଶ୍ୱକୁ ଡ୍ରାଗ କର"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"ଟାସ୍କବାର ଦେଖାଇବା ପାଇଁ ଉପରକୁ ଧୀରେ-ସ୍ୱାଇପ କରନ୍ତୁ"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"ଆପଣଙ୍କ ରୁଟିନ ଆଧାରରେ ଆପ ପରାମର୍ଶଗୁଡ଼ିକୁ ପାଆନ୍ତୁ"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"ଟାସ୍କବାରକୁ ସ୍ୱତଃ-ଲୁଚାଇବା ପାଇଁ ସେଟିଂସରେ ଜେଶ୍ଚର ନାଭିଗେସନକୁ ଚାଲୁ କରନ୍ତୁ"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"ଟାସ୍କବାର ମାଧ୍ୟମରେ ଆହୁରି ଅନେକ କିଛି କରନ୍ତୁ"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"ପରବର୍ତ୍ତୀ"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"ପଛକୁ ଫେରନ୍ତୁ"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"ହୋଇଗଲା"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"ହୋମ"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"କ୍ୱିକ ସେଟିଂସ"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"ଟାସ୍କବାର"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ଟାସ୍କବାର ଦେଖାଯାଇଛି"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ଟାସ୍କବାର ଲୁଚାଯାଇଛି"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ନାଭିଗେସନ ବାର"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ସର୍ବଦା ଟାସ୍କବାର ଦେଖାନ୍ତୁ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"ନାଭିଗେସନ ମୋଡ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ଟାସ୍କବାର ଡିଭାଇଡର"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ଶୀର୍ଷ/ବାମକୁ ମୁଭ କରନ୍ତୁ"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ନିମ୍ନ/ଡାହାଣକୁ ମୁଭ କରନ୍ତୁ"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ଅଧିକ #ଟି ଆପ ଦେଖାନ୍ତୁ।}other{ଅଧିକ #ଟି ଆପ୍ସ ଦେଖାନ୍ତୁ।}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ଏବଂ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"ଡେସ୍କଟପରେ ଆପ ଯୋଗ କରାଯାଉଛି"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ବାତିଲ କରନ୍ତୁ"</string>
</resources>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index fb809cd..c66e26f 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ਐਪ ਸੁਝਾਵਾਂ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ਐਪ ਸੁਝਾਵਾਂ ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"ਪੂਰਵ ਅਨੁਮਾਨਿਤ ਐਪ: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਸੱਜੇ ਜਾਂ ਖੱਬੇ ਪਾਸੇ ਦੇ ਬਿਲਕੁਲ ਕਿਨਾਰੇ ਤੋਂ ਸਵਾਈਪ ਕਰਦੇ ਹੋ।"</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਸੱਜੇ ਜਾਂ ਖੱਬੇ ਕਿਨਾਰੇ ਤੋਂ ਸਕ੍ਰੀਨ ਦੇ ਵਿਚਕਾਰ ਤੱਕ ਸਵਾਈਪ ਕਰਦੇ ਹੋ ਅਤੇ ਛੱਡ ਦਿੰਦੇ ਹੋ।"</string>
- <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"ਤੁਸੀਂ ਪਿੱਛੇ ਜਾਣ ਲਈ ਸੱਜੇ ਪਾਸੇ ਤੋਂ ਸਵਾਈਪ ਕਰਨ ਦਾ ਤਰੀਕਾ ਜਾਣਿਆ। ਅੱਗੇ, ਐਪਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਦਾ ਤਰੀਕਾ ਜਾਣੋ।"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"ਤੁਸੀਂ \'ਵਾਪਸ ਜਾਓ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ।"</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਲੇ ਹਿੱਸੇ ਦੇ ਬਹੁਤ ਨੇੜੇ ਸਵਾਈਪ ਨਾ ਕਰੋ।"</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"ਆਪਣੇ ਡੀਵਾਈਸ ਨੂੰ ਘੁੰਮਾਓ"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"ਕਿਰਪਾ ਕਰਕੇ ਇਸ਼ਾਰਾ ਨੈਵੀਗੇਸ਼ਨ ਟਿਊਟੋਰੀਅਲ ਨੂੰ ਪੂਰਾ ਕਰਨ ਲਈ ਆਪਣੇ ਡੀਵਾਈਸ ਨੂੰ ਘੁੰਮਾਓ"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਸੱਜੇ ਜਾਂ ਖੱਬੇ ਪਾਸੇ ਦੇ ਬਿਲਕੁਲ ਕਿਨਾਰੇ ਤੋਂ ਸਵਾਈਪ ਕਰਦੇ ਹੋ"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਸੱਜੇ ਜਾਂ ਖੱਬੇ ਕਿਨਾਰੇ ਤੋਂ ਸਕ੍ਰੀਨ ਦੇ ਵਿਚਕਾਰ ਤੱਕ ਸਵਾਈਪ ਕਰਦੇ ਹੋ ਅਤੇ ਛੱਡ ਦਿੰਦੇ ਹੋ"</string>
+ <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"ਤੁਸੀਂ ਪਿੱਛੇ ਜਾਣ ਲਈ ਸੱਜੇ ਪਾਸੇ ਤੋਂ ਸਵਾਈਪ ਕਰਨ ਦਾ ਤਰੀਕਾ ਜਾਣਿਆ। ਅੱਗੇ, ਐਪਾਂ ਵਿਚਾਲੇ ਸਵਿੱਚ ਕਰਨ ਦਾ ਤਰੀਕਾ ਜਾਣੋ।"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"ਤੁਸੀਂ \'ਵਾਪਸ ਜਾਓ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਲੇ ਹਿੱਸੇ ਦੇ ਬਹੁਤ ਨੇੜੇ ਸਵਾਈਪ ਨਾ ਕਰੋ"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"ਪਿੱਛੇ ਜਾਣ ਦੇ ਸੰਕੇਤ ਦੀ ਸੰਵੇਦਨਸ਼ੀਲਤਾ ਬਦਲਣ ਲਈ, ਸੈਟਿੰਗਾਂ \'ਤੇ ਜਾਓ"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"ਪਿੱਛੇ ਜਾਣ ਲਈ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"ਪਿਛਲੀ ਸਕ੍ਰੀਨ \'ਤੇ ਵਾਪਸ ਜਾਣ ਲਈ, ਖੱਬੇ ਜਾਂ ਸੱਜੇ ਕਿਨਾਰੇ ਤੋਂ ਸਕ੍ਰੀਨ ਦੇ ਵਿਚਕਾਰ ਤੱਕ ਸਵਾਈਪ ਕਰੋ।"</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"ਪਿਛਲੀ ਸਕ੍ਰੀਨ \'ਤੇ ਵਾਪਸ ਜਾਣ ਲਈ, ਖੱਬੇ ਜਾਂ ਸੱਜੇ ਕਿਨਾਰੇ ਤੋਂ ਸਕ੍ਰੀਨ ਦੇ ਵਿਚਕਾਰ ਤੱਕ 2 ਉਂਗਲਾਂ ਨਾਲ ਸਵਾਈਪ ਕਰੋ।"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਲੇ ਕਿਨਾਰੇ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰਦੇ ਹੋ।"</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"ਪੱਕਾ ਕਰੋ ਕਿ ਸਕ੍ਰੀਨ ਨੂੰ ਛੱਡਣ ਤੋਂ ਪਹਿਲਾਂ ਰੁਕੋ ਨਾ।"</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਸਿੱਧੇ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰਦੇ ਹੋ।"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"ਤੁਸੀਂ \'ਹੋਮ \'ਤੇ ਜਾਓ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ। ਅੱਗੇ, ਜਾਣੋ ਕਿ ਪਿੱਛੇ ਕਿਵੇਂ ਜਾਣਾ ਹੈ।"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"ਤੁਸੀਂ \'ਹੋਮ \'ਤੇ ਜਾਓ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ।"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"ਵਾਪਸ ਜਾਓ"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"ਖੱਬੇ ਜਾਂ ਸੱਜੇ ਕਿਨਾਰੇ ਤੋਂ ਸਕ੍ਰੀਨ ਦੇ ਵਿਚਕਾਰ ਤੱਕ ਸਵਾਈਪ ਕਰੋ"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਲੇ ਕਿਨਾਰੇ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"ਪੱਕਾ ਕਰੋ ਕਿ ਸਕ੍ਰੀਨ ਨੂੰ ਛੱਡਣ ਤੋਂ ਪਹਿਲਾਂ ਰੁਕੋ ਨਾ"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਸਿੱਧਾ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"ਤੁਸੀਂ \'ਹੋਮ \'ਤੇ ਜਾਓ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ। ਅੱਗੇ, ਜਾਣੋ ਕਿ ਪਿੱਛੇ ਕਿਵੇਂ ਜਾਣਾ ਹੈ।"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"ਤੁਸੀਂ \'ਹੋਮ \'ਤੇ ਜਾਓ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"ਹੋਮ \'ਤੇ ਜਾਣ ਲਈ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ। ਇਹ ਇਸ਼ਾਰਾ ਹਮੇਸ਼ਾਂ ਤੁਹਾਨੂੰ ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਲੈ ਜਾਂਦਾ ਹੈ।"</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ 2 ਉਂਗਲਾਂ ਨਾਲ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ। ਇਹ ਇਸ਼ਾਰਾ ਹਮੇਸ਼ਾਂ ਤੁਹਾਨੂੰ ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਲੈ ਜਾਂਦਾ ਹੈ।"</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਜਾਓ"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"ਕਿਸੇ ਵੀ ਸਮੇਂ ਆਪਣੀ ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਜਾਣ ਲਈ, ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਲੇ ਕਿਨਾਰੇ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰਦੇ ਹੋ।"</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"ਛੱਡਣ ਤੋਂ ਪਹਿਲਾਂ ਵਿੰਡੋ ਨੂੰ ਕੁਝ ਸਮੇਂ ਲਈ ਦਬਾ ਕੇ ਰੱਖੋ।"</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਸਿੱਧੇ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰਦੇ ਹੋ, ਫਿਰ ਰੋਕੋ।"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"ਬਹੁਤ ਵਧੀਆ!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਲੇ ਕਿਨਾਰੇ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"ਛੱਡਣ ਤੋਂ ਪਹਿਲਾਂ ਵਿੰਡੋ ਨੂੰ ਕੁਝ ਸਮੇਂ ਲਈ ਦਬਾ ਕੇ ਰੱਖੋ"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਸਿੱਧਾ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ, ਫਿਰ ਰੋਕੋ"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"ਤੁਸੀਂ ਇਸ਼ਾਰੇ ਵਰਤਣ ਬਾਰੇ ਜਾਣਿਆ। ਇਸ਼ਾਰੇ ਬੰਦ ਕਰਨ ਲਈ, ਸੈਟਿੰਗਾਂ \'ਤੇ ਜਾਓ।"</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"ਤੁਸੀਂ \'ਐਪਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰੋ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ।"</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"ਤੁਸੀਂ \'ਐਪਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰੋ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"ਐਪਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਸਵਾਈਪ ਕਰੋ"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"ਐਪਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ, ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰਕੇ ਦਬਾਈ ਰੱਖੋ ਅਤੇ ਫਿਰ ਛੱਡੋ।"</string>
- <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"ਐਪਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ, ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ 2 ਉਂਗਲਾਂ ਨਾਲ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰ ਕੇ ਦਬਾਈ ਰੱਖੋ ਅਤੇ ਫਿਰ ਛੱਡੋ।"</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"ਐਪਾਂ ਵਿਚਾਲੇ ਸਵਿੱਚ ਕਰਨ ਲਈ, ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਤੇ ਸਵਾਈਪ ਕਰ ਕੇ ਦਬਾਈ ਰੱਖੋ ਅਤੇ ਫਿਰ ਛੱਡੋ।"</string>
+ <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"ਐਪਾਂ ਵਿਚਾਲੇ ਸਵਿੱਚ ਕਰਨ ਲਈ, ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ 2 ਉਂਗਲਾਂ ਨਾਲ ਉੱਤੇ ਸਵਾਈਪ ਕਰ ਕੇ ਦਬਾਈ ਰੱਖੋ ਅਤੇ ਫਿਰ ਛੱਡੋ।"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"ਐਪਾਂ ਸਵਿੱਚ ਕਰੋ"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰ ਕੇ ਦਬਾਈ ਰੱਖੋ, ਅਤੇ ਫਿਰ ਛੱਡੋ"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"ਬਹੁਤ ਵਧੀਆ!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"ਪੂਰੀ ਤਰ੍ਹਾਂ ਤਿਆਰ"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"ਹੋ ਗਿਆ"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"ਸੈਟਿੰਗਾਂ"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
<string name="action_split" msgid="2098009717623550676">"ਸਪਲਿਟ"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਨੂੰ ਵਰਤਣ ਲਈ ਕਿਸੇ ਹੋਰ ਐਪ \'ਤੇ ਟੈਪ ਕਰੋ"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਚੋਣ ਤੋਂ ਬਾਹਰ ਜਾਓ"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਵਰਤਣ ਲਈ ਕਿਸੇ ਹੋਰ ਐਪ ਨੂੰ ਚੁਣੋ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਇਸ ਕਾਰਵਾਈ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ਕੀ ਨੈਵੀਗੇਸ਼ਨ ਟਿਊਟੋਰੀਅਲ ਨੂੰ ਛੱਡਣਾ ਹੈ?"</string>
@@ -95,17 +104,13 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ਛੱਡੋ"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"ਸਕ੍ਰੀਨ ਘੁਮਾਓ"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ਟਾਸਕਬਾਰ ਸਿੱਖਿਆ"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"ਟਾਸਕਵਾਰ ਸਿੱਖਿਆ ਪੈਨਲ ਦਿਖਾਇਆ ਗਿਆ"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"ਟਾਸਕਵਾਰ ਸਿੱਖਿਆ ਪੈਨਲ ਬੰਦ ਕੀਤਾ ਗਿਆ"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ਇੱਕ ਵਾਰ ਵਿੱਚ 2 ਐਪਾਂ ਵਰਤਣ ਲਈ, ਐਪ ਨੂੰ ਪਾਸੇ ਵੱਲ ਘਸੀਟੋ"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ਇੱਕੋ ਸਮੇਂ \'ਤੇ 2 ਐਪਾਂ ਵਰਤਣ ਲਈ, ਐਪ ਨੂੰ ਪਾਸੇ ਵੱਲ ਘਸੀਟੋ"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"ਟਾਸਕਬਾਰ ਦਿਖਾਉਣ ਲਈ ਥੋੜ੍ਹਾ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"ਤੁਹਾਡੇ ਨਿਯਮਬੱਧ ਕੰਮ ਦੇ ਆਧਾਰ \'ਤੇ ਐਪ ਸੁਝਾਅ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"ਟਾਸਕਬਾਰ ਨੂੰ ਸਵੈ-ਲੁਕਾਉਣ ਲਈ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਇਸ਼ਾਰਾ ਨੈਵੀਗੇਸ਼ਨ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"ਟਾਸਕਬਾਰ ਦਾ ਹੋਰ ਲਾਹਾ ਲਓ"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"ਅੱਗੇ"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"ਪਿੱਛੇ"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"ਬੰਦ ਕਰੋ"</string>
- <string name="taskbar_edu_done" msgid="6880178093977704569">"ਹੋ ਗਿਆ"</string>
+ <string name="taskbar_edu_done" msgid="6880178093977704569">"ਸਮਝ ਲਿਆ"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"ਘਰ"</string>
<string name="taskbar_button_a11y" msgid="5241161324875094465">"ਪਹੁੰਚਯੋਗਤਾ"</string>
<string name="taskbar_button_back" msgid="8558862226461164514">"ਪਿੱਛੇ"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"ਸੂਚਨਾਵਾਂ"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"ਟਾਸਕਬਾਰ"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ਟਾਸਕਬਾਰ ਨੂੰ ਦਿਖਾਇਆ ਗਿਆ"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ਟਾਸਕਬਾਰ ਨੂੰ ਲੁਕਾਇਆ ਗਿਆ"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ਨੈਵੀਗੇਸ਼ਨ ਵਾਲੀ ਪੱਟੀ"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ਹਮੇਸ਼ਾਂ ਟਾਸਕਬਾਰ ਦਿਖਾਓ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"ਨੈਵੀਗੇਸ਼ਨ ਮੋਡ ਬਦਲੋ"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ਟਾਸਕਬਾਰ ਵਿਭਾਜਕ"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ਸਿਖਰਲੇ/ਖੱਬੇ ਪਾਸੇ ਲੈ ਕੇ ਜਾਓ"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ਹੇਠਾਂ/ਸੱਜੇ ਪਾਸੇ ਲੈ ਕੇ ਜਾਓ"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}one{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}other{# ਹੋਰ ਐਪਾਂ ਦਿਖਾਓ।}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ਅਤੇ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"ਐਪ ਨੂੰ ਡੈਸਕਟਾਪ \'ਤੇ ਸ਼ਾਮਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ਰੱਦ ਕਰੋ"</string>
</resources>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 2761192..7f0600f 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Włączono sugestie aplikacji"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Sugestie aplikacji są wyłączone"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Przewidywana aplikacja: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Pamiętaj, aby przesuwać palcem od samej krawędzi (prawej lub lewej)."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Pamiętaj, aby przesuwać palcem od prawej lub lewej krawędzi do środka ekranu i podnieść palec."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Obróć urządzenie"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Obróć urządzenie, aby ukończyć samouczek nawigacji przy użyciu gestów"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Pamiętaj, aby przesuwać palcem od samej krawędzi (prawej lub lewej)"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Pamiętaj, aby przesuwać palcem od prawej lub lewej krawędzi do środka ekranu i podnieść palec"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Wiesz już, jak przesuwać palcem, aby przejść wstecz. Poćwicz teraz przełączanie aplikacji."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Gest przejścia wstecz został opanowany."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Pamiętaj, aby nie przesuwać palcem zbyt blisko dolnej części ekranu."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Gest przejścia wstecz został opanowany"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Pamiętaj, aby nie przesuwać palcem zbyt blisko dolnej części ekranu"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Czułość gestu cofania możesz zmienić w Ustawieniach"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Przesuń palcem, aby przejść wstecz"</string>
- <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Aby wrócić do ostatniego ekranu, przesuń palcem od lewej lub prawej krawędzi do środka ekranu."</string>
- <string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Aby wrócić do ostatniego ekranu, przesuń 2 palcami od lewej lub prawej krawędzi do środka ekranu."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Pamiętaj, aby przesuwać palcem od dolnej krawędzi ekranu."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Pamiętaj, aby przed podniesieniem palca nie było przerwy."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Pamiętaj, aby przesuwać palcem prosto do góry."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Potrafisz już przejść na ekran główny. Teraz naucz się, jak wrócić do poprzedniego ekranu."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Gest przechodzenia na ekran główny został opanowany."</string>
+ <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Aby wrócić do poprzedniego ekranu, przesuń palcem od lewej lub prawej krawędzi do środka ekranu."</string>
+ <string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Aby wrócić do poprzedniego ekranu, przesuń 2 palcami od lewej lub prawej krawędzi do środka ekranu."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Przejście wstecz"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Przesuń palcem od lewej lub prawej krawędzi do środka ekranu"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Pamiętaj, aby przesuwać palcem od dolnej krawędzi ekranu"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Pamiętaj, aby przed podniesieniem palca nie było przerwy"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Pamiętaj, aby przesuwać palcem prosto do góry"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Gest przechodzenia na ekran główny został opanowany. Poćwicz teraz wracanie do poprzedniego ekranu."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Gest przechodzenia na ekran główny został opanowany"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Przesuń palcem, aby przejść na ekran główny"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Przesuń palcem od dołu ekranu. Ten gest zawsze powoduje przejście na ekran główny."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Przesuń 2 palcami od dołu ekranu. Ten gest zawsze powoduje przejście do ekranu głównego."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Otwórz ekran główny"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Aby wyświetlić ekran główny w dowolnym momencie, przesuń od dołu do góry ekranu"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Pamiętaj, aby przesuwać palcem od dolnej krawędzi ekranu."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Przytrzymaj okno dłużej, zanim podniesiesz palec."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Pamiętaj, aby przesuwać palcem prosto do góry, a potem przerwać ruch."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Przejście na ekran główny"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Przesuń palcem z dołu ekranu w górę"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Brawo!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Pamiętaj, aby przesuwać palcem od dolnej krawędzi ekranu"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Przytrzymaj okno dłużej, zanim podniesiesz palec"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Pamiętaj, aby przesuwać palcem prosto do góry, a potem przerwać ruch"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Wiesz już, jak używać gestów. Aby wyłączyć gesty, przejdź do Ustawień."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Gest przełączania aplikacji został opanowany."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Gest przełączania aplikacji został opanowany"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Przesuń palcem, aby przełączać aplikacje"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Aby przełączać się między aplikacjami, przesuń palcem od dołu ekranu, przytrzymaj i puść."</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Aby przełączać się między aplikacjami, przesuń palcem od dołu do góry ekranu, przytrzymaj i puść."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Aby przełączać się między aplikacjami, przesuń 2 palcami od dołu ekranu, przytrzymaj i puść."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Przełącz aplikację"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Przesuń palcem z dołu ekranu w górę, przytrzymaj i puść"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Brawo!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Wszystko gotowe"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Gotowe"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Ustawienia"</string>
@@ -86,7 +94,8 @@
<string name="action_share" msgid="2648470652637092375">"Udostępnij"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Zrzut ekranu"</string>
<string name="action_split" msgid="2098009717623550676">"Podziel"</string>
- <string name="toast_split_select_app" msgid="8464310533320556058">"Kliknij drugą aplikację, aby podzielić ekran"</string>
+ <string name="toast_split_select_app" msgid="8464310533320556058">"Aby podzielić ekran, kliknij drugą aplikację"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Wyjdź z wyboru podzielonego ekranu"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Wybierz drugą aplikację, aby podzielić ekran"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Nie możesz wykonać tego działania, bo nie zezwala na to aplikacja lub Twoja organizacja"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Pominąć samouczek nawigacji?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Pomiń"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Obróć ekran"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informacje o pasku aplikacji"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Wskazówki na temat paska zadań zostały wyświetlone"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Wskazówki na temat paska zadań zostały zamknięte"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Przeciągnij aplikację w bok, aby używać 2 aplikacji naraz"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Przesuń palcem krótko w górę, aby wyświetlić pasek aplikacji"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Aby wyświetlić pasek aplikacji, przesuń palcem krótko w górę"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Otrzymuj sugestie aplikacji na podstawie rutyny"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Włącz nawigację przy użyciu gestów w Ustawieniach, aby automatycznie ukrywać pasek aplikacji"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Wykorzystaj potencjał paska aplikacji"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Dalej"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Wstecz"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Zamknij"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Gotowe"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Ekran główny"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Powiadomienia"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Szybkie ustawienia"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Pasek aplikacji"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Pasek aplikacji widoczny"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Pasek aplikacji ukryty"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Pasek nawigacyjny"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Zawsze pokazuj pasek aplikacji"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Zmień tryb nawigacji"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Linia dzielenia paska aplikacji"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Przesuń w górny lewy róg"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Przesuń w dolny prawy róg"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Pokaż jeszcze # aplikację.}few{Pokaż jeszcze # aplikacje.}many{Pokaż jeszcze # aplikacji.}other{Pokaż jeszcze # aplikacji.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodaję aplikację do komputera"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Anuluj"</string>
</resources>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index d6385da..791a127 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Sugestões de apps ativadas"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"As sugestões de apps estão desativadas"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"App prevista: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Deslize rapidamente a partir da extremidade mais à direita ou mais à esquerda."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Deslize rapidamente a partir da extremidade esquerda ou direita até ao centro do ecrã e solte."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rode o dispositivo"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rode o seu dispositivo para concluir o tutorial de navegação por gestos"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Deslize rapidamente a partir da extremidade mais à direita ou mais à esquerda"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Deslize rapidamente a partir da extremidade esquerda ou direita até ao centro do ecrã e solte"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Aprendeu a deslizar a partir da direita para retroceder. A seguir, saiba como alternar entre apps."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Concluiu o gesto para retroceder."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Garanta que não desliza rapidamente com o dedo demasiado perto da parte inferior do ecrã."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Concluiu o gesto para retroceder"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Garanta que não desliza rapidamente com o dedo demasiado perto da parte inferior do ecrã"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Altere a sensibilidade do gesto para voltar nas Definições."</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Deslize rapidamente com o dedo para retroceder"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Para voltar ao último ecrã, deslize rapidamente do limite esquerdo ou direito até ao centro do ecrã."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Para voltar ao último ecrã, deslize rapidamente com 2 dedos a partir da extremidade esquerda ou direita até ao centro do ecrã."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Garanta que desliza rapidamente com o dedo a partir do limite inferior do ecrã."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Garanta que não faz uma pausa antes de soltar."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Garanta que desliza rapidamente com o dedo para cima."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Concluiu o gesto para aceder ao ecrã principal. A seguir, saiba como retroceder."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Concluiu o gesto para aceder ao ecrã principal."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Voltar"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Deslize rapidamente a partir da extremidade esquerda ou direita para o meio do ecrã"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Deslize rapidamente com o dedo a partir do limite inferior do ecrã"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Não faça uma pausa antes de soltar"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Deslize rapidamente com o dedo para cima"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Concluiu o gesto para aceder ao ecrã principal. A seguir, saiba como retroceder."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Concluiu o gesto para aceder ao ecrã principal"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Deslize rapidamente com o dedo para aceder ao ecrã principal"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Deslize rapidamente para cima a partir da parte inferior. Este gesto abre sempre o ecrã principal."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Deslize rapidamente para cima com 2 dedos no fundo do ecrã. Este gesto abre sempre o ecrã principal."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Aceda ao ecrã principal"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Para aceder ao ecrã principal em qualquer altura, deslize rapidamente de baixo para cima no seu ecrã"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Deslize rapidamente com o dedo a partir do limite inferior do ecrã."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Experimente premir a janela durante mais tempo antes de soltar."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Garanta que desliza rapidamente com o dedo para cima e, em seguida, faz uma pausa."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Deslize rapidamente para cima a partir da parte inferior do ecrã"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Muito bem!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Deslize rapidamente com o dedo a partir do limite inferior do ecrã"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Experimente premir a janela durante mais tempo antes de soltar"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Garanta que desliza rapidamente com o dedo para cima e, em seguida, faz uma pausa"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Aprendeu a utilizar gestos. Para desativar os gestos, aceda às Definições."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Concluiu o gesto para alternar entre apps."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Concluiu o gesto para alternar entre apps"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Deslize rapidamente com o dedo para alternar entre apps"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Para alternar entre apps, deslize para cima sem soltar a partir da parte inferior do ecrã e solte."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Para mudar de app, deslize rapidamente para cima com 2 dedos sem soltar no fundo do ecrã e solte."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Mude de app"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Deslize rapidamente para cima a partir da parte inferior do ecrã sem soltar e, em seguida, solte"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Muito bem!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Está tudo pronto"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Concluído"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Definições"</string>
@@ -87,6 +95,7 @@
<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="8464310533320556058">"Toque noutra app para usar o ecrã dividido"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Saia da seleção de ecrã dividido"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Escolher outra app para usar o ecrã dividido"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Esta ação não é permitida pela app ou a sua entidade."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ignorar o tutorial de navegação?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Ignorar"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Rodar ecrã"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Educação da Barra de tarefas"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Informação da barra de tarefas apresentada"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Informação da barra de tarefas fechada"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Arraste uma app para o lado para usar 2 apps em simultâneo"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Deslize lentamente para cima para mostrar a Barra de tarefas"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Obtenha sugestões de apps baseadas na sua rotina"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Ative a navegação por gestos em Definições para ocultar automaticamente a Barra de tarefas"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Faça mais com a Barra de tarefas"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Seguinte"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Anterior"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Fechar"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Concluir"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Início"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notificações"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Definiç. rápidas"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Barra de tarefas"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tarefas apresentada"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tarefas ocultada"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegação"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Mostr. sempre Barra de tarefas"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Alterar modo de navegação"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Divisor da Barra de tarefas"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover para a parte superior esquerda"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover para a part superior direita"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar mais # app.}other{Mostrar mais # apps.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"A adicionar a app ao computador"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
</resources>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index 283ec5e..c943da5 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -23,7 +23,7 @@
<string name="recent_task_option_freeform" msgid="48863056265284071">"Forma livre"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nenhum item recente"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configurações de uso do app"</string>
- <string name="recents_clear_all" msgid="5328176793634888831">"Limpar tudo"</string>
+ <string name="recents_clear_all" msgid="5328176793634888831">"Remover tudo"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Apps recentes"</string>
<string name="task_view_closed" msgid="9170038230110856166">"Tarefa encerrada"</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>
@@ -44,37 +44,45 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"O recurso \"sugestões de apps\" está ativado"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"O recurso \"sugestões de apps\" está desativado"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"App previsto: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Deslize da borda direita ou esquerda."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Deslize da borda direita ou esquerda até o meio da tela e solte."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Gire o dispositivo"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Gire o dispositivo para concluir o tutorial da navegação por gestos"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Deslize da borda direita ou esquerda"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Deslize da borda direita ou esquerda até o meio da tela e solte"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Você aprendeu a deslizar da direita para voltar. A seguir, aprenda a trocar de app."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Você concluiu o gesto para voltar."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Não deslize perto demais da parte inferior da tela."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Você concluiu o gesto para voltar"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Não deslize perto demais da parte inferior da tela"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Mude a sensibilidade do gesto de voltar nas configurações"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Deslize para voltar"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Para voltar à tela anterior, deslize da borda esquerda ou direita até o meio da tela."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Para voltar à tela anterior, deslize da borda esquerda ou direita até o meio da tela com dois dedos."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Deslize da borda inferior da tela para cima."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Não pare antes de soltar."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Deslize para cima."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Você concluiu o gesto para acessar a tela inicial. A seguir, aprenda a voltar."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Você concluiu o gesto para acessar a tela inicial."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Volte"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Deslize da borda esquerda ou direita até o meio da tela"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Deslize da borda inferior da tela para cima"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Não pare antes de soltar"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Deslize para cima em linha reta"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Você concluiu o gesto para acessar a tela inicial. Agora, aprenda a voltar."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Você concluiu o gesto para acessar a tela inicial"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Deslizar para voltar à tela inicial"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Deslize de baixo para cima na tela. Esse gesto sempre leva você para a tela inicial."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Deslize de baixo para cima na tela com dois dedos. Esse gesto sempre leva você para a tela inicial."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Ir para a página inicial"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Para acessar sua tela inicial a qualquer momento, deslize de baixo para cima na tela"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Deslize da borda inferior da tela para cima."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Mantenha a janela pressionada por mais tempo antes de soltar."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Deslize para cima e pare."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Vá para a página inicial"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Deslize de baixo para cima na tela"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Muito bem!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Deslize da borda inferior da tela para cima"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Mantenha a janela pressionada por mais tempo antes de soltar"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Deslize para cima e pare"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Você aprendeu. Para desativar os gestos, acesse as Configurações."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Você concluiu o gesto para trocar de app."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Você concluiu o gesto para mudar de app"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Deslizar para trocar de app"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Para mudar de app, deslize de baixo para cima, mantenha a tela pressionada por um tempo e solte."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Para mudar de app, deslize de baixo para cima na tela com dois dedos, segure por um tempo e solte."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Mude de app"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Deslize de baixo para cima na tela, segure e depois solte"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Muito bem!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Tudo pronto"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Concluído"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Configurações"</string>
- <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Tentar novamente"</string>
+ <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Tente de novo"</string>
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Muito bem!"</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">"Tudo pronto!"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Capturar tela"</string>
<string name="action_split" msgid="2098009717623550676">"Dividir"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Toque em outro app para usar a tela dividida"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Sair da seleção de tela dividida"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Escolha outro app para usar na tela dividida"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Essa ação não é permitida pelo app ou pela organização"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Pular o tutorial de navegação?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Pular"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Girar a tela"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informações sobre a barra de tarefas"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"As dicas sobre a barra de tarefas foram abertas"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"As dicas sobre a barra de tarefas foram fechadas"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Arraste um app para o lado e use dois apps ao mesmo tempo"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Deslize para cima para mostrar a Barra de tarefas"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Deslize para cima devagar para mostrar a Barra de tarefas"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Receba sugestões de apps com base na sua rotina"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Ative a navegação por gestos nas configs. para ocultar a Barra de tarefas automaticamente"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Aproveite ainda mais a Barra de tarefas"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Próxima"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Voltar"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Fechar"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Concluído"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Início"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notificações"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Config. rápidas"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Barra de tarefas"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tarefas visível"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tarefas oculta"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegação"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Sempre mostrar a Barra de tarefas"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Mudar o modo de navegação"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Separador da Barra de tarefas"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover para cima/para a esquerda"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover para baixo/para a direita"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar mais # app.}one{Mostrar mais # app.}other{Mostrar mais # apps.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adicionando app ao computador"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
</resources>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index dca735c..5db7859 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Sugestiile de aplicații au fost activate"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Sugestiile de aplicații au fost dezactivate"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Aplicația estimată: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Glisează dinspre marginea dreaptă îndepărtată sau dinspre marginea stângă îndepărtată."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Glisează dinspre marginea dreaptă sau stângă spre mijlocul ecranului și eliberează."</string>
- <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Ai învățat cum să glisezi din dreapta pentru a reveni. Acum află cum să comuți aplicațiile."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Ai finalizat gestul „înapoi”."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Nu glisa prea aproape de partea de jos a ecranului."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotește dispozitivul"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rotește dispozitivul pentru a încheia tutorialul de navigare prin gesturi"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Glisează dinspre marginea dreaptă îndepărtată sau dinspre marginea stângă îndepărtată"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Glisează dinspre marginea dreaptă sau stângă spre mijlocul ecranului și eliberează"</string>
+ <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Ai învățat să revii la ecranul anterior glisând din dreapta. Acum învață să comuți între aplicații."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Ai finalizat gestul „înapoi”"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Nu glisa prea aproape de partea de jos a ecranului"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Schimbă sensibilitatea gestului „Înapoi” accesând Setările"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Glisează pentru a reveni"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Pentru a reveni la ultimul ecran, glisează de la marginea stângă sau dreaptă spre mijlocul ecranului."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Pentru a reveni la ultimul ecran, glisează cu două degete dinspre marginea stângă sau dreaptă spre mijlocul ecranului."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Glisează în sus dinspre marginea de jos a ecranului."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Nu întrerupe gestul înainte de a elibera."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Glisează direct în sus."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Ai finalizat gestul „accesează ecranul de pornire”. Acum află cum să revii."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Ai finalizat gestul „accesează ecranul de pornire”."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Înapoi"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Glisează dinspre marginea stângă sau dreaptă până la jumătatea ecranului"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Glisează în sus dinspre marginea de jos a ecranului"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Nu întrerupe gestul înainte de a elibera"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Glisează direct în sus"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Ai finalizat gestul „accesează ecranul de pornire”. În continuare, află cum să revii."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Ai finalizat gestul „accesează ecranul de pornire”"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Glisează pentru a accesa ecranul de pornire"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Glisează în sus din partea de jos a ecranului. Cu acest gest accesezi mereu ecranul de pornire."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Glisează în sus cu două degete din partea de jos. Cu acest gest accesezi mereu ecranul de pornire."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Înapoi la ecranul de pornire"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Pentru a accesa oricând ecranul de pornire, glisează în sus din partea de jos a ecranului"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Glisează în sus dinspre marginea de jos a ecranului."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Încearcă să ții fereastra mai mult înainte s-o eliberezi."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Glisează direct în sus, apoi întrerupe."</string>
- <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Ai învățat să folosești gesturi. Pentru a dezactiva gesturile, accesează Setările."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Ai finalizat gestul „comută între aplicații”."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Glisează în sus din partea de jos a ecranului"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Excelent!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Glisează în sus dinspre marginea de jos a ecranului"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Încearcă să ții fereastra mai mult înainte s-o eliberezi"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Glisează direct în sus, apoi întrerupe"</string>
+ <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Ai învățat să folosești gesturi. Pentru a dezactiva gesturile, accesează setările."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Ai finalizat gestul „comută între aplicații”"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Glisează pentru a comuta între aplicații"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Ca să comuți între aplicații, glisează în sus din partea de jos a ecranului, așteaptă și eliberează."</string>
- <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Ca să comuți între aplicații, glisează cu două degete de jos în sus, așteaptă și eliberează"</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Ca să comuți între aplicații, glisează de jos în sus, ține degetul pe ecran, apoi ridică-l."</string>
+ <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Ca să comuți între aplicații, glisează cu 2 degete de jos în sus, ține-le pe ecran, apoi ridică-le."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Comută între aplicații"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Glisează în sus din partea de jos a ecranului, ține apăsat, apoi eliberează"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Felicitări!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Gata"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Gata"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Setări"</string>
@@ -78,7 +86,7 @@
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Bravo!"</string>
<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="459504134589971527">"Glisați în sus pentru a accesa pagina principală"</string>
+ <string name="allset_hint" msgid="459504134589971527">"Glisează în sus pentru a accesa ecranul principal"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Atinge butonul ecran de pornire ca să accesezi ecranul de pornire"</string>
<string name="allset_description_generic" msgid="5385500062202019855">"Ești gata să folosești <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="default_device_name" msgid="6660656727127422487">"dispozitivul"</string>
@@ -87,6 +95,7 @@
<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="8464310533320556058">"Atinge altă aplicație pentru ecranul împărțit"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Ieși din selecția cu ecran împărțit"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Alege altă aplicație pentru ecranul împărțit"</string>
<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>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Omite"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Rotește ecranul"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informații despre bara de activități"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Panoul cu informații despre bara de activități s-a afișat"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Panoul cu informații despre bara de activități s-a închis"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Trage în lateral o aplicație ca să folosești 2 aplicații deodată"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Glisează lent în sus pentru a afișa bara de activități"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Primește sugestii de aplicații în funcție de rutina ta"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Activează navigarea prin gesturi în Setări ca să ascunzi automat bara de activități"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Fă mai multe din Bara de activități"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Înainte"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Înapoi"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Închide"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Gata"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Ecran de pornire"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Notificări"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Setări rapide"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Bară de activități"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Bara de activități este afișată"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Bara de activități este ascunsă"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Bară de navigare"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Afișează întotdeauna bara de activități"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Schimbă modul de navigare"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Separator pentru bara de activități"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mută în stânga sus"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mută în dreapta jos"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afișează încă # aplicație}few{Afișează încă # aplicații}other{Afișează încă # de aplicații}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> și <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Se adaugă aplicația pe computer"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Anulează"</string>
</resources>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index dfe8c87..a11175e 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Функция \"Рекомендуемые приложения\" включена."</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Функция \"Рекомендуемые приложения\" отключена."</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Рекомендуемое приложение: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Проведите справа налево или слева направо от самого края экрана."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Проведите от правого или левого края экрана до середины дисплея и отпустите палец."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Поверните устройство"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Чтобы перейти к руководству по жестам, нужно повернуть устройство."</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Проведите справа налево или слева направо от самого края экрана."</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Проведите от правого или левого края экрана к центру и отпустите палец."</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Теперь вы знаете, как вернуться, проведя справа налево. Далее мы расскажем, как переключаться между приложениями."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Вы выполнили жест для перехода назад."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Проведите пальцем не слишком близко к нижнему краю экрана."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Вы выполнили жест для возврата на предыдущий экран."</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Проведите пальцем не слишком близко к нижнему краю экрана."</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Уровень чувствительности можно изменить в настройках."</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Возврат к предыдущему экрану"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Чтобы вернуться к предыдущему экрану, проведите от левого или правого края дисплея к центру."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Чтобы вернуться на предыдущий экран, проведите двумя пальцами от левого или правого края экрана к центру."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Проведите снизу вверх от самого края экрана."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Не приостанавливайтесь перед тем, как отпустить палец."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Проведите по экрану ровно вверх."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Вы выполнили жест для перехода на главный экран. Далее мы расскажем, как вернуться назад."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Вы выполнили жест для перехода на главный экран."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Как вернуться к предыдущему экрану"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Проведите от левого или правого края экрана к центру."</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Проведите снизу вверх от самого края экрана."</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Прежде чем отпустить палец, не задерживайте его в одной точке."</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Проведите по экрану ровно вверх."</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Вы выполнили жест для перехода на главный экран. Далее мы расскажем, как возвращаться назад."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Вы выполнили жест для перехода на главный экран."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Переход на главный экран"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Проведите вверх от нижнего края дисплея. Этот жест открывает главный экран."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Проведите двумя пальцами вверх от нижнего края экрана. Этот жест открывает главный экран."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Переход на главный экран"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Чтобы открыть главный экран, проведите снизу вверх по экрану."</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Проведите снизу вверх от самого края экрана."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Прежде чем отпускать палец, задержите его на дисплее подольше."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Проведите по экрану ровно вверх, а затем задержите палец в крайнем положении."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Как перейти на главный экран"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Проведите вверх от нижнего края экрана."</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"У вас получилось!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Проведите снизу вверх от самого края экрана."</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Прежде чем отпустить палец, задержите его на экране немного дольше."</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Проведите по экрану ровно вверх и задержите палец в конце."</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Теперь вы знаете, как использовать жесты. Чтобы отключить их, перейдите в настройки."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Вы выполнили жест для переключения между приложениями."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Вы выполнили жест для переключения между приложениями."</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Переключение между приложениями"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Чтобы переключиться между приложениями‚ проведите по экрану снизу вверх, задержите палец, а затем отпустите."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Чтобы сменить приложение, проведите двумя пальцами снизу вверх, задержите пальцы, а затем отпустите."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Как переключаться между приложениями"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Проведите вверх от нижнего края экрана, задержите палец в одной точке и отпустите."</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Отлично!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Готово"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Готово"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Настройки"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
<string name="action_split" msgid="2098009717623550676">"Разделить"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Для разделения экрана выберите другое приложение."</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Выйдите из режима разделения экрана."</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Выберите другое приложение для разделения экрана."</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Это действие заблокировано приложением или организацией."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Пропустить руководство по жестам?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Пропустить"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Повернуть экран"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Обучение по работе с панелью задач"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Обучение по работе с панелью задач показано"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Обучение по работе с панелью задач скрыто"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Используйте два приложения сразу, перетащив одно в сторону."</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Чтобы открыть панель задач, медленно проведите снизу вверх."</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Получайте рекомендации, основанные на ваших действиях."</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Чтобы панель задач скрывалась автоматически, включите навигацию с помощью жестов."</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Используйте все возможности панели задач"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Далее"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Назад"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Закрыть"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Главный экран"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Уведомления"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Быстрые настройки"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Панель задач"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Панель задач показана"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Панель задач скрыта"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Панель навигации"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Всегда показывать панель задач"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Изменить режим навигации"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Разделитель панели задач"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Переместить вверх или влево"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Переместить вниз или вправо"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показать ещё # приложение}one{Показать ещё # приложение}few{Показать ещё # приложения}many{Показать ещё # приложений}other{Показать ещё # приложения}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Добавление приложения на компьютер"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Отмена"</string>
</resources>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index 4cb1adf..3722b2f 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"යෙදුම් යෝජනා සබලිතයි"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"යෙදුම් යෝජනා අබල කර ඇත"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"පුරෝකථනය කළ යෙදුම: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"ඔබ ඈත දකුණු හෝ ඈත වම් දාරයේ ස්වයිප් කරන බව සහතික කර ගන්න."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"ඔබ දකුණු හෝ වම් දාරයේ සිට තිරයේ මැදට ස්වයිප් කර අත හරින බව සහතික කර ගන්න."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"ඔබේ උපාංගය කරකවන්න"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"අභින සංචාලන නිබන්ධනය සම්පූර්ණ කිරීම සඳහා ඔබේ උපාංගය කරකවන්න"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ඔබ ඈත දකුණු හෝ ඈත වම් දාරයේ සිට ස්වයිප් කරන බව සහතික කර ගන්න"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"ඔබ දකුණු හෝ වම් දාරයේ සිට තිරයේ මැදට ස්වයිප් කර අත හරින බව සහතික කර ගන්න"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"ආපසු යාමට දකුණේ සිට ස්වයිප් කරන්නේ කෙසේදැයි ඔබ දැන ගත්තේය. ඊළඟට, යෙදුම් මාරු කරන ආකාරය දැන ගන්න."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"ඔබ ආපසු යාමේ ඉංගිතය සම්පූර්ණ කරන ලදි."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"ඔබ තිරයේ පහළට ඉතාම සමීපව ස්වයිප් නොකරන බවට සහතික කර ගන්න."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"ඔබ ආපසු යාමේ ඉංගිතය සම්පූර්ණ කළා"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"ඔබ තිරයේ පහළට ඉතාම සමීපව ස්වයිප් නොකරන බවට සහතික කර ගන්න"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"ආපසු ඉංගිතයෙහි සංවේදීතාව වෙනස් කිරීමට, සැකසීම් වෙත යන්න"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"ආපසු යාමට ස්වයිප් කරන්න"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"අවසාන තිරයට ආපසු යාමට, වම් හෝ දකුණු දාරයෙන් තිරයේ මැදට ස්වයිප් කරන්න."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"අවසාන තිරයට ආපසු යාමට, වම් හෝ දකුණු දාරයෙන් තිරයේ මැදට ඇඟිලි 2කින් ස්වයිප් කරන්න."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"ඔබ තිරයේ පහළ දාරයේ සිට ඉහළට ස්වයිප් කරන බව සහතික කර ගන්න."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"යාමට ඉඩ හැරීමට පෙර ඔබ විරාමයක් නොගන්නා බව සහතික කර ගන්න."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"ඔබ කෙලින්ම ඉහළට ස්වයිප් කරන බව සහතික කර ගන්න."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"ඔබ මුල් පිටුවට යාමේ ඉංගිතය සම්පූර්ණ කරන ලදි. ඊළඟට, ආපසු යන ආකාරය දැන ගන්න."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"ඔබ මුල් පිටුවට යාමේ ඉංගිතය සම්පූර්ණ කරන ලදි."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"ආපසු යන්න"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"වම් හෝ දකුණු කෙළවරේ සිට තිරයේ මැදට ස්වයිප් කරන්න"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"ඔබ තිරයේ පහළ දාරයේ සිට ඉහළට ස්වයිප් කරන බව සහතික කර ගන්න"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"යාමට ඉඩ හැරීමට පෙර ඔබ විරාමයක් නොගන්නා බව සහතික කර ගන්න"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"ඔබ කෙලින්ම ඉහළට ස්වයිප් කරන බව සහතික කර ගන්න"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"ඔබ මුල් පිටුවට යාමේ ඉංගිතය සම්පූර්ණ කළා. මීළඟට, ආපසු යන ආකාරය දැන ගන්න."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"ඔබ මුල් පිටුවට යාමේ ඉංගිතය සම්පූර්ණ කළා"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"මුල් පිටුවට යාමට ස්වයිප් කරන්න"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"ඔබගේ තිරයේ පහළින් උඩට ස්වයිප් කරන්න.මෙම ඉංගිතය සැම විටම ඔබව මුල් තිරයට ගෙන යයි."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"තිරයේ පහළම සිට ඇඟිලි 2කින් ඉහළට ස්වයිප් කරන්න. මෙම ඉංගිතය සැම විටම ඔබව මුල් තිරයට ගෙන යයි."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"මුල් පිටුවට යන්න"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"ඕනෑම වේලාවක දී ඔබේ මුල් තිරයට යාම සඳහා, ඔබේ තිරයෙහි පහළ සිට ඉහළට ස්වයිප් කරන්න"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"ඔබ තිරයේ පහළ දාරයේ සිට ඉහළට ස්වයිප් කරන බව සහතික කර ගන්න."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"මුදා හැරීමට පෙර කවුළුව වැඩි වේලාවක් රඳවා තබා ගැනීමට උත්සාහ කරන්න."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"ඔබ කෙලින්ම ඉහළට ස්වයිප් කර, අනතුරුව විරාම කරන බව සහතික කර ගන්න."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"ඔබේ තිරයේ පහළ සිට උඩට ස්වයිප් කරන්න"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"අනර්ඝ වැඩක්!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"ඔබ තිරයේ පහළ දාරයේ සිට ඉහළට ස්වයිප් කරන බව සහතික කර ගන්න"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"මුදා හැරීමට පෙර කවුළුව වැඩි වේලාවක් රඳවා ගැනීමට උත්සාහ කරන්න"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"ඔබ කෙළින්ම ඉහළට ස්වයිප් කර, පසුව විරාම කරන බව සහතික කර ගන්න"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"ඔබ ඉංගිත භාවිත කරන ආකාරය දැන ගෙන ඇත. ඉංගිත ක්රියාවිරහිත කිරීමට, සැකසීම් වෙත යන්න."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"ඔබ යෙදුම් මාරු කිරීමේ ඉංගිතය සම්පූර්ණ කර ඇත."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"ඔබ යෙදුම් මාරු කිරීමේ ඉංගිතය සම්පූර්ණ කළා"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"යෙදුම් මාරු කිරීමට ස්වයිප් කරන්න"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"යෙදුම් අතර මාරු වීමට, ඔබගේ තිරයේ පහළම සිට උඩට ස්වයිප් කර, අල්ලාගෙන සිට, අනතුරුව මුදා හරින්න."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"යෙදුම් අතර මාරු වීමට, ඔබගේ තිරයේ පහළම සිට උඩට ඇඟිලි 2කින් ස්වයිප් කර, අල්ලාගෙන සිට, අනතුරුව මුදා හරින්න."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"යෙදුම් මාරු කරන්න"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"ඔබේ තිරයේ පහළ සිට ඉහළට ස්වයිප් කරන්න, රඳවා ගෙන සිට, පසුව මුදා හරින්න"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"හොඳින් කළා!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"සියල්ල සකසා ඇත"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"නිමයි"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"සැකසීම්"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"තිර රුව"</string>
<string name="action_split" msgid="2098009717623550676">"බෙදන්න"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"බෙදුම් තිරය භාවිතා කිරීමට තවත් යෙදුමක් තට්ටු කරන්න"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"බෙදීම් තිර තේරීමෙන් පිටවන්න"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"බෙදීම් තිරය භාවිතා කිරීමට වෙනත් යෙදුමක් තෝරා ගන්න"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"මෙම ක්රියාව යෙදුම හෝ ඔබේ සංවිධානය මගින් ඉඩ නොදේ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"නිබන්ධනය සංචාලනය මඟ හරින්නද?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"මඟ හරින්න"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"තිරය කරකවන්න"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"කාර්ය තීරු අධ්යාපනය"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"කාර්ය තීරු අධ්යාපනය දිස් විය"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"කාර්ය තීරු අධ්යාපනය වසා ඇත"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"එකවර යෙදුම් 2ක් භාවිතා කිරීමට යෙදුමක් පැත්තට අදින්න"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"කාර්ය තීරුව පෙන්වීමට ඉහළට සෙමින් ස්වයිප් කරන්න"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"ඔබේ දිනචරියාව මත පදනම්ව යෙදුම් යෝජනා ලබා ගන්න"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"කාර්ය තීරුව ස්වයංක්රීයව සැඟවීමට සැකසීම් තුළ අභින සංචලනය සක්රීය කරන්න"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"කාර්ය තීරුව සමග තවත් කරන්න"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"ඊළඟ"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"ආපසු"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"වසන්න"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"නිමයි"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"මුල් පිටුව"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"දැනුම්දීම්"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"ඉක්මන් සැකසීම්"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"කාර්ය තීරුව"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"කාර්ය තීරුව පෙන්වා ඇත"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"කාර්ය තීරුව සඟවා ඇත"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"සංචලන තීරුව"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"සෑම විටම කාර්ය තීරුව පෙන්වන්න"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"සංචාලන ප්රකාරය වෙනස් කරන්න"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"කාර්ය තීරු බෙදනය"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ඉහළ/වම වෙත ගෙන යන්න"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"පහළ/දකුණ වෙත ගෙන යන්න"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{තවත් # යෙදුමක් පෙන්වන්න.}one{තවත් යෙදුම් #ක් පෙන්වන්න.}other{තවත් යෙදුම් #ක් පෙන්වන්න.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> සහ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"ඩෙස්ක්ටොප් වෙත යෙදුම එක් කිරීම"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"අවලංගු කරන්න"</string>
</resources>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index a34c210..aee281c 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Návrhy aplikácií zapnuté"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Návrhy aplikácií vypnuté"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predpovedaná aplikácia: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Musíte potiahnuť úplne z pravého alebo ľavého okraja."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Musíte potiahnuť z pravého alebo ľavého okraja do stredu obrazovky a potom uvoľniť."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Otočte zariadenie"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Otočte zariadenie a dokončite tak návod, ako navigovať gestami"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Musíte potiahnuť úplne z pravého alebo ľavého okraja"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Musíte potiahnuť z pravého alebo ľavého okraja do stredu obrazovky a potom uvoľniť"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Naučili ste sa prejsť späť potiahnutím sprava. V ďalšom kroku sa naučíte prepínať aplikácie."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Dokončili ste gesto na prechod späť."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Nesmiete potiahnuť príliš blízko dolnej časti obrazovky."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Dokončili ste gesto na prechod späť"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Nesmiete potiahnuť príliš blízko dolnej časti obrazovky"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Ak chcete zmeniť citlivosť gesta Späť, prejdite do Nastavení"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Prechod späť potiahnutím"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Na poslednú obrazovku prejdete potiahnutím z ľavého alebo pravého okraja do stredu obrazovky."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Na poslednú obrazovku sa vrátite potiahnutím dvoma prstami z ľavého alebo pravého okraja do stredu obrazovky."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Musíte potiahnuť nahor z dolného okraja obrazovky."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Pred uvoľnením nesmiete zastať."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Musíte potiahnuť priamo hore."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Dokončili ste gesto na prechod na plochu. V ďalšom kroku sa naučíte, ako sa vrátiť späť."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Dokončili ste gesto na prechod na plochu."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Prechod späť"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Potiahnite z ľavého alebo pravého okraja do stredu obrazovky"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Musíte potiahnuť nahor z dolného okraja obrazovky"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Pred uvoľnením nesmiete zastať"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Musíte potiahnuť priamo nahor"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Dokončili ste gesto prechodu na plochu. Teraz sa naučíte, ako sa vrátiť späť."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Dokončili ste gesto prechodu na plochu"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Prechod na plochu potiahnutím"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Potiahnite nahor zdola obrazovky. Týmto gestom sa vždy vrátite na plochu."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Postiahnite dvoma prstami z dolnej časti obrazovky. Týmto gestom sa vždy vrátite na plochu."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Prejdenie na plochu"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Na plochu môžete kedykoľvek prejsť potiahnutím nahor z dolnej časti obrazovky"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Musíte potiahnuť nahor z dolného okraja obrazovky."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Skúste okno pred uvoľnením podržať dlhšie."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Musite potiahnuť priamo hore a potom zastať."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Prechod na plochu"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Potiahnite z dolnej časti obrazovky nahor"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Skvelé!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Musíte potiahnuť nahor z dolného okraja obrazovky"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Skúste okno pred uvoľnením podržať dlhšie"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Musite potiahnuť priamo nahor a potom zastať"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Naučili ste sa používať gestá. Gestá môžete vypnúť v nastaveniach."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Dokončili ste gesto na prepnutie aplikácií."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Dokončili ste gesto na prepnutie aplikácií"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Prepínanie aplikácií potiahnutím"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Aplikácie môžete prepínať potiahnutím obrazovky zdola nahor, pridržaním a následným uvoľnením."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Aplikácie prepnete potiahnutím dvoma prstami z dolnej časti obrazovky, ich pridržaním a uvoľnením."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Prepnutie aplikácií"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Potiahnite nahor z dolného okraja obrazovky, pridržte a uvoľnite"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Výborne"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Hotovo"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Hotovo"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Nastavenia"</string>
@@ -86,7 +94,8 @@
<string name="action_share" msgid="2648470652637092375">"Zdieľať"</string>
<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="8464310533320556058">"Rozdelenú obrazovku spustíte klep. na inú aplik."</string>
+ <string name="toast_split_select_app" msgid="8464310533320556058">"Obrazovku rozdelíte klepnutím na inú aplikáciu"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Ukončite výber rozdelenej obrazovky"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Na použitie rozd. obrazovky vyberte inú aplikáciu"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikácia alebo vaša organizácia túto akciu nepovoľuje"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Chcete preskočiť návod na navigáciu?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Preskočiť"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Otočiť obrazovku"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Panel vzdelávacích aplikácií"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Zobrazila sa výuka k hlavnému panelu"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Výuka k hlavnému panelu bola zatvorená"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Ak chcete použ. dve aplikácie naraz, presuňte aplik. nabok"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Ak chcete použiť dve aplikácie naraz, presuňte aplikáciu nabok"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Panel aplikácií zobrazíte pomalým potiahnutím nahor"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Získavajte návrhy aplikácií na základe svojich zvykov"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Ak chcete, aby sa panel aplikácií autom. skrýval, zapnite v Nastaveniach navigáciu gestami"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Panel aplikácií vám ponúka ďalšie možnosti"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Ďalej"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Späť"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Zavrieť"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Hotovo"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Plocha"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Upozornenia"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Rýchle nastavenia"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Panel aplikácií"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Panel aplikácií je zobrazený"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Panel aplikácií je skrytý"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigačný panel"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Zobrazovať panel aplikácií"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Zmeniť režim navigácie"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Rozdeľovač panela aplikácií"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Presunúť hore alebo doľava"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Presunúť dole alebo doprava"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Zobraziť # ďalšiu aplikáciu.}few{Zobraziť # ďalšie aplikácie.}many{Show # more apps.}other{Zobraziť # ďalších aplikácií.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> a <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Pridanie aplikácie na plochu"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Zrušiť"</string>
</resources>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index 83e1d5e..4787f04 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Predlogi aplikacij so omogočeni."</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Predlogi aplikacij so onemogočeni."</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predvidena aplikacija: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Pazite, da povlečete s skrajno desnega ali skrajno levega roba."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Pazite, da povlečete z desnega ali levega roba do sredine zaslona in dvignete prst."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Zasukajte napravo"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Zasukajte napravo, če si želite ogledati vadnico za krmarjenje s potezami"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Pazite, da povlečete s skrajno desnega ali skrajno levega roba."</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Pazite, da povlečete z desnega ali levega roba do sredine zaslona in dvignete prst."</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Naučili ste se, kako povlečete z desne za vrnitev. Zdaj se naučite preklapljanja med aplikacijami."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Izvedli ste potezo za pomik nazaj."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Pazite, da ne povlečete preblizu dna zaslona."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Izvedli ste potezo za pomik nazaj."</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Pazite, da ne povlečete preblizu dna zaslona."</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Občutljivost poteze za nazaj lahko spremenite v nastavitvah."</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Povlecite za vrnitev"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Če se želite vrniti na prejšnji zaslon, povlecite z levega ali desnega roba do sredine zaslona."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Če se želite vrniti na zadnji prikazani zaslon, z dvema prstoma povlecite z levega ali desnega roba do sredine zaslona."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Pazite, da povlečete s spodnjega roba zaslona navzgor."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Pazite, da ne zaustavite prsta, preden ga dvignete."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Pazite, da povlečete naravnost navzgor."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Izvedli ste potezo za pomik na začetni zaslon. Zdaj se naučite, kako se pomaknete nazaj."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Izvedli ste potezo za pomik na začetni zaslon."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Pomik nazaj"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Povlecite z levega ali desnega roba do sredine zaslona."</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Pazite, da povlečete s spodnjega roba zaslona navzgor."</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Pazite, da ne zaustavite prsta, preden ga dvignete."</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Pazite, da povlečete naravnost navzgor."</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Izvedli ste potezo za pomik na začetni zaslon. Zdaj se naučite, kako se pomaknete nazaj."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Izvedli ste potezo za pomik na začetni zaslon."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Povlecite za pomik na začetni zaslon"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Z dna zaslona s prstom povlecite navzgor. S to potezo lahko vedno odprete začetni zaslon."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Z dvema prstoma povlecite navzgor z dna zaslona. S to potezo lahko vedno odprete začetni zaslon."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Pomik na začetni zaslon"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Za pomik na začetni zaslon lahko kadar koli povlečete navzgor z dna zaslona."</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Pazite, da povlečete s spodnjega roba zaslona navzgor."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Poskusite okno pridržati dalj časa, preden ga izpustite."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Pazite, da povlečete naravnost navzgor in nato zaustavite prst."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Z dna zaslona s prstom povlecite navzgor."</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Odlično!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Pazite, da povlečete s spodnjega roba zaslona navzgor."</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Poskusite okno pridržati dalj časa, preden ga izpustite."</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Pazite, da povlečete naravnost navzgor in nato zaustavite prst."</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Naučili ste se uporabljati poteze. Poteze lahko izklopite v nastavitvah."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Izvedli ste potezo za preklapljanje med aplikacijami."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Izvedli ste potezo za preklapljanje med aplikacijami."</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Povlecite za preklapljanje med aplikacijami"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Za preklapljanje med aplikacijami povlecite navzgor z dna zaslona, pridržite in nato izpustite."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Za preklop med aplikacijami z dvema prstoma povlecite navzgor z dna zaslona, pridržite in spustite."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Preklop aplikacij"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Povlecite navzgor z dna zaslona, pridržite, nato izpustite."</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Odlično!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Zdaj znate"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Končano"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Nastavitve"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Posnetek zaslona"</string>
<string name="action_split" msgid="2098009717623550676">"Razdeli"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Za razdeljeni zaslon se dotaknite še 1 aplikacije"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Zapri izbiro razdeljenega zaslona"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Izberite drugo aplikacijo za uporabo razdeljenega zaslona."</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikacija ali vaša organizacija ne dovoljuje tega dejanja"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Želite preskočiti vadnico za krmarjenje?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Preskoči"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Sukanje zaslona"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Poučni nasveti o opravilni vrstici"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Poučni nasveti o opravilni vrstici so prikazani."</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Poučni nasveti o opravilni vrstici so zaprti."</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Povlecite aplikacijo vstran za uporabo 2 aplikacij hkrati."</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Počasi povlecite navzgor za prikaz opravilne vrstice."</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Povlecite aplikacijo na stran za uporabo 2 aplikacij hkrati."</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Počasi povlecite navzgor za prikaz opravilne vrstice"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Prejemajte predloge aplikacij na podlagi svojih navad."</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"V nastavitvah vklopite krmarjenje s potezami, da se bo opravilna vrstica samodejno skrila."</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Naredite več z opravilno vrstico"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Naprej"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Nazaj"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Zapri"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Končano"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Začetni zaslon"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Obvestila"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Hitre nastavitve"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Opravilna vrstica"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Opravilna vrstica je prikazana"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Opravilna vrstica je skrita"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Vrstica za krmarjenje"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Stalen prikaz opravilne vrstice"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Spreminjanje načina navigacije"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Razdelilnik opravilne vrstice"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premakni na vrh/levo"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premakni na dno/desno"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Pokaži še # aplikacijo.}one{Pokaži še # aplikacijo.}two{Pokaži še # aplikaciji.}few{Pokaži še # aplikacije.}other{Pokaži še # aplikacij.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> in <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodajanje aplikacije na namizje"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Prekliči"</string>
</resources>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index 9a995fb..a9e8b94 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Aplikacionet e sugjeruara janë aktivizuar"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Sugjerimet e aplikacioneve janë çaktivizuar"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Aplikacioni i parashikuar: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Sigurohu që të rrëshqasësh shpejt nga skaji më i djathtë ose më i majtë."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Sigurohu që të rrëshqasësh shpejt nga skaji i djathtë ose i majtë drejt mesit të ekranit dhe lëshoje."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rrotullo pajisjen"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rrotullo pajisjen për të përfunduar udhëzuesin e navigimit me gjeste"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Sigurohu që të rrëshqasësh shpejt nga skaji më i djathtë ose më i majtë"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Sigurohu që të rrëshqasësh shpejt nga skaji i djathtë ose i majtë drejt mesit të ekranit dhe lëshoje"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Ke mësuar si të rrëshqasësh shpejt nga e djathta për t\'u kthyer prapa. Në vijim do të mësosh se si t\'i ndërrosh aplikacionet."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"E ke përfunduar gjestin e kthimit prapa."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Sigurohu që të mos rrëshqasësh shumë afër fundit të ekranit."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"E ke përfunduar gjestin e kthimit prapa"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Sigurohu që të mos rrëshqasësh shpejt shumë afër pjesës së poshtme të ekranit"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Për të ndryshuar ndjeshmërinë e gjestit të kthimit prapa, shko te \"Cilësimet\""</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Rrëshqit shpejt për t\'u kthyer prapa"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Për t\'u kthyer prapa tek ekrani i fundit, rrëshqit shpejt nga skaji i majtë ose i djathtë drejt mesit të ekranit"</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Për t\'u kthyer prapa tek ekrani i fundit, rrëshqit shpejt me 2 gishta nga skaji i majtë ose i djathtë drejt mesit të ekranit."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Sigurohu që të rrëshqasësh shpejt lart nga skaji i poshtëm i ekranit."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Sigurohu që të mos ndalosh para se ta lëshosh."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Sigurohu që të rrëshqasësh shpejt drejt lart."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"E ke përfunduar gjestin e kalimit tek ekrani bazë. Në vijim do të mësosh si të kthehesh prapa."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"E ke përfunduar gjestin e kalimit tek ekrani bazë."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Kthehu prapa"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Rrëshqit shpejt nga skaji i majtë ose i djathtë drejt mesit të ekranit"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Sigurohu që të rrëshqasësh shpejt lart nga skaji i poshtëm i ekranit"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Sigurohu që të mos ndalosh para se ta lëshosh"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Sigurohu që të rrëshqasësh shpejt drejt lart"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"E ke përfunduar gjestin e kalimit tek ekrani bazë. Në vijim, mëso si të kthehesh prapa."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"E ke përfunduar gjestin e kalimit tek ekrani bazë"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Rrëshqit shpejt për të kaluar tek ekrani bazë"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Rrëshqit shpejt lart nga fundi i ekranit tënd. Ky gjest të dërgon gjithmonë tek ekrani bazë."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Rrëshqit shpejt lart me 2 gishta nga fundi i ekranit. Ky gjest të dërgon gjithmonë tek ekrani bazë."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Shko tek ekrani bazë"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Për të shkuar tek ekrani bazë në çdo kohë, rrëshqit shpejt lart nga fundi i ekranit"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Sigurohu që të rrëshqasësh shpejt lart nga skaji i poshtëm i ekranit."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Provo ta mbash shtypur dritaren për një kohë më të gjatë para se ta lëshosh."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Sigurohu që të rrëshqasësh shpejt drejt lart dhe më pas ndalo."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Rrëshqit shpejt lart nga pjesa e poshtme e ekranit"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Punë e shkëlqyer!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Sigurohu që të rrëshqasësh shpejt lart nga skaji i poshtëm i ekranit"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Provo ta mbash shtypur dritaren për një kohë më të gjatë para se ta lëshosh"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Sigurohu që të rrëshqasësh shpejt drejt lart dhe më pas ndalo"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Ke mësuar si të përdorësh gjestet. Për t\'i çaktivizuar gjestet, shko te \"Cilësimet\"."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"E ke përfunduar gjestin e ndërrimit të aplikacioneve."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"E ke përfunduar gjestin e ndërrimit të aplikacioneve"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Rrëshqit shpejt për të ndërruar aplikacionet"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Për të ndërruar mes aplikacioneve, rrëshqit shpejt lart nga fundi i ekranit tënd, mbaj dhe pastaj lësho."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Për të ndërruar mes aplikacioneve, rrëshqit lart me 2 gishta nga fundi i ekranit, mbaje dhe lëshoje."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Ndërro aplikacionet"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Rrëshqit shpejt lart nga fundi i ekranit, mbaje të shtypur dhe më pas lëshoje"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Shumë mirë!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Plotësisht gati"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"U krye"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Cilësimet"</string>
@@ -80,13 +88,14 @@
<string name="allset_title" msgid="5021126669778966707">"Plotësisht gati!"</string>
<string name="allset_hint" msgid="459504134589971527">"Rrëshqit shpejt lart për të shkuar në ekranin bazë"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Trokit te butoni \"kreu\" për të shkuar tek ekrani bazë"</string>
- <string name="allset_description_generic" msgid="5385500062202019855">"Je gati që të fillosh të përdorësh <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="allset_description_generic" msgid="5385500062202019855">"Je gati që të fillosh ta përdorësh këtë <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="default_device_name" msgid="6660656727127422487">"pajisje"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Cilësimet e navigimit të sistemit"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Ndaj"</string>
<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="8464310533320556058">"Trokit një apl. tjetër; përdor ekranin e ndarë"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Dil nga zgjedhja e ekranit të ndarë"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Zgjidh një aplikacion tjetër për të përdorur ekranin e ndarë"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Ky veprim nuk lejohet nga aplikacioni ose organizata jote"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Të kapërcehet udhëzuesi i navigimit?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Kapërce"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Rrotullo ekranin"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Edukimi për shiritin e detyrave"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Edukimi i shiritit të detyrave u shfaq"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Edukimi nga shiriti i detyrave u mbyll"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Zvarrit një aplikacion në anë për të përdorur 2 aplikacione njëherësh"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Rrëshqit lart ngadalë për të shfaqur \"Shiritin e detyrave\""</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Merr sugjerime për aplikacion bazuar në rutinën tënde"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Aktivizo navigimin me gjeste te \"Cilësimet\" për të fshehur \"Shiritin e detyrave\""</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Bëj më shumë me \"Shiritin e detyrave\""</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Para"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Pas"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Mbyll"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"U krye"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Faqja kryesore"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Njoftimet"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Cilësimet shpejt"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Shiriti i detyrave"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Shiriti i detyrave i shfaqur"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Shiriti i detyrave i fshehur"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Shiriti i navigimit"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Shfaq gjithmonë shiritin e detyrave"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Ndrysho modalitetin e navigimit"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Ndarësi i shiritit të detyrave"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Lëviz në krye/majtas"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Lëviz në fund/djathtas"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Shfaq # aplikacion tjetër.}other{Shfaq # aplikacione të tjera.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> dhe <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Shtimi i aplikacionit te desktopi"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Anulo"</string>
</resources>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index 56cc6ff..da057d8 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Предлози апликација су омогућени"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Предлози апликација су онемогућени"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Предвиђамо апликацију: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Обавезно превуците од саме десне или леве ивице."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Обавезно превуците од десне или леве ивице до средине екрана и отпустите."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Ротирајте уређај"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Ротирајте уређај да бисте довршили водич за навигацију помоћу покрета"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Обавезно превуците од саме десне или леве ивице"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Обавезно превуците од десне или леве ивице до средине екрана и отпустите"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Научили сте како да превлачите здесна да бисте се вратили уназад. Сада научите да замените апликације."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Довршили сте покрет за повратак."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Никако не превлачите превише близу дна екрана."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Довршили сте покрет за повратак"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Никако не превлачите превише близу дна екрана"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Осетљивост пок. за назад можете да промените у Подешавањима"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Превуците да бисте се вратили уназад"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Да бисте се вратили на последњи екран, превуците од леве или десне ивице до средине екрана."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Да бисте се вратили на последњи екран, превуците помоћу два прста од леве или десне ивице до средине екрана."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Обавезно превуците нагоре од доње ивице екрана."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Никако не стајте пре отпуштања."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Обавезно превуците право нагоре."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Довршили сте покрет за повратак на почетну страницу. Сада сазнајте како да се вратите."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Довршили сте покрет за повратак на почетну страницу."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Назад"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Превуците од леве или десне ивице до средине екрана"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Обавезно превуците нагоре од доње ивице екрана"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Никако не стајте пре отпуштања"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Обавезно превуците право нагоре"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Довршили сте покрет за повратак на почетну страницу. Сада сазнајте како да се вратите."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Довршили сте покрет за повратак на почетну страницу."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Превуците да бисте отишли на почетну страницу"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Превуците нагоре од дна екрана. Овај покрет вас увек води на почетни екран."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Превуците помоћу два прста нагоре од дна екрана. Овим покретом увек отварате почетни екран."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Идите на почетни екран"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Да бисте отишли на почетни екран у било ком тренутку, превуците нагоре од дна екрана."</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Обавезно превуците нагоре од доње ивице екрана."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Пробајте да држите прозор дуже пре отпуштања."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Обавезно превуците право нагоре, па застаните."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Превуците нагоре са доњег дела екрана"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Одлично!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Обавезно превуците нагоре од доње ивице екрана"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Пробајте да држите прозор дуже пре отпуштања"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Обавезно превуците право нагоре, па застаните"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Научили сте како да користите покрете. Да бисте искључили покрете, идите на подешавања."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Довршили сте покрет за промену апликација."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Довршили сте покрет за промену апликација"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Превуците да бисте заменили апликације"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"За прелазак са једне апликације на другу превуците нагоре од дна екрана, задржите, па пустите."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"За прелазак између апликација превуците помоћу два прста нагоре од дна екрана, задржите, па пустите."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Пређите на другу апликацију"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Превуците нагоре од дна екрана, задржите, па пустите"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Одлично!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"То је то"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Готово"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Подешавања"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Снимак екрана"</string>
<string name="action_split" msgid="2098009717623550676">"Подели"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Додирните другу апликацију за подељени екран"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Излазак из бирања подељеног екрана"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Одаберите другу апликацију за подељени екран"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Апликација или организација не дозвољавају ову радњу"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Желите да прескочите водич за кретање?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Прескочи"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Ротирајте екран"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Упутства на траци задатака"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Едукативно окно из траке задатака се појавило"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Едукативно окно из траке задатака је затворено"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Превуците на страну да бисте користили 2 апликације одједном"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Накратко превуците нагоре да бисте приказали траку задатака"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Споро превуците нагоре да бисте приказали траку задатака"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Добијајте предлоге апликација на основу рутине"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Укључите навигацију помоћу покрета у Подешавањима ради аутоматског скривања траке задатака"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Урадите више помоћу траке задатака"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Даље"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Назад"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Затвори"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Почетна"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Обавештења"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Брза подешавања"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Трака задатака"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Трака задатака је приказана"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Трака задатака је скривена"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Трака за навигацију"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Увек приказуј траку задатака"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Промени режим навигације"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Разделник траке задатака"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Премести горе лево"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Премести доле десно"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Прикажи још # апликацију.}one{Прикажи још # апликацију.}few{Прикажи још # апликације.}other{Прикажи још # апликација.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Додаје се апликација на радну поврршину"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Откажи"</string>
</resources>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index 0200c50..31853f9 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -21,7 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fäst"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Fritt format"</string>
- <string name="recents_empty_message" msgid="7040467240571714191">"Listan med de senaste åtgärderna är tom"</string>
+ <string name="recents_empty_message" msgid="7040467240571714191">"Listan är tom"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Inställningar för appanvändning"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Rensa alla"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Senaste apparna"</string>
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Appförslag har aktiverats"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Appförslag har inaktiverats"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Appförslag: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Se till att du sveper ända från högerkanten eller vänsterkanten."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Se till att du sveper från den högra eller vänstra kanten till mitten av skärmen och sedan släpper."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotera enheten"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rotera enheten för att slutföra guiden för navigering med rörelser"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Se till att du sveper ända från högerkanten eller vänsterkanten"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Se till att du sveper från den högra eller vänstra kanten till mitten av skärmen och sedan släpper"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Nu kan du svepa från höger för att gå tillbaka. Nu ska du få lära dig hur du byter mellan appar."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Du är klar med rörelsen för att gå tillbaka."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Se till att du inte sveper för nära skärmens nederkant."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Du är klar med rörelsen för att gå tillbaka"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Se till att du inte sveper för nära skärmens nederkant"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Öppna inställningarna om du vill ändra rörelsens känslighet"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Svep för att återgå"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Återgå till den senaste skärmen genom att svepa från skärmens vänster- eller högerkant till mitten."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Gå tillbaka till den senaste skärmen genom att med två fingrar svepa mot mitten av skärmen från vänster eller höger kant."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Se till att du sveper från nederkanten på skärmen."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Se till att du sveper i en jämn rörelse innan du släpper."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Se till att du sveper rakt uppåt."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Du är klar med rörelsen för att öppna startskärmen. Nu ska du få lära dig hur du går tillbaka."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Du är klar med rörelsen för att öppna startskärmen."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Tillbaka"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Svep från den högra eller vänstra kanten till mitten av skärmen"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Se till att du sveper uppåt från nederkanten av skärmen"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Se till att du sveper i en jämn rörelse innan du släpper"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Se till att du sveper rakt uppåt"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Du är klar med rörelsen för att öppna startskärmen. Nu ska du få lära dig hur du går tillbaka."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Du är klar med rörelsen för att öppna startskärmen"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Svep för att öppna startskärmen"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Svep uppåt från skärmens nederkant. Du kan alltid återgå till startskärmen med den här rörelsen."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Svep uppåt med två fingrar från skärmens nederkant. Så kommer du alltid tillbaka till startskärmen."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Öppna startskärmen"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Öppna startskärmen när som helst genom att svepa uppåt från skärmens nederkant"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Se till att du sveper från nederkanten på skärmen."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Testa att trycka längre på fönstret innan du släpper."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Se till att du sveper rakt uppåt och sedan pausar."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Svep uppåt från skärmens nederkant"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Bra jobbat!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Se till att du sveper uppåt från nederkanten av skärmen"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Testa att trycka längre på fönstret innan du släpper"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Se till att du sveper rakt uppåt och sedan pausar"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Du har lärt dig hur du använder rörelser. Om du vill inaktivera rörelser öppnar du inställningarna."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Du är klar med rörelsen för att byta mellan appar."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Du är klar med rörelsen för att byta mellan appar"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Svep för att byta mellan appar"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Byt mellan appar genom att svepa uppåt från skärmens nederkant. Håll fingret nedtryckt och släpp."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Byta mellan appar: Svep uppåt med två fingrar från skärmens nederkant, håll kvar och släpp sedan."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Byt app"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Svep uppåt från skärmens nederkant. Håll fingret nedtryckt och släpp sedan"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Bra gjort!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Klart"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Klar"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Inställningar"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skärmbild"</string>
<string name="action_split" msgid="2098009717623550676">"Delat"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tryck på en annan app för att använda delad skärm"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Avsluta val av delad skärm"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Välj en annan app för att använda delad skärm"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Appen eller organisationen tillåter inte den här åtgärden"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vill du hoppa över självstudierna?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Hoppa över"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Rotera skärmen"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Aktivitetsfältsutbildning"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Information om aktivitetsfältet visades"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Information om aktivitetsfältet stängdes"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Dra en app till sidan om du vill använda två appar samtidigt"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Svep långsamt uppåt för att visa aktivitetsfältet"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Få appförslag utifrån dina rutiner"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Slå på navigering med rörelser i Inställningar för att dölja aktivitetsfältet automatiskt"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Gör mer med aktivitetsfältet"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Nästa"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Tillbaka"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Stäng"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Klar"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Startsida"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Aviseringar"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Snabbinställn."</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Aktivitetsfält"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Aktivitetsfältet visas"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Aktivitetsfältet är dolt"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigeringsfält"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Visa alltid aktivitetsfältet"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Ändra navigeringsläge"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Avdelare för aktivitetsfältet"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Flytta högst upp/till vänster"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Flytta längst ned/till höger"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Visa # app till.}other{Visa # appar till.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> och <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Lägger till appen på skrivbordet"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Avbryt"</string>
</resources>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index a4d4b28..8c438f4 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Mapendekezo ya programu yamewashwa"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Umezima mapendekezo ya programu"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Programu iliyotabiriwa: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Hakikisha unatelezesha kidole kuanzia ukingo wa kulia kabisa au ukingo wa kushoto kabisa."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Hakikisha unatelezesha kidole kuanzia ukingo wa kulia au kushoto kuelekea katikati ya skrini na uachilie."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Zungusha kifaa chako"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Tafadhali zungusha kifaa chako ili ukamilishe mafunzo ya usogezaji kwa kutumia ishara"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Hakikisha unatelezesha kidole kutoka ukingo wa kulia au kushoto kabisa"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Hakikisha unatelezesha kidole kutoka ukingo wa kulia au kushoto hadi katikati ya skrini na uachilie"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Umejifunza jinsi ya kutelezesha kidole kuanzia kulia ili kurudi nyuma. Sasa jifunze jinsi ya kubadilisha programu."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Umekamilisha ishara ya kurudi nyuma."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Hakikisha hutelezeshi kidole karibu sana na sehemu ya chini ya skrini."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Umeweka ishara ya kurudi nyuma"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Hakikisha hutelezeshi kidole karibu sana na sehemu ya chini ya skrini"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Kubadilisha hisi ya ishara ya nyuma, nenda kwenye Mipangilio"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Telezesha kidole ili urudi nyuma"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Ili urudi kwenye skrini iliyotangulia, telezesha kidole kuanzia ukingo wa kushoto au wa kulia kuelekea katikati ya skrini."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Ili urudi kwenye skrini iliyopita, telezesha vidole viwili kuanzia ukingo wa kushoto au wa kulia kuelekea katikati ya skrini."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Hakikisha unatelezesha kidole juu kuanzia ukingo wa chini wa skrini."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Hakikisha kuwa husimamishi kabla ya kuachilia."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Hakikisha unatelezesha kidole kuelekea juu."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Umekamilisha ishara ya kwenda kwenye Skrini ya kwanza. Sasa jifunze jinsi ya kurudi nyuma."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Umekamilisha ishara ya kwenda kwenye Skrini ya kwanza."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Rudi nyuma"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Telezesha kidole kutoka ukingo wa kushoto au kulia hadi katikati ya skrini"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Hakikisha unatelezesha kidole juu kuanzia ukingo wa chini wa skrini"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Hakikisha husitishi kabla ya kuachilia"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Hakikisha unatelezesha kidole juu"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Umeweka ishara ya kwenda kwenye Skrini ya kwanza. Inayofuata, jifunze jinsi ya kurudi nyuma."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Umeweka ishara ya kwenda kwenye skrini ya kwanza"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Telezesha kidole ili uende kwenye skrini ya kwanza"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Telezesha kidole juu kuanzia chini ya skrini yako. Ishara hii kila wakati hukupeleka kwenye Skrini ya kwanza."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Telezesha vidole viwili kuelekea juu kuanzia sehemu ya chini ya skrini. Ishara hii kila wakati hukupeleka kwenye Skrini ya kwanza."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Nenda kwenye ukurasa wa mwanzo"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Ili uende kwenye skrini ya kwanza muda wowote, telezesha kidole juu kutoka sehemu ya chini ya skrini"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Hakikisha unatelezesha kidole juu kuanzia ukingo wa chini wa skrini."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Jaribu kushikilia dirisha kwa muda mrefu kabla ya kuachilia."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Hakikisha unatelezesha kidole kuelekea juu, kisha usimamishe."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Telezesha kidole juu kutoka sehemu ya chini ya skrini yako"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Kazi nzuri!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Hakikisha unatelezesha kidole juu kuanzia ukingo wa chini wa skrini"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Jaribu kushikilia dirisha kwa muda mrefu kabla ya kuachilia"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Hakikisha unatelezesha kidole juu, kisha usitishe"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Umejifunza jinsi ya kutumia ishara. Ili uzime ishara, nenda kwenye Mipangilio."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Umekamilisha ishara ya kubadilisha programu."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Umeweka ishara ya kubadilisha programu"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Telezesha kidole ili ubadilishe programu"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Ili ubadili kati ya programu, telezesha kidole juu kuanzia sehemu ya chini ya skrini yako, ushikilie, kisha uachilie."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Ili ubadilishe kati ya programu, telezesha vidole viwili kuelekea juu kuanzia sehemu ya chini ya skrini yako, ushikilie, kisha uachilie."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Badilisha programu"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Telezesha kidole juu kutoka sehemu ya chini ya skrini yako, shikilia kisha uachilie"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Hongera!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Kila kitu kiko tayari"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Nimemaliza"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Mipangilio"</string>
@@ -80,13 +88,14 @@
<string name="allset_title" msgid="5021126669778966707">"Tayari!"</string>
<string name="allset_hint" msgid="459504134589971527">"Telezesha kidole juu ili uende kwenye skrini ya kwanza"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Gusa kitufe cha ukurasa wa mwanzo ili uende kwenye skrini ya kwanza"</string>
- <string name="allset_description_generic" msgid="5385500062202019855">"Uko tayari kuanza kutumia <xliff:g id="DEVICE">%1$s</xliff:g> yako"</string>
+ <string name="allset_description_generic" msgid="5385500062202019855">"Uko tayari kuanza kutumia <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="default_device_name" msgid="6660656727127422487">"kifaa"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Mipangilio ya usogezaji kwenye mfumo"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Shiriki"</string>
<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="8464310533320556058">"Gusa programu nyingine ili utumie kipengele cha kugawa skrini"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Ondoka kwenye hali ya skrini iliyogawanywa"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Chagua programu nyingine ili utumie hali ya kugawa skrini"</string>
<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>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Ruka"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Zungusha skrini"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Elimu ya Upauzana"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Paneli ya elimu kwenye upau wa shughuli inaonyeshwa"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Paneli ya elimu kwenye upau wa shughuli imefungwa"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Buruta programu pembeni ili utumie programu 2 kwa wakati mmoja"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Telezesha kidole juu taratibu ili uonyeshe Upauzana"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Telezesha kidole juu taratibu ili ufungue Upauzana"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Pata mapendekezo ya programu kulingana na ratiba yako"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Washa usogezaji kwa kutumia ishara kwenye Mipangilio ili ufiche Upauzana kiotomatiki"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Kamilisha mengi kwa kutumia Upauzana huu"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Endelea"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Nyuma"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Funga"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Imemaliza"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Mwanzo"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Arifa"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Mipangilio ya Haraka"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Upauzana"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Upauzana umeonyeshwa"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Upauzana umefichwa"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Sehemu ya viungo muhimu"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Onyesha Upauzana kila wakati"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Badilisha hali ya usogezaji"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Kitenganishi cha Upauzana"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Sogeza juu/kushoto"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Sogeza chini/kulia"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Onyesha programu # zaidi.}other{Onyesha programu # zaidi.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> na <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Kuweka programu kwenye Eneo-kazi"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Ghairi"</string>
</resources>
diff --git a/quickstep/res/values-sw720dp/dimens.xml b/quickstep/res/values-sw720dp/dimens.xml
index 9e832bc..1caffb8 100644
--- a/quickstep/res/values-sw720dp/dimens.xml
+++ b/quickstep/res/values-sw720dp/dimens.xml
@@ -43,4 +43,7 @@
<dimen name="taskbar_app_window_threshold">100dp</dimen>
<dimen name="taskbar_home_overview_threshold">180dp</dimen>
<dimen name="taskbar_catch_up_threshold">300dp</dimen>
+
+ <!-- Taskbar swipe up threshold multipliers -->
+ <item name="taskbar_nav_threshold_mult" format="float" type="dimen">3</item>
</resources>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index cdc0312..ef5bd3f 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ஆப்ஸ் பரிந்துரைகள் இயக்கப்பட்டுள்ளன"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ஆப்ஸ் பரிந்துரைகள் முடக்கப்பட்டுள்ளன"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"கணித்த ஆப்ஸ்: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"வலது அல்லது இடது ஓரத்தின் விளிம்பிலிருந்து ஸ்வைப் செய்வதை உறுதிசெய்க."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"வலது அல்லது இடது ஓரத்திலிருந்து திரையின் மையப் பகுதிக்கு ஸ்வைப் செய்தபிறகு விடுவிப்பதை உறுதிசெய்க."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"உங்கள் சாதனத்தைச் சுழற்றுங்கள்"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"சைகை வழிசெலுத்தல் பயிற்சியை நிறைவுசெய்ய உங்கள் சாதனத்தைச் சுழற்றுங்கள்"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"வலது அல்லது இடது ஓரத்தின் விளிம்பிலிருந்து ஸ்வைப் செய்வதை உறுதிசெய்துகொள்ளுங்கள்"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"வலது அல்லது இடது ஓரத்திலிருந்து திரையின் மையப் பகுதிக்கு ஸ்வைப் செய்தபிறகு விடுவிப்பதை உறுதிசெய்க"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"பின்செல்வதற்கு எப்படி வலதுபுறத்திலிருந்து ஸ்வைப் செய்வதென்று கற்றுக்கொண்டீர்கள். அடுத்து ஆப்ஸுக்கிடையே எப்படி மாறுவது என்பதை அறிக."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"பின்செல் சைகைப் பயிற்சியை முடித்துவிட்டீர்கள்."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"திரையின் கீழ்பகுதிக்கு மிக நெருக்கமாக ஸ்வைப் செய்யவில்லை என்பதை உறுதிசெய்துகொள்ளுங்கள்."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"பின்செல் சைகைப் பயிற்சியை நிறைவுசெய்துவிட்டீர்கள்"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"திரையின் கீழ்ப்பகுதிக்கு மிக நெருக்கமாக ஸ்வைப் செய்யவில்லை என்பதை உறுதிசெய்துகொள்ளுங்கள்"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"பின்செல் சைகையின் உணர்திறனை மாற்ற அமைப்புகளுக்குச் செல்க"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"பின்செல்ல ஸ்வைப் செய்யுங்கள்"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"முந்தைய திரைக்கு மீண்டும் செல்ல, இடது/வலது ஓரத்திலிருந்து திரையின் மையப் பகுதிக்கு ஸ்வைப் செய்க."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"முந்தைய திரைக்கு மீண்டும் செல்ல, 2 விரல்களால் இடது அல்லது வலது ஓரத்திலிருந்து திரையின் மையப் பகுதிக்கு ஸ்வைப் செய்யுங்கள்."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"திரையின் கீழ் ஓரத்திலிருந்து மேல்நோக்கி ஸ்வைப் செய்வதை உறுதிசெய்துகொள்ளுங்கள்."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"விடுவிப்பதற்கு முன்பாக இடைநிறுத்தவில்லை என்பதை உறுதிசெய்துகொள்ளுங்கள்."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"மேல்நோக்கி நேராக ஸ்வைப் செய்வதை உறுதிசெய்துகொள்ளுங்கள்."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"முகப்புக்குச் செல் சைகைப் பயிற்சியை முடித்துவிட்டீர்கள். அடுத்து, பின்செல்வது எப்படி என்பதை அறிக."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"முகப்புக்குச் செல் சைகைப் பயிற்சியை முடித்துவிட்டீர்கள்."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"பின்செல்லுதல்"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"வலது அல்லது இடது ஓரத்திலிருந்து திரையின் மையப் பகுதிக்கு ஸ்வைப் செய்யுங்கள்"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"திரையின் கீழ் ஓரத்திலிருந்து மேல்நோக்கி ஸ்வைப் செய்வதை உறுதிசெய்துகொள்ளுங்கள்"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"விடுவிப்பதற்கு முன்பாக இடைநிறுத்தவில்லை என்பதை உறுதிசெய்துகொள்ளுங்கள்"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"மேல்நோக்கி நேராக ஸ்வைப் செய்வதை உறுதிசெய்துகொள்ளுங்கள்"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"முகப்புக்குச் செல் சைகைப் பயிற்சியை நிறைவுசெய்துவிட்டீர்கள். அடுத்து பின்செல்வது எப்படி என்பதை அறிக."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"முகப்புக்குச் செல் சைகைப் பயிற்சியை நிறைவுசெய்துவிட்டீர்கள்"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"முகப்புக்குச் செல்ல ஸ்வைப் செய்யுங்கள்"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"திரையின் கீழிருந்து மேலாக ஸ்வைப் செய்க. இந்தச் சைகை எப்போதும் முகப்புத் திரைக்கு அழைத்துச் செல்லும்."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"2 விரலால் திரையின் கீழிருந்து மேலாக ஸ்வைப் செய்க. இந்தச் சைகை முகப்புத் திரைக்கு அழைத்துச் செல்லும்."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"முகப்புக்குச் செல்லுதல்"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"எந்தத் திரையிலிருந்தும் முகப்புத் திரைக்குச் செல்ல திரையின் கீழிருந்து மேல்நோக்கி ஸ்வைப் செய்யுங்கள்"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"திரையின் கீழ் ஓரத்திலிருந்து மேல்நோக்கி ஸ்வைப் செய்வதை உறுதிசெய்துகொள்ளுங்கள்."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"விடுவிப்பதற்கு முன்பாக நீண்டநேரம் சாளரத்தை அழுத்திப் பிடித்திருங்கள்."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"மேல்நோக்கி நேராக ஸ்வைப் செய்தபிறகு இடைநிறுத்துவதை உறுதிசெய்துகொள்ளுங்கள்."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"திரையின் கீழிருந்து மேல்நோக்கி ஸ்வைப் செய்யுங்கள்"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"அருமை!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"திரையின் கீழ் ஓரத்திலிருந்து மேல்நோக்கி ஸ்வைப் செய்வதை உறுதிசெய்துகொள்ளுங்கள்"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"விடுவிப்பதற்கு முன்பாக நீண்டநேரம் சாளரத்தை அழுத்திப் பிடித்திருங்கள்"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"மேல்நோக்கி நேராக ஸ்வைப் செய்தபிறகு இடைநிறுத்துவதை உறுதிசெய்துகொள்ளுங்கள்"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"சைகைகளை எப்படி உபயோகிப்பது என்று கற்றுக்கொண்டீர்கள். சைகைகளை முடக்க அமைப்புகளுக்குச் செல்லுங்கள்."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"ஆப்ஸுக்கிடையே மாறும் சைகைப் பயிற்சியை முடித்துவிட்டீர்கள்."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"ஆப்ஸுக்கிடையே மாறும் சைகைப் பயிற்சியை நிறைவுசெய்துவிட்டீர்கள்"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"ஆப்ஸுக்கிடையே மாற ஸ்வைப் செய்யுங்கள்"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"ஆப்ஸுக்கு இடையே மாற, திரையின் கீழிலிருந்து மேலாக ஸ்வைப் செய்து, பிடித்திருந்து, பிறகு விடுவிக்கவும்."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"ஆப்ஸுக்கிடையே மாற, திரையின் கீழிருந்து மேலாக 2 விரலால் ஸ்வைப் செய்து, பிடித்து, பிறகு விடுவிக்கவும்."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"ஆப்ஸுக்கிடையே மாறுதல்"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"உங்கள் திரையின் கீழ்ப்பகுதியில் இருந்து மேலே ஸ்வைப் செய்து, பிடித்து, பிறகு விடுவியுங்கள்"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"அருமை!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"எல்லாம் தயார்"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"முடிந்தது"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"அமைப்புகள்"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ஸ்கிரீன்ஷாட்"</string>
<string name="action_split" msgid="2098009717623550676">"பிரி"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"திரைப் பிரிப்பைப் பயன்படுத்த வேறு ஆப்ஸைத் தட்டவும்"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"திரைப் பிரிப்பு தேர்வில் இருந்து வெளியேறும்"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"திரைப் பிரிப்பை பயன்படுத்த வேறு ஆப்ஸை தேர்வுசெய்க"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ஆப்ஸோ உங்கள் நிறுவனமோ இந்த செயலை அனுமதிப்பதில்லை"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"வழிகாட்டுதல் பயிற்சியைத் தவிர்க்கவா?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"தவிர்"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"திரையைச் சுழற்றும்"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"செயல் பட்டியைப் பயன்படுத்தும் விதம்"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"பணிப்பட்டியை எவ்வாறு பயன்படுத்துவது என்பது பற்றிய பலகம் காட்டப்படுகிறது"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"பணிப்பட்டியை எவ்வாறு பயன்படுத்துவது என்பது பற்றிய பலகம் மூடப்பட்டது"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ஒரே நேரத்தில் 2 ஆப்ஸைப் பயன்படுத்தப் பக்கவாட்டில் இழுக்கவும்"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"செயல் பட்டியைக் காட்ட மேல்நோக்கி மெதுவாக ஸ்வைப் செய்யவும்"</string>
- <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"உங்கள் வழக்கத்திற்கேற்ப ஆப்ஸ் பரிந்துரைகளைப் பெறுவீர்கள்"</string>
+ <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"உங்கள் வழக்கத்திற்கேற்ப ஆப்ஸ் பரிந்துரைகளைப் பெறலாம்"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"செயல் பட்டியைத் தானாக மறைக்க அமைப்புகளில் சைகை வழிசெலுத்தலை இயக்கவும்"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"செயல் பட்டி மூலம் மேலும் பலவற்றைச் செய்யுங்கள்"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"அடுத்து"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"பின்செல்"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"மூடுக"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"முடிந்தது"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"முகப்பு"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"அறிவிப்புகள்"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"விரைவு அமைப்புகள்"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"செயல் பட்டி"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"செயல் பட்டி காட்டப்படுகிறது"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"செயல் பட்டி மறைக்கப்பட்டுள்ளது"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"வழிசெலுத்தல் பட்டி"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"செயல் பட்டியை எப்போதும் காட்டு"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"வழிசெலுத்தல் பயன்முறையை மாற்று"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"செயல் பட்டிப் பிரிப்பான்"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"மேலே/இடதுபுறம் நகர்த்தும்"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"கீழே/வலதுபுறம் நகர்த்தும்"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{மேலும் # ஆப்ஸைக் காட்டு.}other{மேலும் # ஆப்ஸைக் காட்டு.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> மற்றும் <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"ஆப்ஸை டெஸ்க்டாப்பில் சேர்க்கிறது"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ரத்துசெய்"</string>
</resources>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index 5c1f429..a2adfe1 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="recent_task_option_pin" msgid="7929860679018978258">"పిన్ చేయి"</string>
+ <string name="recent_task_option_pin" msgid="7929860679018978258">"పిన్ చేయండి"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"సంప్రదాయేతర"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ఇటీవలి అంశాలు ఏవీ లేవు"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"యాప్ వినియోగ సెట్టింగ్లు"</string>
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"యాప్ సలహాలు ఎనేబుల్ చేయబడ్డాయి"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"యాప్ సూచనలు డిజేబుల్ చేయబడ్డాయి"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"సూచించబడిన యాప్: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"కుడి వైపు చిట్ట చివరి లేదా ఎడమ వైపు చిట్ట చివరి అంచు నుండి స్వైప్ చేస్తున్నారని నిర్ధారించుకోండి."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"మీరు కుడి లేదా ఎడమ అంచు నుండి స్క్రీన్ మధ్యలోకి స్వైప్ చేశారని నిర్ధారించుకోని, మీ వేలిని ఎత్తండి."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"మీ పరికరాన్ని రొటేట్ చేయండి"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"సంజ్ఞ నావిగేషన్ ట్యుటోరియల్ను పూర్తి చేయడానికి దయచేసి మీ పరికరాన్ని రొటేట్ చేయండి"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"కుడి వైపు చిట్ట చివరి లేదా ఎడమ వైపు చిట్ట చివరి అంచు నుండి స్వైప్ చేస్తున్నారని నిర్ధారించుకోండి"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"మీరు కుడి లేదా ఎడమ అంచు నుండి స్క్రీన్ మధ్యలోకి స్వైప్ చేశారని నిర్ధారించుకుని, మీ వేలిని ఎత్తండి"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"వెనుకకు వెళ్లడానికి కుడి నుండి స్వైప్ ఎలానో మీకు తెలుసు. తర్వాత, యాప్ల మధ్య ఎలా మారాలో తెలుసుకోండి."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"మీరు తిరిగి వెనక్కు వెళ్లే సంజ్ఞను పూర్తి చేశారు."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"మీరు స్క్రీన్ దిగువకు చాలా దగ్గరగా స్వైప్ చేయలేదని నిర్ధారించుకోండి."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"మీరు పేజీ నుండి వెనుకకు వెళ్లే సంజ్ఞను పూర్తి చేశారు"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"మీరు స్క్రీన్ దిగువకు చాలా దగ్గరగా స్వైప్ చేయకుండా చూసుకోండి"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"వెనుక సంజ్ఞ సున్నితత్వం మార్చడానికి, సెట్టింగ్లకు వెళ్లండి"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"వెనుకకు వెళ్ళడం కోసం స్వైప్ చేయండి"</string>
- <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"మునుపటి స్క్రీన్కు తిరిగి వెళ్లడానికి, ఎడమ లేదా కుడి అంచు నుండి స్క్రీన్ మధ్యలోకి స్వైప్ చేయండి."</string>
+ <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"మునుపటి స్క్రీన్కు తిరిగి వెళ్లడానికి, ఎడమ లేదా కుడి అంచు నుండి స్క్రీన్ మధ్యలోకి స్వయిప్ చేయండి."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"గత స్క్రీన్కు తిరిగి వెళ్లడానికి, ఎడమ లేదా కుడి అంచు నుండి స్క్రీన్ మధ్యలోకి 2 వేళ్లతో స్వైప్ చేయండి."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"మీరు స్క్రీన్ దిగువ అంచు నుండి పైకి స్వయిప్ చేస్తున్నారని నిర్ధారించుకోండి."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"బయలుదేరే ముందు మీరు పాజ్ చేయకుండా చూసుకోండి."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"మీరు నేరుగా పైకి స్వైప్ చేశారని నిర్ధారించుకోండి."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"మీరు మొదటి స్క్రీన్కు వెళ్లే సంజ్ఞను పూర్తి చేశారు. తర్వాత, వెనుకకు ఎలా వెళ్లాలో తెలుసుకోండి."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"మీరు మొదటి ట్యాబ్కు వెళ్లే సంజ్ఞను పూర్తి చేశారు."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"వెనుకకు వెళ్లండి"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"ఎడమ లేదా కుడి అంచు నుండి స్క్రీన్ మధ్యకు స్వైప్ చేయండి"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"మీరు స్క్రీన్ దిగువ అంచు నుండి పైకి స్వైప్ చేశారని నిర్ధారించుకోండి"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"మీరు స్క్రీన్పై మీ వేలిని ఎత్తే ముందు స్వైపింగ్ను ఆపకుండా చూసుకోండి"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"మీరు నేరుగా పైకి స్వైప్ చేశారని నిర్ధారించుకోండి"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"మీరు మొదటి స్క్రీన్కు వెళ్లే సంజ్ఞను పూర్తి చేశారు. తర్వాత, వెనుకకు ఎలా వెళ్లాలో తెలుసుకోండి."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"మీరు మొదటి స్క్రీన్కు వెళ్లే సంజ్ఞను పూర్తి చేశారు"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"మొదటి స్క్రీన్కు వెళ్లడానికి స్వైప్ చేయండి"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"స్క్రీన్ కింది నుండి పైకి స్వైప్ చేయండి. ఈ సంజ్ఞ ఎప్పుడూ మిమ్మల్ని మొదటి స్క్రీన్కు తీసుకెళ్తుంది."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"స్క్రీన్ కింది నుండి 2 వేళ్లతో పైకి స్వైప్ చేయండి. సంజ్ఞ ఎల్లప్పుడూ మొదటి స్క్రీన్కు తీసుకెళ్తుంది."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"మొదటి ట్యాబ్కు వెళ్లండి"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"ఎప్పుడైనా మీ మొదటి స్క్రీన్కు వెళ్లడానికి, మీ స్క్రీన్ దిగువ భాగం నుండి పైకి స్వైప్ చేయండి"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"మీరు స్క్రీన్ దిగువ అంచు నుండి పైకి స్వయిప్ చేస్తున్నారని నిర్ధారించుకోండి."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"రిలీజ్ చేయడానికి ముందు విండోను ఎక్కువసేపు పట్టుకోడానికి ట్రై చేయండి."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"మీరు నేరుగా స్వైప్ చేశారని నిర్ధారించుకోండి, ఆపై పాజ్ చేయండి."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"స్క్రీన్ కింది భాగం నుండి పైకి స్వైప్ చేయండి"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"బాగా చేశారు!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"మీరు స్క్రీన్ దిగువ అంచు నుండి పైకి స్వైప్ చేశారని నిర్ధారించుకోండి"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"వేలిని రిలీజ్ చేయడానికి ముందు విండోను ఎక్కువసేపు నొక్కి, పట్టుకోవడానికి ట్రై చేయండి"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"స్క్రీన్పై నేరుగా పైకి స్వైప్ చేసి, ఆపై పాజ్ చేయండి"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"మీరు సంజ్ఞలను ఎలా ఉపయోగించాలో నేర్చుకున్నారు. సంజ్ఞలను ఆఫ్ చేయడానికి, సెట్టింగ్లకు వెళ్లండి."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"మీరు \'యాప్ల మధ్య మార్పు\' సంజ్ఞను పూర్తి చేశారు."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"మీరు \'యాప్ల మధ్య మార్పు\' సంజ్ఞను పూర్తి చేశారు"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"యాప్ల మధ్య మార్చడం కోసం స్వైప్ చేయండి"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"యాప్ల మధ్య మారడానికి, మీ స్క్రీన్ కింది వైపు నుండి పైకి స్వైప్ చేసి, పట్టుకుని, తర్వాత వదలండి."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"యాప్ల మధ్య మారడానికి, మీ స్క్రీన్ కింది నుండి 2 వేళ్లతో పైకి స్వైప్ చేసి, నొక్కి పట్టి, వదలండి."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"యాప్ల మధ్య స్విచ్ అవ్వండి"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"మీ స్క్రీన్ కింది వైపు నుండి పైకి స్వైప్ చేసి, పట్టుకుని, తర్వాత వదలండి"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"చాలా బాగా చేశారు!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"అంతా సిద్ధంగా ఉంది"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"పూర్తయింది"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"సెట్టింగ్లు"</string>
@@ -78,7 +86,7 @@
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"పనితీరు బాగుంది!"</string>
<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="459504134589971527">"హోమ్కు వెళ్లడానికి పైకి స్వైప్ చేయండి"</string>
+ <string name="allset_hint" msgid="459504134589971527">"వర్చువల్ హోమ్కు వెళ్లడానికి పైకి స్వైప్ చేయండి"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"మీ మొదటి స్క్రీన్కు వెళ్లడానికి హోమ్ బటన్ను ట్యాప్ చేయండి"</string>
<string name="allset_description_generic" msgid="5385500062202019855">"మీరు ఇప్పుడు మీ <xliff:g id="DEVICE">%1$s</xliff:g>ను ఉపయోగించడం ప్రారంభించవచ్చు"</string>
<string name="default_device_name" msgid="6660656727127422487">"పరికరం"</string>
@@ -86,7 +94,8 @@
<string name="action_share" msgid="2648470652637092375">"షేర్ చేయండి"</string>
<string name="action_screenshot" msgid="8171125848358142917">"స్క్రీన్షాట్"</string>
<string name="action_split" msgid="2098009717623550676">"స్ప్లిట్ చేయండి"</string>
- <string name="toast_split_select_app" msgid="8464310533320556058">"మరొక యాప్ను ట్యాప్ చేసి, స్ప్లిట్ స్క్రీన్ వాడండి"</string>
+ <string name="toast_split_select_app" msgid="8464310533320556058">"స్ప్లిట్ స్క్రీన్ కోసం మరొక యాప్ను ట్యాప్ చేయండి"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"స్ప్లిట్ స్క్రీన్ ఎంపిక నుండి ఎగ్జిట్ అవ్వండి"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"స్ప్లిట్ స్క్రీన్ ఉపయోగానికి మరొక యాప్ ఎంచుకోండి"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ఈ చర్యను యాప్ గానీ, మీ సంస్థ గానీ అనుమతించవు"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"నావిగేషన్ ట్యుటోరియల్ను స్కిప్ చేయాలా?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"స్కిప్ చేయండి"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"స్క్రీన్ను తిప్పండి"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"టాస్క్బార్ ఎడ్యుకేషన్"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"టాస్క్బార్ శిక్షణకు సంబంధించిన ప్యానెల్ కనిపించింది"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"టాస్క్బార్ శిక్షణకు సంబంధించిన ప్యానెల్ మూసివేయబడింది"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ఒకేసారి 2 యాప్లను ఉపయోగించడానికి యాప్ను పక్కకు లాగండి"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"టాస్క్బార్ను చూపడానికి నెమ్మదిగా పైకి స్వైప్ చేయండి"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"మీ రొటీన్ ఆధారంగా యాప్ సూచనలను పొందండి"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"టాస్క్బార్ను ఆటోమేటిక్గా దాచడానికి, సెట్టింగ్లలో సంజ్ఞ నావిగేషన్ను ఆన్ చేయండి"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"టాస్క్బార్తో మరిన్ని చేయండి"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"తర్వాత"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"వెనుకకు"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"మూసివేయండి"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"పూర్తయింది"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"మొదటి ట్యాబ్"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"నోటిఫికేషన్లు"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"క్విక్ సెట్టింగ్లు"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"టాస్క్బార్"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"టాస్క్బార్ చూపబడింది"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"టాస్క్బార్ దాచబడింది"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"నావిగేషన్ బార్"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ఎప్పుడూ టాస్క్బార్ చూపించండి"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"నావిగేషన్ మోడ్ను మార్చండి"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"టాస్క్బార్ డివైడర్"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ఎగువ/ఎడమ వైపునకు తరలించండి"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"దిగువ/కుడి వైపునకు తరలించండి"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{మరో # యాప్ను చూడండి.}other{మరో # యాప్లను చూడండి.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"డెస్క్టాప్నకు యాప్ను జోడిస్తోంది"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"రద్దు చేయండి"</string>
</resources>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 42fe347..0339046 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"เปิดใช้แอปแนะนำแล้ว"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ปิดใช้คำแนะนำเกี่ยวกับแอปอยู่"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"แอปที่คาดว่าจะใช้: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"ตรวจสอบว่าปัดจากขอบด้านขวาสุดหรือซ้ายสุด"</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"ตรวจสอบว่าปัดจากขอบด้านขวาหรือซ้ายไปตรงกลางหน้าจอ แล้วยกนิ้วขึ้น"</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"หมุนอุปกรณ์ของคุณ"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"โปรดหมุนอุปกรณ์เพื่อทำตามบทแนะนำการนำทางด้วยท่าทางสัมผัสให้เสร็จสมบูรณ์"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ตรวจสอบว่าปัดจากขอบด้านขวาสุดหรือซ้ายสุด"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"ตรวจสอบว่าปัดจากขอบด้านขวาหรือซ้ายไปตรงกลางหน้าจอ แล้วยกนิ้วขึ้น"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"คุณรู้วิธีปัดจากด้านขวาเพื่อย้อนกลับแล้ว ต่อไปดูวิธีสลับแอป"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"คุณทำท่าทางสัมผัสเพื่อย้อนกลับเสร็จแล้ว"</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"ตรวจสอบว่าไม่ได้ปัดใกล้กับด้านล่างของหน้าจอมากเกินไป"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"คุณทำท่าทางสัมผัสเพื่อย้อนกลับเสร็จแล้ว"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"ไม่ปัดใกล้กับด้านล่างของหน้าจอมากเกินไป"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"เปลี่ยนความไวของท่าทางสัมผัสเพื่อย้อนกลับได้ที่การตั้งค่า"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"ปัดเพื่อย้อนกลับ"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"หากต้องการย้อนกลับไปที่หน้าจอล่าสุด ให้ปัดจากขอบด้านซ้ายหรือขวาไปตรงกลางหน้าจอ"</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"หากต้องการย้อนกลับไปที่หน้าจอล่าสุด ให้ใช้ 2 นิ้วปัดจากขอบด้านซ้ายหรือขวาไปตรงกลางหน้าจอ"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"ปัดขึ้นจากขอบด้านล่างของหน้าจอ"</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"ตรวจสอบว่าไม่มีการหยุดชั่วคราวก่อนยกนิ้วขึ้น"</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"ตรวจสอบว่าปัดขึ้นในแนวตรง"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"คุณทำท่าทางสัมผัสเพื่อไปที่หน้าแรกเสร็จแล้ว ต่อไปดูวิธีย้อนกลับ"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"คุณทำท่าทางสัมผัสเพื่อไปที่หน้าแรกเสร็จแล้ว"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"ย้อนกลับ"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"ปัดจากขอบด้านซ้ายหรือขวาไปตรงกลางหน้าจอ"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"ปัดขึ้นจากขอบด้านล่างของหน้าจอ"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"ไม่ต้องหยุดชั่วคราวก่อนยกนิ้วขึ้น"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"ปัดขึ้นในแนวตรง"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"คุณทำท่าทางสัมผัสเพื่อไปที่หน้าแรกเสร็จแล้ว ต่อไปดูวิธีย้อนกลับ"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"คุณทำท่าทางสัมผัสเพื่อไปที่หน้าแรกเสร็จแล้ว"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"ปัดเพื่อไปที่หน้าแรก"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"ปัดขึ้นจากด้านล่างของหน้าจอ ท่าทางสัมผัสนี้จะนำคุณไปที่หน้าจอหลักเสมอ"</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"ใช้ 2 นิ้วปัดขึ้นจากด้านล่างของหน้าจอ ท่าทางสัมผัสนี้จะนำคุณไปที่หน้าจอหลักเสมอ"</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"ไปที่หน้าแรก"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"ปัดขึ้นจากด้านล่างของหน้าจอเพื่อไปที่หน้าจอหลักได้ทุกเมื่อ"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"ปัดขึ้นจากขอบด้านล่างของหน้าจอ"</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"ลองแตะหน้าต่างค้างไว้นานขึ้นก่อนปล่อยนิ้ว"</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"ตรวจสอบว่าปัดขึ้นในแนวตรง แล้วหยุดชั่วคราว"</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"ไปที่หน้าจอหลัก"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"ปัดขึ้นจากด้านล่างของหน้าจอ"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"เก่งมาก"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"ปัดขึ้นจากขอบด้านล่างของหน้าจอ"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"ลองแตะหน้าต่างค้างไว้นานขึ้นก่อนปล่อยนิ้ว"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"ตรวจสอบว่าปัดขึ้นในแนวตรง แล้วหยุดชั่วคราว"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"คุณรู้วิธีใช้ท่าทางสัมผัสแล้ว หากต้องการปิดท่าทางสัมผัส ให้ไปที่การตั้งค่า"</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"คุณทำท่าทางสัมผัสเพื่อสลับแอปเสร็จแล้ว"</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"คุณทำท่าทางสัมผัสเพื่อสลับแอปเสร็จแล้ว"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"ปัดเพื่อสลับแอป"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"หากต้องการสลับระหว่างแอปต่างๆ ให้ปัดขึ้นจากด้านล่างของหน้าจอ ค้างไว้ แล้วปล่อย"</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"หากต้องการสลับระหว่างแอป ให้ใช้ 2 นิ้วปัดขึ้นจากด้านล่างของหน้าจอค้างไว้แล้วปล่อย"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"เปลี่ยนแอป"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"ปัดขึ้นจากด้านล่างของหน้าจอ ค้างไว้ แล้วปล่อย"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"เยี่ยมมาก"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"เรียบร้อย"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"เสร็จสิ้น"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"การตั้งค่า"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ภาพหน้าจอ"</string>
<string name="action_split" msgid="2098009717623550676">"แยก"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"แตะแอปอื่นเพื่อใช้การแยกหน้าจอ"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ออกจากการเลือกโหมดแยกหน้าจอ"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"เลือกแอปอื่นเพื่อใช้การแยกหน้าจอ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"แอปหรือองค์กรของคุณไม่อนุญาตการดำเนินการนี้"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ข้ามบทแนะนำการนำทางไหม"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ข้าม"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"หมุนหน้าจอ"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"แถบงาน Education"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"แถบงาน Education ปรากฎขึ้น"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"ปิดแถบงาน Education แล้ว"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ลากแอปไปด้านข้างเพื่อใช้ 2 แอปพร้อมกัน"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"ปัดขึ้นช้าๆ เพื่อแสดงแถบงาน"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"รับคำแนะนำเกี่ยวกับแอปตามกิจวัตรของคุณ"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"เปิดการนำทางด้วยท่าทางสัมผัสในการตั้งค่าเพื่อซ่อนแถบงานโดยอัตโนมัติ"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"ทำสิ่งต่างๆ ได้มากขึ้นด้วยแถบงาน"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"ถัดไป"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"กลับ"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"ปิด"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"เสร็จ"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"หน้าแรก"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"การแจ้งเตือน"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"การตั้งค่าด่วน"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"แถบงาน"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"แถบงานแสดงอยู่"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"แถบงานซ่อนอยู่"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"แถบนำทาง"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"แสดงแถบงานเสมอ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"เปลี่ยนโหมดการนําทาง"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ตัวแบ่งแถบงาน"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ย้ายไปที่ด้านบนหรือด้านซ้าย"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ย้ายไปที่ด้านล่างหรือด้านขวา"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{แสดงเพิ่มเติมอีก # แอป}other{แสดงเพิ่มเติมอีก # แอป}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> และ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"การเพิ่มแอปไปยังเดสก์ท็อป"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ยกเลิก"</string>
</resources>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index bec2d17..7bb38c2 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Naka-enable ang mga iminumungkahing app"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Naka-disable ang mga iminumungkahing app"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Hinulaang app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Tiyaking magsa-swipe ka mula sa dulong kanan o dulong kaliwang gilid."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Tiyaking mag-swipe mula sa kanan o kaliwang gilid papunta sa gitna ng screen at iangat ang daliri."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"I-rotate ang iyong device"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Paki-rotate ang iyong device para tapusin ang tutorial sa navigation gamit ang galaw"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Tiyaking magsa-swipe ka mula sa dulong kanan o dulong kaliwang gilid"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Tiyaking magsa-swipe mula sa kanan o kaliwang gilid papunta sa gitna ng screen at iangat ang daliri"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Natuto kang mag-swipe mula sa kanan para bumalik. Sunod, alamin kung paano magpalipat-lipat ng app."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Nakumpleto mo na ang galaw para bumalik."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Tiyaking hindi ka magsa-swipe nang masyadong malapit sa ibaba ng screen."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Nakumpleto mo na ang galaw para bumalik"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Tiyaking hindi ka magsa-swipe nang masyadong malapit sa ibaba ng screen"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Pumunta sa Settings para baguhin ang sensitivity ng pagbalik"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Mag-swipe para bumalik"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Para bumalik sa nakaraang screen, mag-swipe mula sa kaliwa o kanang gilid patungo sa gitna ng screen."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Para bumalik sa huling screen, mag-swipe gamit ang 2 daliri mula sa kaliwa o kanang gilid hanggang sa gitna ng screen."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Tiyaking magsa-swipe ka pataas mula sa pinakaibaba ng screen."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Tiyaking hindi ka magpo-pause bago iangat ang iyong daliri."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Tiyaking magsa-swipe ka nang diretso pataas."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Nakumpleto mo na ang galaw para pumunta sa Home. Susunod, alamin kung paano bumalik."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Nakumpleto mo na ang galaw para pumunta sa Home."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Bumalik"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Mag-swipe mula sa kaliwa o kanang gilid papunta sa gitna ng screen"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Tiyaking magsa-swipe ka pataas mula sa pinakaibaba ng screen"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Tiyaking hindi ka magpo-pause bago iangat ang iyong daliri"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Tiyaking magsa-swipe ka nang diretso pataas"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Nakumpleto mo na ang galaw para pumunta sa home. Susunod, alamin kung paano bumalik."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Nakumpleto mo na ang galaw para pumunta sa home"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Mag-swipe para pumunta sa home"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Mag-swipe pataas mula sa ibaba ng iyong screen. Dadalhin ka palagi ng galaw na ito sa Home screen."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Mag-swipe pataas gamit ang 2 daliri mula sa ibaba ng screen. Dadalhin ka palagi nito sa Home screen."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Pumunta sa home"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Para pumunta sa iyong home screen anumang oras, mag-swipe pataas mula sa ibaba ng screen mo"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Tiyaking magsa-swipe ka pataas mula sa pinakaibaba ng screen."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Subukang pindutin nang mas matagal ang window bago ito bitawan."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Tiyaking magsa-swipe ka nang diretso pataas, pagkatapos ay mag-pause."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Mag-swipe pataas mula sa ibabang bahagi ng iyong screen"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Magaling!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Tiyaking magsa-swipe ka pataas mula sa pinakaibaba ng screen"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Subukang pindutin nang mas matagal ang window bago ito bitawan"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Tiyaking magsa-swipe ka nang diretso pataas, pagkatapos ay mag-pause"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Alam mo na kung paano gumamit ng mga galaw. Para i-off ang mga galaw, pumunta sa Mga Setting."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Nakumpleto mo na ang galaw para magpalipat-lipat sa mga app."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Nakumpleto mo na ang galaw para magpalipat-lipat sa mga app"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Mag-swipe para lumipat ng app"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Para lumipat ng app, mag-swipe pataas mula sa ibaba ng iyong screen, mag-hold, at iangat ang daliri."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Para lumipat ng app, mag-swipe pataas gamit ang 2 daliri mula sa ibaba, mag-hold, at bumitaw."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Lumipat ng app"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Mag-swipe pataas mula sa ibaba ng iyong screen, i-hold ito saka bitawan"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Magaling!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Handa na ang lahat"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Tapos na"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Mga Setting"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Mag-tap ng ibang app para gamitin ang split screen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Lumabas sa pagpili ng split screen"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Pumili ng ibang app para gamitin ang split screen"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Hindi pinapayagan ng app o ng iyong organisasyon ang pagkilos na ito"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Laktawan ang tutorial sa pag-navigate?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Laktawan"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"I-rotate ang screen"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Impormasyon sa taskbar"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Lumabas ang edukasyon sa taskbar"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Sarado ang edukasyon sa taskbar"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Mag-drag ng app sa gilid para makagamit ng 2 app nang sabay"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Mag-swipe nang mabagal pataas para ipakita ang Taskbar"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Makakuha ng mga iminumungkahing app batay sa iyong routine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"I-on ang navigation gamit ang galaw sa Mga Setting para i-auto hide ang Taskbar"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Mas maraming magawa gamit ang Taskbar"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Susunod"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Bumalik"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Isara"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Tapos na"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Mga Notification"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Taskbar"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Ipinapakita ang taskbar"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Nakatago ang taskbar"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Palaging ipakita ang Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Magpalit ng navigation mode"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Divider ng Taskbar"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Ilipat sa itaas/kaliwa"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Ilipat sa ibaba/kanan"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Magpakita ng # pang app.}one{Magpakita ng # pang app.}other{Magpakita ng # pang app.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> at <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Idinaragdag ang app sa Desktop"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Kanselahin"</string>
</resources>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 9d422e9..905183a 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Uygulama önerileri etkinleştirildi"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Uygulama önerileri devre dışı bırakıldı"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Tahmin edilen uygulama: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"En sağ veya en sol kenardan kaydırdığınızdan emin olun."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Ekranın sağ veya sol kenarından ortasına doğru sürükleyip bıraktığınızdan emin olun."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Cihazınızı döndürün"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Hareketle gezinme eğitimini tamamlamak için lütfen cihazınızı döndürün"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"En sağ veya en sol kenardan kaydırdığınızdan emin olun"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Ekranın sağ veya sol kenarından ortasına doğru sürükleyip bıraktığınızdan emin olun."</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Geri dönmek için sağdan kaydırmayı öğrendiniz. Sırada uygulamalar arasında geçiş yapma var."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Geri dön hareketini tamamladınız."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Ekranın alt kısmına çok yakın bir şekilde kaydırmadığınızdan emin olun."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Geri dön hareketini tamamladınız"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Ekranın alt kısmına çok yakın bir şekilde kaydırmadığınızdan emin olun"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Geri hareketinin hassasiyetini değiştirmek için Ayarlar\'a gidin"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Geri dönmek için kaydırma"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Son ekrana geri gitmek için sol veya sağ kenardan ekranın ortasına doğru kaydırın."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Son ekrana geri gitmek için sol veya sağ kenardan ekranın ortasına doğru 2 parmağınızla kaydırın."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Ekranın alt kenarından yukarı kaydırdığınızdan emin olun."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Bırakmadan önce parmağınızı duraklatmadığınızdan emin olun."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Düz bir şekilde yukarı kaydırdığınızdan emin olun."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Ana ekrana git hareketini tamamladınız. Şimdi nasıl geri döneceğinizi öğreneceksiniz."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Ana ekrana git hareketini tamamladınız."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Geri dönme"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Sol veya sağ kenardan ekranın ortasına doğru kaydırın"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Ekranın alt kenarından yukarı kaydırdığınızdan emin olun"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Bırakmadan önce parmağınızı duraklatmadığınızdan emin olun"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Düz bir şekilde yukarı kaydırdığınızdan emin olun"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Ana ekrana git hareketini tamamladınız. Şimdi ana ekrana nasıl gideceğinizi öğreneceksiniz."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Ana ekrana git hareketini tamamladınız"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Ana ekrana gitmek için kaydırma"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Ekranın alt kısmından yukarıya doğru kaydırın. Bu hareket sizi her zaman Ana ekrana götürür."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Ekranın alt kısmından 2 parmağınızla yukarı kaydırın. Bu hareket sizi her zaman Ana ekrana götürür."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Ana sayfaya gidin"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"İstediğiniz zaman ana ekrana gitmek için ekranınızın altından yukarı doğru kaydırın"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Ekranın alt kenarından yukarı kaydırdığınızdan emin olun."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Bırakmadan önce pencereyi daha uzun süre tutmayı deneyin."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Düz bir şekilde yukarı kaydırıp ardından parmağınızı duraklattığınızdan emin olun."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Ana sayfaya gitme"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Parmağınızı ekranın alt kısmından yukarıya doğru kaydırın"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Tebrikler!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Ekranın alt kenarından yukarı kaydırdığınızdan emin olun"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Bırakmadan önce pencereyi daha uzun süre tutmayı deneyin"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Düz bir şekilde yukarı kaydırıp ardından parmağınızı duraklattığınızdan emin olun"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Hareketleri nasıl kullanacağınızı öğrendiniz. Hareketleri kapatmak için Ayarlar\'a gidin."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Uygulamalar arasında geçiş yapma hareketini tamamladınız."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Uygulamalar arasında geçiş yapma hareketini tamamladınız"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Uygulamalar arasında geçiş yapmak için kaydırma"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Uygulamalar arasında geçiş yapmak için ekranınızın altından yukarı kaydırıp basılı tutun ve sonra bırakın."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Uygulamalara geçiş yapmak için ekranın altından 2 parmakla yukarı kaydırıp basılı tutun ve bırakın."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Uygulamalar arasında geçiş yapma"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Ekranınızın alt tarafından yukarı doğru kaydırın, tutun ve sonra bırakın"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Tebrikler!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Hepsi bu kadar"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Bitti"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Ayarlar"</string>
@@ -87,6 +95,7 @@
<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="8464310533320556058">"Bölünmüş ekran için başka bir uygulamaya dokunun"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Bölünmüş ekran seçiminden çıkın"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Bölünmüş ekran kullanmak için başka bir uygulama seçin"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Uygulamanız veya kuruluşunuz bu işleme izin vermiyor"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Gezinme eğitimi atlansın mı?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Atla"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Ekranı döndür"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Görev çubuğu eğitimi"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Görev çubuğu eğitimi görüntülendi"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Görev çubuğu eğitimi kapatıldı"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Aynı anda iki uygulama kullanmak için birini yana sürükleyin"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Görev çubuğunu göstermek için yukarı doğru yavaşça kaydırın"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Rutininize göre uygulama önerileri alın"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Görev çubuğunu otomatik olarak gizlemek için Ayarlar\'dan hareketle gezinmeyi etkinleştirin"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Görev çubuğuyla daha fazla şey yapın"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"İleri"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Geri"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Kapat"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Bitti"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Ana ekran"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Bildirimler"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Hızlı Ayarlar"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Görev çubuğu."</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Görev çubuğu gösteriliyor"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Görev çubuğu gizlendi"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Gezinme çubuğu"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Görev çubuğunu daima göster"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Gezinme modunu değiştir"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Görev Çubuğu Ayırıcısı"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Sol üste taşı"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Sağ alta taşı"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# uygulama daha göster.}other{# uygulama daha göster}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ve <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Uygulama Masaüstü\'ne ekleniyor"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"İptal"</string>
</resources>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 70c0e1b..6cbf71f 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -44,49 +44,58 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Рекомендовані додатки ввімкнено"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Рекомендовані додатки вимкнено"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Передбачений додаток: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Проведіть пальцем саме від правого або лівого краю екрана."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Проведіть пальцем від правого або лівого краю до середини екрана й підніміть палець."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Оберніть пристрій"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Обертайте пристрій, щоб ознайомитися з посібником із навігації за допомогою жестів"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Проведіть пальцем від самого краю екрана (правого або лівого)"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Проведіть пальцем від правого або лівого краю до середини екрана й підніміть палець"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Тепер ви знаєте, як повернутися на попередній екран, провівши пальцем справа наліво. Дізнайтеся, як переключатися між додатками."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Ви виконали жест \"Назад\"."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Не проводьте пальцем надто близько до нижнього краю екрана."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Ви виконали жест \"Назад\""</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Не проводьте пальцем надто близько до нижнього краю екрана"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Щоб змінити чутливість жесту \"Назад\", відкрийте налаштування"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Щоб повернутися, проведіть пальцем по екрану"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Щоб перейти на попередній екран, проведіть пальцем від лівого чи правого краю до середини екрана."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Щоб перейти на попередній екран, проведіть двома пальцями від лівого чи правого краю до середини екрана."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Проведіть пальцем угору від нижнього краю екрана."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Не робіть паузу перед тим, як відірвати палець від екрана."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Проводьте пальцем вертикально вгору."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Ви виконали жест переходу на головний екран. Тепер дізнайтеся, як повернутися."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Ви виконали жест переходу на головний екран."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Повернення на попередній екран"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Проведіть пальцем від лівого чи правого краю до середини екрана"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Проведіть пальцем угору від нижнього краю екрана"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Не робіть паузу перед тим, як відірвати палець від екрана"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Проводьте пальцем вертикально вгору"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Ви виконали жест переходу на головний екран. Тепер дізнайтеся, як повернутися."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Ви виконали жест переходу на головний екран"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Проведіть пальцем, щоб перейти на головний екран"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Проведіть пальцем по екрану знизу вгору. Цей жест завжди повертатиме вас на головний екран."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Проведіть двома пальцями вгору від низу екрана. Цей жест завжди спрямовує вас на головний екран."</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Перейти на головний екран"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Щоб будь-коли перейти на головний екран, проведіть пальцем вгору від низу екрана"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Проведіть пальцем угору від нижнього краю екрана."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Спробуйте втримувати вікно довше, перш ніж відпустити."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Проведіть пальцем вертикально вгору, а тоді зробіть паузу."</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Перехід на головний екран"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Проведіть пальцем угору від низу екрана"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Чудово!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Проведіть пальцем угору від нижнього краю екрана"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Спробуйте втримувати вікно довше, перш ніж відпустити"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Проведіть пальцем вертикально вгору, а тоді зробіть паузу"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Ви вивчили жести. Щоб вимкнути їх, перейдіть у налаштування."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Ви виконали жест переходу в інший додаток."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Ви виконали жест переходу в інший додаток"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Проведіть пальцем, щоб перейти в інший додаток"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Щоб переключатися між додатками, проведіть знизу вгору по екрану, утримуйте палець, а потім відпустіть."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Щоб перейти в інший додаток, проведіть 2 пальцями від низу екрана, потримайте й відпустіть палець."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Перемикання між додатками"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Проведіть пальцем знизу вгору, утримуйте палець на екрані, а потім відпустіть"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Чудово!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Усе готово!"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Готово"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Налаштування"</string>
<string name="gesture_tutorial_try_again" msgid="65962545858556697">"Спробуйте ще"</string>
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Чудово!"</string>
<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_title" msgid="5021126669778966707">"Готово!"</string>
<string name="allset_hint" msgid="459504134589971527">"Щоб перейти на головний екран, проведіть пальцем угору"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"Натисніть кнопку головного екрана, щоб відкрити його"</string>
- <string name="allset_description_generic" msgid="5385500062202019855">"Тепер ви можете користуватися цим пристроєм: <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+ <string name="allset_description_generic" msgid="5385500062202019855">"Тепер ви можете використовувати <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="default_device_name" msgid="6660656727127422487">"пристрій"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Системні налаштування навігації"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Поділитися"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Знімок екрана"</string>
<string name="action_split" msgid="2098009717623550676">"Розділити"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Щоб розділити екран, виберіть ще один додаток"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Вийти з режиму розділення екрана"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Щоб розділити екран, виберіть ще один додаток"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Ця дія заборонена додатком або адміністратором організації"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Пропустити посібник із навігації?"</string>
@@ -95,26 +104,31 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Пропустити"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Обернути екран"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Панель завдань Education"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Панель завдань Education відкрито"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Панель завдань Education закрито"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Перетягніть убік, щоб використовувати 2 додатки одночасно"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Щоб відкрити панель завдань, повільно проведіть угору"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Отримуйте рекомендації додатків залежно від їх використання"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Увімкніть навігацію жестами в налаштуваннях, щоб автоматично приховувати панель завдань"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Більше можливостей завдяки панелі завдань"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Далі"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Назад"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Закрити"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Головний екран"</string>
- <string name="taskbar_button_a11y" msgid="5241161324875094465">"Спеціальні можливості"</string>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Доступність"</string>
<string name="taskbar_button_back" msgid="8558862226461164514">"Назад"</string>
<string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Перемикач IME"</string>
<string name="taskbar_button_recents" msgid="7273376136216613134">"Нещодавні"</string>
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Сповіщення"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Швидкі налаштув."</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Панель завдань"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Панель завдань показано"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Панель завдань приховано"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Панель навігації"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Завжди показув. панель завдань"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Змінити режим навігації"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Розділювач панелі завдань"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Перемістити вгору або вліво"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Перемістити вниз або вправо"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показати ще # додаток.}one{Показати ще # додаток.}few{Показати ще # додатки.}many{Показати ще # додатків.}other{Показати ще # додатка.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> та <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Встановлення додатка на комп’ютер"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Скасувати"</string>
</resources>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index 8382890..2392c6c 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ایپ کی تجاویز فعال ہیں"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ایپ کی تجاویز غیر فعال ہیں"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"پیشن گوئی کردہ ایپ: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"یقینی بنائیں کہ آپ دائیں یا بائیں کنارے سے دور سے سوئپ کریں۔"</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"یقینی بنائیں کہ آپ دائیں یا بائیں کنارے سے اسکرین کے وسط تک سوائپ کریں اور پھر اپنی انگلی اٹھا لیں۔"</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"اپنا آلہ گھمائیں"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"براہ کرم اشاروں والی نیویگیشن کا ٹیوٹوریل مکمل کرنے کے لیے اپنا آلہ گھمائیں"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"یقینی بنائیں کہ آپ دائیں یا بائیں کنارے سے دور سے سوائپ کریں"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"یقینی بنائیں کہ آپ دائیں یا بائیں کنارے سے اسکرین کے وسط تک سوائپ کریں اور پھر اپنی انگلی اٹھا لیں"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"آپ نے واپس جانے کے لیے دائیں کنارے سے سوائپ کرنے کا طریقہ سیکھ لیا۔ اس کے بعد ایپس سوئچ کرنے کا طریقہ جانیں۔"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"آپ نے واپس جائیں اشارے کو مکمل کر لیا۔"</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"اس بات کو یقینی بنائیں کہ آپ اسکرین کے نچلے حصے سے زیادہ قریب سے سوائپ نہ کریں۔"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"آپ نے واپس جائیں اشارے کو مکمل کر لیا"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"اس بات کو یقینی بنائیں کہ آپ اسکرین کے نچلے حصے سے زیادہ قریب سے سوائپ نہ کریں"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"پچھلے اشارے کی حساسیت تبدیل کرنے کے لیے ترتیبات پر جائیں"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"واپس جانے کے لیے سوائپ کریں"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"پچھلی اسکرین پر واپس جانے کے لیے بائیں یا دائیں کنارے سے اسکرین کے وسط تک سوائپ کریں۔"</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"آخری اسکرین پر واپس جانے کے لیے، 2 انگلیوں سے بائیں یا دائیں کنارے سے اسکرین کے وسط تک سوائپ کریں۔"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"اس بات کو یقینی بنائیں کہ آپ اسکرین کے نچلے کنارے سے اوپر کی طرف سوائپ کریں۔"</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"اس بات کو یقینی بنائیں کہ آپ اپنی انگلی اوپر اٹھانے سے پہلے موقوف نہ کریں۔"</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"اس بات کو یقینی بنائیں کہ آپ سیدھا اوپر کی طرف سوائپ کریں۔"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"آپ نے ہوم پر جانے کا اشارہ مکمل کر لیا۔ اس کے بعد واپس جانے کا طریقہ جانیں۔"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"آپ نے ہوم پر جانے کا اشارہ مکمل کر لیا۔"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"واپس جائیں"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"دائیں یا بائیں کنارے سے اسکرین کے وسط تک سوائپ کریں"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"اس بات کو یقینی بنائیں کہ آپ اسکرین کے نچلے کنارے سے اوپر کی طرف سوائپ کریں"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"اس بات کو یقینی بنائیں کہ آپ اپنی انگلی اوپر اٹھانے سے پہلے موقوف نہ کریں"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"اس بات کو یقینی بنائیں کہ آپ سیدھا اوپر کی طرف سوائپ کریں"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"آپ نے ہوم پر جانے کا اشارہ مکمل کر لیا۔ اس کے بعد، واپس جانے کا طریقہ جانیں۔"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"آپ نے ہوم پر جانے کا اشارہ مکمل کر لیا"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"ہوم پر جانے کے لیے سوائپ کریں"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"اپنی اسکرین کے نیچے سے اوپر کی طرف سوائپ کریں۔ یہ اشارہ آپ کو ہمیشہ ہوم اسکرین پر لے جاتا ہے۔"</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"اسکرین کے نیچے سے 2 انگلیوں سے اوپر سوائپ کریں۔ یہ اشارہ آپ کو ہمیشہ ہوم اسکرین پر لے جاتا ہے۔"</string>
- <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"گھر جائیں"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"کسی بھی وقت اپنی ہوم اسکرین پر جانے کے لیے، اپنی اسکرین کے نیچے سے اوپر سوائپ کریں"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"اس بات کو یقینی بنائیں کہ آپ اسکرین کے نچلے کنارے سے اوپر کی طرف سوائپ کریں۔"</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"انگلی اٹھانے سے پہلے ونڈو کو زیادہ دیر تک پکڑنے کی کوشش کریں۔"</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"اس بات کو یقینی بنائیں کہ آپ سیدھا اوپر کی طرف سوائپ کریں، پھر موقوف کریں۔"</string>
+ <string name="home_gesture_tutorial_title" msgid="3126834347496917376">"ہوم پر جائیں"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"اپنی اسکرین کے نچلے حصے سے اوپر کی طرف سوائپ کریں"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"بہترین!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"اس بات کو یقینی بنائیں کہ آپ اسکرین کے نچلے کنارے سے اوپر کی طرف سوائپ کریں"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"انگلی اٹھانے سے پہلے ونڈو کو زیادہ دیر تک پکڑنے کی کوشش کریں"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"اس بات کو یقینی بنائیں کہ آپ سیدھا اوپر کی طرف سوائپ کریں، پھر موقوف کریں"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"آپ نے اشاروں کو استعمال کرنے کا طریقہ سیکھ لیا۔ اشاروں کو آف کرنے کے لیے ترتیبات پر جائیں۔"</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"آپ نے ایپس کو سوئچ کرنے کا اشارہ مکمل کر لیا۔"</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"آپ نے ایپس کو سوئچ کرنے کا اشارہ مکمل کر لیا"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"ایپس سوئچ کرنے کے لیے سوائپ کریں"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"ایپس کے مابین سوئچ کرنے کے لیے، اپنی اسکرین کے نچلے حصے سے اوپر کی جانب سوائپ کریں، پکڑے رکھیں، پھر چھوڑ دیں۔"</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"ایپس کے مابین سوئچ کرنے کیلئے، اپنی اسکرین کے نیچے سے 2 انگلیوں سے اوپر سوائپ کریں، دبائے رکھیں پھر چھوڑ دیں۔"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"ایپس سوئچ کریں"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"اپنی اسکرین کے نچلے حصے سے اوپر کی جانب سوائپ کریں، دبائے رکھیں، پھر چھوڑ دیں"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"بہت خوب!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"سب ہو گیا"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"ہو گیا"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"ترتیبات"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"اسکرین شاٹ"</string>
<string name="action_split" msgid="2098009717623550676">"اسپلٹ"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"اسپلٹ اسکرین کا استعمال کرنے کیلئے دوسری ایپ پر تھپتھپائیں"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"اسپلٹ اسکرین کے انتخاب سے باہر نکلیں"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"اسپلٹ اسکرین کے استعمال کیلئے دوسری ایپ منتخب کریں"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ایپ یا آپ کی تنظیم کی جانب سے اس کارروائی کی اجازت نہیں ہے"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"نیویگیشن کا ٹیوٹوریل نظر انداز کریں؟"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"نظر انداز کریں"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"اسکرین کو گھمائیں"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"ٹاسک بار کی تعلیم"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"ٹاکس بار کا تعلیمی پینل ظاہر ہو گیا"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"ٹاسک بار کا تعلیمی پینل بند ہو گیا"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"ایک وقت میں 2 ایپس استعمال کرنے کیلئے ایپ سائیڈ پر گھسیٹیں"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"ٹاسک بار دکھانے کے لیے آہستہ سے اوپر سوائپ کریں"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"اپنی روٹین پر مبنی ایپس کی تجاویز حاصل کریں"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"ٹاسک بار کو خودکار طور پر چھپانے کیلئے \'ترتیبات\' میں اشاروں والی نیویگیشن آن کریں"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"ٹاسک بار سے بہت کچھ کریں"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"آگے"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"پیچھے"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"بند کریں"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"ہو گیا"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"ہوم"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"اطلاعات"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"فوری ترتیبات"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"ٹاسک بار"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ٹاشک بار دکھایا گیا"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ٹاسک بار چھپایا گیا"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"نیویگیشن بار"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ہمیشہ ٹاسک بار دکھائیں"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"نیویگیشن موڈ تبدیل کریں"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ٹاسک بار ڈیوائیڈر"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"اوپر/بائیں طرف منتقل کریں"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"نیچے/دائیں طرف منتقل کریں"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# مزید ایپ دکھائیں۔}other{# مزید ایپس دکھائیں۔}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> اور <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"ڈیسک ٹاپ پر ایپ شامل کرنا"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"منسوخ کریں"</string>
</resources>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index 09b6699..da2d363 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -24,7 +24,7 @@
<string name="recents_empty_message" msgid="7040467240571714191">"Yaqinda ishlatilgan ilovalar yo‘q"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ilovadan foydalanish sozlamalari"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Hammasini tozalash"</string>
- <string name="accessibility_recent_apps" msgid="4058661986695117371">"Yaqinda ishlatilgan ilovalar"</string>
+ <string name="accessibility_recent_apps" msgid="4058661986695117371">"Oxirgi ilovalar"</string>
<string name="task_view_closed" msgid="9170038230110856166">"Vazifalar yopildi"</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 daqiqa"</string>
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Ilova tavsiyalari yoqildi"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Endi ilova takliflari chiqmaydi"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Taklif etilgan ilova: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Ekran chetidan boshlab oʻngdan yoki chapdan suring."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Ekranning oʻng yoki chap chetidan oʻrtasiga suring va qoʻyib yuboring."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Qurilmangizni buring"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Ishorali navigatsiya darsligini tugatish uchun qurilmani buring"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Ekran chetidan boshlab oʻngdan yoki chapdan suring"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Ekranning oʻng yoki chap chetidan oʻrtasigacha suring va qoʻyib yuboring"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Ortga qaytish uchun oʻngdan surishni oʻrgandingiz. Endi ilovalarni almashtirishni oʻrganamiz."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Ortga qaytish ishorasi darsini tamomladingiz."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Barmoqni ekran pastiga yaqin surmaslikka harakat qiling."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Ortga qaytish ishorasi darsini tamomladingiz"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Barmoqni ekran pastiga yaqin surmaslikka harakat qiling"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Orqaga ishorasi sezuvchanligi Sozlamalardan oʻzgartiriladi"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Orqaga qaytish"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Ortga qaytish uchun barmoqni ekranning yon chekkalaridan oʻrtasigacha suring."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Oxirgi ekranga qaytish uchun 2 barmoq bilan ekranning chap yoki oʻng chekkasidan oʻrtasigacha suring."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Barmoqni ekranning pastki chetidan yuqoriga suring."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Barmoqni ekrandan pauzasiz qoʻyib uzing."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Barmoqni tik tepaga suring."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Bosh ekranni ochish ishorasi darsini tamomladingiz. Endi orqaga qaytishni oʻrganamiz."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Bosh ekranni ochish ishorasi darsini tamomladingiz."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Orqaga"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Chap yoki oʻng chetidan ekranning oʻrtasiga suring"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Barmoqni ekranning pastki chetidan yuqoriga suring."</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Barmoqni ekrandan pauzasiz qoʻyib uzing"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Barmoqni tik tepaga suring"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Bosh ekranni ochish ishorasi darsini tamomladingiz. Endi orqaga qaytishni oʻrganamiz."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Bosh ekranni ochish ishorasi darsini tamomladingiz"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Svayp bilan bosh ekranni ochish"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Ekranning pastidan tepaga qarab suring. Bu ishora doim Bosh ekranni ochadi."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"2 barmoq bilan ekranning quyidan tepasiga suring. Bu ishora har doim Bosh ekranni ochadi."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Boshiga"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Istalgan vaqtda bosh ekranga oʻtish uchun ekranning pastidan tepaga suring"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Barmoqni ekranning pastki chetidan yuqoriga suring."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Barmoqni uzishdan oldin oynani biroz bosib turing."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Avval tik tepaga surib, keyin pauza qiling."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Ekranning quyi qismidan tepaga torting"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Barakalla!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Barmoqni ekranning pastki chetidan yuqoriga suring."</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Barmoqni uzishdan oldin oynani biroz bosib turing"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Avval tik tepaga surib, keyin pauza qiling"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Ishoralardan qanday foydalanishni oʻrganib oldingiz. Ishoralarni oʻchirish uchun Sozlamalarga kiring."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Ilovalarni almashtirish darsini tamomladingiz."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Ilovalarni almashtirish darsini tamomladingiz"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Ilovalar orasida almashish"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Ilovalarni ochish uchun ekranning pastidan tepaga qarab suring, biroz ushlab turing va qoʻyib yuboring"</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Ilovalarni almashtirish uchun 2 barmoq bilan ekranning quyidan tepasiga surib turib, qoʻyib yuboring"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Ilovalarni almashtirish"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Ekranning pastidan tepaga qarab suring, biroz ushlab turing va qoʻyib yuboring"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Juda soz!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Tayyor"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Tayyor"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Sozlamalar"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skrinshot"</string>
<string name="action_split" msgid="2098009717623550676">"Ajratish"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Ekranni ikkiga ajratish uchun boshqa ilovani bosing"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Ekranni ikkiga ajratish tanlovidan chiqish"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Ekranni ikkiga ajratish uchun boshqa ilovani tanlang"</string>
<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>
@@ -95,26 +104,31 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Tashlab ketish"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Ekranni burish"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Vazifalar paneli qoʻllanmasi"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Taʼlim vazifalar paneli chiqdi"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Taʼlim vazifalar paneli yopildi"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Bitta ilovani yon tomonga sudrab, bir vaqtda 2 ta ilovadan foydalaning."</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Vazifalar panelini ochish uchun tepaga asta suring"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Harakatlaringiz asosida tavsiyalar oling."</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Vazifalar paneli avtomatik yopilishi uchun ishorali navigatsiyani yoqing"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Vazifalar panelidan maksimal darajada foydalaning"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Keyingisi"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Orqaga"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Yopish"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Tayyor"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Bosh ekran"</string>
- <string name="taskbar_button_a11y" msgid="5241161324875094465">"Maxsus imkoniyatlar"</string>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Qulayliklar"</string>
<string name="taskbar_button_back" msgid="8558862226461164514">"Orqaga"</string>
<string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME tugmasi"</string>
<string name="taskbar_button_recents" msgid="7273376136216613134">"Oxirgilar"</string>
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Bildirishnomalar"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Tezkor sozlamalar"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Vazifalar paneli"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Vazifalar paneli ochiq"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Vazifalar paneli yopiq"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigatsiya paneli"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Doim vazifalar paneli chiqsin"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Navigatsiya rejimini oʻzgartirish"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Vazifalar panelini ajratkich"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Yuqoriga yoki chapga oʻtkazish"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Pastga yoki oʻngga oʻtkazish"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Yana # ta ilovani chiqarish}other{Yana # ta ilovani chiqarish}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> va <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Ilova kompyuterga qoʻshilmoqda"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Bekor qilish"</string>
</resources>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index a946d1b..dae4212 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Đã bật tính năng Ứng dụng đề xuất"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Tính năng Ứng dụng đề xuất bị tắt"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Ứng dụng dự đoán: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Hãy vuốt từ mép ngoài cùng bên phải hoặc ngoài cùng bên trái."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Hãy vuốt từ mép phải hoặc mép trái tới giữa màn hình rồi thả tay ra."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Xoay thiết bị của bạn"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Vui lòng xoay thiết bị của bạn để hoàn tất hướng dẫn thao tác bằng cử chỉ"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Hãy vuốt từ mép ngoài cùng bên phải hoặc ngoài cùng bên trái"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Hãy vuốt từ mép phải hoặc mép trái tới giữa màn hình rồi nhấc ngón tay ra"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Bạn đã học được cách vuốt từ mép phải để quay lại. Tiếp theo, hãy tìm hiểu cách chuyển đổi ứng dụng."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Bạn đã thực hiện xong cử chỉ quay lại."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Hãy nhớ không được vuốt quá gần phần cuối màn hình."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Bạn đã thực hiện xong cử chỉ quay lại"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Hãy nhớ không được vuốt quá gần phần dưới cùng của màn hình"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Để thay đổi độ nhạy của cử chỉ quay lại, hãy vào mục Cài đặt"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Vuốt để quay lại"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Để quay lại màn hình gần đây nhất, hãy vuốt từ mép trái hoặc mép phải tới chính giữa màn hình."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Để quay lại màn hình trước đó, hãy vuốt 2 ngón tay từ cạnh trái hoặc phải vào giữa màn hình."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Hãy vuốt lên từ mép dưới cùng của màn hình."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Hãy nhớ không được tạm dừng trước khi nhấc ngón tay."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Hãy vuốt thẳng lên."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Bạn đã thực hiện xong cử chỉ chuyển đến Màn hình chính. Tiếp theo, hãy tìm hiểu cách quay lại."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Bạn đã thực hiện xong cử chỉ chuyển đến Màn hình chính."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Quay lại"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Hãy vuốt từ mép trái hoặc mép phải tới giữa màn hình"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Hãy vuốt lên từ mép dưới cùng của màn hình"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Hãy nhớ không được dừng trước khi nhấc ngón tay"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Hãy vuốt thẳng lên"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Bạn đã thực hiện xong cử chỉ chuyển đến Màn hình chính. Tiếp theo, hãy tìm hiểu cách quay lại."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Bạn đã thực hiện xong cử chỉ chuyển đến Màn hình chính"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Vuốt để chuyển đến Màn hình chính"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Vuốt lên từ cuối màn hình. Cử chỉ này luôn đưa bạn đến Màn hình chính."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Vuốt 2 ngón tay lên từ cuối màn hình. Cử chỉ này luôn đưa bạn về Màn hình chính."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Chuyển đến màn hình chính"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Để chuyển đến màn hình chính bất cứ lúc nào, hãy vuốt lên từ cuối màn hình"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Hãy vuốt lên từ mép dưới cùng của màn hình."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Hãy thử giữ cửa sổ lâu hơn trước khi thả tay ra."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Hãy vuốt thẳng lên, sau đó tạm dừng."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Vuốt lên từ mép dưới cùng của màn hình"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Tuyệt vời!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Hãy vuốt lên từ mép dưới cùng của màn hình"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Hãy thử giữ cửa sổ lâu hơn trước khi nhấc ngón tay ra"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Hãy vuốt thẳng lên rồi tạm dừng"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Bạn đã tìm hiểu cách sử dụng cử chỉ. Để tắt cử chỉ, hãy chuyển đến phần Cài đặt."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Bạn đã thực hiện xong cử chỉ chuyển đổi ứng dụng."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Bạn đã thực hiện xong cử chỉ chuyển đổi ứng dụng"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Vuốt để chuyển đổi ứng dụng"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Để chuyển đổi giữa các ứng dụng, hãy vuốt lên từ cuối màn hình, giữ rồi thả ra."</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Để chuyển đổi ứng dụng, hãy vuốt lên từ cuối màn hình, giữ rồi thả ra."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Để chuyển đổi giữa các ứng dụng, hãy vuốt 2 ngón tay lên từ cuối màn hình, giữ rồi thả ra."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Chuyển đổi ứng dụng"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Vuốt lên từ mép dưới cùng của màn hình, giữ rồi nhấc ngón tay ra"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Rất tốt!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Đã hoàn tất"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Xong"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Cài đặt"</string>
@@ -87,6 +95,7 @@
<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="8464310533320556058">"Nhấn vào ứng dụng khác để chia đôi màn hình"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Thoát khỏi lựa chọn chia đôi màn hình"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Chọn một ứng dụng khác để dùng chế độ chia đôi màn hình"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Ứng dụng hoặc tổ chức của bạn không cho phép thực hiện hành động này"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Bỏ qua phần hướng dẫn thao tác?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Bỏ qua"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Xoay màn hình"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Cách sử dụng thanh tác vụ"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Đã hiện bảng hướng dẫn trên thanh tác vụ"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Đã đóng bảng hướng dẫn trên thanh tác vụ"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Kéo một ứng dụng sang bên để dùng 2 ứng dụng cùng lúc"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Từ từ vuốt lên để Thanh tác vụ xuất hiện"</string>
- <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Nhận ứng dụng đề xuất dựa trên quy trình của bạn"</string>
+ <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Nhận ứng dụng đề xuất dựa trên thói quen của bạn"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Bật tính năng thao tác bằng cử chỉ trong phần Cài đặt để tự động ẩn Thanh tác vụ"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Làm nhiều việc hơn qua Thanh tác vụ"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Tiếp theo"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Quay lại"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Đóng"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Xong"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Màn hình chính"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Thông báo"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Cài đặt nhanh"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"Thanh tác vụ"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Đã hiện thanh thao tác"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Đã ẩn thanh thao tác"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Thanh điều hướng"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Luôn hiển thị Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Thay đổi chế độ điều hướng"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Đường phân chia Taskbar"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Chuyển lên trên cùng/sang bên trái"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Chuyển xuống dưới cùng/sang bên phải"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Hiện thêm # ứng dụng.}other{Hiện thêm # ứng dụng.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> và <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Đang thêm ứng dụng vào máy tính"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Huỷ"</string>
</resources>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index e6dd8f5..3980b21 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"已启用应用建议"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"已停用应用建议"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"预测的应用:<xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"请从最右侧或最左侧边缘开始滑动。"</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"请从右侧或左侧边缘滑动到屏幕中间位置后再松开手指。"</string>
- <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"您已了解如何使用“从右侧向左滑动”手势返回。接下来了解如何切换应用。"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"您完成了“返回”手势教程。"</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"请确保滑动时手的位置不要太靠近屏幕底部。"</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"请旋转设备"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"请旋转设备,完成手势导航教程"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"确保从最右侧或最左侧边缘开始滑动"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"确保从右侧或左侧边缘滑动到屏幕中间位置后再松开手指"</string>
+ <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"您已了解如何使用“从右侧向左滑动”手势返回。接下来学习切换应用吧!"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"您完成了“返回”手势"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"确保滑动时手的位置不要太靠近屏幕底部"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"如要调节“返回”手势的灵敏度,请转到“设置”"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"滑动即可返回"</string>
- <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"如要返回上一个屏幕,请从左侧或右侧边缘滑动到屏幕中间位置。"</string>
+ <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"如要返回上一个屏幕,请从屏幕左侧或右侧边缘往屏幕中间滑动。"</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"若要返回上一个屏幕,请用两根手指从屏幕左侧或右侧边缘向中间滑动。"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"请确保从屏幕底部边缘向上滑动。"</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"松开手指前,请确保不要停下来。"</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"请确保直接向上滑动。"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"您完成了“转到主屏幕”手势教程。接下来了解如何返回。"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"您完成了“转到主屏幕”手势教程。"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"返回"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"从屏幕左侧或右侧边缘滑动到中间"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"确保从屏幕底部边缘向上滑动"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"松开手指前,请勿中途停顿"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"确保笔直向上滑动"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"您完成了“转到主屏幕”手势。接下来了解如何返回。"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"您完成了“转到主屏幕”手势"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"上滑可转到主屏幕"</string>
- <string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"从屏幕底部向上滑动。这个手势会一律将您转到主屏幕。"</string>
+ <string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"从屏幕底部向上滑动,即可随时回到主屏幕。"</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"用两根手指从屏幕底部向上滑动,这个手势会一律使您回到主屏幕。"</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"前往主屏幕"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"若要随时前往主屏幕,请从屏幕的底部向上滑动"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"请确保从屏幕底部边缘向上滑动。"</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"请尝试按住窗口较长时间,然后再松开手指。"</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"请确保直接向上滑动,然后停住。"</string>
- <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"您已了解如何使用手势了。如要关闭手势,请转到“设置”。"</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"您完成了“切换应用”手势教程。"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"从屏幕底部向上滑动"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"太棒了!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"确保从屏幕底部边缘向上滑动"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"尝试按住窗口较长时间,然后再松开手指"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"确保笔直向上滑动,然后停住"</string>
+ <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"您已了解如何使用手势了。如要关闭手势,请前往“设置”。"</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"您完成了应用切换手势"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"滑动即可切换应用"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"如需在应用之间切换,请从屏幕底部向上滑动后按住,然后松开。"</string>
- <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"若要在应用之间切换,请用两根手指从屏幕底部向上滑动并按住,然后松开。"</string>
+ <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"如需在应用之间切换,请从屏幕底部向上滑动,按住,然后松开。"</string>
+ <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"如需在应用之间切换,请从屏幕底部向上滑动,按住,然后松开。"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"切换应用"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"从屏幕底部向上滑动后按住,然后松开"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"恭喜!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"大功告成"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"完成"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"设置"</string>
@@ -78,7 +86,7 @@
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"很好!"</string>
<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="459504134589971527">"向上滑动可转到主屏幕"</string>
+ <string name="allset_hint" msgid="459504134589971527">"向上滑动可前往主屏幕"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"点按主屏幕按钮即可前往主屏幕"</string>
<string name="allset_description_generic" msgid="5385500062202019855">"您可以开始使用<xliff:g id="DEVICE">%1$s</xliff:g>了"</string>
<string name="default_device_name" msgid="6660656727127422487">"设备"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"屏幕截图"</string>
<string name="action_split" msgid="2098009717623550676">"拆分"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"点按另一个应用即可使用分屏"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"退出分屏选择模式"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"另外选择一个应用才可使用分屏模式"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"该应用或您所在的单位不允许执行此操作"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"要跳过导航教程吗?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"跳过"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"旋转屏幕"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"任务栏教程"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"任务栏教程已显示"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"任务栏教程已关闭"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"将一个应用拖动到一侧,即可一次使用两个应用"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"将一个应用拖到一侧,即可一次使用两个应用"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"缓慢向上滑动即可显示任务栏"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"根据您的日常安排获取应用建议"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"在设置中开启手势导航后,任务栏会自动隐藏"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"体验任务栏的更多功能"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"继续"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"返回"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"关闭"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"完成"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"主屏幕"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"通知"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"快捷设置"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"任务栏"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"任务栏已显示"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"任务栏已隐藏"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"导航栏"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"始终显示任务栏"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"更改导航模式"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"任务栏分隔线"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"移到顶部/左侧"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"移到底部/右侧"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{显示另外 # 个应用。}other{显示另外 # 个应用。}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g>和<xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"将应用添加到桌面"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"取消"</string>
</resources>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index 91ba9e0..0532ae5 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -30,11 +30,11 @@
<string name="shorter_duration_less_than_one_minute" msgid="4722015666335015336">"少於 1 分鐘"</string>
<string name="time_left_for_app" msgid="3111996412933644358">"今天剩餘時間:<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="title_app_suggestions" msgid="4185902664111965088">"應用程式建議"</string>
- <string name="all_apps_prediction_tip" msgid="2672336544844936186">"您的預測應用程式"</string>
+ <string name="all_apps_prediction_tip" msgid="2672336544844936186">"你的預測應用程式"</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"在主畫面底部取得應用程式建議"</string>
<string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"在主畫面「我的最愛」列取得應用程式建議"</string>
- <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"在主畫面輕鬆存取常用的應用程式。系統會根據您的日常安排更改建議,並將底部的應用程式移到主畫面。"</string>
- <string name="hotseat_edu_message_migrate_landscape" msgid="4248943380443387697">"在主畫面輕鬆存取最常用的應用程式。系統會根據您的日常安排變更建議,「我的最愛」列中的應用程式會移至主畫面。"</string>
+ <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"在主畫面輕鬆存取常用的應用程式。系統會根據你的日常安排更改建議,並將底部的應用程式移到主畫面。"</string>
+ <string name="hotseat_edu_message_migrate_landscape" msgid="4248943380443387697">"在主畫面輕鬆存取最常用的應用程式。系統會根據你的日常安排變更建議,「我的最愛」列中的應用程式會移至主畫面。"</string>
<string name="hotseat_edu_accept" msgid="1611544083278999837">"取得應用程式建議"</string>
<string name="hotseat_edu_dismiss" msgid="2781161822780201689">"不用了,謝謝"</string>
<string name="hotseat_prediction_settings" msgid="6246554993566070818">"設定"</string>
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"已啟用應用程式建議"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"已停用應用程式建議"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"預測應用程式:<xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"請從螢幕右側或左側邊緣滑動。"</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"請從螢幕右側或左側邊緣往中央滑動,然後放開手指。"</string>
- <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"您已瞭解如何透過「由右向左滑動」手勢返回。接下來一起瞭解如何切換應用程式。"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"您已完成「返回」手勢的教學課程。"</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"滑動時,手的位置不要太接近螢幕底部。"</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"旋轉裝置方向"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"請旋轉裝置方向以完成手勢導覽教學課程"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"請確保從螢幕最右側或最左側邊緣滑動"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"請確保從螢幕右側或左側邊緣往中央滑動,然後放開手指"</string>
+ <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"你已瞭解如何透過「由右向左滑動」手勢返回。接下來一起瞭解如何切換應用程式。"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"你已完成「返回」手勢的教學課程"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"滑動時,手的位置不要太接近螢幕底部"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"如要變更「返回」手勢的敏感度,請前往「設定」"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"滑動即可返回"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"如要返回上一個畫面,請從螢幕左側或右側邊緣往中央滑動。"</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"如要返回上一個畫面,請用 2 隻手指從螢幕左側或右側邊緣往中央滑動。"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"請從螢幕底部邊緣向上滑動。"</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"放開手指前請勿停下來。"</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"請向上滑動。"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"您已完成「返回主畫面」手勢的教學課程。接著,一起來瞭解如何返回上一個畫面。"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"您已完成「返回主畫面」手勢的教學課程。"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"返回"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"從螢幕左側或右側邊緣往中央滑動"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"請確保從螢幕底部邊緣向上滑動"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"放開手指前請勿停下來"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"請確保向上滑動"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"你已完成「返回主畫面」手勢的教學課程。接著,一起來瞭解如何返回上一個畫面。"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"你已完成「返回主畫面」手勢的教學課程"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"向上滑動即可返回主畫面"</string>
- <string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"從螢幕底部向上滑動。這個手勢在所有畫面下都可讓您返回主畫面。"</string>
- <string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"請用 2 隻手指從螢幕底部向上滑動。這個手勢在所有畫面下都可讓您返回主畫面。"</string>
+ <string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"從螢幕底部向上滑動。這個手勢在所有畫面下都可讓你返回主畫面。"</string>
+ <string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"請用 2 隻手指從螢幕底部向上滑動。這個手勢在所有畫面下都可讓你返回主畫面。"</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"返回主畫面"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"只要從螢幕底部向上滑動,隨時可以返回主畫面"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"請從螢幕底部邊緣向上滑動。"</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"請嘗試按住視窗更長時間,然後再放開。"</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"請向上滑動,然後停住。"</string>
- <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"您已學會如何使用手勢。如要關閉手勢,請前往「設定」。"</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"您已完成「切換應用程式」手勢的教學課程。"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"從螢幕底部向上滑動"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"太好了!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"請確保從螢幕底部邊緣向上滑動"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"請嘗試按住視窗更長時間,然後再放開"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"請向上滑動,然後停住"</string>
+ <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"你已學會如何使用手勢。如要關閉手勢,請前往「設定」。"</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"你已完成「切換應用程式」手勢的教學課程"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"滑動即可切換應用程式"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"如要切換應用程式,請從螢幕底部向上滑動並按住,然後放開。"</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"如要切換應用程式,請用 2 隻手指從螢幕底部向上滑動並按住,然後放開手指。"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"切換應用程式"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"從螢幕底部向上滑動並按住,然後放開"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"做得好!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"大功告成"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"完成"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"設定"</string>
@@ -80,30 +88,27 @@
<string name="allset_title" msgid="5021126669778966707">"設定完成!"</string>
<string name="allset_hint" msgid="459504134589971527">"向上滑動即可前往主畫面"</string>
<string name="allset_button_hint" msgid="2395219947744706291">"輕按主按鈕即可前往主畫面"</string>
- <string name="allset_description_generic" msgid="5385500062202019855">"您可以開始使用 <xliff:g id="DEVICE">%1$s</xliff:g> 了"</string>
+ <string name="allset_description_generic" msgid="5385500062202019855">"你可以開始使用<xliff:g id="DEVICE">%1$s</xliff:g>了"</string>
<string name="default_device_name" msgid="6660656727127422487">"裝置"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"系統導覽設定"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"分享"</string>
<string name="action_screenshot" msgid="8171125848358142917">"螢幕截圖"</string>
<string name="action_split" msgid="2098009717623550676">"分割"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"輕按其他應用程式以使用分割螢幕"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"退出分割螢幕選取頁面"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"選擇其他應用程式才能使用分割螢幕"</string>
- <string name="blocked_by_policy" msgid="2071401072261365546">"應用程式或您的機構不允許此操作"</string>
+ <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>
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"你之後可以在「<xliff:g id="NAME">%1$s</xliff:g>」應用程式找到這些說明"</string>
<string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"取消"</string>
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"略過"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"旋轉螢幕"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"工作列教學"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"顯示咗工作列教學"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"閂咗工作列教學"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"將應用程式拖曳到一邊,即可同時使用 2 個應用程式"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"慢慢向上滑動即可顯示工作列"</string>
- <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"根據您的日常安排提供應用程式建議"</string>
+ <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"根據你的日常安排提供應用程式建議"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"在「設定」中啟用手勢操作後,工作列就會自動隱藏"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"工作列助您事半功倍"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"繼續"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"返回"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"工作列助你事半功倍"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"關閉"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"完成"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"住宅"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"通知"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"快速設定"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"工作列"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"顯示咗工作列"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"隱藏咗工作列"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"導覽列"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"一律顯示工作列"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"變更導覽模式"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"工作列分隔線"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"移至上方/左側"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"移至底部/右側"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{顯示另外 # 個應用程式。}other{顯示另外 # 個應用程式。}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"「<xliff:g id="APP_NAME_1">%1$s</xliff:g>」和「<xliff:g id="APP_NAME_2">%2$s</xliff:g>」"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"正在新增應用程式至桌面"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"取消"</string>
</resources>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index 339f844..214fcfd 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -44,38 +44,46 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"應用程式建議功能已啟用"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"應用程式建議功能已停用"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"預測的應用程式:<xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"請從螢幕右側或左側邊緣滑動。"</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"請從螢幕右側或左側邊緣往中央滑動,然後放開手指。"</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"旋轉裝置螢幕方向"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"如要完成手勢操作教學課程,請旋轉裝置螢幕方向"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"請務必從螢幕最右側或最左側滑動"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"請務必從螢幕右側或左側往中央滑動,然後放開手指"</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"你已瞭解如何透過「由右向左滑動」手勢返回。接著,一起來瞭解如何切換應用程式。"</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"你已完成「返回」手勢的教學課程。"</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"滑動時,手的位置不要太接近螢幕底部。"</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"你已完成「返回」手勢的教學課程"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"滑動時,手的位置不要太接近螢幕底部"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"如要變更「返回」手勢的敏感度,請前往「設定」"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"滑動即可返回"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"如要返回上一個畫面,請從螢幕左側或右側邊緣往中央滑動。"</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"如要返回上一個畫面,請用 2 指從螢幕左側或右側邊緣往中央滑動。"</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"請從螢幕底部邊緣向上滑動。"</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"放開手指前請勿停下來。"</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"請向上滑動。"</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"你已完成「返回主畫面」手勢的教學課程。接著,一起來瞭解如何返回上一個畫面。"</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"你已完成「返回主畫面」手勢的教學課程。"</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"返回"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"從螢幕右側或左側往中央滑動"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"請務必從螢幕底部向上滑動"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"放開手指前請勿停下來"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"請務必向上滑動"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"你已完成「返回主畫面」手勢教學課程,接著一起來瞭解如何返回上一個畫面。"</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"你已完成「返回主畫面」手勢的教學課程"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"使用滑動手勢返回主畫面"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"從螢幕底部向上滑動,即可返回主畫面。"</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"用 2 指從螢幕底部向上滑動,即可回到主畫面。"</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"返回主畫面"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"只要從螢幕底部向上滑動,隨時可以返回主畫面"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"請從螢幕底部邊緣向上滑動。"</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"請按住視窗久一點,然後再放開。"</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"請向上滑動,然後停住。"</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"從螢幕底部向上滑動"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"太棒了!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"請務必從螢幕底部向上滑動"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"請按住視窗久一點再放開"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"請務必向上滑動,然後停住"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"你已瞭解如何使用手勢了。如要關閉手勢,請前往「設定」。"</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"你已完成「切換應用程式」手勢的教學課程。"</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"你已完成「切換應用程式」手勢的教學課程"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"使用滑動手勢切換應用程式"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"如要切換不同的應用程式,請從螢幕底部向上滑動並按住,然後放開手指。"</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"如要切換應用程式,請用 2 指從螢幕底部向上滑動並按住,然後放開手指。"</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"切換應用程式"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"從螢幕底部向上滑動並按住,然後放開手指"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"非常好!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"大功告成"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"完成"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"設定"</string>
<string name="gesture_tutorial_try_again" msgid="65962545858556697">"重試"</string>
- <string name="gesture_tutorial_nice" msgid="2936275692616928280">"很好!"</string>
+ <string name="gesture_tutorial_nice" msgid="2936275692616928280">"太棒了!"</string>
<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="459504134589971527">"向上滑動即可前往主畫面"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"螢幕截圖"</string>
<string name="action_split" msgid="2098009717623550676">"分割"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"輕觸另一個應用程式即可使用分割畫面"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"退出分割畫面選擇器"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"必須選擇另一個應用程式才能使用分割畫面"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"這個應用程式或貴機構不允許執行這個動作"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"要略過手勢操作教學課程嗎?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"略過"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"旋轉螢幕"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"工作列教學課程"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"工作列教學課程已顯示"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"工作列教學課程已關閉"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"將應用程式拖曳到一邊即可同時使用 2 個應用程式"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"緩慢向上滑動即可讓工作列顯示在畫面上"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"根據你的日常安排建議應用程式"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"在設定中啟用手勢操作後,工作列就會自動隱藏"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"充分發揮工作列的功用"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"繼續"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"返回"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"關閉"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"完成"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"主畫面"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"通知"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"快速設定"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"工作列"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"已顯示工作列"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"已隱藏工作列"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"導覽列"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"一律顯示工作列"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"變更操作模式"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"工作列分隔線"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"移到上方/左側"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"移到底部/右側"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{顯示另外 # 個應用程式。}other{顯示另外 # 個應用程式。}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"「<xliff:g id="APP_NAME_1">%1$s</xliff:g>」和「<xliff:g id="APP_NAME_2">%2$s</xliff:g>」"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"新增應用程式至桌面"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"取消"</string>
</resources>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index 7304959..9655a44 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -44,33 +44,41 @@
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Iziphakamiso zohlelo lokusebenza zinikwe amandla"</string>
<string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Iziphakamiso zohlelo lokusebenza zikhutshaziwe"</string>
<string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Uhlelo lokusebenza olubikezelwe: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="1711645592102201538">"Qiniseka ukuthi uswayipha kusuka onqenqemeni olukude ngakwesokudla noma olukude ngakwesokunxele."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Qiniseka ukuthi uswayipha kusuka kunqenqema ongakwesokudla noma ongakwesokunxele kuya maphakathi nesikrini bese uyadedela."</string>
+ <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Zungezisa idivayisi yakho"</string>
+ <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Sicela uzungezise idivayisi yakho ukuze uqedele okokufundisa kokufuna ngokuthinta"</string>
+ <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Qinisekisa ukuthi uswayipha ukusuka onqenqemeni olukude ngakwesokudla noma olukude ngakwesokunxele"</string>
+ <string name="back_gesture_feedback_cancelled" msgid="762621530959111290">"Qinisekisa ukuthi uswayipha ukusuka kunqenqema olungakwesokudla noma olungakwesokunxele ukuya maphakathi nesikrini bese uyadedela."</string>
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Ufunde indlela yokuswayipha kusuka kwesokudla ukuze ubuyele emuva. Ngokulandelayo, funda indlela yokushintsha ama-app."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Ukuqedile ukuthinta kokubuyela emuva."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Qiniseka ukuba awuswayipheli eduze kakhulu naphansi kwesikrini."</string>
+ <string name="back_gesture_feedback_complete_without_follow_up" msgid="197189945858268342">"Ukuqedile ukuthinta kokubuyela emuva"</string>
+ <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="9157480023651452969">"Qinisekisa ukuba awuswayipheli eduze kakhulu naphansi kwesikrini"</string>
<string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Ukuze ushintshe ukuzwela kokuthinta emuva, iya Kumasethingi"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Swayipha ukuze uye emuva"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Ukuze ubuyele emuva esikrinini sokugcina, swapha kusuka emngceleni wesobunxele noma wesokudla kuya phakathi kwesikrini."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Ukuze ubuyele esikrinini sokugcina, swayipha ngeminwe emi-2 ukusuka kwesokunxele noma kwesokudla emphethweni uye phakathi kwesikrini."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Qiniseka ukuthi uswayiphela phezulu kusuka emngceleni ophansi wesikrini."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Qiniseka ukuthi awumisi ngaphambi kokudedela."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Qiniseka ukuthi uswayiphela ngqo phezulu."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Ukuqedile ukuthinta kokuya Ekhaya. Ngokulandelayo, funda indlela yokuya emuva."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Ukuqedile ukuthinta kokuya Ekhaya."</string>
+ <string name="back_gesture_tutorial_title" msgid="1944737946101059789">"Iya emuva"</string>
+ <string name="back_gesture_tutorial_subtitle" msgid="6639993416000920142">"Swayipha ukusuka kwesokunxele noma kwesokudla ukuya phakathi kwesikrini"</string>
+ <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="4816365433160895458">"Qiniseka ukuthi uswayiphela phezulu ukusuka emngceleni ophansi wesikrini"</string>
+ <string name="home_gesture_feedback_overview_detected" msgid="5177627157303895077">"Qinisekisa ukuthi awumisi ngaphambi kokudedela"</string>
+ <string name="home_gesture_feedback_wrong_swipe_direction" msgid="8328465201424027148">"Qiniseka ukuthi uswayiphela ngqo phezulu"</string>
+ <string name="home_gesture_feedback_complete_with_follow_up" msgid="8766981412895888417">"Ukuqedile ukuthinta kokuya ekhaya. Ngokulandelayo, funda indlela yokuya emuva."</string>
+ <string name="home_gesture_feedback_complete_without_follow_up" msgid="2978063221383413443">"Ukuqedile ukuthinta kokuya ekhaya"</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Swayipha ukuze uye ekhaya"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Swayiphela phezulu kusuka phansi kwesikrini sakho.Lokhu kuthinta kuhlala kukusa esikrinini sasekhaya."</string>
<string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Swayiphela phezulu ngeminwe emi-2 kusukela phansi esikrinini. Lesi senzo sihlala sikuyisa esikrinini Sasekhaya."</string>
<string name="home_gesture_tutorial_title" msgid="3126834347496917376">"Iya ekhasini lokuqala"</string>
- <string name="home_gesture_tutorial_subtitle" msgid="8979014952569486971">"Ukuze uye esikrinini sakho sasekhaya noma kunini, swayiphela phezulu ukusuka phansi esikrinini sakho"</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Qiniseka ukuthi uswayiphela phezulu kusuka emngceleni ophansi wesikrini."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Zama ukubamba iwindi isikhashana ngaphambi kokulidedela."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Qiniseka ukuthi uswayiphela ngqo phezulu bese uyamisa."</string>
+ <string name="home_gesture_tutorial_subtitle" msgid="7245995490408668778">"Swayiphela phezulu ukusuka phansi esikrinini sakho"</string>
+ <string name="home_gesture_tutorial_success" msgid="1736295017642244751">"Umsebenzi omuhle!"</string>
+ <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="6402349235265407385">"Qiniseka ukuthi uswayiphela phezulu ukusuka emngceleni ophansi wesikrini"</string>
+ <string name="overview_gesture_feedback_home_detected" msgid="663432226180397138">"Zama ukubamba iwindi isikhashana ngaphambi kokulidedela"</string>
+ <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="1191055451018584958">"Qinisekisa ukuthi uswayiphela ngqo phezulu bese uyamisa"</string>
<string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Ufunde ukusebenzisa ukuthinta. Ukuze uvale ukuthinta, iya kokuthi Amasethingi."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Ukuqedile ukuthinta kokushintsha ama-app."</string>
+ <string name="overview_gesture_feedback_complete_without_follow_up" msgid="2903050864432331629">"Ukuqedile ukuthinta kokushintsha ama-app"</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Swayipha ukuze ushintshe ama-app"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Ukuze ushintshe phakathi kwama-app, swayiphela phezulu kusuka ngezansi kwesikrini sakho, bese uyadedela."</string>
<string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"Ukuze ushintshe phakathi kwama-app, swayiphela phezulu ngeminwe emi-2 kusukela phansi esikrinini sakho, ubambe, bese uyakhulula."</string>
+ <string name="overview_gesture_tutorial_title" msgid="4125835002668708720">"Shintsha ama-app"</string>
+ <string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Swayiphela phezulu ukusuka phansi esikrinini sakho, ubambe, bese uyadedela"</string>
+ <string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Wenze kahle!"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Konke kusethiwe"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Kwenziwe"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Amasethingi"</string>
@@ -87,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Isithombe-skrini"</string>
<string name="action_split" msgid="2098009717623550676">"Hlukanisa"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Thepha enye i-app ukuze usebenzise isikrini sokuhlukanisa"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Phuma ekukhetheni ukuhlukaniswa kwesikrini"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Khetha enye i-app ukuze usebenzise ukuhlukanisa isikrini"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Lesi senzo asivunyelwanga uhlelo lokusebenza noma inhlangano yakho"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Yeqa isifundo sokuzulazula?"</string>
@@ -95,15 +104,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Yeqa"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Zungezisa isikrini"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Imfundo ye-taskbar"</string>
- <string name="taskbar_edu_opened" msgid="3950252793551919129">"Imfuno yebha yomsebenzi ivelile"</string>
- <string name="taskbar_edu_closed" msgid="126643734478892862">"Imfundo yebha yomsebenzi ivaliwe"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Hudula i-app ukusebenzisa ama-app ama-2 ngesikhathi esisodwa"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Swayiphela phezulu kancane ukuze ubonise i-Taskbar"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Thola iziphakamiso ze-app ngokusekelwe kumjikelezo wakho"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Vula ukufuna kokuthinta Kumasethingi ukuze ufihle ngokuzenzakalela ibha yomsebenzi"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Yenza okwengeziwe nge-Taskbar"</string>
- <string name="taskbar_edu_next" msgid="4007618274426775841">"Okulandelayo"</string>
- <string name="taskbar_edu_previous" msgid="459202320127201702">"Emuva"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Vala"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Kwenziwe"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Ikhaya"</string>
@@ -114,7 +119,16 @@
<string name="taskbar_button_notifications" msgid="7471740351507357318">"Izaziso"</string>
<string name="taskbar_button_quick_settings" msgid="227662894293189391">"Amasethingi Asheshayo"</string>
<string name="taskbar_a11y_title" msgid="6432169809852243110">"I-Taskbar"</string>
+ <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Ibha yomsebenzi ibonisiwe"</string>
+ <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Ibha yomsebenzi ifihliwe"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Ibha yokufuna"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Bonisa i-Taskbar njalo."</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Shintsha imodi yokufuna"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Isihlukanisi se-Taskbar"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Hamba phezulu/kwesokunxele"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Hamba phansi/kwesokudla"</string>
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Bonisa i-app e-# ngaphezulu.}one{Bonisa ama-app angu-# ngaphezulu.}other{Bonisa ama-app angu-# ngaphezulu.}}"</string>
+ <string name="quick_switch_split_task" msgid="5598194724255333896">"I-<xliff:g id="APP_NAME_1">%1$s</xliff:g> ne-<xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+ <string name="desktop_select_app_toast" msgid="2306057322833956910">"Yengeza i-app ku-Deskithophu"</string>
+ <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Khansela"</string>
</resources>
diff --git a/quickstep/res/values/attrs.xml b/quickstep/res/values/attrs.xml
index fb51919..7288774 100644
--- a/quickstep/res/values/attrs.xml
+++ b/quickstep/res/values/attrs.xml
@@ -26,7 +26,8 @@
-->
<declare-styleable name="TaskView">
<!-- Border color for a keyboard quick switch task views -->
- <attr name="borderColor" format="color" />
+ <attr name="focusBorderColor" format="color" />
+ <attr name="hoverBorderColor" format="color" />
</declare-styleable>
<!--
diff --git a/quickstep/res/values/colors.xml b/quickstep/res/values/colors.xml
index 36c7352..1b5b0ee 100644
--- a/quickstep/res/values/colors.xml
+++ b/quickstep/res/values/colors.xml
@@ -25,6 +25,10 @@
<!-- Taskbar -->
<color name="taskbar_nav_icon_selection_ripple">#E0E0E0</color>
+ <color name="taskbar_nav_icon_light_color_on_home">#ffffff</color>
+ <!-- The dark navigation button color is only used in the rare cases that taskbar isn't drawing
+ its background and the underlying app has requested dark buttons. -->
+ <color name="taskbar_nav_icon_dark_color_on_home">#99000000</color>
<color name="taskbar_stashed_handle_light_color">#EBffffff</color>
<color name="taskbar_stashed_handle_dark_color">#99000000</color>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index bb4f74d..aeb453c 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -38,6 +38,8 @@
<dimen name="task_thumbnail_icon_size">48dp</dimen>
<!-- The icon size for the focused task, placed in center of touch target -->
<dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
+ <!-- The border width shown when task is hovered -->
+ <dimen name="task_hover_border_width">4dp</dimen>
<!-- The space under the focused task icon -->
<dimen name="overview_task_margin">16dp</dimen>
<!-- The horizontal space between tasks -->
@@ -269,6 +271,9 @@
<dimen name="floating_rotation_button_taskbar_left_margin">20dp</dimen>
<dimen name="floating_rotation_button_taskbar_bottom_margin">10dp</dimen>
+ <!-- Copied from frameworks/base/packages/SystemUI -->
+ <dimen name="navigation_home_handle_width">108dp</dimen>
+
<!-- Taskbar -->
<dimen name="taskbar_size">@*android:dimen/taskbar_frame_height</dimen>
<dimen name="taskbar_ime_size">48dp</dimen>
@@ -301,7 +306,7 @@
<dimen name="taskbar_home_button_left_margin_kids">48dp</dimen>
<dimen name="taskbar_icon_size_kids">32dp</dimen>
<dimen name="taskbar_all_apps_button_translation_x_offset">6dp</dimen>
-
+ <dimen name="taskbar_all_apps_search_button_translation_x_offset">4.5dp</dimen>
<!-- Transient taskbar -->
<dimen name="transient_taskbar_padding">12dp</dimen>
@@ -312,6 +317,8 @@
<dimen name="transient_taskbar_stashed_height">32dp</dimen>
<dimen name="transient_taskbar_all_apps_button_translation_x_offset">4dp</dimen>
<dimen name="transient_taskbar_stash_spring_velocity_dp_per_s">400dp</dimen>
+ <dimen name="taskbar_tooltip_vertical_padding">8dp</dimen>
+ <dimen name="taskbar_tooltip_horizontal_padding">16dp</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>
@@ -323,6 +330,12 @@
<!-- Taskbar swipe down threshold -->
<dimen name="taskbar_to_nav_threshold">24dp</dimen>
+ <!-- Taskbar swipe up threshold multipliers -->
+ <item name="taskbar_nav_threshold_mult" format="float" type="dimen">4.5</item>
+ <item name="taskbar_app_window_threshold_mult" format="float" type="dimen">10</item>
+ <item name="taskbar_home_overview_threshold_mult" format="float" type="dimen">18</item>
+ <item name="taskbar_catch_up_threshold_mult" format="float" type="dimen">30</item>
+
<!-- Taskbar 3 button spacing -->
<dimen name="taskbar_button_space_inbetween">24dp</dimen>
<dimen name="taskbar_button_space_inbetween_phone">40dp</dimen>
@@ -356,13 +369,23 @@
<dimen name="bubblebar_stashed_size">@dimen/transient_taskbar_stashed_height</dimen>
<dimen name="bubblebar_stashed_handle_height">@dimen/taskbar_stashed_handle_height</dimen>
<dimen name="bubblebar_pointer_size">8dp</dimen>
+ <dimen name="bubblebar_elevation">1dp</dimen>
+ <dimen name="bubblebar_hotseat_adjustment_threshold">90dp</dimen>
<dimen name="bubblebar_icon_size">50dp</dimen>
<dimen name="bubblebar_badge_size">24dp</dimen>
<dimen name="bubblebar_icon_overlap">12dp</dimen>
+ <dimen name="bubblebar_overflow_inset">24dp</dimen>
<dimen name="bubblebar_icon_spacing">3dp</dimen>
<dimen name="bubblebar_icon_elevation">1dp</dimen>
+ <!-- Bubble bar dismiss view -->
+ <dimen name="bubblebar_dismiss_target_size">96dp</dimen>
+ <dimen name="bubblebar_dismiss_target_small_size">60dp</dimen>
+ <dimen name="bubblebar_dismiss_target_icon_size">24dp</dimen>
+ <dimen name="bubblebar_dismiss_target_bottom_margin">50dp</dimen>
+ <dimen name="bubblebar_dismiss_floating_gradient_height">548dp</dimen>
+
<!-- Launcher splash screen -->
<!-- Note: keep this value in sync with the WindowManager/Shell dimens.xml -->
<!-- starting_surface_exit_animation_window_shift_length -->
@@ -383,4 +406,12 @@
<dimen name="keyboard_quick_switch_task_view_radius">16dp</dimen>
<dimen name="keyboard_quick_switch_no_recent_items_icon_size">24dp</dimen>
<dimen name="keyboard_quick_switch_no_recent_items_icon_margin">8dp</dimen>
+
+ <!-- Desktop mode -->
+ <dimen name="desktop_mode_floating_app_select_height">56dp</dimen>
+ <dimen name="desktop_mode_floating_app_select_elevation">4dp</dimen>
+ <dimen name="desktop_mode_floating_app_select_margin">16dp</dimen>
+ <dimen name="desktop_mode_floating_app_select_text_size">14sp</dimen>
+ <dimen name="desktop_mode_floating_app_select_text_margin">8dp</dimen>
+
</resources>
diff --git a/quickstep/res/values/override.xml b/quickstep/res/values/override.xml
index 4f472f0..df32626 100644
--- a/quickstep/res/values/override.xml
+++ b/quickstep/res/values/override.xml
@@ -25,6 +25,14 @@
<string name="model_delegate_class" translatable="false">com.android.launcher3.model.QuickstepModelDelegate</string>
+ <string name="nav_handle_long_press_handler_class" translatable="false"></string>
+
+ <string name="assist_utils_class" translatable="false"></string>
+
<string name="secondary_display_predictions_class" translatable="false">com.android.launcher3.secondarydisplay.SecondaryDisplayPredictionsImpl</string>
+ <string name="taskbar_model_callbacks_factory_class" translatable="false">com.android.launcher3.taskbar.TaskbarModelCallbacksFactory</string>
+
+ <string name="assist_state_manager_class" translatable="false"></string>
+
</resources>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 6d0dbae..dd9fc63 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -230,6 +230,7 @@
<string name="action_split">Split</string>
<!-- Label for toast with instructions for split screen selection mode. [CHAR_LIMIT=50] -->
<string name="toast_split_select_app">Tap another app to use split screen</string>
+ <string name="toast_split_select_cont_desc">Exit split screen selection</string>
<!-- Label for toast when app selected for split isn't supported. [CHAR_LIMIT=50] -->
<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] -->
@@ -308,4 +309,10 @@
<!-- Accessibility label for quick switch tiles showing split tasks [CHAR LIMIT=NONE] -->
<string name="quick_switch_split_task"><xliff:g id="app_name_1" example="Chrome">%1$s</xliff:g> and <xliff:g id="app_name_2" example="Gmail">%2$s</xliff:g></string>
+
+ <!-- ******* Desktop ******* -->
+ <!-- Text shown in popup to choose a desktop app. [CHAR LIMIT=60] -->
+ <string name="desktop_select_app_toast">Adding app to Desktop</string>
+ <!-- Text shown on a button that closes the popup for choosing a desktop app. [CHAR_LIMIT=40] -->
+ <string name="desktop_button_close_app_toast">Cancel</string>
</resources>
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index 21b7fd5..fc03704 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -298,4 +298,9 @@
<style name="rotate_prompt_subtitle" parent="TextAppearance.GestureTutorial.Dialog.Subtitle">
<item name="android:textColor">?androidprv:attr/materialColorOnSurfaceVariant</item>
</style>
+
+ <style name="ArrowTipTaskbarStyle">
+ <item name="arrowTipBackground">?androidprv:attr/materialColorSurfaceContainer</item>
+ <item name="arrowTipTextColor">?androidprv:attr/materialColorOnSurface</item>
+ </style>
</resources>
diff --git a/quickstep/src/com/android/launcher3/LauncherInitListener.java b/quickstep/src/com/android/launcher3/LauncherInitListener.java
index 28bd701..f64b5cf 100644
--- a/quickstep/src/com/android/launcher3/LauncherInitListener.java
+++ b/quickstep/src/com/android/launcher3/LauncherInitListener.java
@@ -15,23 +15,16 @@
*/
package com.android.launcher3;
-import android.animation.AnimatorSet;
import android.annotation.TargetApi;
import android.os.Build;
-import android.os.CancellationSignal;
-import android.view.RemoteAnimationTarget;
-import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.quickstep.util.ActivityInitListener;
-import com.android.quickstep.util.RemoteAnimationProvider;
import java.util.function.BiPredicate;
@TargetApi(Build.VERSION_CODES.P)
public class LauncherInitListener extends ActivityInitListener<Launcher> {
- private RemoteAnimationProvider mRemoteAnimationProvider;
-
/**
* @param onInitListener a callback made when the activity is initialized. The callback should
* return true to continue receiving callbacks (ie. for if the activity is
@@ -43,37 +36,7 @@
@Override
public boolean handleInit(Launcher launcher, boolean alreadyOnHome) {
- if (mRemoteAnimationProvider != null) {
- QuickstepTransitionManager appTransitionManager =
- ((QuickstepLauncher) launcher).getAppTransitionManager();
-
- // Set a one-time animation provider. After the first call, this will get cleared.
- // TODO: Probably also check the intended target id.
- CancellationSignal cancellationSignal = new CancellationSignal();
- appTransitionManager.setRemoteAnimationProvider(new RemoteAnimationProvider() {
- @Override
- public AnimatorSet createWindowAnimation(RemoteAnimationTarget[] appTargets,
- RemoteAnimationTarget[] wallpaperTargets) {
-
- // On the first call clear the reference.
- cancellationSignal.cancel();
- RemoteAnimationProvider provider = mRemoteAnimationProvider;
- mRemoteAnimationProvider = null;
-
- if (provider != null && launcher.getStateManager().getState().overviewUi) {
- return provider.createWindowAnimation(appTargets, wallpaperTargets);
- }
- return null;
- }
- }, cancellationSignal);
- }
launcher.deferOverlayCallbacksUntilNextResumeOrStop();
return super.handleInit(launcher, alreadyOnHome);
}
-
- @Override
- public void unregister() {
- mRemoteAnimationProvider = null;
- super.unregister();
- }
}
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index f3e62c1..841fc8f 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -22,6 +22,8 @@
import static android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_OPEN;
@@ -31,6 +33,12 @@
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
import static android.window.TransitionFilter.CONTAINER_ORDER_TOP;
+import static com.android.app.animation.Interpolators.ACCELERATE_1_5;
+import static com.android.app.animation.Interpolators.AGGRESSIVE_EASE;
+import static com.android.app.animation.Interpolators.DECELERATE_1_5;
+import static com.android.app.animation.Interpolators.DECELERATE_1_7;
+import static com.android.app.animation.Interpolators.EXAGGERATED_EASE;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.BaseActivity.INVISIBLE_ALL;
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_APP_TRANSITIONS;
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_PENDING_FLAGS;
@@ -42,12 +50,6 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.Utilities.mapBoundToRange;
-import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
-import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
-import static com.android.launcher3.anim.Interpolators.EXAGGERATED_EASE;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_BACK_SWIPE_HOME_ANIMATION;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SCRIM_FOR_APP_LAUNCH;
import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION;
@@ -60,6 +62,8 @@
import static com.android.launcher3.views.FloatingIconView.getFloatingIconView;
import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
+import static com.android.systemui.shared.system.InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME;
+import static com.android.systemui.shared.system.InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME_FALLBACK;
import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
@@ -82,7 +86,6 @@
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.os.CancellationSignal;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -140,7 +143,6 @@
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.RectFSpringAnim.DefaultSpringConfig;
import com.android.quickstep.util.RectFSpringAnim.TaskbarHotseatSpringConfig;
-import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.util.SurfaceTransaction;
import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
@@ -151,6 +153,7 @@
import com.android.quickstep.views.RecentsView;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.DelegateLaunchAnimatorController;
+import com.android.systemui.animation.LaunchableView;
import com.android.systemui.animation.RemoteAnimationDelegate;
import com.android.systemui.shared.system.BlurUtils;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
@@ -159,6 +162,7 @@
import com.android.wm.shell.startingsurface.IStartingWindowListener;
import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
@@ -183,7 +187,7 @@
private static final String CONTROL_REMOTE_APP_TRANSITION_PERMISSION =
"android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS";
- private static final long APP_LAUNCH_DURATION = 500;
+ public static final long APP_LAUNCH_DURATION = 500;
private static final long APP_LAUNCH_ALPHA_DURATION = 50;
private static final long APP_LAUNCH_ALPHA_START_DELAY = 25;
@@ -225,11 +229,11 @@
private final float mClosingWindowTransY;
private final float mMaxShadowRadius;
- private final StartingWindowListener mStartingWindowListener = new StartingWindowListener();
+ private final StartingWindowListener mStartingWindowListener =
+ new StartingWindowListener(this);
private DeviceProfile mDeviceProfile;
- private RemoteAnimationProvider mRemoteAnimationProvider;
// Strong refs to runners which are cleared when the launcher activity is destroyed
private RemoteAnimationFactory mWallpaperOpenRunner;
private RemoteAnimationFactory mAppLaunchRunner;
@@ -238,6 +242,8 @@
private RemoteAnimationFactory mWallpaperOpenTransitionRunner;
private RemoteTransition mLauncherOpenTransition;
+ private final RemoteAnimationCoordinateTransfer mCoordinateTransfer;
+
private LauncherBackAnimationController mBackAnimationController;
private final AnimatorListenerAdapter mForceInvisibleListener = new AnimatorListenerAdapter() {
@Override
@@ -279,14 +285,14 @@
}
};
- mStartingWindowListener.setTransitionManager(this);
SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(
mStartingWindowListener);
}
mOpeningXInterpolator = AnimationUtils.loadInterpolator(context, R.interpolator.app_open_x);
mOpeningInterpolator = AnimationUtils.loadInterpolator(context,
- R.interpolator.three_point_fast_out_extra_slow_in);
+ R.interpolator.emphasized_interpolator);
+ mCoordinateTransfer = new RemoteAnimationCoordinateTransfer(mLauncher);
}
@Override
@@ -311,8 +317,8 @@
mAppLaunchRunner = new AppLaunchAnimationRunner(v, onEndCallback);
ItemInfo tag = (ItemInfo) v.getTag();
if (tag != null && tag.shouldUseBackgroundAnimation()) {
- ContainerAnimationRunner containerAnimationRunner =
- ContainerAnimationRunner.from(v, mStartingWindowListener, onEndCallback);
+ ContainerAnimationRunner containerAnimationRunner = ContainerAnimationRunner.from(
+ v, mLauncher, mStartingWindowListener, onEndCallback);
if (containerAnimationRunner != null) {
mAppLaunchRunner = containerAnimationRunner;
}
@@ -468,16 +474,6 @@
return bounds;
}
- public void setRemoteAnimationProvider(final RemoteAnimationProvider animationProvider,
- CancellationSignal cancellationSignal) {
- mRemoteAnimationProvider = animationProvider;
- cancellationSignal.setOnCancelListener(() -> {
- if (animationProvider == mRemoteAnimationProvider) {
- mRemoteAnimationProvider = null;
- }
- });
- }
-
/** Dump debug logs to bug report. */
public void dump(@NonNull String prefix, @NonNull PrintWriter printWriter) {}
@@ -566,7 +562,7 @@
ObjectAnimator scaleAnim = ObjectAnimator.ofFloat(view, SCALE_PROPERTY, scales)
.setDuration(CONTENT_SCALE_DURATION);
- scaleAnim.setInterpolator(DEACCEL_1_5);
+ scaleAnim.setInterpolator(DECELERATE_1_5);
launcherAnimator.play(scaleAnim);
});
@@ -584,7 +580,7 @@
ObjectAnimator scrim = ObjectAnimator.ofArgb(scrimView, VIEW_BACKGROUND_COLOR,
colors);
scrim.setDuration(CONTENT_SCRIM_DURATION);
- scrim.setInterpolator(DEACCEL_1_5);
+ scrim.setInterpolator(DECELERATE_1_5);
launcherAnimator.play(scrim);
}
@@ -1163,7 +1159,6 @@
public void onActivityDestroyed() {
unregisterRemoteAnimations();
unregisterRemoteTransitions();
- mStartingWindowListener.setTransitionManager(null);
SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(null);
}
@@ -1234,7 +1229,7 @@
* ie. pressing home, swiping up from nav bar.
*/
RemoteAnimationFactory createWallpaperOpenRunner(boolean fromUnlock) {
- return new WallpaperOpenLauncherAnimationRunner(mHandler, fromUnlock);
+ return new WallpaperOpenLauncherAnimationRunner(fromUnlock);
}
/**
@@ -1352,7 +1347,7 @@
/**
* Closing animator that animates the window into its final location on the workspace.
*/
- private RectFSpringAnim getClosingWindowAnimators(AnimatorSet animation,
+ protected RectFSpringAnim getClosingWindowAnimators(AnimatorSet animation,
RemoteAnimationTarget[] targets, View launcherView, PointF velocityPxPerS,
RectF closingWindowStartRect, float startWindowCornerRadius) {
FloatingIconView floatingIconView = null;
@@ -1399,8 +1394,9 @@
targetRect));
// Hook up floating views to the closing window animators.
- final int rotationChange = getRotationChange(targets);
- Rect windowTargetBounds = getWindowTargetBounds(targets, rotationChange);
+ // note the coordinate of closingWindowStartRect is based on launcher
+ Rect windowTargetBounds = new Rect();
+ closingWindowStartRect.round(windowTargetBounds);
if (floatingIconView != null) {
anim.addAnimatorListener(floatingIconView);
floatingIconView.setOnTargetChangeListener(anim::onTargetPositionChanged);
@@ -1477,11 +1473,11 @@
float startShadowRadius = areAllTargetsTranslucent(appTargets) ? 0 : mMaxShadowRadius;
closingAnimator.setDuration(duration);
closingAnimator.addUpdateListener(new MultiValueUpdateListener() {
- FloatProp mDy = new FloatProp(0, mClosingWindowTransY, 0, duration, DEACCEL_1_7);
- FloatProp mScale = new FloatProp(1f, 1f, 0, duration, DEACCEL_1_7);
+ FloatProp mDy = new FloatProp(0, mClosingWindowTransY, 0, duration, DECELERATE_1_7);
+ FloatProp mScale = new FloatProp(1f, 1f, 0, duration, DECELERATE_1_7);
FloatProp mAlpha = new FloatProp(1f, 0f, 25, 125, LINEAR);
FloatProp mShadowRadius = new FloatProp(startShadowRadius, 0, 0, duration,
- DEACCEL_1_7);
+ DECELERATE_1_7);
@Override
public void onUpdate(float percent, boolean initOnly) {
@@ -1592,89 +1588,80 @@
RectF startRect,
float startWindowCornerRadius,
boolean fromPredictiveBack) {
- AnimatorSet anim = null;
+ AnimatorSet anim = new AnimatorSet();
RectFSpringAnim rectFSpringAnim = null;
- RemoteAnimationProvider provider = mRemoteAnimationProvider;
- if (provider != null) {
- anim = provider.createWindowAnimation(appTargets, wallpaperTargets);
+ final boolean launcherIsForceInvisibleOrOpening = mLauncher.isForceInvisible()
+ || launcherIsATargetWithMode(appTargets, MODE_OPENING);
+
+ View launcherView = findLauncherView(appTargets);
+ boolean playFallBackAnimation = (launcherView == null
+ && launcherIsForceInvisibleOrOpening)
+ || mLauncher.getWorkspace().isOverlayShown()
+ || shouldPlayFallbackClosingAnimation(appTargets);
+
+ boolean playWorkspaceReveal = true;
+ boolean skipAllAppsScale = false;
+ if (fromUnlock) {
+ anim.play(getUnlockWindowAnimator(appTargets, wallpaperTargets));
+ } else if (ENABLE_BACK_SWIPE_HOME_ANIMATION.get()
+ && !playFallBackAnimation) {
+ // Use a fixed velocity to start the animation.
+ float velocityPxPerS = DynamicResource.provider(mLauncher)
+ .getDimension(R.dimen.unlock_staggered_velocity_dp_per_s);
+ PointF velocity = new PointF(0, -velocityPxPerS);
+ rectFSpringAnim = getClosingWindowAnimators(
+ anim, appTargets, launcherView, velocity, startRect,
+ startWindowCornerRadius);
+ if (mLauncher.isInState(LauncherState.ALL_APPS)) {
+ // Skip scaling all apps, otherwise FloatingIconView will get wrong
+ // layout bounds.
+ skipAllAppsScale = true;
+ } else if (!fromPredictiveBack) {
+ anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y,
+ true /* animateOverviewScrim */, launcherView).getAnimators());
+
+ if (!areAllTargetsTranslucent(appTargets)) {
+ anim.play(ObjectAnimator.ofFloat(mLauncher.getDepthController().stateDepth,
+ MULTI_PROPERTY_VALUE,
+ BACKGROUND_APP.getDepth(mLauncher), NORMAL.getDepth(mLauncher)));
+ }
+
+ // We play StaggeredWorkspaceAnim as a part of the closing window animation.
+ playWorkspaceReveal = false;
+ }
+ } else {
+ anim.play(getFallbackClosingWindowAnimators(appTargets));
}
- if (anim == null) {
- anim = new AnimatorSet();
+ // Normally, we run the launcher content animation when we are transitioning
+ // home, but if home is already visible, then we don't want to animate the
+ // contents of launcher unless we know that we are animating home as a result
+ // of the home button press with quickstep, which will result in launcher being
+ // started on touch down, prior to the animation home (and won't be in the
+ // targets list because it is already visible). In that case, we force
+ // invisibility on touch down, and only reset it after the animation to home
+ // is initialized.
+ if (launcherIsForceInvisibleOrOpening) {
+ addCujInstrumentation(anim, playFallBackAnimation
+ ? CUJ_APP_CLOSE_TO_HOME_FALLBACK : CUJ_APP_CLOSE_TO_HOME);
+ // Only register the content animation for cancellation when state changes
+ mLauncher.getStateManager().setCurrentAnimation(anim);
- final boolean launcherIsForceInvisibleOrOpening = mLauncher.isForceInvisible()
- || launcherIsATargetWithMode(appTargets, MODE_OPENING);
-
- View launcherView = findLauncherView(appTargets);
- boolean playFallBackAnimation = (launcherView == null
- && launcherIsForceInvisibleOrOpening)
- || mLauncher.getWorkspace().isOverlayShown()
- || shouldPlayFallbackClosingAnimation(appTargets);
-
- boolean playWorkspaceReveal = true;
- boolean skipAllAppsScale = false;
- if (fromUnlock) {
- anim.play(getUnlockWindowAnimator(appTargets, wallpaperTargets));
- } else if (ENABLE_BACK_SWIPE_HOME_ANIMATION.get()
- && !playFallBackAnimation) {
- // Use a fixed velocity to start the animation.
- float velocityPxPerS = DynamicResource.provider(mLauncher)
- .getDimension(R.dimen.unlock_staggered_velocity_dp_per_s);
- PointF velocity = new PointF(0, -velocityPxPerS);
- rectFSpringAnim = getClosingWindowAnimators(
- anim, appTargets, launcherView, velocity, startRect,
- startWindowCornerRadius);
- if (mLauncher.isInState(LauncherState.ALL_APPS)) {
- // Skip scaling all apps, otherwise FloatingIconView will get wrong
- // layout bounds.
- skipAllAppsScale = true;
- } else if (!fromPredictiveBack) {
- anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y,
- true /* animateOverviewScrim */, launcherView).getAnimators());
-
- if (!areAllTargetsTranslucent(appTargets)) {
- anim.play(ObjectAnimator.ofFloat(mLauncher.getDepthController().stateDepth,
- MULTI_PROPERTY_VALUE,
- BACKGROUND_APP.getDepth(mLauncher), NORMAL.getDepth(mLauncher)));
+ if (mLauncher.isInState(LauncherState.ALL_APPS)) {
+ Pair<AnimatorSet, Runnable> contentAnimator =
+ getLauncherContentAnimator(false, LAUNCHER_RESUME_START_DELAY,
+ skipAllAppsScale);
+ anim.play(contentAnimator.first);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ contentAnimator.second.run();
}
-
- // We play StaggeredWorkspaceAnim as a part of the closing window animation.
- playWorkspaceReveal = false;
- }
+ });
} else {
- anim.play(getFallbackClosingWindowAnimators(appTargets));
- }
-
- // Normally, we run the launcher content animation when we are transitioning
- // home, but if home is already visible, then we don't want to animate the
- // contents of launcher unless we know that we are animating home as a result
- // of the home button press with quickstep, which will result in launcher being
- // started on touch down, prior to the animation home (and won't be in the
- // targets list because it is already visible). In that case, we force
- // invisibility on touch down, and only reset it after the animation to home
- // is initialized.
- if (launcherIsForceInvisibleOrOpening) {
- addCujInstrumentation(
- anim, InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME);
- // Only register the content animation for cancellation when state changes
- mLauncher.getStateManager().setCurrentAnimation(anim);
-
- if (mLauncher.isInState(LauncherState.ALL_APPS)) {
- Pair<AnimatorSet, Runnable> contentAnimator =
- getLauncherContentAnimator(false, LAUNCHER_RESUME_START_DELAY,
- skipAllAppsScale);
- anim.play(contentAnimator.first);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- contentAnimator.second.run();
- }
- });
- } else {
- if (playWorkspaceReveal) {
- anim.play(new WorkspaceRevealAnim(mLauncher, false).getAnimators());
- }
+ if (playWorkspaceReveal) {
+ anim.play(new WorkspaceRevealAnim(mLauncher, false).getAnimators());
}
}
}
@@ -1687,11 +1674,9 @@
*/
protected class WallpaperOpenLauncherAnimationRunner implements RemoteAnimationFactory {
- private final Handler mHandler;
private final boolean mFromUnlock;
- public WallpaperOpenLauncherAnimationRunner(Handler handler, boolean fromUnlock) {
- mHandler = handler;
+ public WallpaperOpenLauncherAnimationRunner(boolean fromUnlock) {
mFromUnlock = fromUnlock;
}
@@ -1715,8 +1700,18 @@
RectF windowTargetBounds =
new RectF(getWindowTargetBounds(appTargets, getRotationChange(appTargets)));
+
+ final RectF resolveRectF = new RectF(windowTargetBounds);
+ for (RemoteAnimationTarget t : appTargets) {
+ if (t.mode == MODE_CLOSING) {
+ transferRectToTargetCoordinate(
+ t, windowTargetBounds, true, resolveRectF);
+ break;
+ }
+ }
+
Pair<RectFSpringAnim, AnimatorSet> pair = createWallpaperOpenAnimations(
- appTargets, wallpaperTargets, mFromUnlock, windowTargetBounds,
+ appTargets, wallpaperTargets, mFromUnlock, resolveRectF,
QuickStepContract.getWindowCornerRadius(mLauncher),
false /* fromPredictiveBack */);
@@ -1797,9 +1792,9 @@
}
@Nullable
- private static ContainerAnimationRunner from(
- View v, StartingWindowListener startingWindowListener, RunnableList onEndCallback) {
- View viewToUse = findViewWithBackground(v);
+ private static ContainerAnimationRunner from(View v, Launcher launcher,
+ StartingWindowListener startingWindowListener, RunnableList onEndCallback) {
+ View viewToUse = findLaunchableViewWithBackground(v);
if (viewToUse == null) {
viewToUse = v;
}
@@ -1823,8 +1818,13 @@
}
};
- ActivityLaunchAnimator.Callback callback = task -> ColorUtils.setAlphaComponent(
- startingWindowListener.getBackgroundColor(), 255);
+ ActivityLaunchAnimator.Callback callback = task -> {
+ final int backgroundColor =
+ startingWindowListener.mBackgroundColor == Color.TRANSPARENT
+ ? launcher.getScrimView().getBackgroundColor()
+ : startingWindowListener.mBackgroundColor;
+ return ColorUtils.setAlphaComponent(backgroundColor, 255);
+ };
ActivityLaunchAnimator.Listener listener = new ActivityLaunchAnimator.Listener() {
@Override
@@ -1837,11 +1837,15 @@
new ActivityLaunchAnimator.AnimationDelegate(controller, callback, listener));
}
- /** Finds the closest parent of [view] (inclusive) with a background drawable. */
+ /**
+ * Finds the closest parent of [view] (inclusive) that implements {@link LaunchableView} and
+ * has a background drawable.
+ */
@Nullable
- private static View findViewWithBackground(View view) {
+ private static <T extends View & LaunchableView> T findLaunchableViewWithBackground(
+ View view) {
View current = view;
- while (current.getBackground() == null) {
+ while (current.getBackground() == null || !(current instanceof LaunchableView)) {
if (!(current.getParent() instanceof View)) {
return null;
}
@@ -1849,7 +1853,7 @@
current = (View) view.getParent();
}
- return current;
+ return (T) current;
}
@Override
@@ -1934,24 +1938,67 @@
}
}
- private class StartingWindowListener extends IStartingWindowListener.Stub {
- private QuickstepTransitionManager mTransitionManager;
+ private static class StartingWindowListener extends IStartingWindowListener.Stub {
+ private final WeakReference<QuickstepTransitionManager> mTransitionManagerRef;
private int mBackgroundColor;
- public void setTransitionManager(QuickstepTransitionManager transitionManager) {
- mTransitionManager = transitionManager;
+ private StartingWindowListener(QuickstepTransitionManager transitionManager) {
+ mTransitionManagerRef = new WeakReference<>(transitionManager);
}
@Override
public void onTaskLaunching(int taskId, int supportedType, int color) {
- mTransitionManager.mTaskStartParams.put(taskId, Pair.create(supportedType, color));
+ QuickstepTransitionManager transitionManager = mTransitionManagerRef.get();
+ if (transitionManager != null) {
+ transitionManager.mTaskStartParams.put(taskId, Pair.create(supportedType, color));
+ }
mBackgroundColor = color;
}
+ }
- public int getBackgroundColor() {
- return mBackgroundColor == Color.TRANSPARENT
- ? mLauncher.getScrimView().getBackgroundColor()
- : mBackgroundColor;
+ /**
+ * Transfer the rectangle to another coordinate if needed.
+ * @param toLauncher which one is the anchor of this transfer, if true then transfer from
+ * animation target to launcher, false transfer from launcher to animation
+ * target.
+ */
+ public void transferRectToTargetCoordinate(RemoteAnimationTarget target, RectF currentRect,
+ boolean toLauncher, RectF resultRect) {
+ mCoordinateTransfer.transferRectToTargetCoordinate(
+ target, currentRect, toLauncher, resultRect);
+ }
+
+ private static class RemoteAnimationCoordinateTransfer {
+ private final QuickstepLauncher mLauncher;
+ private final Rect mDisplayRect = new Rect();
+ private final Rect mTmpResult = new Rect();
+
+ RemoteAnimationCoordinateTransfer(QuickstepLauncher launcher) {
+ mLauncher = launcher;
+ }
+
+ void transferRectToTargetCoordinate(RemoteAnimationTarget target, RectF currentRect,
+ boolean toLauncher, RectF resultRect) {
+ final int taskRotation = target.windowConfiguration.getRotation();
+ final DeviceProfile profile = mLauncher.getDeviceProfile();
+
+ final int rotationDelta = toLauncher
+ ? android.util.RotationUtils.deltaRotation(taskRotation, profile.rotationHint)
+ : android.util.RotationUtils.deltaRotation(profile.rotationHint, taskRotation);
+ if (rotationDelta != ROTATION_0) {
+ // Get original display size when task is on top but with different rotation
+ if (rotationDelta % 2 != 0 && toLauncher && (profile.rotationHint == ROTATION_0
+ || profile.rotationHint == ROTATION_180)) {
+ mDisplayRect.set(0, 0, profile.heightPx, profile.widthPx);
+ } else {
+ mDisplayRect.set(0, 0, profile.widthPx, profile.heightPx);
+ }
+ currentRect.round(mTmpResult);
+ android.util.RotationUtils.rotateBounds(mTmpResult, mDisplayRect, rotationDelta);
+ resultRect.set(mTmpResult);
+ } else {
+ resultRect.set(currentRect);
+ }
}
}
@@ -1977,6 +2024,20 @@
mEndRadius = Math.max(1, targetRect.width()) / 2f;
mSurfaceApplier = new SurfaceTransactionApplier(mDragLayer);
mWindowTargetBounds.set(windowTargetBounds);
+
+ // transfer the coordinate based on animation target.
+ if (mAppTargets != null) {
+ for (RemoteAnimationTarget t : mAppTargets) {
+ if (t.mode == MODE_CLOSING) {
+ final RectF targetBounds = new RectF(mWindowTargetBounds);
+ final RectF result = new RectF();
+ transferRectToTargetCoordinate(
+ t, targetBounds, false, result);
+ result.round(mWindowTargetBounds);
+ break;
+ }
+ }
+ }
}
public float getCornerRadius(float progress) {
@@ -1997,6 +2058,8 @@
}
if (target.mode == MODE_CLOSING) {
+ final RectF before = new RectF(currentRectF);
+ transferRectToTargetCoordinate(target, currentRectF, false, currentRectF);
currentRectF.round(mCurrentRect);
// Scale the target window to match the currentRectF.
@@ -2047,7 +2110,7 @@
if (progress >= end) {
return 0f;
}
- return Utilities.mapToRange(progress, start, end, 1, 0, ACCEL_1_5);
+ return Utilities.mapToRange(progress, start, end, 1, 0, ACCELERATE_1_5);
}
}
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index 34316db..f82474a 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -36,13 +36,11 @@
import com.android.launcher3.allapps.FloatingHeaderRow;
import com.android.launcher3.allapps.FloatingHeaderView;
import com.android.launcher3.anim.AlphaUpdateListener;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.keyboard.FocusIndicatorHelper;
import com.android.launcher3.keyboard.FocusIndicatorHelper.SimpleFocusIndicatorHelper;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.touch.ItemLongClickListener;
import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList;
@@ -65,7 +63,6 @@
private FloatingHeaderView mParent;
private boolean mPredictionsEnabled = false;
- private OnLongClickListener mOnIconLongClickListener = ItemLongClickListener.INSTANCE_ALL_APPS;
public PredictionRowView(@NonNull Context context) {
this(context, null);
@@ -106,22 +103,12 @@
mActivityContext.getAppsView().getAppsStore().unregisterIconContainer(this);
}
}
-
- // Set the predicted row in All Apps' text line to 1.
- if (FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get()
- || FeatureFlags.ENABLE_TWOLINE_DEVICESEARCH.get()) {
- for (int i = 0; i < getChildCount(); i++) {
- BubbleTextView icon = (BubbleTextView) getChildAt(i);
- icon.setMaxLines(1);
- }
- }
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(getExpectedHeight(),
MeasureSpec.EXACTLY));
- updateVisibility();
}
@Override
@@ -185,15 +172,6 @@
applyPredictionApps();
}
- /**
- * Sets the long click listener for predictions for any future predictions.
- *
- * Existing predictions in the container are not updated with this new callback.
- */
- public void setOnIconLongClickListener(OnLongClickListener onIconLongClickListener) {
- mOnIconLongClickListener = onIconLongClickListener;
- }
-
@Override
public void onDeviceProfileChanged(DeviceProfile dp) {
mNumPredictedAppsPerRow = dp.numShownAllAppsColumns;
@@ -209,9 +187,9 @@
LayoutInflater inflater = mActivityContext.getAppsView().getLayoutInflater();
while (getChildCount() < mNumPredictedAppsPerRow) {
BubbleTextView icon = (BubbleTextView) inflater.inflate(
- R.layout.all_apps_icon, this, false);
+ R.layout.all_apps_prediction_row_icon, this, false);
icon.setOnClickListener(mActivityContext.getItemOnClickListener());
- icon.setOnLongClickListener(mOnIconLongClickListener);
+ icon.setOnLongClickListener(mActivityContext.getAllAppsItemLongClickListener());
icon.setLongPressTimeoutFactor(1f);
icon.setOnFocusChangeListener(mFocusHelper);
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
index 048243e..b77c43f 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
@@ -95,9 +95,7 @@
}
}
if (pageId == -1) {
- pageId = LauncherSettings.Settings.call(mLauncher.getContentResolver(),
- LauncherSettings.Settings.METHOD_NEW_SCREEN_ID)
- .getInt(LauncherSettings.Settings.EXTRA_VALUE);
+ pageId = mLauncher.getModel().getModelDbController().getNewScreenId();
mNewScreens = IntArray.wrap(pageId);
}
boolean isPortrait = !mLauncher.getDeviceProfile().isVerticalBarLayout();
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
index 80bdb6f..db225be 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
@@ -19,7 +19,6 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_EDU_DENY;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_EDU_SEEN;
-import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -37,7 +36,6 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.uioverrides.PredictedAppIcon;
@@ -160,14 +158,11 @@
}
private void animateOpen() {
- if (mIsOpen || mOpenCloseAnimator.isRunning()) {
+ if (mIsOpen || mOpenCloseAnimation.getAnimationPlayer().isRunning()) {
return;
}
mIsOpen = true;
- mOpenCloseAnimator.setValues(
- PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
- mOpenCloseAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- mOpenCloseAnimator.start();
+ setUpDefaultOpenAnimation().start();
}
@Override
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
index 85d0ab5..a63f9e8 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -22,11 +22,13 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_PREDICTION_PINNED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_RANKED;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.FlagDebugUtils.appendFlag;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.ComponentName;
+import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.View;
import android.view.ViewGroup;
@@ -60,9 +62,11 @@
import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.views.Snackbar;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.StringJoiner;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -74,6 +78,7 @@
SystemShortcut.Factory<QuickstepLauncher>, DeviceProfile.OnDeviceProfileChangeListener,
DragSource, ViewGroup.OnHierarchyChangeListener {
+ private static final String TAG = "HotseatPredictionController";
private static final int FLAG_UPDATE_PAUSED = 1 << 0;
private static final int FLAG_DRAG_IN_PROGRESS = 1 << 1;
private static final int FLAG_FILL_IN_PROGRESS = 1 << 2;
@@ -114,8 +119,7 @@
WorkspaceItemInfo dragItem = new WorkspaceItemInfo((WorkspaceItemInfo) v.getTag());
v.setVisibility(View.INVISIBLE);
mLauncher.getWorkspace().beginDragShared(
- v, null, this, dragItem, new DragPreviewProvider(v),
- mLauncher.getDefaultWorkspaceDragOptions());
+ v, null, this, dragItem, new DragPreviewProvider(v), new DragOptions());
return true;
};
@@ -184,6 +188,7 @@
}
private void fillGapsWithPrediction(boolean animate) {
+ Log.d(TAG, "fillGapsWithPrediction flags: " + getStateString(mPauseFlags));
if (mPauseFlags != 0) {
return;
}
@@ -208,12 +213,16 @@
View child = mHotseat.getChildAt(
mHotseat.getCellXFromOrder(rank),
mHotseat.getCellYFromOrder(rank));
+ Log.d(TAG, "Hotseat app child is: " + child + " and isPredictedIcon() evaluates to"
+ + ": " + isPredictedIcon(child));
if (child != null && !isPredictedIcon(child)) {
continue;
}
if (mPredictedItems.size() <= predictionIndex) {
// Remove predicted apps from the past
+ Log.d(TAG, "Remove predicted apps from the past\nPrediction Index: "
+ + predictionIndex);
if (isPredictedIcon(child)) {
mHotseat.removeView(child);
}
@@ -221,6 +230,11 @@
}
WorkspaceItemInfo predictedItem =
(WorkspaceItemInfo) mPredictedItems.get(predictionIndex++);
+ Log.d(TAG, "Predicted item is: " + predictedItem);
+ if (child != null) {
+ Log.d(TAG, "Predicted item is enabled: " + child.isEnabled());
+ }
+
if (isPredictedIcon(child) && child.isEnabled()) {
PredictedAppIcon icon = (PredictedAppIcon) child;
boolean animateIconChange = icon.shouldAnimateIconChange(predictedItem);
@@ -240,6 +254,7 @@
}
private void bindItems(List<WorkspaceItemInfo> itemsToAdd, boolean animate) {
+ Log.d(TAG, "bindItems to hotseat: " + itemsToAdd);
AnimatorSet animationSet = new AnimatorSet();
for (WorkspaceItemInfo item : itemsToAdd) {
PredictedAppIcon icon = PredictedAppIcon.createIcon(mHotseat, item);
@@ -279,6 +294,7 @@
* start and pauses predicted apps update on the hotseat
*/
public void setPauseUIUpdate(boolean paused) {
+ Log.d(TAG, "setPauseUIUpdate parameter `paused` is " + paused);
mPauseFlags = paused
? (mPauseFlags | FLAG_UPDATE_PAUSED)
: (mPauseFlags & ~FLAG_UPDATE_PAUSED);
@@ -293,8 +309,10 @@
public void setPredictedItems(FixedContainerItems items) {
mPredictedItems = new ArrayList(items.items);
if (mPredictedItems.isEmpty()) {
+ Log.d(TAG, "Predicted items is initially empty");
HotseatRestoreHelper.restoreBackup(mLauncher);
}
+ Log.d(TAG, "Predicted items: " + mPredictedItems);
fillGapsWithPrediction();
}
@@ -501,4 +519,21 @@
&& ((WorkspaceItemInfo) view.getTag()).container
== LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
}
+
+ private static String getStateString(int flags) {
+ StringJoiner str = new StringJoiner("|");
+ appendFlag(str, flags, FLAG_UPDATE_PAUSED, "FLAG_UPDATE_PAUSED");
+ appendFlag(str, flags, FLAG_DRAG_IN_PROGRESS, "FLAG_DRAG_IN_PROGRESS");
+ appendFlag(str, flags, FLAG_FILL_IN_PROGRESS, "FLAG_FILL_IN_PROGRESS");
+ appendFlag(str, flags, FLAG_REMOVING_PREDICTED_ICON,
+ "FLAG_REMOVING_PREDICTED_ICON");
+ return str.toString();
+ }
+
+ public void dump(String prefix, PrintWriter writer) {
+ writer.println(prefix + this.getClass().getSimpleName());
+ writer.println(prefix + "\tFlags: " + getStateString(mPauseFlags));
+ writer.println(prefix + "\tmHotSeatItemsCount: " + mHotSeatItemsCount);
+ writer.println(prefix + "\tmPredictedItems: " + mPredictedItems);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java
index 726abff..8c01d04 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java
@@ -22,9 +22,10 @@
import android.content.Context;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.LauncherModel;
import com.android.launcher3.model.GridBackupTable;
-import com.android.launcher3.provider.LauncherDbUtils;
+import com.android.launcher3.model.ModelDbController;
+import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
/**
* A helper class to manage migration revert restoration for hybrid hotseat
@@ -36,16 +37,13 @@
*/
public static void createBackup(Context context) {
MODEL_EXECUTOR.execute(() -> {
- try (LauncherDbUtils.SQLiteTransaction transaction = (LauncherDbUtils.SQLiteTransaction)
- LauncherSettings.Settings.call(
- context.getContentResolver(),
- LauncherSettings.Settings.METHOD_NEW_TRANSACTION)
- .getBinder(LauncherSettings.Settings.EXTRA_VALUE)) {
+ ModelDbController dbController = LauncherAppState.getInstance(context)
+ .getModel().getModelDbController();
+ try (SQLiteTransaction transaction = dbController.newTransaction()) {
GridBackupTable backupTable = new GridBackupTable(context, transaction.getDb());
backupTable.createCustomBackupTable(HYBRID_HOTSEAT_BACKUP_TABLE);
transaction.commit();
- LauncherSettings.Settings.call(context.getContentResolver(),
- LauncherSettings.Settings.METHOD_REFRESH_HOTSEAT_RESTORE_TABLE);
+ dbController.refreshHotseatRestoreTable();
}
});
}
@@ -55,18 +53,15 @@
*/
public static void restoreBackup(Context context) {
MODEL_EXECUTOR.execute(() -> {
- try (LauncherDbUtils.SQLiteTransaction transaction = (LauncherDbUtils.SQLiteTransaction)
- LauncherSettings.Settings.call(
- context.getContentResolver(),
- LauncherSettings.Settings.METHOD_NEW_TRANSACTION)
- .getBinder(LauncherSettings.Settings.EXTRA_VALUE)) {
+ LauncherModel model = LauncherAppState.getInstance(context).getModel();
+ try (SQLiteTransaction transaction = model.getModelDbController().newTransaction()) {
if (!tableExists(transaction.getDb(), HYBRID_HOTSEAT_BACKUP_TABLE)) {
return;
}
GridBackupTable backupTable = new GridBackupTable(context, transaction.getDb());
backupTable.restoreFromCustomBackupTable(HYBRID_HOTSEAT_BACKUP_TABLE, true);
transaction.commit();
- LauncherAppState.getInstance(context).getModel().forceReload();
+ model.forceReload();
}
});
}
diff --git a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
index bc97df1..32361a8 100644
--- a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
+++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
@@ -52,6 +52,7 @@
import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
import com.android.launcher3.InvariantDeviceProfile;
@@ -93,11 +94,14 @@
private static final boolean IS_DEBUG = false;
private static final String TAG = "QuickstepModelDelegate";
- private final PredictorState mAllAppsState =
+ @VisibleForTesting
+ final PredictorState mAllAppsState =
new PredictorState(CONTAINER_PREDICTION, "all_apps_predictions");
- private final PredictorState mHotseatState =
+ @VisibleForTesting
+ final PredictorState mHotseatState =
new PredictorState(CONTAINER_HOTSEAT_PREDICTION, "hotseat_predictions");
- private final PredictorState mWidgetsRecommendationState =
+ @VisibleForTesting
+ final PredictorState mWidgetsRecommendationState =
new PredictorState(CONTAINER_WIDGETS_PREDICTION, "widgets_prediction");
private final InvariantDeviceProfile mIDP;
@@ -348,12 +352,7 @@
.build()));
// TODO: get bundle
- registerPredictor(mHotseatState, apm.createAppPredictionSession(
- new AppPredictionContext.Builder(context)
- .setUiSurface("hotseat")
- .setPredictedTargetCount(mIDP.numDatabaseHotseatIcons)
- .setExtras(convertDataModelToAppTargetBundle(context, mDataModel))
- .build()));
+ registerHotseatPredictor(apm, context);
registerWidgetsPredictor(apm.createAppPredictionSession(
new AppPredictionContext.Builder(context)
@@ -363,6 +362,29 @@
.build()));
}
+ @WorkerThread
+ private void recreateHotseatPredictor() {
+ mHotseatState.destroyPredictor();
+ if (!mActive) {
+ return;
+ }
+ Context context = mApp.getContext();
+ AppPredictionManager apm = context.getSystemService(AppPredictionManager.class);
+ if (apm == null) {
+ return;
+ }
+ registerHotseatPredictor(apm, context);
+ }
+
+ private void registerHotseatPredictor(AppPredictionManager apm, Context context) {
+ registerPredictor(mHotseatState, apm.createAppPredictionSession(
+ new AppPredictionContext.Builder(context)
+ .setUiSurface("hotseat")
+ .setPredictedTargetCount(mIDP.numDatabaseHotseatIcons)
+ .setExtras(convertDataModelToAppTargetBundle(context, mDataModel))
+ .build()));
+ }
+
private void registerPredictor(PredictorState state, AppPredictor predictor) {
state.setTargets(Collections.emptyList());
state.predictor = predictor;
@@ -393,7 +415,8 @@
mWidgetsRecommendationState.predictor.requestPredictionUpdate();
}
- private void onAppTargetEvent(AppTargetEvent event, int client) {
+ @VisibleForTesting
+ void onAppTargetEvent(AppTargetEvent event, int client) {
PredictorState state;
switch(client) {
case CONTAINER_PREDICTION:
@@ -411,6 +434,13 @@
state.predictor.notifyAppTargetEvent(event);
Log.d(TAG, "notifyAppTargetEvent action=" + event.getAction()
+ " launchLocation=" + event.getLaunchLocation());
+ if (state == mHotseatState
+ && (event.getAction() == AppTargetEvent.ACTION_PIN
+ || event.getAction() == AppTargetEvent.ACTION_UNPIN)) {
+ // Recreate hot seat predictor when we need to query for hot seat due to pin or
+ // unpin app icons.
+ recreateHotseatPredictor();
+ }
}
}
diff --git a/quickstep/src/com/android/launcher3/proxy/ProxyActivityStarter.java b/quickstep/src/com/android/launcher3/proxy/ProxyActivityStarter.java
index 4d7cc85..6d90b035 100644
--- a/quickstep/src/com/android/launcher3/proxy/ProxyActivityStarter.java
+++ b/quickstep/src/com/android/launcher3/proxy/ProxyActivityStarter.java
@@ -24,6 +24,8 @@
import android.os.Bundle;
import android.util.Log;
+import com.android.launcher3.util.StartActivityParams;
+
public class ProxyActivityStarter extends Activity {
private static final String TAG = "ProxyActivityStarter";
diff --git a/quickstep/src/com/android/launcher3/secondarydisplay/SecondaryDisplayPredictionsImpl.java b/quickstep/src/com/android/launcher3/secondarydisplay/SecondaryDisplayPredictionsImpl.java
index 8720bd8..b982688 100644
--- a/quickstep/src/com/android/launcher3/secondarydisplay/SecondaryDisplayPredictionsImpl.java
+++ b/quickstep/src/com/android/launcher3/secondarydisplay/SecondaryDisplayPredictionsImpl.java
@@ -18,9 +18,7 @@
import static com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT;
import android.content.Context;
-import android.view.View;
-import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.appprediction.AppsDividerView;
import com.android.launcher3.appprediction.PredictionRowView;
import com.android.launcher3.model.BgDataModel;
@@ -56,12 +54,4 @@
.findFixedRowByType(PredictionRowView.class)
.setPredictedApps(item.items);
}
-
- @Override
- public void setLongClickListener(ActivityAllAppsContainerView<?> appsView,
- View.OnLongClickListener onIconLongClickListener) {
- appsView.getFloatingHeaderView()
- .findFixedRowByType(PredictionRowView.class)
- .setOnIconLongClickListener(onIconLongClickListener);
- }
}
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index 70aa5d7..882682d 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -16,7 +16,7 @@
package com.android.launcher3.statehandlers;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_DEPTH;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_DEPTH_CONTROLLER;
import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
@@ -193,5 +193,6 @@
writer.println(prefix + "\tmIgnoreStateChangesDuringMultiWindowAnimation="
+ mIgnoreStateChangesDuringMultiWindowAnimation);
writer.println(prefix + "\tmPauseBlurs=" + mPauseBlurs);
+ writer.println(prefix + "\tmWaitingOnSurfaceValidity=" + mWaitingOnSurfaceValidity);
}
}
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
index d087d39..42e6809 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
@@ -15,14 +15,22 @@
*/
package com.android.launcher3.statehandlers;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
import android.os.SystemProperties;
import android.util.Log;
import android.view.View;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.quickstep.GestureState;
+import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.views.DesktopAppSelectView;
+import com.android.wm.shell.desktopmode.IDesktopTaskListener;
/**
* Controls the visibility of the workspace and the resumed / paused state when desktop mode
@@ -32,23 +40,73 @@
private static final String TAG = "DesktopVisController";
private static final boolean DEBUG = false;
-
+ private static final boolean IS_STASHING_ENABLED = SystemProperties.getBoolean(
+ "persist.wm.debug.desktop_stashing", false);
private final Launcher mLauncher;
private boolean mFreeformTasksVisible;
private boolean mInOverviewState;
private boolean mGestureInProgress;
+ @Nullable
+ private IDesktopTaskListener mDesktopTaskListener;
+ private DesktopAppSelectView mSelectAppToast;
+
public DesktopVisibilityController(Launcher launcher) {
mLauncher = launcher;
}
/**
+ * Register a listener with System UI to receive updates about desktop tasks state
+ */
+ public void registerSystemUiListener() {
+ mDesktopTaskListener = new IDesktopTaskListener.Stub() {
+ @Override
+ public void onVisibilityChanged(int displayId, boolean visible) {
+ MAIN_EXECUTOR.execute(() -> {
+ if (displayId == mLauncher.getDisplayId()) {
+ if (DEBUG) {
+ Log.d(TAG, "desktop visibility changed value=" + visible);
+ }
+ setFreeformTasksVisible(visible);
+ }
+ });
+ }
+
+ @Override
+ public void onStashedChanged(int displayId, boolean stashed) {
+ if (!IS_STASHING_ENABLED) {
+ return;
+ }
+ MAIN_EXECUTOR.execute(() -> {
+ if (displayId == mLauncher.getDisplayId()) {
+ if (DEBUG) {
+ Log.d(TAG, "desktop stashed changed value=" + stashed);
+ }
+ if (stashed) {
+ showSelectAppToast();
+ } else {
+ hideSelectAppToast();
+ }
+ }
+ });
+ }
+ };
+ SystemUiProxy.INSTANCE.get(mLauncher).setDesktopTaskListener(mDesktopTaskListener);
+ }
+
+ /**
+ * Clear listener from System UI that was set with {@link #registerSystemUiListener()}
+ */
+ public void unregisterSystemUiListener() {
+ SystemUiProxy.INSTANCE.get(mLauncher).setDesktopTaskListener(null);
+ }
+
+ /**
* Whether desktop mode is supported.
*/
private boolean isDesktopModeSupported() {
- return SystemProperties.getBoolean("persist.wm.debug.desktop_mode", false)
- || SystemProperties.getBoolean("persist.wm.debug.desktop_mode_2", false);
+ return SystemProperties.getBoolean("persist.wm.debug.desktop_mode_2", false);
}
/**
@@ -68,6 +126,7 @@
if (!isDesktopModeSupported()) {
return;
}
+
if (freeformTasksVisible != mFreeformTasksVisible) {
mFreeformTasksVisible = freeformTasksVisible;
if (mFreeformTasksVisible) {
@@ -101,7 +160,9 @@
if (mInOverviewState) {
setLauncherViewsVisibility(View.VISIBLE);
markLauncherResumed();
- } else if (mFreeformTasksVisible) {
+ } else if (mFreeformTasksVisible && !mGestureInProgress) {
+ // Switching out of overview state and gesture finished.
+ // If freeform tasks are still visible, hide launcher again.
setLauncherViewsVisibility(View.INVISIBLE);
markLauncherPaused();
}
@@ -111,25 +172,54 @@
/**
* Whether recents gesture is currently in progress.
*/
- public boolean isGestureInProgress() {
+ public boolean isRecentsGestureInProgress() {
return mGestureInProgress;
}
/**
- * Sets whether recents gesture is in progress.
+ * Notify controller that recents gesture has started.
*/
- public void setGestureInProgress(boolean gestureInProgress) {
- if (DEBUG) {
- Log.d(TAG, "setGestureInProgress: inProgress=" + gestureInProgress);
- }
+ public void setRecentsGestureStart() {
if (!isDesktopModeSupported()) {
return;
}
+ setRecentsGestureInProgress(true);
+ }
+
+ /**
+ * Notify controller that recents gesture finished with the given
+ * {@link com.android.quickstep.GestureState.GestureEndTarget}
+ */
+ public void setRecentsGestureEnd(@Nullable GestureState.GestureEndTarget endTarget) {
+ if (!isDesktopModeSupported()) {
+ return;
+ }
+ setRecentsGestureInProgress(false);
+
+ if (endTarget == null) {
+ // Gesture did not result in a new end target. Ensure launchers gets paused again.
+ markLauncherPaused();
+ }
+ }
+
+ private void setRecentsGestureInProgress(boolean gestureInProgress) {
+ if (DEBUG) {
+ Log.d(TAG, "setGestureInProgress: inProgress=" + gestureInProgress);
+ }
if (gestureInProgress != mGestureInProgress) {
mGestureInProgress = gestureInProgress;
}
}
+ /**
+ * Handle launcher moving to home due to home gesture or home button press.
+ */
+ public void onHomeActionTriggered() {
+ if (IS_STASHING_ENABLED && areFreeformTasksVisible()) {
+ SystemUiProxy.INSTANCE.get(mLauncher).stashDesktopApps(mLauncher.getDisplayId());
+ }
+ }
+
private void setLauncherViewsVisibility(int visibility) {
if (DEBUG) {
Log.d(TAG, "setLauncherViewsVisibility: visibility=" + visibility);
@@ -168,4 +258,28 @@
activity.setResumed();
}
}
+
+ private void showSelectAppToast() {
+ if (mSelectAppToast != null) {
+ return;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "show toast to select desktop apps");
+ }
+ Runnable onCloseCallback = () -> {
+ SystemUiProxy.INSTANCE.get(mLauncher).hideStashedDesktopApps(mLauncher.getDisplayId());
+ };
+ mSelectAppToast = DesktopAppSelectView.show(mLauncher, onCloseCallback);
+ }
+
+ private void hideSelectAppToast() {
+ if (mSelectAppToast == null) {
+ return;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "hide toast to select desktop apps");
+ }
+ mSelectAppToast.hide();
+ mSelectAppToast = null;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
index 885afff..29c5204 100644
--- a/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_NOTIFICATIONS;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_QUICK_SETTINGS;
+import android.content.pm.ActivityInfo.Config;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -56,6 +57,11 @@
@Override
public void init(TaskbarControllers controllers) {
mControllers = controllers;
+ super.init(controllers);
+ }
+
+ @Override
+ protected void setupController() {
mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarHeight;
// Quick settings and notifications buttons
@@ -72,4 +78,7 @@
/** Cleans up on destroy */
@Override
public void onDestroy() { }
+
+ @Override
+ public void onConfigurationChanged(@Config int configChanges) { }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
index 7f655cf..dda8446 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
@@ -22,9 +22,13 @@
import androidx.annotation.Nullable;
import com.android.launcher3.R;
+import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
+import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.RecentsModel;
+import com.android.quickstep.util.DesktopTask;
import com.android.quickstep.util.GroupTask;
+import com.android.quickstep.views.DesktopTaskView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -102,21 +106,74 @@
mQuickSwitchViewController = new KeyboardQuickSwitchViewController(
mControllers, overlayContext, keyboardQuickSwitchView, mControllerCallbacks);
+ DesktopVisibilityController desktopController =
+ LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
+ final boolean onDesktop =
+ DesktopTaskView.DESKTOP_MODE_SUPPORTED
+ && desktopController != null
+ && desktopController.areFreeformTasksVisible();
+
if (mModel.isTaskListValid(mTaskListChangeId)) {
- mQuickSwitchViewController.openQuickSwitchView(
- mTasks, mNumHiddenTasks, /* updateTasks= */ false, currentFocusedIndex);
+ mQuickSwitchViewController.openQuickSwitchView(mTasks,
+ mNumHiddenTasks, /* updateTasks= */ false, currentFocusedIndex, onDesktop);
return;
}
+
mTaskListChangeId = mModel.getTasks((tasks) -> {
- // Only store MAX_TASK tasks, from most to least recent
- Collections.reverse(tasks);
- mTasks = tasks.stream().limit(MAX_TASKS).collect(Collectors.toList());
- mNumHiddenTasks = Math.max(0, tasks.size() - MAX_TASKS);
- mQuickSwitchViewController.openQuickSwitchView(
- mTasks, mNumHiddenTasks, /* updateTasks= */ true, currentFocusedIndex);
+ if (onDesktop) {
+ processLoadedTasksOnDesktop(tasks);
+ } else {
+ processLoadedTasks(tasks);
+ }
+ mQuickSwitchViewController.openQuickSwitchView(mTasks,
+ mNumHiddenTasks, /* updateTasks= */ true, currentFocusedIndex, onDesktop);
});
}
+ private void processLoadedTasks(ArrayList<GroupTask> tasks) {
+ // Only store MAX_TASK tasks, from most to least recent
+ Collections.reverse(tasks);
+
+ // Hide all desktop tasks and show them on the hidden tile
+ int hiddenDesktopTasks = 0;
+ if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
+ DesktopTask desktopTask = findDesktopTask(tasks);
+ if (desktopTask != null) {
+ hiddenDesktopTasks = desktopTask.tasks.size();
+ tasks = tasks.stream()
+ .filter(t -> !(t instanceof DesktopTask))
+ .collect(Collectors.toCollection(ArrayList<GroupTask>::new));
+ }
+ }
+ mTasks = tasks.stream()
+ .limit(MAX_TASKS)
+ .collect(Collectors.toList());
+ mNumHiddenTasks = Math.max(0, tasks.size() - MAX_TASKS) + hiddenDesktopTasks;
+ }
+
+ private void processLoadedTasksOnDesktop(ArrayList<GroupTask> tasks) {
+ // Find the single desktop task that contains a grouping of desktop tasks
+ DesktopTask desktopTask = findDesktopTask(tasks);
+
+ if (desktopTask != null) {
+ mTasks = desktopTask.tasks.stream().map(GroupTask::new).collect(Collectors.toList());
+ // All other tasks, apart from the grouped desktop task, are hidden
+ mNumHiddenTasks = Math.max(0, tasks.size() - 1);
+ } else {
+ // Desktop tasks were visible, but the recents entry is missing. Fall back to empty list
+ mTasks = Collections.emptyList();
+ mNumHiddenTasks = tasks.size();
+ }
+ }
+
+ @Nullable
+ private DesktopTask findDesktopTask(ArrayList<GroupTask> tasks) {
+ return (DesktopTask) tasks.stream()
+ .filter(t -> t instanceof DesktopTask)
+ .findFirst()
+ .orElse(null);
+ }
+
void closeQuickSwitchView() {
if (mQuickSwitchViewController == null) {
return;
@@ -169,7 +226,7 @@
class ControllerCallbacks {
int getTaskCount() {
- return mNumHiddenTasks == 0 ? mTasks.size() : MAX_TASKS + 1;
+ return mTasks.size() + (mNumHiddenTasks == 0 ? 0 : 1);
}
@Nullable
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
index 8a11b57..3e1a6ae 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
@@ -80,7 +80,7 @@
setWillNotDraw(false);
mBorderColor = ta.getColor(
- R.styleable.TaskView_borderColor, DEFAULT_BORDER_COLOR);
+ R.styleable.TaskView_focusBorderColor, DEFAULT_BORDER_COLOR);
ta.recycle();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
index 2cdfb18..42c423c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
@@ -42,10 +42,12 @@
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatedFloat;
-import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.testing.TestLogging;
+import com.android.launcher3.testing.shared.TestProtocol;
import com.android.quickstep.util.GroupTask;
import java.util.HashMap;
@@ -190,8 +192,12 @@
ConstraintLayout.LayoutParams lp = new ConstraintLayout.LayoutParams(
width, mTaskViewHeight);
- lp.endToEnd = PARENT_ID;
- lp.startToEnd = previousView.getId();
+ if (previousView == null) {
+ lp.startToStart = PARENT_ID;
+ } else {
+ lp.endToEnd = PARENT_ID;
+ lp.startToEnd = previousView.getId();
+ }
lp.topToTop = PARENT_ID;
lp.bottomToBottom = PARENT_ID;
lp.setMarginEnd(mSpacing);
@@ -356,11 +362,8 @@
OPEN_OUTLINE_INTERPOLATOR));
}
});
- if (currentFocusIndexOverride == -1) {
- initializeScroll(/* index= */ 0, /* shouldTruncateTarget= */ false);
- } else {
- animateFocusMove(-1, currentFocusIndexOverride);
- }
+ animateFocusMove(-1, currentFocusIndexOverride == -1
+ ? Math.min(mContent.getChildCount(), 1) : currentFocusIndexOverride);
displayedContent.setVisibility(VISIBLE);
setVisibility(VISIBLE);
requestFocus();
@@ -409,7 +412,8 @@
// there are more tasks
initializeScroll(
firstVisibleTaskIndex,
- /* shouldTruncateTarget= */ firstVisibleTaskIndex != toIndex);
+ /* shouldTruncateTarget= */ firstVisibleTaskIndex != 0
+ && firstVisibleTaskIndex != toIndex);
} else if (toIndex > fromIndex || toIndex == 0) {
// Scrolling to next task view
if (mIsRtl) {
@@ -435,6 +439,13 @@
}
@Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ TestLogging.recordKeyEvent(
+ TestProtocol.SEQUENCE_MAIN, "KeyboardQuickSwitchView key event", event);
+ return super.dispatchKeyEvent(event);
+ }
+
+ @Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
return (mViewCallbacks != null
&& mViewCallbacks.onKeyUp(keyCode, event, mIsRtl, mDisplayingRecentTasks))
@@ -450,56 +461,80 @@
return;
}
if (mIsRtl) {
- scrollRightTo(
- task, shouldTruncateTarget, /* smoothScroll= */ false);
- } else {
scrollLeftTo(
- task, shouldTruncateTarget, /* smoothScroll= */ false);
+ task,
+ shouldTruncateTarget,
+ /* smoothScroll= */ false,
+ /* waitForLayout= */ true);
+ } else {
+ scrollRightTo(
+ task,
+ shouldTruncateTarget,
+ /* smoothScroll= */ false,
+ /* waitForLayout= */ true);
}
}
private void scrollRightTo(@NonNull View targetTask) {
- scrollRightTo(targetTask, /* shouldTruncateTarget= */ false, /* smoothScroll= */ true);
+ scrollRightTo(
+ targetTask,
+ /* shouldTruncateTarget= */ false,
+ /* smoothScroll= */ true,
+ /* waitForLayout= */ false);
}
private void scrollRightTo(
- @NonNull View targetTask, boolean shouldTruncateTarget, boolean smoothScroll) {
+ @NonNull View targetTask,
+ boolean shouldTruncateTarget,
+ boolean smoothScroll,
+ boolean waitForLayout) {
if (!mDisplayingRecentTasks) {
return;
}
if (smoothScroll && !shouldScroll(targetTask, shouldTruncateTarget)) {
return;
}
- int scrollTo = targetTask.getLeft() - mSpacing
- + (shouldTruncateTarget ? targetTask.getWidth() / 2 : 0);
- // Scroll so that the focused task is to the left of the list
- if (smoothScroll) {
- mScrollView.smoothScrollTo(scrollTo, 0);
- } else {
- mScrollView.scrollTo(scrollTo, 0);
- }
+ runScrollCommand(waitForLayout, () -> {
+ int scrollTo = targetTask.getLeft() - mSpacing
+ + (shouldTruncateTarget ? targetTask.getWidth() / 2 : 0);
+ // Scroll so that the focused task is to the left of the list
+ if (smoothScroll) {
+ mScrollView.smoothScrollTo(scrollTo, 0);
+ } else {
+ mScrollView.scrollTo(scrollTo, 0);
+ }
+ });
}
private void scrollLeftTo(@NonNull View targetTask) {
- scrollLeftTo(targetTask, /* shouldTruncateTarget= */ false, /* smoothScroll= */ true);
+ scrollLeftTo(
+ targetTask,
+ /* shouldTruncateTarget= */ false,
+ /* smoothScroll= */ true,
+ /* waitForLayout= */ false);
}
private void scrollLeftTo(
- @NonNull View targetTask, boolean shouldTruncateTarget, boolean smoothScroll) {
+ @NonNull View targetTask,
+ boolean shouldTruncateTarget,
+ boolean smoothScroll,
+ boolean waitForLayout) {
if (!mDisplayingRecentTasks) {
return;
}
if (smoothScroll && !shouldScroll(targetTask, shouldTruncateTarget)) {
return;
}
- int scrollTo = targetTask.getRight() + mSpacing - mScrollView.getWidth()
- - (shouldTruncateTarget ? targetTask.getWidth() / 2 : 0);
- // Scroll so that the focused task is to the right of the list
- if (smoothScroll) {
- mScrollView.smoothScrollTo(scrollTo, 0);
- } else {
- mScrollView.scrollTo(scrollTo, 0);
- }
+ runScrollCommand(waitForLayout, () -> {
+ int scrollTo = targetTask.getRight() + mSpacing - mScrollView.getWidth()
+ - (shouldTruncateTarget ? targetTask.getWidth() / 2 : 0);
+ // Scroll so that the focused task is to the right of the list
+ if (smoothScroll) {
+ mScrollView.smoothScrollTo(scrollTo, 0);
+ } else {
+ mScrollView.scrollTo(scrollTo, 0);
+ }
+ });
}
private boolean shouldScroll(@NonNull View targetTask, boolean shouldTruncateTarget) {
@@ -510,6 +545,21 @@
return isTargetTruncated && !shouldTruncateTarget;
}
+ private void runScrollCommand(boolean waitForLayout, @NonNull Runnable scrollCommand) {
+ if (!waitForLayout) {
+ scrollCommand.run();
+ return;
+ }
+ mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ scrollCommand.run();
+ mScrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ }
+ });
+ }
+
@Nullable
protected KeyboardQuickSwitchTaskView getTaskAt(int index) {
return !mDisplayingRecentTasks || index < 0 || index >= mContent.getChildCount()
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
index 3230c66..cbb991d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
@@ -24,9 +24,10 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayDragLayer;
+import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.util.GroupTask;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -52,6 +53,8 @@
private int mCurrentFocusIndex = -1;
+ private boolean mOnDesktop;
+
protected KeyboardQuickSwitchViewController(
@NonNull TaskbarControllers controllers,
@NonNull TaskbarOverlayContext overlayContext,
@@ -71,10 +74,12 @@
@NonNull List<GroupTask> tasks,
int numHiddenTasks,
boolean updateTasks,
- int currentFocusIndexOverride) {
+ int currentFocusIndexOverride,
+ boolean onDesktop) {
TaskbarOverlayDragLayer dragLayer = mOverlayContext.getDragLayer();
dragLayer.addView(mKeyboardQuickSwitchView);
dragLayer.runOnClickOnce(v -> closeQuickSwitchView(true));
+ mOnDesktop = onDesktop;
mKeyboardQuickSwitchView.applyLoadPlan(
mOverlayContext,
@@ -87,27 +92,19 @@
protected void closeQuickSwitchView(boolean animate) {
if (mCloseAnimation != null) {
- if (animate) {
- // Let currently-running animation finish.
- return;
- } else {
- mCloseAnimation.cancel();
+ // Let currently-running animation finish.
+ if (!animate) {
+ mCloseAnimation.end();
}
+ return;
}
if (!animate) {
- mCloseAnimation = null;
onCloseComplete();
return;
}
mCloseAnimation = mKeyboardQuickSwitchView.getCloseAnimation();
- mCloseAnimation.addListener(new AnimationSuccessListener() {
- @Override
- public void onAnimationSuccess(Animator animator) {
- mCloseAnimation = null;
- onCloseComplete();
- }
- });
+ mCloseAnimation.addListener(AnimatorListeners.forEndCallback(this::onCloseComplete));
mCloseAnimation.start();
}
@@ -136,6 +133,10 @@
GroupTask task = mControllerCallbacks.getTaskAt(index);
if (task == null) {
return Math.max(0, index);
+ } else if (mOnDesktop) {
+ UI_HELPER_EXECUTOR.execute(() ->
+ SystemUiProxy.INSTANCE.get(mKeyboardQuickSwitchView.getContext())
+ .showDesktopApp(task.task1.key.id));
} else if (task.task2 == null) {
UI_HELPER_EXECUTOR.execute(() ->
ActivityManagerWrapper.getInstance().startActivityFromRecents(
@@ -151,6 +152,7 @@
}
private void onCloseComplete() {
+ mCloseAnimation = null;
mOverlayContext.getDragLayer().removeView(mKeyboardQuickSwitchView);
mControllerCallbacks.onCloseComplete();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index abf49eb..e6dfe0f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -41,6 +41,7 @@
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.taskbar.bubbles.BubbleBarController;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.MultiPropertyFactory;
@@ -202,10 +203,18 @@
return mTaskbarLauncherStateController.applyState(fromInit ? 0 : duration, startAnimation);
}
+ @Override
public void refreshResumedState() {
onLauncherResumedOrPaused(mLauncher.hasBeenResumed());
}
+ @Override
+ public void adjustHotseatForBubbleBar(boolean isBubbleBarVisible) {
+ if (mLauncher.getHotseat() != null) {
+ mLauncher.getHotseat().adjustForBubbleBar(isBubbleBarVisible);
+ }
+ }
+
/**
* Create Taskbar animation when going from an app to Launcher as part of recents transition.
* @param toState If known, the state we will end up in when reaching Launcher.
@@ -317,6 +326,8 @@
.getTaskbarNavButtonTranslationYForInAppDisplay()
.updateValue(mLauncher.getDeviceProfile().getTaskbarOffsetY()
* mTaskbarInAppDisplayProgress.value);
+ mControllers.navbarButtonsViewController
+ .getOnTaskbarBackgroundNavButtonColorOverride().updateValue(progress);
}
}
@@ -325,6 +336,21 @@
return mTaskbarInAppDisplayProgress.value > 0;
}
+ public boolean isBubbleBarEnabled() {
+ return BubbleBarController.BUBBLE_BAR_ENABLED;
+ }
+
+ /** Whether the bubble bar has any bubbles. */
+ public boolean hasBubbles() {
+ if (mControllers == null) {
+ return false;
+ }
+ if (mControllers.bubbleControllers.isEmpty()) {
+ return false;
+ }
+ return mControllers.bubbleControllers.get().bubbleBarViewController.hasBubbles();
+ }
+
@Override
public void onExpandPip() {
super.onExpandPip();
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 9c463cb..fa16b61 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -88,6 +88,7 @@
import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory;
import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.NavButtonLayoutter;
import com.android.launcher3.util.DimensionUtils;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.TouchController;
@@ -148,8 +149,8 @@
// Used for IME+A11Y buttons
private final ViewGroup mEndContextualContainer;
private final ViewGroup mStartContextualContainer;
- private final int mLightIconColor;
- private final int mDarkIconColor;
+ private final int mLightIconColorOnHome;
+ private final int mDarkIconColorOnHome;
/** Color to use for navigation bar buttons, if they are on on a Taskbar surface background. */
private final int mOnBackgroundIconColor;
@@ -197,6 +198,7 @@
this::onComputeInsetsForSeparateWindow;
private final RecentsHitboxExtender mHitboxExtender = new RecentsHitboxExtender();
private ImageView mRecentsButton;
+ private DisplayController mDisplayController;
public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) {
mContext = context;
@@ -205,9 +207,11 @@
mEndContextualContainer = mNavButtonsView.findViewById(R.id.end_contextual_buttons);
mStartContextualContainer = mNavButtonsView.findViewById(R.id.start_contextual_buttons);
- mLightIconColor = context.getColor(R.color.taskbar_nav_icon_light_color);
- mDarkIconColor = context.getColor(R.color.taskbar_nav_icon_dark_color);
- mOnBackgroundIconColor = Utilities.isDarkTheme(context) ? mLightIconColor : mDarkIconColor;
+ mLightIconColorOnHome = context.getColor(R.color.taskbar_nav_icon_light_color_on_home);
+ mDarkIconColorOnHome = context.getColor(R.color.taskbar_nav_icon_dark_color_on_home);
+ mOnBackgroundIconColor = Utilities.isDarkTheme(context)
+ ? context.getColor(R.color.taskbar_nav_icon_light_color)
+ : context.getColor(R.color.taskbar_nav_icon_dark_color);
}
/**
@@ -215,15 +219,21 @@
*/
public void init(TaskbarControllers controllers) {
mControllers = controllers;
+ setupController();
+ }
+
+ protected void setupController() {
boolean isThreeButtonNav = mContext.isThreeButtonNav();
DeviceProfile deviceProfile = mContext.getDeviceProfile();
Resources resources = mContext.getResources();
Point p = !mContext.isUserSetupComplete()
- ? new Point(0, controllers.taskbarActivityContext.getSetupWindowHeight())
+ ? new Point(0, mControllers.taskbarActivityContext.getSetupWindowHeight())
: DimensionUtils.getTaskbarPhoneDimensions(deviceProfile, resources,
TaskbarManager.isPhoneMode(deviceProfile));
mNavButtonsView.getLayoutParams().height = p.y;
+ mDisplayController = DisplayController.INSTANCE.get(mContext);
+
mIsImeRenderingNavButtons =
InputMethodService.canImeRenderGesturalNavButtons() && mContext.imeDrawsImeNavBar();
if (!mIsImeRenderingNavButtons) {
@@ -630,18 +640,20 @@
private void updateNavButtonColor() {
final ArgbEvaluator argbEvaluator = ArgbEvaluator.getInstance();
- final int sysUiNavButtonIconColor = (int) argbEvaluator.evaluate(
+ final int sysUiNavButtonIconColorOnHome = (int) argbEvaluator.evaluate(
mTaskbarNavButtonDarkIntensity.value,
- mLightIconColor,
- mDarkIconColor);
+ mLightIconColorOnHome,
+ mDarkIconColorOnHome);
+
// Override the color from framework if nav buttons are over an opaque Taskbar surface.
final int iconColor = (int) argbEvaluator.evaluate(
mOnBackgroundNavButtonColorOverrideMultiplier.value
* Math.max(
mOnTaskbarBackgroundNavButtonColorOverride.value,
mSlideInViewVisibleNavButtonColorOverride.value),
- sysUiNavButtonIconColor,
+ sysUiNavButtonIconColorOnHome,
mOnBackgroundIconColor);
+
for (ImageView button : mAllButtons) {
button.setImageTintList(ColorStateList.valueOf(iconColor));
}
@@ -723,15 +735,12 @@
boolean isInKidsMode = mContext.isNavBarKidsModeActive();
if (TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW) {
- if (!isThreeButtonNav) {
- return;
- }
-
NavButtonLayoutter navButtonLayoutter =
NavButtonLayoutFactory.Companion.getUiLayoutter(
dp, mNavButtonsView, res, isInKidsMode, isInSetup, isThreeButtonNav,
- TaskbarManager.isPhoneMode(dp));
+ TaskbarManager.isPhoneMode(dp), mDisplayController.getInfo().rotation);
navButtonLayoutter.layoutButtons(dp, isContextualButtonShowing());
+ updateNavButtonColor();
return;
}
@@ -937,8 +946,6 @@
pw.println(prefix + "NavbarButtonsViewController:");
pw.println(prefix + "\tmState=" + getStateString(mState));
- pw.println(prefix + "\tmLightIconColor=" + Integer.toHexString(mLightIconColor));
- pw.println(prefix + "\tmDarkIconColor=" + Integer.toHexString(mDarkIconColor));
pw.println(prefix + "\tmFloatingRotationButtonBounds=" + mFloatingRotationButtonBounds);
pw.println(prefix + "\tmSysuiStateFlags=" + QuickStepContract.getSystemUiStateString(
mSysuiStateFlags));
@@ -949,6 +956,14 @@
+ mTaskbarNavButtonTranslationYForInAppDisplay.value);
pw.println(prefix + "\t\tmTaskbarNavButtonTranslationYForIme="
+ mTaskbarNavButtonTranslationYForIme.value);
+ pw.println(prefix + "\t\tmTaskbarNavButtonDarkIntensity="
+ + mTaskbarNavButtonDarkIntensity.value);
+ pw.println(prefix + "\t\tmSlideInViewVisibleNavButtonColorOverride="
+ + mSlideInViewVisibleNavButtonColorOverride.value);
+ pw.println(prefix + "\t\tmOnTaskbarBackgroundNavButtonColorOverride="
+ + mOnTaskbarBackgroundNavButtonColorOverride.value);
+ pw.println(prefix + "\t\tmOnBackgroundNavButtonColorOverrideMultiplier="
+ + mOnBackgroundNavButtonColorOverrideMultiplier.value);
}
private static String getStateString(int flags) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index a1390ae..0aa02f2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -27,11 +27,13 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
import static com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_OVERLAY_PROXY;
import static com.android.launcher3.Utilities.isRunningInTestHarness;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NO_RECREATION;
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;
import static com.android.launcher3.taskbar.TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW;
import static com.android.launcher3.testing.shared.ResourceUtils.getBoolByName;
+import static com.android.launcher3.util.VibratorWrapper.EFFECT_CLICK;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING;
@@ -49,14 +51,15 @@
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.os.Process;
-import android.os.SystemProperties;
import android.os.Trace;
import android.provider.Settings;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.RoundedCorner;
+import android.view.Surface;
import android.view.View;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.Toast;
@@ -90,6 +93,8 @@
import com.android.launcher3.taskbar.bubbles.BubbleBarView;
import com.android.launcher3.taskbar.bubbles.BubbleBarViewController;
import com.android.launcher3.taskbar.bubbles.BubbleControllers;
+import com.android.launcher3.taskbar.bubbles.BubbleDismissController;
+import com.android.launcher3.taskbar.bubbles.BubbleDragController;
import com.android.launcher3.taskbar.bubbles.BubbleStashController;
import com.android.launcher3.taskbar.bubbles.BubbleStashedHandleViewController;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
@@ -106,6 +111,7 @@
import com.android.launcher3.util.SettingsCache;
import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
import com.android.launcher3.util.TraceHelper;
+import com.android.launcher3.util.VibratorWrapper;
import com.android.launcher3.util.ViewCache;
import com.android.launcher3.views.ActivityContext;
import com.android.quickstep.views.RecentsView;
@@ -117,6 +123,7 @@
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
import java.io.PrintWriter;
+import java.util.Collections;
import java.util.Optional;
/**
@@ -128,8 +135,6 @@
private static final String IME_DRAWS_IME_NAV_BAR_RES_NAME = "config_imeDrawsImeNavBar";
- private static final boolean ENABLE_THREE_BUTTON_TASKBAR =
- SystemProperties.getBoolean("persist.debug.taskbar_three_button", false);
private static final String TAG = "TaskbarActivityContext";
private static final String WINDOW_TITLE = "Taskbar";
@@ -146,7 +151,7 @@
private int mLastRequestedNonFullscreenHeight;
private NavigationMode mNavMode;
- private final boolean mImeDrawsImeNavBar;
+ private boolean mImeDrawsImeNavBar;
private final ViewCache mViewCache = new ViewCache();
private final boolean mIsSafeModeEnabled;
@@ -169,30 +174,27 @@
TaskbarNavButtonController buttonController, ScopedUnfoldTransitionProgressProvider
unfoldTransitionProgressProvider) {
super(windowContext);
+
+ applyDeviceProfile(launcherDp);
+
final Resources resources = getResources();
- matchDeviceProfile(launcherDp, getResources());
-
- mNavMode = DisplayController.getNavigationMode(windowContext);
mImeDrawsImeNavBar = getBoolByName(IME_DRAWS_IME_NAV_BAR_RES_NAME, resources, false);
mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode",
() -> getPackageManager().isSafeMode());
+
+ // TODO(b/244231596) For shared Taskbar window, update this value in applyDeviceProfile()
+ // instead so to get correct value when recreating the taskbar
SettingsCache settingsCache = SettingsCache.INSTANCE.get(this);
mIsUserSetupComplete = settingsCache.getValue(
Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 0);
- mIsNavBarForceVisible = settingsCache.getValue(
- Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_KIDS_MODE), 0);
-
- // TODO(b/244231596) For shared Taskbar window, update this value in init() instead so
- // to get correct value when recreating the taskbar
mIsNavBarKidsMode = settingsCache.getValue(
Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_KIDS_MODE), 0);
+ mIsNavBarForceVisible = mIsNavBarKidsMode;
// Get display and corners first, as views might use them in constructor.
Display display = windowContext.getDisplay();
- Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY
- ? windowContext.getApplicationContext()
- : windowContext.getApplicationContext().createDisplayContext(display);
+ Context c = getApplicationContext();
mWindowManager = c.getSystemService(WindowManager.class);
mLeftCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
mRightCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
@@ -216,29 +218,34 @@
// If Bubble bar is present, TaskbarControllers depends on it so build it first.
Optional<BubbleControllers> bubbleControllersOptional = Optional.empty();
- if (BubbleBarController.BUBBLE_BAR_ENABLED) {
+ if (BubbleBarController.BUBBLE_BAR_ENABLED && bubbleBarView != null) {
bubbleControllersOptional = Optional.of(new BubbleControllers(
new BubbleBarController(this, bubbleBarView),
new BubbleBarViewController(this, bubbleBarView),
new BubbleStashController(this),
- new BubbleStashedHandleViewController(this, bubbleHandleView)));
+ new BubbleStashedHandleViewController(this, bubbleHandleView),
+ new BubbleDragController(this),
+ new BubbleDismissController(this, mDragLayer)));
}
// Construct controllers.
+ RotationButtonController rotationButtonController = new RotationButtonController(this,
+ c.getColor(R.color.floating_rotation_button_light_color),
+ c.getColor(R.color.floating_rotation_button_dark_color),
+ R.drawable.ic_sysbar_rotate_button_ccw_start_0,
+ R.drawable.ic_sysbar_rotate_button_ccw_start_90,
+ R.drawable.ic_sysbar_rotate_button_cw_start_0,
+ R.drawable.ic_sysbar_rotate_button_cw_start_90,
+ () -> getDisplay().getRotation());
+ rotationButtonController.setBgExecutor(Executors.THREAD_POOL_EXECUTOR);
+
mControllers = new TaskbarControllers(this,
new TaskbarDragController(this),
buttonController,
isDesktopMode
? new DesktopNavbarButtonsViewController(this, navButtonsView)
: new NavbarButtonsViewController(this, navButtonsView),
- new RotationButtonController(this,
- c.getColor(R.color.floating_rotation_button_light_color),
- c.getColor(R.color.floating_rotation_button_dark_color),
- R.drawable.ic_sysbar_rotate_button_ccw_start_0,
- R.drawable.ic_sysbar_rotate_button_ccw_start_90,
- R.drawable.ic_sysbar_rotate_button_cw_start_0,
- R.drawable.ic_sysbar_rotate_button_cw_start_90,
- () -> getDisplay().getRotation()),
+ rotationButtonController,
new TaskbarDragLayerController(this, mDragLayer),
new TaskbarViewController(this, taskbarView),
new TaskbarScrimViewController(this, taskbarScrimView),
@@ -267,13 +274,53 @@
bubbleControllersOptional);
}
+ /** Updates {@link DeviceProfile} instances for any Taskbar windows. */
+ public void updateDeviceProfile(DeviceProfile launcherDp) {
+ applyDeviceProfile(launcherDp);
+
+ mControllers.taskbarOverlayController.updateLauncherDeviceProfile(launcherDp);
+ AbstractFloatingView.closeAllOpenViewsExcept(this, false, TYPE_REBIND_SAFE);
+ // Reapply fullscreen to take potential new screen size into account.
+ setTaskbarWindowFullscreen(mIsFullscreen);
+
+ dispatchDeviceProfileChanged();
+ }
+
+ /**
+ * Copy the original DeviceProfile, match the number of hotseat icons and qsb width and update
+ * the icon size
+ */
+ private void applyDeviceProfile(DeviceProfile originDeviceProfile) {
+ mDeviceProfile = originDeviceProfile.toBuilder(this)
+ .withDimensionsOverride(deviceProfile -> {
+ // Taskbar should match the number of icons of hotseat
+ deviceProfile.numShownHotseatIcons = originDeviceProfile.numShownHotseatIcons;
+ // Same QSB width to have a smooth animation
+ deviceProfile.hotseatQsbWidth = originDeviceProfile.hotseatQsbWidth;
+
+ // Update icon size
+ deviceProfile.iconSizePx = deviceProfile.taskbarIconSize;
+ deviceProfile.updateIconSize(1f, getResources());
+ }).build();
+ mNavMode = DisplayController.getNavigationMode(this);
+ }
+
+ /** Called when the visibility of the bubble bar changed. */
+ public void bubbleBarVisibilityChanged(boolean isVisible) {
+ mControllers.uiController.adjustHotseatForBubbleBar(isVisible);
+ mControllers.taskbarViewController.resetIconAlignmentController();
+ }
+
public void init(@NonNull TaskbarSharedState sharedState) {
+ mImeDrawsImeNavBar = getBoolByName(IME_DRAWS_IME_NAV_BAR_RES_NAME, getResources(), false);
mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight();
- mWindowLayoutParams =
- createDefaultWindowLayoutParams(TYPE_NAVIGATION_BAR_PANEL, WINDOW_TITLE);
+ mWindowLayoutParams = createAllWindowParams();
// Initialize controllers after all are constructed.
mControllers.init(sharedState);
+ // This may not be necessary and can be reverted once we move towards recreating all
+ // controllers without re-creating the window
+ mControllers.rotationButtonController.onNavigationModeChanged(mNavMode.resValue);
updateSysuiStateFlags(sharedState.sysuiStateFlags, true /* fromInit */);
disableNavBarElements(sharedState.disableNavBarDisplayId, sharedState.disableNavBarState1,
sharedState.disableNavBarState2, false /* animate */);
@@ -288,11 +335,11 @@
mIsDestroyed = false;
}
- if (!mAddedWindow) {
+ if (!ENABLE_TASKBAR_NO_RECREATION.get() && !mAddedWindow) {
mWindowManager.addView(mDragLayer, mWindowLayoutParams);
mAddedWindow = true;
} else {
- mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
+ notifyUpdateLayoutParams();
}
}
@@ -303,24 +350,21 @@
mControllers.taskbarStashController.showTaskbarFromBroadcast();
}
+ /** Toggles Taskbar All Apps overlay. */
+ public void toggleAllApps() {
+ mControllers.taskbarAllAppsController.toggle();
+ }
+
+ /** Toggles Taskbar All Apps overlay with keyboard ready for search. */
+ public void toggleAllAppsSearch() {
+ mControllers.taskbarAllAppsController.toggleSearch();
+ }
+
@Override
public DeviceProfile getDeviceProfile() {
return mDeviceProfile;
}
- /** Updates {@link DeviceProfile} instances for any Taskbar windows. */
- public void updateDeviceProfile(DeviceProfile launcherDp, NavigationMode navMode) {
- mNavMode = navMode;
- mControllers.taskbarOverlayController.updateLauncherDeviceProfile(launcherDp);
- matchDeviceProfile(launcherDp, getResources());
-
- AbstractFloatingView.closeAllOpenViewsExcept(this, false, TYPE_REBIND_SAFE);
- // Reapply fullscreen to take potential new screen size into account.
- setTaskbarWindowFullscreen(mIsFullscreen);
-
- dispatchDeviceProfileChanged();
- }
-
@Override
public void dispatchDeviceProfileChanged() {
super.dispatchDeviceProfileChanged();
@@ -329,24 +373,6 @@
}
/**
- * Copy the original DeviceProfile, match the number of hotseat icons and qsb width and update
- * the icon size
- */
- private void matchDeviceProfile(DeviceProfile originDeviceProfile, Resources resources) {
- mDeviceProfile = originDeviceProfile.toBuilder(this)
- .withDimensionsOverride(deviceProfile -> {
- // Taskbar should match the number of icons of hotseat
- deviceProfile.numShownHotseatIcons = originDeviceProfile.numShownHotseatIcons;
- // Same QSB width to have a smooth animation
- deviceProfile.hotseatQsbWidth = originDeviceProfile.hotseatQsbWidth;
-
- // Update icon size
- deviceProfile.iconSizePx = deviceProfile.taskbarIconSize;
- deviceProfile.updateIconSize(1f, resources);
- }).build();
- }
-
- /**
* Returns the View bounds of transient taskbar.
*/
public Rect getTransientTaskbarBounds() {
@@ -365,11 +391,6 @@
* @param title The window title to pass to the created WindowManager.LayoutParams.
*/
public WindowManager.LayoutParams createDefaultWindowLayoutParams(int type, String title) {
- DeviceProfile deviceProfile = getDeviceProfile();
- // Taskbar is on the logical bottom of the screen
- boolean isVerticalBarLayout = TaskbarManager.isPhoneButtonNavMode(this) &&
- deviceProfile.isLandscape;
-
int windowFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SLIPPERY
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
@@ -378,17 +399,14 @@
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
}
WindowManager.LayoutParams windowLayoutParams = new WindowManager.LayoutParams(
- isVerticalBarLayout ? mLastRequestedNonFullscreenHeight : MATCH_PARENT,
- isVerticalBarLayout ? MATCH_PARENT : mLastRequestedNonFullscreenHeight,
+ MATCH_PARENT,
+ mLastRequestedNonFullscreenHeight,
type,
windowFlags,
PixelFormat.TRANSLUCENT);
windowLayoutParams.setTitle(title);
windowLayoutParams.packageName = getPackageName();
- windowLayoutParams.gravity = !isVerticalBarLayout ?
- Gravity.BOTTOM :
- Gravity.END; // TODO(b/230394142): seascape
-
+ windowLayoutParams.gravity = Gravity.BOTTOM;
windowLayoutParams.setFitInsetsTypes(0);
windowLayoutParams.receiveInsetsIgnoringZOrder = true;
windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
@@ -399,6 +417,64 @@
TaskbarManager.isPhoneMode(mDeviceProfile)
? R.string.taskbar_phone_a11y_title
: R.string.taskbar_a11y_title);
+
+ return windowLayoutParams;
+ }
+
+ /**
+ * Creates {@link WindowManager.LayoutParams} for Taskbar, and also sets LP.paramsForRotation
+ * for taskbar showing as navigation bar
+ */
+ private WindowManager.LayoutParams createAllWindowParams() {
+ WindowManager.LayoutParams windowLayoutParams =
+ createDefaultWindowLayoutParams(TYPE_NAVIGATION_BAR_PANEL,
+ TaskbarActivityContext.WINDOW_TITLE);
+ boolean isPhoneNavMode = TaskbarManager.isPhoneButtonNavMode(this);
+ if (!isPhoneNavMode) {
+ return windowLayoutParams;
+ }
+
+ // Provide WM layout params for all rotations to cache, see NavigationBar#getBarLayoutParams
+ int width = WindowManager.LayoutParams.MATCH_PARENT;
+ int height = WindowManager.LayoutParams.MATCH_PARENT;
+ int gravity = Gravity.BOTTOM;
+ windowLayoutParams.paramsForRotation = new WindowManager.LayoutParams[4];
+ for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
+ WindowManager.LayoutParams lp =
+ createDefaultWindowLayoutParams(TYPE_NAVIGATION_BAR_PANEL,
+ TaskbarActivityContext.WINDOW_TITLE);
+ switch (rot) {
+ case Surface.ROTATION_0, Surface.ROTATION_180 -> {
+ // Defaults are fine
+ width = WindowManager.LayoutParams.MATCH_PARENT;
+ height = mLastRequestedNonFullscreenHeight;
+ gravity = Gravity.BOTTOM;
+ }
+ case Surface.ROTATION_90 -> {
+ width = mLastRequestedNonFullscreenHeight;
+ height = WindowManager.LayoutParams.MATCH_PARENT;
+ gravity = Gravity.END;
+ }
+ case Surface.ROTATION_270 -> {
+ width = mLastRequestedNonFullscreenHeight;
+ height = WindowManager.LayoutParams.MATCH_PARENT;
+ gravity = Gravity.START;
+ }
+
+ }
+ lp.width = width;
+ lp.height = height;
+ lp.gravity = gravity;
+ windowLayoutParams.paramsForRotation[rot] = lp;
+ }
+
+ // Override current layout params
+ WindowManager.LayoutParams currentParams =
+ windowLayoutParams.paramsForRotation[getDisplay().getRotation()];
+ windowLayoutParams.width = currentParams.width;
+ windowLayoutParams.height = currentParams.height;
+ windowLayoutParams.gravity = currentParams.gravity;
+
return windowLayoutParams;
}
@@ -448,6 +524,11 @@
return mControllers.taskbarDragController;
}
+ @Nullable
+ public BubbleControllers getBubbleControllers() {
+ return mControllers.bubbleControllers.orElse(null);
+ }
+
@Override
public ViewCache getViewCache() {
return mViewCache;
@@ -579,6 +660,8 @@
Executors.MAIN_EXECUTOR.getHandler(), null,
elapsedRealTime -> callbacks.executeAllAndDestroy());
options.setSplashScreenStyle(splashScreenStyle);
+ options.setPendingIntentBackgroundActivityStartMode(
+ ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
return new ActivityOptionsWrapper(options, callbacks);
}
@@ -608,7 +691,7 @@
mIsDestroyed = true;
setUIController(TaskbarUIController.DEFAULT);
mControllers.onDestroy();
- if (!FLAG_HIDE_NAVBAR_WINDOW) {
+ if (!ENABLE_TASKBAR_NO_RECREATION.get() && !FLAG_HIDE_NAVBAR_WINDOW) {
mWindowManager.removeViewImmediate(mDragLayer);
mAddedWindow = false;
}
@@ -638,8 +721,12 @@
mControllers.taskbarForceVisibleImmersiveController.updateSysuiFlags(systemUiStateFlags);
mControllers.voiceInteractionWindowController.setIsVoiceInteractionWindowVisible(
(systemUiStateFlags & SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING) != 0, fromInit);
-
mControllers.uiController.updateStateForSysuiFlags(systemUiStateFlags);
+ mControllers.bubbleControllers.ifPresent(controllers -> {
+ controllers.bubbleBarController.updateStateForSysuiFlags(systemUiStateFlags);
+ controllers.bubbleStashedHandleViewController.setIsHomeButtonDisabled(
+ mControllers.navbarButtonsViewController.isHomeDisabled());
+ });
}
/**
@@ -735,8 +822,8 @@
}
}
mWindowLayoutParams.height = height;
- mControllers.taskbarInsetsController.onTaskbarWindowHeightOrInsetsChanged();
- mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
+ mControllers.taskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
+ notifyUpdateLayoutParams();
}
/**
@@ -779,7 +866,22 @@
} else {
mWindowLayoutParams.flags |= FLAG_NOT_FOCUSABLE;
}
- mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
+ notifyUpdateLayoutParams();
+ }
+
+ /**
+ * Applies forcibly show flag to taskbar window iff transient taskbar is unstashed.
+ */
+ public void applyForciblyShownFlagWhileTransientTaskbarUnstashed(boolean shouldForceShow) {
+ if (!DisplayController.isTransientTaskbar(this)) {
+ return;
+ }
+ if (shouldForceShow) {
+ mWindowLayoutParams.forciblyShownTypes |= WindowInsets.Type.navigationBars();
+ } else {
+ mWindowLayoutParams.forciblyShownTypes &= ~WindowInsets.Type.navigationBars();
+ }
+ notifyUpdateLayoutParams();
}
/**
@@ -888,8 +990,8 @@
}
} catch (NullPointerException
- | ActivityNotFoundException
- | SecurityException e) {
+ | 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);
@@ -936,9 +1038,10 @@
if (recents == null) {
return;
}
- recents.getSplitSelectController().findLastActiveTaskAndRunCallback(
- info.getComponentKey(),
- foundTask -> {
+ recents.getSplitSelectController().findLastActiveTasksAndRunCallback(
+ Collections.singletonList(info.getComponentKey()),
+ foundTasks -> {
+ @Nullable Task foundTask = foundTasks.get(0);
if (foundTask != null) {
TaskView foundTaskView =
recents.getTaskViewByTaskId(foundTask.key.id);
@@ -982,6 +1085,7 @@
/**
* Called when we detect a long press in the nav region before passing the gesture slop.
+ *
* @return Whether taskbar handled the long press, and thus should cancel the gesture.
*/
public boolean onLongPressToUnstashTaskbar() {
@@ -992,10 +1096,20 @@
* Called when we want to unstash taskbar when user performs swipes up gesture.
*/
public void onSwipeToUnstashTaskbar() {
- mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(false);
+ VibratorWrapper.INSTANCE.get(this).vibrate(EFFECT_CLICK);
+ mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(/* stash= */ false);
mControllers.taskbarEduTooltipController.hide();
}
+ /**
+ * Called when we want to open bubblebar when user performs swipes up gesture.
+ */
+ public void onSwipeToOpenBubblebar() {
+ mControllers.bubbleControllers.ifPresent(controllers -> {
+ controllers.bubbleStashController.showBubbleBar(/* expandBubbles= */ true);
+ });
+ }
+
/** Returns {@code true} if Taskbar All Apps is open. */
public boolean isTaskbarAllAppsOpen() {
return mControllers.taskbarAllAppsController.isOpen();
@@ -1041,7 +1155,7 @@
* Called when we detect a motion down or up/cancel in the nav region while stashed.
*
* @param animateForward Whether to animate towards the unstashed hint state or back to stashed.
- * @param forceUnstash Whether we force the unstash hint.
+ * @param forceUnstash Whether we force the unstash hint.
*/
public void startTaskbarUnstashHint(boolean animateForward, boolean forceUnstash) {
// TODO(b/270395798): Clean up forceUnstash after removing long-press unstashing code.
@@ -1149,12 +1263,16 @@
mWindowLayoutParams.privateFlags &=
~WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION;
}
- mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
+ notifyUpdateLayoutParams();
}
void notifyUpdateLayoutParams() {
if (mDragLayer.isAttachedToWindow()) {
- mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
+ if (ENABLE_TASKBAR_NO_RECREATION.get()) {
+ mWindowManager.updateViewLayout(mDragLayer.getRootView(), mWindowLayoutParams);
+ } else {
+ mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
+ }
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
index 70999e7..8ab2ffa 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
@@ -45,6 +45,8 @@
public static final int FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER = 1 << 4;
// Transient Taskbar is temporarily unstashed (pending a timeout).
public static final int FLAG_AUTOHIDE_SUSPEND_TRANSIENT_TASKBAR = 1 << 5;
+ // User has hovered the taskbar.
+ public static final int FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS = 1 << 6;
@IntDef(flag = true, value = {
FLAG_AUTOHIDE_SUSPEND_FULLSCREEN,
@@ -53,6 +55,7 @@
FLAG_AUTOHIDE_SUSPEND_EDU_OPEN,
FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER,
FLAG_AUTOHIDE_SUSPEND_TRANSIENT_TASKBAR,
+ FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface AutohideSuspendFlag {}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
index ca2d1f8..d237c1f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -22,12 +22,12 @@
import android.graphics.Paint
import android.graphics.Path
import android.graphics.RectF
+import com.android.app.animation.Interpolators
import com.android.launcher3.DeviceProfile
import com.android.launcher3.R
import com.android.launcher3.Utilities
import com.android.launcher3.Utilities.mapRange
import com.android.launcher3.Utilities.mapToRange
-import com.android.launcher3.anim.Interpolators
import com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound
import com.android.launcher3.util.DisplayController
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index d3f80e3..d82f501 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -239,6 +239,7 @@
taskbarPopupController.onDestroy();
taskbarForceVisibleImmersiveController.onDestroy();
taskbarOverlayController.onDestroy();
+ taskbarAllAppsController.onDestroy();
navButtonController.onDestroy();
taskbarInsetsController.onDestroy();
voiceInteractionWindowController.onDestroy();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupController.kt
index 83a3343..a2c61ce 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupController.kt
@@ -18,6 +18,10 @@
import android.view.View
import com.android.launcher3.LauncherPrefs
import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING
+import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_DIVIDER_MENU_CLOSE
+import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_DIVIDER_MENU_OPEN
+import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_PINNED
+import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_UNPINNED
import com.android.launcher3.taskbar.TaskbarDividerPopupView.Companion.createAndPopulate
import java.io.PrintWriter
@@ -27,6 +31,7 @@
private lateinit var controllers: TaskbarControllers
private val launcherPrefs = LauncherPrefs.get(context)
+ private val statsLogManager = context.statsLogManager
fun init(taskbarControllers: TaskbarControllers) {
controllers = taskbarControllers
@@ -41,6 +46,7 @@
popupView.onCloseCallback =
callback@{ didPreferenceChange ->
+ statsLogManager.logger().log(LAUNCHER_TASKBAR_DIVIDER_MENU_CLOSE)
context.dragLayer.post { context.onPopupVisibilityChanged(false) }
if (!didPreferenceChange) {
@@ -49,8 +55,10 @@
if (launcherPrefs.get(TASKBAR_PINNING)) {
animateTransientToPersistentTaskbar()
+ statsLogManager.logger().log(LAUNCHER_TASKBAR_PINNED)
} else {
animatePersistentToTransientTaskbar()
+ statsLogManager.logger().log(LAUNCHER_TASKBAR_UNPINNED)
}
}
popupView.changePreference = {
@@ -58,6 +66,7 @@
}
context.onPopupVisibilityChanged(true)
popupView.show()
+ statsLogManager.logger().log(LAUNCHER_TASKBAR_DIVIDER_MENU_OPEN)
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
index a347908..b200858 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt
@@ -17,7 +17,6 @@
import android.annotation.SuppressLint
import android.content.Context
-import android.content.Intent
import android.graphics.Rect
import android.graphics.drawable.GradientDrawable
import android.util.AttributeSet
@@ -44,9 +43,6 @@
companion object {
private const val TAG = "TaskbarDividerPopupView"
private const val DIVIDER_POPUP_CLOSING_DELAY = 500L
- private const val SETTINGS_PACKAGE_NAME = "com.android.settings"
- private const val CHANGE_NAVIGATION_MODE_ACTION =
- "com.android.settings.NAVIGATION_MODE_SETTINGS"
@JvmStatic
fun createAndPopulate(
@@ -63,6 +59,7 @@
return taskMenuViewWithArrow.populateForView(view)
}
}
+
private lateinit var dividerView: View
private val menuWidth =
@@ -101,23 +98,14 @@
@SuppressLint("UseSwitchCompatOrMaterialCode")
override fun onFinishInflate() {
super.onFinishInflate()
- val taskbarSwitchOption = findViewById<LinearLayout>(R.id.taskbar_switch_option)
- val alwaysShowTaskbarSwitch = findViewById<Switch>(R.id.taskbar_pinning_switch)
- val navigationModeChangeOption =
- findViewById<LinearLayout>(R.id.navigation_mode_switch_option)
+ val taskbarSwitchOption = requireViewById<LinearLayout>(R.id.taskbar_switch_option)
+ val alwaysShowTaskbarSwitch = requireViewById<Switch>(R.id.taskbar_pinning_switch)
alwaysShowTaskbarSwitch.isChecked = alwaysShowTaskbarOn
taskbarSwitchOption.setOnClickListener {
alwaysShowTaskbarSwitch.isClickable = true
alwaysShowTaskbarSwitch.isChecked = !alwaysShowTaskbarOn
onClickAlwaysShowTaskbarSwitchOption()
}
- navigationModeChangeOption.setOnClickListener {
- context.startActivity(
- Intent(CHANGE_NAVIGATION_MODE_ACTION)
- .setPackage(SETTINGS_PACKAGE_NAME)
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- )
- }
}
/** Orient object as usual and then center object horizontally. */
@@ -191,13 +179,19 @@
override fun closeComplete() {
onCloseCallback(didPreferenceChange)
+ onCloseCallback = {}
super.closeComplete()
}
private fun onClickAlwaysShowTaskbarSwitchOption() {
didPreferenceChange = true
changePreference()
+ changePreference = {}
// Allow switch animation to finish and then close the popup.
- postDelayed(DIVIDER_POPUP_CLOSING_DELAY) { close(true) }
+ postDelayed(DIVIDER_POPUP_CLOSING_DELAY) {
+ if (isOpen) {
+ close(false)
+ }
+ }
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 040b8f7..4ad5c88 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -15,16 +15,18 @@
*/
package com.android.launcher3.taskbar;
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
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;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SEARCH_ACTION;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
+import android.app.PendingIntent;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.Intent;
@@ -47,6 +49,7 @@
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.internal.logging.InstanceId;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BubbleTextView;
@@ -55,7 +58,6 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragDriver;
import com.android.launcher3.dragndrop.DragOptions;
@@ -73,6 +75,7 @@
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.ItemInfoMatcher;
+import com.android.launcher3.views.BubbleTextHolder;
import com.android.quickstep.util.LogUtils;
import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.systemui.shared.recents.model.Task;
@@ -149,6 +152,9 @@
View view,
@Nullable DragPreviewProvider dragPreviewProvider,
@Nullable Point iconShift) {
+ if (view instanceof BubbleTextHolder) {
+ view = ((BubbleTextHolder) view).getBubbleText();
+ }
if (!(view instanceof BubbleTextView) || mDisallowLongClick) {
return false;
}
@@ -193,13 +199,21 @@
dragLayerY += dragRect.top;
DragOptions dragOptions = new DragOptions();
- dragOptions.preDragCondition = null;
- PopupContainerWithArrow<BaseTaskbarContext> popupContainer =
- mControllers.taskbarPopupController.showForIcon(btv);
- if (popupContainer != null) {
- dragOptions.preDragCondition = popupContainer.createPreDragCondition(false);
- }
+ // First, see if view is a search result that needs custom pre-drag conditions.
+ dragOptions.preDragCondition =
+ mControllers.taskbarAllAppsController.createPreDragConditionForSearch(btv);
+
if (dragOptions.preDragCondition == null) {
+ // See if view supports a popup container.
+ PopupContainerWithArrow<BaseTaskbarContext> popupContainer =
+ mControllers.taskbarPopupController.showForIcon(btv);
+ if (popupContainer != null) {
+ dragOptions.preDragCondition = popupContainer.createPreDragCondition(false);
+ }
+ }
+
+ if (dragOptions.preDragCondition == null) {
+ // Fallback pre-drag condition.
dragOptions.preDragCondition = new DragOptions.PreDragCondition() {
private DragView mDragView;
@@ -213,13 +227,8 @@
mDragView = dragObject.dragView;
if (!shouldStartDrag(0)) {
- mDragView.setOnAnimationEndCallback(() -> {
- // Drag might be cancelled during the DragView animation, so check
- // mIsPreDrag again.
- if (mIsInPreDrag) {
- callOnDragStart();
- }
- });
+ mDragView.setOnScaleAnimEndCallback(
+ TaskbarDragController.this::onPreDragAnimationEnd);
}
}
@@ -230,12 +239,13 @@
};
}
+ Point dragOffset = dragOptions.preDragCondition.getDragOffset();
return startDrag(
drawable,
/* view = */ null,
/* originalView = */ btv,
- dragLayerX,
- dragLayerY,
+ dragLayerX + dragOffset.x,
+ dragLayerY + dragOffset.y,
(View target, DropTarget.DragObject d, boolean success) -> {} /* DragSource */,
(ItemInfo) btv.getTag(),
dragRect,
@@ -249,6 +259,8 @@
DraggableView originalView, int dragLayerX, int dragLayerY, DragSource source,
ItemInfo dragInfo, Rect dragRegion, float initialDragViewScale,
float dragViewScaleOnDrop, DragOptions options) {
+ mActivity.hideKeyboard();
+
mOptions = options;
mRegistrationX = mMotionDown.x - dragLayerX;
@@ -290,6 +302,11 @@
mDragObject.dragInfo = dragInfo;
mDragObject.originalDragInfo = mDragObject.dragInfo.makeShallowCopy();
+ if (mOptions.preDragCondition != null) {
+ dragView.setHasDragOffset(mOptions.preDragCondition.getDragOffset().x != 0
+ || mOptions.preDragCondition.getDragOffset().y != 0);
+ }
+
if (dragRegion != null) {
dragView.setDragRegion(new Rect(dragRegion));
}
@@ -308,6 +325,14 @@
return dragView;
}
+ /** Invoked when an animation running as part of pre-drag finishes. */
+ public void onPreDragAnimationEnd() {
+ // Drag might be cancelled during the DragView animation, so check mIsPreDrag again.
+ if (mIsInPreDrag) {
+ callOnDragStart();
+ }
+ }
+
@Override
protected void callOnDragStart() {
super.callOnDragStart();
@@ -383,6 +408,17 @@
item.user));
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, item.getIntent().getPackage());
intent.putExtra(Intent.EXTRA_SHORTCUT_ID, deepShortcutId);
+ } else if (item.itemType == ITEM_TYPE_SEARCH_ACTION) {
+ // TODO(b/289261756): Buggy behavior when split opposite to an existing search pane.
+ intent.putExtra(
+ ClipDescription.EXTRA_PENDING_INTENT,
+ PendingIntent.getActivityAsUser(
+ mActivity,
+ /* requestCode= */ 0,
+ item.getIntent(),
+ PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT,
+ /* options= */ null,
+ item.user));
} else {
intent.putExtra(ClipDescription.EXTRA_PENDING_INTENT,
launcherApps.getMainActivityLaunchIntent(item.getIntent().getComponent(),
@@ -642,7 +678,7 @@
final FloatProp mScale = new FloatProp(1f, toScale, 0,
ANIM_DURATION_RETURN_ICON_TO_TASKBAR, FAST_OUT_SLOW_IN);
final FloatProp mAlpha = new FloatProp(1f, toAlpha, 0,
- ANIM_DURATION_RETURN_ICON_TO_TASKBAR, Interpolators.ACCEL_2);
+ ANIM_DURATION_RETURN_ICON_TO_TASKBAR, Interpolators.ACCELERATE_2);
@Override
public void onUpdate(float percent, boolean initOnly) {
animListener.updateDragShadow(mDx.value, mDy.value, mScale.value, mAlpha.value);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index f6de926..e521154 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.RectF;
+import android.media.permission.SafeCloseable;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.view.KeyEvent;
@@ -31,6 +32,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.app.viewcapture.SettingsAwareViewCapture;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
@@ -68,6 +70,7 @@
// Initialized in init.
private TaskbarDragLayerController.TaskbarDragLayerCallbacks mControllerCallbacks;
+ private SafeCloseable mViewCaptureCloseable;
private float mTaskbarBackgroundOffset;
@@ -128,12 +131,14 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getViewTreeObserver().addOnComputeInternalInsetsListener(mTaskbarInsetsComputer);
+ mViewCaptureCloseable = SettingsAwareViewCapture.getInstance(getContext())
+ .startCapture(getRootView(), ".Taskbar");
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
-
+ mViewCaptureCloseable.close();
onDestroy(true);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltip.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltip.kt
index 9b50c5d..c45c667 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltip.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltip.kt
@@ -97,8 +97,8 @@
override fun onFinishInflate() {
super.onFinishInflate()
- content = findViewById(R.id.content)
- arrow = findViewById(R.id.arrow)
+ content = requireViewById(R.id.content)
+ arrow = requireViewById(R.id.arrow)
arrow.background =
RoundedArrowDrawable(
arrowWidth,
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
index e99fa50..de4175d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
@@ -93,7 +93,7 @@
tooltipStep = TOOLTIP_STEP_FEATURES
inflateTooltip(R.layout.taskbar_edu_swipe)
tooltip?.run {
- findViewById<LottieAnimationView>(R.id.swipe_animation).supportLightTheme()
+ requireViewById<LottieAnimationView>(R.id.swipe_animation).supportLightTheme()
show()
}
}
@@ -112,10 +112,10 @@
tooltipStep = TOOLTIP_STEP_NONE
inflateTooltip(R.layout.taskbar_edu_features)
tooltip?.run {
- val splitscreenAnim = findViewById<LottieAnimationView>(R.id.splitscreen_animation)
- val suggestionsAnim = findViewById<LottieAnimationView>(R.id.suggestions_animation)
- val settingsAnim = findViewById<LottieAnimationView>(R.id.settings_animation)
- val settingsEdu = findViewById<View>(R.id.settings_edu)
+ val splitscreenAnim = requireViewById<LottieAnimationView>(R.id.splitscreen_animation)
+ val suggestionsAnim = requireViewById<LottieAnimationView>(R.id.suggestions_animation)
+ val settingsAnim = requireViewById<LottieAnimationView>(R.id.settings_animation)
+ val settingsEdu = requireViewById<View>(R.id.settings_edu)
splitscreenAnim.supportLightTheme()
suggestionsAnim.supportLightTheme()
settingsAnim.supportLightTheme()
@@ -186,7 +186,7 @@
private fun createAccessibilityDelegate() =
object : View.AccessibilityDelegate() {
override fun performAccessibilityAction(
- host: View?,
+ host: View,
action: Int,
args: Bundle?
): Boolean {
@@ -197,22 +197,22 @@
return super.performAccessibilityAction(host, action, args)
}
- override fun onPopulateAccessibilityEvent(host: View?, event: AccessibilityEvent?) {
+ override fun onPopulateAccessibilityEvent(host: View, event: AccessibilityEvent) {
super.onPopulateAccessibilityEvent(host, event)
- if (event?.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
- event.text?.add(host?.context?.getText(R.string.taskbar_edu_a11y_title))
+ if (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+ event.text.add(host.context?.getText(R.string.taskbar_edu_a11y_title))
}
}
override fun onInitializeAccessibilityNodeInfo(
- host: View?,
- info: AccessibilityNodeInfo?
+ host: View,
+ info: AccessibilityNodeInfo
) {
super.onInitializeAccessibilityNodeInfo(host, info)
- info?.addAction(
+ info.addAction(
AccessibilityNodeInfo.AccessibilityAction(
R.id.close,
- host?.context?.getText(R.string.taskbar_edu_close)
+ host.context?.getText(R.string.taskbar_edu_close)
)
)
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarHoverToolTipController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarHoverToolTipController.java
new file mode 100644
index 0000000..2c72b2c
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarHoverToolTipController.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar;
+
+import static android.view.MotionEvent.ACTION_HOVER_ENTER;
+import static android.view.MotionEvent.ACTION_HOVER_EXIT;
+import static android.view.View.ALPHA;
+import static android.view.View.SCALE_Y;
+import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_TEXT;
+
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.launcher3.AbstractFloatingView.TYPE_ALL_EXCEPT_ON_BOARD_POPUP;
+import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS;
+import static com.android.launcher3.views.ArrowTipView.TEXT_ALPHA;
+
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.ContextThemeWrapper;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.app.animation.Interpolators;
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.compat.AccessibilityManagerCompat;
+import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.views.ArrowTipView;
+
+/**
+ * Controls showing a tooltip in the taskbar above each icon when it is hovered.
+ */
+public class TaskbarHoverToolTipController implements View.OnHoverListener {
+
+ private static final int HOVER_TOOL_TIP_REVEAL_DURATION = 250;
+ private static final int HOVER_TOOL_TIP_EXIT_DURATION = 150;
+
+ private final Handler mHoverToolTipHandler = new Handler(Looper.getMainLooper());
+ private final Runnable mRevealHoverToolTipRunnable = this::revealHoverToolTip;
+ private final Runnable mHideHoverToolTipRunnable = this::hideHoverToolTip;
+
+ private final TaskbarActivityContext mActivity;
+ private final TaskbarView mTaskbarView;
+ private final View mHoverView;
+ private final ArrowTipView mHoverToolTipView;
+ private final String mToolTipText;
+
+ public TaskbarHoverToolTipController(TaskbarActivityContext activity, TaskbarView taskbarView,
+ View hoverView) {
+ mActivity = activity;
+ mTaskbarView = taskbarView;
+ mHoverView = hoverView;
+
+ if (mHoverView instanceof BubbleTextView) {
+ mToolTipText = ((BubbleTextView) mHoverView).getText().toString();
+ } else if (mHoverView instanceof FolderIcon
+ && ((FolderIcon) mHoverView).mInfo.title != null) {
+ mToolTipText = ((FolderIcon) mHoverView).mInfo.title.toString();
+ } else {
+ mToolTipText = null;
+ }
+
+ ContextThemeWrapper arrowContextWrapper = new ContextThemeWrapper(mActivity,
+ R.style.ArrowTipTaskbarStyle);
+ mHoverToolTipView = new ArrowTipView(arrowContextWrapper, /* isPointingUp = */ false,
+ R.layout.arrow_toast);
+ int verticalPadding = arrowContextWrapper.getResources().getDimensionPixelSize(
+ R.dimen.taskbar_tooltip_vertical_padding);
+ int horizontalPadding = arrowContextWrapper.getResources().getDimensionPixelSize(
+ R.dimen.taskbar_tooltip_horizontal_padding);
+ mHoverToolTipView.findViewById(R.id.text).setPadding(horizontalPadding, verticalPadding,
+ horizontalPadding, verticalPadding);
+
+ AnimatorSet hoverCloseAnimator = new AnimatorSet();
+ ObjectAnimator textCloseAnimator = ObjectAnimator.ofInt(mHoverToolTipView, TEXT_ALPHA, 0);
+ textCloseAnimator.setInterpolator(Interpolators.clampToProgress(LINEAR, 0, 0.33f));
+ ObjectAnimator alphaCloseAnimator = ObjectAnimator.ofFloat(mHoverToolTipView, ALPHA, 0);
+ alphaCloseAnimator.setInterpolator(Interpolators.clampToProgress(LINEAR, 0.33f, 0.66f));
+ ObjectAnimator scaleCloseAnimator = ObjectAnimator.ofFloat(mHoverToolTipView, SCALE_Y, 0);
+ scaleCloseAnimator.setInterpolator(Interpolators.STANDARD);
+ hoverCloseAnimator.playTogether(
+ textCloseAnimator,
+ alphaCloseAnimator,
+ scaleCloseAnimator);
+ hoverCloseAnimator.setStartDelay(0);
+ hoverCloseAnimator.setDuration(HOVER_TOOL_TIP_EXIT_DURATION);
+ mHoverToolTipView.setCustomCloseAnimation(hoverCloseAnimator);
+
+ AnimatorSet hoverOpenAnimator = new AnimatorSet();
+ ObjectAnimator textOpenAnimator =
+ ObjectAnimator.ofInt(mHoverToolTipView, TEXT_ALPHA, 0, 255);
+ textOpenAnimator.setInterpolator(Interpolators.clampToProgress(LINEAR, 0.15f, 0.75f));
+ ObjectAnimator scaleOpenAnimator =
+ ObjectAnimator.ofFloat(mHoverToolTipView, SCALE_Y, 0f, 1f);
+ scaleOpenAnimator.setInterpolator(Interpolators.EMPHASIZED);
+ ObjectAnimator alphaOpenAnimator = ObjectAnimator.ofFloat(mHoverToolTipView, ALPHA, 0f, 1f);
+ alphaOpenAnimator.setInterpolator(Interpolators.clampToProgress(LINEAR, 0f, 0.33f));
+ hoverOpenAnimator.playTogether(
+ scaleOpenAnimator,
+ textOpenAnimator,
+ alphaOpenAnimator);
+ hoverOpenAnimator.setDuration(HOVER_TOOL_TIP_REVEAL_DURATION);
+ mHoverToolTipView.setCustomOpenAnimation(hoverOpenAnimator);
+
+ mHoverToolTipView.addOnLayoutChangeListener(
+ (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+ mHoverToolTipView.setPivotY(bottom);
+ mHoverToolTipView.setY(mTaskbarView.getTop() - (bottom - top));
+ });
+ }
+
+ @Override
+ public boolean onHover(View v, MotionEvent event) {
+ boolean isAnyOtherFloatingViewOpen =
+ AbstractFloatingView.hasOpenView(mActivity, TYPE_ALL_EXCEPT_ON_BOARD_POPUP);
+ if (isAnyOtherFloatingViewOpen) {
+ mHoverToolTipHandler.removeCallbacksAndMessages(null);
+ }
+ // If hover leaves a taskbar icon animate the tooltip closed.
+ if (event.getAction() == ACTION_HOVER_EXIT) {
+ startHideHoverToolTip();
+ mActivity.setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS, false);
+ return true;
+ } else if (!isAnyOtherFloatingViewOpen && event.getAction() == ACTION_HOVER_ENTER) {
+ if (!mActivity.isTaskbarWindowFullscreen()) {
+ // First time we want to animate a tooltip open, we set the drag layer to
+ // fullscreen so the tooltip will fit within the window. This causes a layout
+ // pass which will trigger a hover exit and hover enter event while still
+ // hovering the view, so we do not animate open on the first hover enter if we
+ // are not already in fullscreen.
+ mActivity.setTaskbarWindowFullscreen(true);
+ return false;
+ }
+ // If hovering above a taskbar icon starts, animate the tooltip open. Do not
+ // reveal if any floating views such as folders or edu pop-ups are open.
+ startRevealHoverToolTip();
+ mActivity.setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS, true);
+ return true;
+ }
+ return false;
+ }
+
+ private void startRevealHoverToolTip() {
+ mHoverToolTipHandler.post(mRevealHoverToolTipRunnable);
+ }
+
+ private void revealHoverToolTip() {
+ if (mHoverView == null || mToolTipText == null) {
+ return;
+ }
+ if (mHoverView instanceof FolderIcon && !((FolderIcon) mHoverView).getIconVisible()) {
+ return;
+ }
+ Rect iconViewBounds = Utilities.getViewBounds(mHoverView);
+ mHoverToolTipView.showAtLocation(mToolTipText, iconViewBounds.centerX(),
+ mTaskbarView.getTop(), /* shouldAutoClose= */ false);
+ }
+
+ private void startHideHoverToolTip() {
+ int accessibilityHideTimeout = AccessibilityManagerCompat.getRecommendedTimeoutMillis(
+ mActivity, /* originalTimeout= */ 0, FLAG_CONTENT_TEXT);
+ mHoverToolTipHandler.postDelayed(mHideHoverToolTipRunnable, accessibilityHideTimeout);
+ }
+
+ private void hideHoverToolTip() {
+ mHoverToolTipView.close(/* animate = */ true);
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index d6e559a..881f5c4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -17,10 +17,13 @@
import android.graphics.Insets
import android.graphics.Region
+import android.inputmethodservice.InputMethodService.ENABLE_HIDE_IME_CAPTION_BAR
import android.os.Binder
import android.os.IBinder
+import android.view.Gravity
import android.view.InsetsFrameProvider
import android.view.InsetsFrameProvider.SOURCE_DISPLAY
+import android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER
import android.view.InsetsSource.FLAG_SUPPRESS_SCRIM
import android.view.ViewTreeObserver
import android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME
@@ -38,9 +41,11 @@
import com.android.launcher3.DeviceProfile
import com.android.launcher3.R
import com.android.launcher3.anim.AlphaUpdateListener
+import com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NO_RECREATION
import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
import com.android.launcher3.util.DisplayController
import java.io.PrintWriter
+import kotlin.jvm.optionals.getOrNull
/** Handles the insets that Taskbar provides to underlying apps and the IME. */
class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTaskbarController {
@@ -55,13 +60,13 @@
private val touchableRegion: Region = Region()
private val insetsOwner: IBinder = Binder()
private val deviceProfileChangeListener = { _: DeviceProfile ->
- onTaskbarWindowHeightOrInsetsChanged()
+ onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
}
private val gestureNavSettingsObserver =
GestureNavigationSettingsObserver(
context.mainThreadHandler,
context,
- this::onTaskbarWindowHeightOrInsetsChanged
+ this::onTaskbarOrBubblebarWindowHeightOrInsetsChanged
)
// Initialized in init.
@@ -71,7 +76,7 @@
fun init(controllers: TaskbarControllers) {
this.controllers = controllers
windowLayoutParams = context.windowLayoutParams
- onTaskbarWindowHeightOrInsetsChanged()
+ onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
context.addOnDeviceProfileChangeListener(deviceProfileChangeListener)
gestureNavSettingsObserver.registerForCallingUser()
@@ -82,109 +87,192 @@
gestureNavSettingsObserver.unregister()
}
- fun onTaskbarWindowHeightOrInsetsChanged() {
- if (context.isGestureNav) {
- windowLayoutParams.providedInsets =
- arrayOf(
- InsetsFrameProvider(insetsOwner, 0, navigationBars())
- .setFlags(FLAG_SUPPRESS_SCRIM, FLAG_SUPPRESS_SCRIM),
- InsetsFrameProvider(insetsOwner, 0, tappableElement()),
- InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures()),
- InsetsFrameProvider(insetsOwner, INDEX_LEFT, systemGestures())
- .setSource(SOURCE_DISPLAY),
- InsetsFrameProvider(insetsOwner, INDEX_RIGHT, systemGestures())
- .setSource(SOURCE_DISPLAY)
- )
- } else {
- windowLayoutParams.providedInsets =
- arrayOf(
- InsetsFrameProvider(insetsOwner, 0, navigationBars()),
- InsetsFrameProvider(insetsOwner, 0, tappableElement()),
- InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures())
- )
- }
-
- val touchableHeight = controllers.taskbarStashController.touchableHeight
- touchableRegion.set(
- 0,
- windowLayoutParams.height - touchableHeight,
- context.deviceProfile.widthPx,
- windowLayoutParams.height
- )
- val contentHeight = controllers.taskbarStashController.contentHeightToReportToApps
+ fun onTaskbarOrBubblebarWindowHeightOrInsetsChanged() {
val tappableHeight = controllers.taskbarStashController.tappableHeightToReportToApps
- val res = context.resources
- for (provider in windowLayoutParams.providedInsets) {
- if (provider.type == navigationBars() || provider.type == mandatorySystemGestures()) {
- provider.insetsSize = getInsetsByNavMode(contentHeight)
- } else if (provider.type == tappableElement()) {
- provider.insetsSize = getInsetsByNavMode(tappableHeight)
- } else if (provider.type == systemGestures() && provider.index == INDEX_LEFT) {
- provider.insetsSize =
- Insets.of(
- gestureNavSettingsObserver.getLeftSensitivityForCallingUser(res),
- 0,
- 0,
- 0
- )
- } else if (provider.type == systemGestures() && provider.index == INDEX_RIGHT) {
- provider.insetsSize =
- Insets.of(
- 0,
- 0,
- gestureNavSettingsObserver.getRightSensitivityForCallingUser(res),
- 0
- )
- }
- }
-
- val imeInsetsSize = getInsetsByNavMode(taskbarHeightForIme)
- val insetsSizeOverride =
- arrayOf(
- InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, imeInsetsSize),
- )
- // Use 0 tappableElement insets for the VoiceInteractionWindow when gesture nav is enabled.
- val visInsetsSizeForGestureNavTappableElement = getInsetsByNavMode(0)
- val insetsSizeOverrideForGestureNavTappableElement =
- arrayOf(
- InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, imeInsetsSize),
- InsetsFrameProvider.InsetsSizeOverride(
- TYPE_VOICE_INTERACTION,
- visInsetsSizeForGestureNavTappableElement
- ),
- )
- for (provider in windowLayoutParams.providedInsets) {
- if (context.isGestureNav && provider.type == tappableElement()) {
- provider.insetsSizeOverrides = insetsSizeOverrideForGestureNavTappableElement
- } else if (provider.type != systemGestures()) {
- // We only override insets at the bottom of the screen
- provider.insetsSizeOverrides = insetsSizeOverride
- }
- }
-
// We only report tappableElement height for unstashed, persistent taskbar,
// which is also when we draw the rounded corners above taskbar.
- windowLayoutParams.insetsRoundedCornerFrame = tappableHeight > 0
+ val insetsRoundedCornerFlag =
+ if (tappableHeight > 0) {
+ FLAG_INSETS_ROUNDED_CORNER
+ } else {
+ 0
+ }
+
+ windowLayoutParams.providedInsets =
+ if (ENABLE_TASKBAR_NO_RECREATION.get()) {
+ getProvidedInsets(controllers.sharedState!!.insetsFrameProviders!!,
+ insetsRoundedCornerFlag)
+ } else {
+ getProvidedInsets(insetsRoundedCornerFlag)
+ }
+
+ if (!context.isGestureNav) {
+ if (windowLayoutParams.paramsForRotation != null) {
+ for (layoutParams in windowLayoutParams.paramsForRotation) {
+ layoutParams.providedInsets = getProvidedInsets(insetsRoundedCornerFlag)
+ }
+ }
+ }
+
+ val taskbarTouchableHeight = controllers.taskbarStashController.touchableHeight
+ val bubblesTouchableHeight =
+ if (controllers.bubbleControllers.isPresent) {
+ controllers.bubbleControllers.get().bubbleStashController.touchableHeight
+ } else {
+ 0
+ }
+ val touchableHeight = Math.max(taskbarTouchableHeight, bubblesTouchableHeight)
+
+ if (
+ controllers.bubbleControllers.isPresent &&
+ controllers.bubbleControllers.get().bubbleStashController.isBubblesShowingOnHome
+ ) {
+ val iconBounds =
+ controllers.bubbleControllers.get().bubbleBarViewController.bubbleBarBounds
+ touchableRegion.set(
+ iconBounds.left,
+ iconBounds.top,
+ iconBounds.right,
+ iconBounds.bottom
+ )
+ } else {
+ touchableRegion.set(
+ 0,
+ windowLayoutParams.height - touchableHeight,
+ context.deviceProfile.widthPx,
+ windowLayoutParams.height
+ )
+ }
+
+ val gravity = windowLayoutParams.gravity
+ for (provider in windowLayoutParams.providedInsets) {
+ setProviderInsets(provider, gravity)
+ }
+
+ if (windowLayoutParams.paramsForRotation != null) {
+ // Add insets for navbar rotated params
+ for (layoutParams in windowLayoutParams.paramsForRotation) {
+ for (provider in layoutParams.providedInsets) {
+ setProviderInsets(provider, layoutParams.gravity)
+ }
+ }
+ }
context.notifyUpdateLayoutParams()
}
/**
- * @return [Insets] where the [bottomInset] is either used as a bottom inset or
- *
- * ```
- * right/left inset if using 3 button nav
- * ```
+ * This is for when ENABLE_TASKBAR_NO_RECREATION is enabled. We generate one instance of
+ * providedInsets and use it across the entire lifecycle of TaskbarManager. The only thing
+ * we need to reset is nav bar flags based on insetsRoundedCornerFlag.
*/
- private fun getInsetsByNavMode(bottomInset: Int): Insets {
- val devicePortrait = !context.deviceProfile.isLandscape
- if (!TaskbarManager.isPhoneButtonNavMode(context) || devicePortrait) {
+ private fun getProvidedInsets(providedInsets: Array<InsetsFrameProvider>,
+ insetsRoundedCornerFlag: Int): Array<InsetsFrameProvider> {
+ val navBarsFlag =
+ (if (context.isGestureNav) FLAG_SUPPRESS_SCRIM else 0) or insetsRoundedCornerFlag
+ for (provider in providedInsets) {
+ if (provider.type == navigationBars()) {
+ provider.setFlags(
+ navBarsFlag,
+ FLAG_SUPPRESS_SCRIM or FLAG_INSETS_ROUNDED_CORNER
+ )
+ }
+ }
+ return providedInsets
+ }
+
+ /**
+ * The inset types and number of insets provided have to match for both gesture nav and button
+ * nav. The values and the order of the elements in array are allowed to differ.
+ * Reason being WM does not allow types and number of insets changing for a given window once it
+ * is added into the hierarchy for performance reasons.
+ */
+ private fun getProvidedInsets(insetsRoundedCornerFlag: Int): Array<InsetsFrameProvider> {
+ val navBarsFlag =
+ (if (context.isGestureNav) FLAG_SUPPRESS_SCRIM else 0) or insetsRoundedCornerFlag
+ return arrayOf(
+ InsetsFrameProvider(insetsOwner, 0, navigationBars())
+ .setFlags(
+ navBarsFlag,
+ FLAG_SUPPRESS_SCRIM or FLAG_INSETS_ROUNDED_CORNER
+ ),
+ InsetsFrameProvider(insetsOwner, 0, tappableElement()),
+ InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures()),
+ InsetsFrameProvider(insetsOwner, INDEX_LEFT, systemGestures())
+ .setSource(SOURCE_DISPLAY),
+ InsetsFrameProvider(insetsOwner, INDEX_RIGHT, systemGestures())
+ .setSource(SOURCE_DISPLAY)
+ )
+ }
+
+ private fun setProviderInsets(provider: InsetsFrameProvider, gravity: Int) {
+ val contentHeight = controllers.taskbarStashController.contentHeightToReportToApps
+ val tappableHeight = controllers.taskbarStashController.tappableHeightToReportToApps
+ val res = context.resources
+ if (provider.type == navigationBars() || provider.type == mandatorySystemGestures()) {
+ provider.insetsSize = getInsetsForGravity(contentHeight, gravity)
+ } else if (provider.type == tappableElement()) {
+ provider.insetsSize = getInsetsForGravity(tappableHeight, gravity)
+ } else if (provider.type == systemGestures() && provider.index == INDEX_LEFT) {
+ val leftIndexInset =
+ if (context.isThreeButtonNav) 0
+ else gestureNavSettingsObserver.getLeftSensitivityForCallingUser(res)
+ provider.insetsSize = Insets.of(leftIndexInset, 0, 0, 0)
+ } else if (provider.type == systemGestures() && provider.index == INDEX_RIGHT) {
+ val rightIndexInset =
+ if (context.isThreeButtonNav) 0
+ else gestureNavSettingsObserver.getRightSensitivityForCallingUser(res)
+ provider.insetsSize = Insets.of(0, 0, rightIndexInset, 0)
+ }
+
+
+ // When in gesture nav, report the stashed height to the IME, to allow hiding the
+ // IME navigation bar.
+ val imeInsetsSize = if (ENABLE_HIDE_IME_CAPTION_BAR && context.isGestureNav) {
+ getInsetsForGravity(controllers.taskbarStashController.stashedHeight, gravity);
+ } else {
+ getInsetsForGravity(taskbarHeightForIme, gravity)
+ }
+ val imeInsetsSizeOverride =
+ arrayOf(
+ InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, imeInsetsSize),
+ )
+ // Use 0 tappableElement insets for the VoiceInteractionWindow when gesture nav is enabled.
+ val visInsetsSizeForTappableElement =
+ if (context.isGestureNav) getInsetsForGravity(0, gravity)
+ else getInsetsForGravity(tappableHeight, gravity)
+ val insetsSizeOverrideForTappableElement =
+ arrayOf(
+ InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, imeInsetsSize),
+ InsetsFrameProvider.InsetsSizeOverride(
+ TYPE_VOICE_INTERACTION,
+ visInsetsSizeForTappableElement
+ ),
+ )
+ if ((context.isGestureNav || TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ && provider.type == tappableElement()) {
+ provider.insetsSizeOverrides = insetsSizeOverrideForTappableElement
+ } else if (provider.type != systemGestures()) {
+ // We only override insets at the bottom of the screen
+ provider.insetsSizeOverrides = imeInsetsSizeOverride
+ }
+ }
+
+ /**
+ * @return [Insets] where the [inset] is either used as a bottom inset or
+ * right/left inset if using 3 button nav
+ */
+ private fun getInsetsForGravity(inset: Int, gravity: Int): Insets {
+ if ((gravity and Gravity.BOTTOM) == Gravity.BOTTOM) {
// Taskbar or portrait phone mode
- return Insets.of(0, 0, 0, bottomInset)
+ return Insets.of(0, 0, 0, inset)
}
// TODO(b/230394142): seascape
- return Insets.of(0, 0, bottomInset, 0)
+ val isSeascape = (gravity and Gravity.START) == Gravity.START
+ val leftInset = if (isSeascape) inset else 0
+ val rightInset = if (isSeascape) 0 else inset
+ return Insets.of(leftInset , 0, rightInset, 0)
}
/**
@@ -199,6 +287,9 @@
context.dragLayer,
insetsInfo.touchableRegion
)
+ val bubbleBarVisible =
+ controllers.bubbleControllers.isPresent &&
+ controllers.bubbleControllers.get().bubbleBarViewController.isBubbleBarVisible()
var insetsIsTouchableRegion = true
if (context.dragLayer.alpha < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) {
// Let touches pass through us.
@@ -219,16 +310,33 @@
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_FRAME)
insetsIsTouchableRegion = false
} else if (
- controllers.taskbarViewController.areIconsVisible() || context.isNavBarKidsModeActive
+ controllers.taskbarViewController.areIconsVisible() ||
+ context.isNavBarKidsModeActive ||
+ bubbleBarVisible
) {
// Taskbar has some touchable elements, take over the full taskbar area
if (
controllers.uiController.isInOverview &&
DisplayController.isTransientTaskbar(context)
) {
- insetsInfo.touchableRegion.set(
+ val region =
controllers.taskbarActivityContext.dragLayer.lastDrawnTransientRect.toRegion()
- )
+ val bubbleBarBounds =
+ controllers.bubbleControllers.getOrNull()?.let { bubbleControllers ->
+ if (!bubbleControllers.bubbleStashController.isBubblesShowingOnOverview) {
+ return@let null
+ }
+ if (!bubbleControllers.bubbleBarViewController.isBubbleBarVisible) {
+ return@let null
+ }
+ bubbleControllers.bubbleBarViewController.bubbleBarBounds
+ }
+
+ // Include the bounds of the bubble bar in the touchable region if they exist.
+ if (bubbleBarBounds != null) {
+ region.op(bubbleBarBounds, Region.Op.UNION)
+ }
+ insetsInfo.touchableRegion.set(region)
} else {
insetsInfo.touchableRegion.set(touchableRegion)
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index ddea51f..88ae349 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -18,6 +18,7 @@
import static com.android.app.animation.Interpolators.EMPHASIZED;
import static com.android.launcher3.taskbar.TaskbarKeyguardController.MASK_ANY_SYSUI_LOCKED;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
+import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_OVERVIEW;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE;
import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME;
import static com.android.launcher3.util.FlagDebugUtils.appendFlag;
@@ -204,7 +205,7 @@
updateStateForFlag(FLAG_LAUNCHER_IN_STATE_TRANSITION, false);
// TODO(b/279514548) Cleans up bad state that can occur when user interacts with
// taskbar on top of transparent activity.
- if (finalState == LauncherState.NORMAL && mLauncher.isResumed()) {
+ if (finalState == LauncherState.NORMAL && mLauncher.hasBeenResumed()) {
updateStateForFlag(FLAG_RESUMED, true);
}
applyState();
@@ -249,7 +250,6 @@
mIconAlignment.finishAnimation();
- Log.d("b/260135164", "onDestroy - updateIconAlphaForHome(1)");
mLauncher.getHotseat().setIconsAlpha(1f);
mLauncher.getStateManager().removeStateListener(mStateListener);
@@ -409,6 +409,17 @@
+ ", mLauncherState: " + mLauncherState
+ ", toAlignment: " + toAlignment);
}
+ mControllers.bubbleControllers.ifPresent(controllers -> {
+ // Show the bubble bar when on launcher home or in overview.
+ boolean onHome = isInLauncher && mLauncherState == LauncherState.NORMAL;
+ boolean onOverview = mLauncherState == LauncherState.OVERVIEW;
+ controllers.bubbleStashController.setBubblesShowingOnHome(onHome);
+ controllers.bubbleStashController.setBubblesShowingOnOverview(onOverview);
+ });
+
+ mControllers.taskbarStashController.updateStateForFlag(FLAG_IN_OVERVIEW,
+ mLauncherState == LauncherState.OVERVIEW);
+
AnimatorSet animatorSet = new AnimatorSet();
if (hasAnyFlag(changedFlags, FLAG_LAUNCHER_IN_STATE_TRANSITION)) {
@@ -479,7 +490,8 @@
public void onAnimationEnd(Animator animation) {
TaskbarStashController stashController =
mControllers.taskbarStashController;
- stashController.updateAndAnimateTransientTaskbar(/* stash */ true);
+ stashController.updateAndAnimateTransientTaskbar(
+ /* stash */ true, /* bubblesShouldFollow */ true);
}
});
} else {
@@ -636,8 +648,6 @@
public void onAnimationEnd(Animator animation) {
if (isInStashedState && committed) {
// Reset hotseat alpha to default
- Log.d("b/260135164",
- "playStateTransitionAnim#onAnimationEnd - setIconsAlpha(1)");
mLauncher.getHotseat().setIconsAlpha(1);
}
}
@@ -705,8 +715,6 @@
private void updateIconAlphaForHome(float alpha) {
if (mControllers.taskbarActivityContext.isDestroyed()) {
- Log.e("b/260135164", "updateIconAlphaForHome is called after Taskbar is destroyed",
- new Exception());
return;
}
mIconAlphaForHome.setValue(alpha);
@@ -717,9 +725,6 @@
* Hide Launcher Hotseat icons when Taskbar icons have opacity. Both icon sets
* should not be visible at the same time.
*/
- Log.d("b/260135164",
- "updateIconAlphaForHome - setIconsAlpha(" + (hotseatVisible ? 1 : 0)
- + "), isTaskbarPresent: " + mLauncher.getDeviceProfile().isTaskbarPresent);
mLauncher.getHotseat().setIconsAlpha(hotseatVisible ? 1 : 0);
if (mIsQsbInline) {
mLauncher.getHotseat().setQsbAlpha(hotseatVisible ? 1 : 0);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 738ff87..e922c4c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -22,13 +22,16 @@
import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING;
import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING_KEY;
-import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
-import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NO_RECREATION;
import static com.android.launcher3.util.DisplayController.TASKBAR_NOT_DESTROYED_TAG;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange;
+import static com.android.quickstep.util.SystemActionConstants.ACTION_SHOW_TASKBAR;
+import static com.android.quickstep.util.SystemActionConstants.SYSTEM_ACTION_ID_TASKBAR;
import android.annotation.SuppressLint;
+import android.app.Activity;
import android.app.PendingIntent;
import android.content.ComponentCallbacks;
import android.content.Context;
@@ -41,28 +44,32 @@
import android.net.Uri;
import android.os.Handler;
import android.os.SystemProperties;
+import android.os.Trace;
import android.provider.Settings;
import android.util.Log;
import android.view.Display;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.taskbar.unfold.NonDestroyableScopedUnfoldTransitionProgressProvider;
import com.android.launcher3.uioverrides.QuickstepLauncher;
-import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.NavigationMode;
+import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter;
import com.android.launcher3.util.SettingsCache;
import com.android.launcher3.util.SimpleBroadcastReceiver;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TouchInteractionService;
+import com.android.quickstep.util.AssistUtils;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
@@ -77,6 +84,22 @@
private static final String TAG = "TaskbarManager";
private static final boolean DEBUG = false;
+ /**
+ * All the configurations which do not initiate taskbar recreation.
+ * This includes all the configurations defined in Launcher's manifest entry and
+ * ActivityController#filterConfigChanges
+ */
+ private static final int SKIP_RECREATE_CONFIG_CHANGES = ActivityInfo.CONFIG_WINDOW_CONFIGURATION
+ | ActivityInfo.CONFIG_KEYBOARD
+ | ActivityInfo.CONFIG_KEYBOARD_HIDDEN
+ | ActivityInfo.CONFIG_MCC
+ | ActivityInfo.CONFIG_MNC
+ | ActivityInfo.CONFIG_NAVIGATION
+ | ActivityInfo.CONFIG_ORIENTATION
+ | ActivityInfo.CONFIG_SCREEN_SIZE
+ | ActivityInfo.CONFIG_SCREEN_LAYOUT
+ | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
+
public static final boolean FLAG_HIDE_NAVBAR_WINDOW =
SystemProperties.getBoolean("persist.wm.debug.hide_navbar_window", false);
@@ -87,12 +110,14 @@
Settings.Secure.NAV_BAR_KIDS_MODE);
private final Context mContext;
- private final DisplayController mDisplayController;
+ private WindowManager mWindowManager;
+ private FrameLayout mTaskbarRootLayout;
+ private boolean mAddedWindow;
private final TaskbarNavButtonController mNavButtonController;
- private final SettingsCache.OnChangeListener mUserSetupCompleteListener;
- private final SettingsCache.OnChangeListener mNavBarKidsModeListener;
private final ComponentCallbacks mComponentCallbacks;
- private final SimpleBroadcastReceiver mShutdownReceiver;
+
+ private final SimpleBroadcastReceiver mShutdownReceiver =
+ new SimpleBroadcastReceiver(i -> destroyExistingTaskbar());
// The source for this provider is set when Launcher is available
// We use 'non-destroyable' version here so the original provider won't be destroyed
@@ -100,7 +125,6 @@
// It's destruction/creation will be managed by the activity.
private final ScopedUnfoldTransitionProgressProvider mUnfoldProgressProvider =
new NonDestroyableScopedUnfoldTransitionProgressProvider();
- private NavigationMode mNavMode;
private TaskbarActivityContext mTaskbarActivityContext;
private StatefulActivity mActivity;
@@ -111,29 +135,14 @@
private final TaskbarSharedState mSharedState = new TaskbarSharedState();
/**
- * We use WindowManager's ComponentCallbacks() for most of the config changes, however for
- * navigation mode, that callback gets called too soon, before it's internal navigation mode
- * reflects the current one.
- * DisplayController's callback is delayed enough to get the correct nav mode value
- *
- * We also use density change here because DeviceProfile has had a chance to update it's state
- * whereas density for component callbacks registered in this class don't update DeviceProfile.
- * Confused? Me too. Make it less confusing (TODO: b/227669780)
- *
- * Flags used with {@link #mDispInfoChangeListener}
+ * We use WindowManager's ComponentCallbacks() for internal UI changes (similar to an Activity)
+ * which comes via a different channel
*/
- private static final int CHANGE_FLAGS = CHANGE_NAVIGATION_MODE | CHANGE_DENSITY;
- private final DisplayController.DisplayInfoChangeListener mDispInfoChangeListener;
+ private final OnIDPChangeListener mIdpChangeListener = c -> recreateTaskbar();
+ private final SettingsCache.OnChangeListener mOnSettingsChangeListener = c -> recreateTaskbar();
private boolean mUserUnlocked = false;
- public static final int SYSTEM_ACTION_ID_TASKBAR = 499;
-
- /**
- * For Taskbar broadcast intent filter.
- */
- public static final String ACTION_SHOW_TASKBAR = "ACTION_SHOW_TASKBAR";
-
private final SimpleBroadcastReceiver mTaskbarBroadcastReceiver =
new SimpleBroadcastReceiver(this::showTaskbarFromBroadcast);
@@ -144,101 +153,92 @@
}
};
+ private final ActivityLifecycleCallbacksAdapter mLifecycleCallbacks =
+ new ActivityLifecycleCallbacksAdapter() {
+ @Override
+ public void onActivityDestroyed(Activity activity) {
+ if (mActivity != activity) return;
+ if (mActivity != null) {
+ mActivity.removeOnDeviceProfileChangeListener(
+ mDebugActivityDeviceProfileChanged);
+ mActivity.unregisterActivityLifecycleCallbacks(this);
+ }
+ mActivity = null;
+ debugWhyTaskbarNotDestroyed("clearActivity");
+ if (mTaskbarActivityContext != null) {
+ mTaskbarActivityContext.setUIController(TaskbarUIController.DEFAULT);
+ }
+ mUnfoldProgressProvider.setSourceProvider(null);
+ }
+ };
+
@SuppressLint("WrongConstant")
public TaskbarManager(TouchInteractionService service) {
- mDisplayController = DisplayController.INSTANCE.get(service);
Display display =
service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
mContext = service.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null);
+ if (ENABLE_TASKBAR_NO_RECREATION.get()) {
+ mWindowManager = mContext.getSystemService(WindowManager.class);
+ mTaskbarRootLayout = new FrameLayout(mContext);
+ }
mNavButtonController = new TaskbarNavButtonController(service,
- SystemUiProxy.INSTANCE.get(mContext), new Handler());
- mUserSetupCompleteListener = isUserSetupComplete -> recreateTaskbar();
- mNavBarKidsModeListener = isNavBarKidsMode -> recreateTaskbar();
- // TODO(b/227669780): Consolidate this w/ DisplayController callbacks
+ SystemUiProxy.INSTANCE.get(mContext), new Handler(),
+ AssistUtils.newInstance(mContext));
mComponentCallbacks = new ComponentCallbacks() {
private Configuration mOldConfig = mContext.getResources().getConfiguration();
@Override
public void onConfigurationChanged(Configuration newConfig) {
+ Trace.instantForTrack(Trace.TRACE_TAG_APP, "TaskbarManager",
+ "onConfigurationChanged: " + newConfig);
debugWhyTaskbarNotDestroyed(
"TaskbarManager#mComponentCallbacks.onConfigurationChanged: " + newConfig);
DeviceProfile dp = mUserUnlocked
? LauncherAppState.getIDP(mContext).getDeviceProfile(mContext)
: null;
- int configDiff = mOldConfig.diff(newConfig);
- int configDiffForRecreate = configDiff;
- int configsRequiringRecreate = ActivityInfo.CONFIG_ASSETS_PATHS
- | ActivityInfo.CONFIG_LAYOUT_DIRECTION | ActivityInfo.CONFIG_UI_MODE
- | ActivityInfo.CONFIG_SCREEN_SIZE;
- if ((configDiff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0
- && mTaskbarActivityContext != null && dp != null
- && !isPhoneMode(dp)) {
- // Additional check since this callback gets fired multiple times w/o
- // screen size changing, or when simply rotating the device.
- // In the case of phone device rotation, we do want to call recreateTaskbar()
- DeviceProfile oldDp = mTaskbarActivityContext.getDeviceProfile();
- boolean isOrientationChange =
- (configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0;
+ int configDiff = mOldConfig.diff(newConfig) & ~SKIP_RECREATE_CONFIG_CHANGES;
- int newOrientation = newConfig.windowConfiguration.getRotation();
- int oldOrientation = mOldConfig.windowConfiguration.getRotation();
- int oldWidth = isOrientationChange ? oldDp.heightPx : oldDp.widthPx;
- int oldHeight = isOrientationChange ? oldDp.widthPx : oldDp.heightPx;
-
- if ((dp.widthPx == oldWidth && dp.heightPx == oldHeight)
- || (newOrientation == oldOrientation)) {
- configDiffForRecreate &= ~ActivityInfo.CONFIG_SCREEN_SIZE;
- }
- }
if ((configDiff & ActivityInfo.CONFIG_UI_MODE) != 0) {
// Only recreate for theme changes, not other UI mode changes such as docking.
int oldUiNightMode = (mOldConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK);
int newUiNightMode = (newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK);
if (oldUiNightMode == newUiNightMode) {
- configDiffForRecreate &= ~ActivityInfo.CONFIG_UI_MODE;
+ configDiff &= ~ActivityInfo.CONFIG_UI_MODE;
}
}
debugWhyTaskbarNotDestroyed("ComponentCallbacks#onConfigurationChanged() "
- + "configDiffForRecreate="
- + Configuration.configurationDiffToString(configDiffForRecreate));
- if ((configDiffForRecreate & configsRequiringRecreate) != 0) {
+ + "configDiff=" + Configuration.configurationDiffToString(configDiff));
+ if (configDiff != 0 || mTaskbarActivityContext == null) {
recreateTaskbar();
} else {
// Config change might be handled without re-creating the taskbar
- if (mTaskbarActivityContext != null) {
- if (dp != null && !isTaskbarPresent(dp)) {
- destroyExistingTaskbar();
- } else {
- if (dp != null && isTaskbarPresent(dp)) {
- mTaskbarActivityContext.updateDeviceProfile(dp, mNavMode);
+ if (dp != null && !isTaskbarPresent(dp)) {
+ destroyExistingTaskbar();
+ } else {
+ if (dp != null && isTaskbarPresent(dp)) {
+ if (FLAG_HIDE_NAVBAR_WINDOW) {
+ // Re-initialize for screen size change? Should this be done
+ // by looking at screen-size change flag in configDiff in the
+ // block above?
+ recreateTaskbar();
+ } else {
+ mTaskbarActivityContext.updateDeviceProfile(dp);
}
- mTaskbarActivityContext.onConfigurationChanged(configDiff);
}
+ mTaskbarActivityContext.onConfigurationChanged(configDiff);
}
}
- mOldConfig = newConfig;
+ mOldConfig = new Configuration(newConfig);
}
@Override
public void onLowMemory() { }
};
- mShutdownReceiver = new SimpleBroadcastReceiver(i ->
- destroyExistingTaskbar());
- mDispInfoChangeListener = (context, info, flags) -> {
- if ((flags & CHANGE_FLAGS) != 0) {
- mNavMode = info.navigationMode;
- recreateTaskbar();
- }
- debugWhyTaskbarNotDestroyed("DisplayInfoChangeListener#"
- + mDisplayController.getChangeFlagsString(flags));
- };
- mNavMode = mDisplayController.getInfo().navigationMode;
- mDisplayController.addChangeListener(mDispInfoChangeListener);
- SettingsCache.INSTANCE.get(mContext).register(USER_SETUP_COMPLETE_URI,
- mUserSetupCompleteListener);
- SettingsCache.INSTANCE.get(mContext).register(NAV_BAR_KIDS_MODE,
- mNavBarKidsModeListener);
+ SettingsCache.INSTANCE.get(mContext)
+ .register(USER_SETUP_COMPLETE_URI, mOnSettingsChangeListener);
+ SettingsCache.INSTANCE.get(mContext)
+ .register(NAV_BAR_KIDS_MODE, mOnSettingsChangeListener);
mContext.registerComponentCallbacks(mComponentCallbacks);
mShutdownReceiver.register(mContext, Intent.ACTION_SHUTDOWN);
UI_HELPER_EXECUTOR.execute(() -> {
@@ -263,10 +263,15 @@
LauncherPrefs.get(mContext).removeListener(mTaskbarPinningPreferenceChangeListener,
TASKBAR_PINNING);
mTaskbarActivityContext.onDestroy();
- if (!FLAG_HIDE_NAVBAR_WINDOW) {
+ if (!FLAG_HIDE_NAVBAR_WINDOW || ENABLE_TASKBAR_NO_RECREATION.get()) {
mTaskbarActivityContext = null;
}
}
+ DeviceProfile dp = mUserUnlocked ?
+ LauncherAppState.getIDP(mContext).getDeviceProfile(mContext) : null;
+ if (dp == null || !isTaskbarPresent(dp)) {
+ removeTaskbarRootViewFromWindow();
+ }
}
/**
@@ -279,6 +284,25 @@
}
/**
+ * Toggles All Apps for Taskbar or Launcher depending on the current state.
+ *
+ * @param homeAllAppsIntent Intent used if Taskbar is not enabled or Launcher is resumed.
+ */
+ public void toggleAllApps(Intent homeAllAppsIntent) {
+ if (mTaskbarActivityContext == null) {
+ mContext.startActivity(homeAllAppsIntent);
+ return;
+ }
+
+ if (mActivity != null && mActivity.isResumed() && !mActivity.isInState(OVERVIEW)) {
+ mContext.startActivity(homeAllAppsIntent);
+ return;
+ }
+
+ mTaskbarActivityContext.toggleAllAppsSearch();
+ }
+
+ /**
* Displays a frame of the first Launcher reveal animation.
*
* This should be used to run a first Launcher reveal animation whose progress matches a swipe
@@ -294,7 +318,9 @@
*/
public void onUserUnlocked() {
mUserUnlocked = true;
+ LauncherAppState.getIDP(mContext).addOnChangeListener(mIdpChangeListener);
recreateTaskbar();
+ addTaskbarRootViewToWindow();
}
/**
@@ -306,10 +332,12 @@
}
if (mActivity != null) {
mActivity.removeOnDeviceProfileChangeListener(mDebugActivityDeviceProfileChanged);
+ mActivity.unregisterActivityLifecycleCallbacks(mLifecycleCallbacks);
}
mActivity = activity;
debugWhyTaskbarNotDestroyed("Set mActivity=" + mActivity);
mActivity.addOnDeviceProfileChangeListener(mDebugActivityDeviceProfileChanged);
+ mActivity.registerActivityLifecycleCallbacks(mLifecycleCallbacks);
UnfoldTransitionProgressProvider unfoldTransitionProgressProvider =
getUnfoldTransitionProgressProviderForActivity(activity);
mUnfoldProgressProvider.setSourceProvider(unfoldTransitionProgressProvider);
@@ -349,59 +377,56 @@
}
/**
- * Clears a previously set {@link StatefulActivity}
- */
- public void clearActivity(@NonNull StatefulActivity activity) {
- if (mActivity == activity) {
- mActivity.removeOnDeviceProfileChangeListener(mDebugActivityDeviceProfileChanged);
- mActivity = null;
- debugWhyTaskbarNotDestroyed("clearActivity");
- if (mTaskbarActivityContext != null) {
- mTaskbarActivityContext.setUIController(TaskbarUIController.DEFAULT);
- }
- mUnfoldProgressProvider.setSourceProvider(null);
- }
- }
-
- /**
* This method is called multiple times (ex. initial init, then when user unlocks) in which case
* we fully want to destroy an existing taskbar and create a new one.
* In other case (folding/unfolding) we don't need to remove and add window.
*/
@VisibleForTesting
public void recreateTaskbar() {
- DeviceProfile dp = mUserUnlocked ?
+ Trace.beginSection("recreateTaskbar");
+ try {
+ DeviceProfile dp = mUserUnlocked ?
LauncherAppState.getIDP(mContext).getDeviceProfile(mContext) : null;
- destroyExistingTaskbar();
+ destroyExistingTaskbar();
- boolean isTaskbarEnabled = dp != null && isTaskbarPresent(dp);
- debugWhyTaskbarNotDestroyed("recreateTaskbar: isTaskbarEnabled=" + isTaskbarEnabled
+ boolean isTaskbarEnabled = dp != null && isTaskbarPresent(dp);
+ debugWhyTaskbarNotDestroyed("recreateTaskbar: isTaskbarEnabled=" + isTaskbarEnabled
+ " [dp != null (i.e. mUserUnlocked)]=" + (dp != null)
+ " FLAG_HIDE_NAVBAR_WINDOW=" + FLAG_HIDE_NAVBAR_WINDOW
+ " dp.isTaskbarPresent=" + (dp == null ? "null" : dp.isTaskbarPresent));
- if (!isTaskbarEnabled) {
- SystemUiProxy.INSTANCE.get(mContext)
+ if (!isTaskbarEnabled) {
+ SystemUiProxy.INSTANCE.get(mContext)
.notifyTaskbarStatus(/* visible */ false, /* stashed */ false);
- return;
- }
+ return;
+ }
- if (mTaskbarActivityContext == null) {
- mTaskbarActivityContext = new TaskbarActivityContext(mContext, dp, mNavButtonController,
- mUnfoldProgressProvider);
- } else {
- mTaskbarActivityContext.updateDeviceProfile(dp, mNavMode);
- }
- mTaskbarActivityContext.init(mSharedState);
+ if (ENABLE_TASKBAR_NO_RECREATION.get() || mTaskbarActivityContext == null) {
+ mTaskbarActivityContext = new TaskbarActivityContext(mContext, dp,
+ mNavButtonController, mUnfoldProgressProvider);
+ } else {
+ mTaskbarActivityContext.updateDeviceProfile(dp);
+ }
+ mTaskbarActivityContext.init(mSharedState);
- if (mActivity != null) {
- mTaskbarActivityContext.setUIController(
+ if (mActivity != null) {
+ mTaskbarActivityContext.setUIController(
createTaskbarUIControllerForActivity(mActivity));
- }
+ }
- // We to wait until user unlocks the device to attach listener.
- LauncherPrefs.get(mContext).addListener(mTaskbarPinningPreferenceChangeListener,
+ if (ENABLE_TASKBAR_NO_RECREATION.get()) {
+ addTaskbarRootViewToWindow();
+ mTaskbarRootLayout.removeAllViews();
+ mTaskbarRootLayout.addView(mTaskbarActivityContext.getDragLayer());
+ mTaskbarActivityContext.notifyUpdateLayoutParams();
+ }
+
+ // We to wait until user unlocks the device to attach listener.
+ LauncherPrefs.get(mContext).addListener(mTaskbarPinningPreferenceChangeListener,
TASKBAR_PINNING);
+ } finally {
+ Trace.endSection();
+ }
}
public void onSystemUiFlagsChanged(int systemUiStateFlags) {
@@ -493,11 +518,13 @@
UI_HELPER_EXECUTOR.execute(
() -> mTaskbarBroadcastReceiver.unregisterReceiverSafely(mContext));
destroyExistingTaskbar();
- mDisplayController.removeChangeListener(mDispInfoChangeListener);
- SettingsCache.INSTANCE.get(mContext).unregister(USER_SETUP_COMPLETE_URI,
- mUserSetupCompleteListener);
- SettingsCache.INSTANCE.get(mContext).unregister(NAV_BAR_KIDS_MODE,
- mNavBarKidsModeListener);
+ if (mUserUnlocked) {
+ LauncherAppState.getIDP(mContext).removeOnChangeListener(mIdpChangeListener);
+ }
+ SettingsCache.INSTANCE.get(mContext)
+ .unregister(USER_SETUP_COMPLETE_URI, mOnSettingsChangeListener);
+ SettingsCache.INSTANCE.get(mContext)
+ .unregister(NAV_BAR_KIDS_MODE, mOnSettingsChangeListener);
mContext.unregisterComponentCallbacks(mComponentCallbacks);
mContext.unregisterReceiver(mShutdownReceiver);
}
@@ -515,6 +542,22 @@
}
}
+ private void addTaskbarRootViewToWindow() {
+ if (ENABLE_TASKBAR_NO_RECREATION.get() && !mAddedWindow
+ && mTaskbarActivityContext != null) {
+ mWindowManager.addView(mTaskbarRootLayout,
+ mTaskbarActivityContext.getWindowLayoutParams());
+ mAddedWindow = true;
+ }
+ }
+
+ private void removeTaskbarRootViewFromWindow() {
+ if (ENABLE_TASKBAR_NO_RECREATION.get() && mAddedWindow) {
+ mWindowManager.removeViewImmediate(mTaskbarRootLayout);
+ mAddedWindow = false;
+ }
+ }
+
/** Temp logs for b/254119092. */
public void debugWhyTaskbarNotDestroyed(String debugReason) {
StringJoiner log = new StringJoiner("\n");
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
index 6cf63a9..7692760 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
@@ -57,7 +57,7 @@
private final TaskbarView mContainer;
// Initialized in init.
- private TaskbarControllers mControllers;
+ protected TaskbarControllers mControllers;
// Used to defer any UI updates during the SUW unstash animation.
private boolean mDeferUpdatesForSUW;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacksFactory.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacksFactory.kt
new file mode 100644
index 0000000..eb03b4a
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacksFactory.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar
+
+import android.content.Context
+import com.android.launcher3.R
+import com.android.launcher3.util.ResourceBasedOverride
+import com.android.launcher3.util.ResourceBasedOverride.Overrides
+
+/** Creates [TaskbarModelCallbacks] instances. */
+open class TaskbarModelCallbacksFactory : ResourceBasedOverride {
+
+ open fun create(
+ activityContext: TaskbarActivityContext,
+ container: TaskbarView,
+ ): TaskbarModelCallbacks = TaskbarModelCallbacks(activityContext, container)
+
+ companion object {
+ @JvmStatic
+ fun newInstance(context: Context): TaskbarModelCallbacksFactory {
+ return Overrides.getObject(
+ TaskbarModelCallbacksFactory::class.java,
+ context,
+ R.string.taskbar_model_callbacks_factory_class,
+ )
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index 610efeb..533785f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -43,12 +43,16 @@
import com.android.launcher3.R;
import com.android.launcher3.logging.StatsLogManager;
+import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
+import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.TouchInteractionService;
+import com.android.quickstep.util.AssistUtils;
+import com.android.quickstep.views.DesktopTaskView;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -105,15 +109,17 @@
private final TouchInteractionService mService;
private final SystemUiProxy mSystemUiProxy;
private final Handler mHandler;
+ private final AssistUtils mAssistUtils;
@Nullable private StatsLogManager mStatsLogManager;
private final Runnable mResetLongPress = this::resetScreenUnpin;
public TaskbarNavButtonController(TouchInteractionService service,
- SystemUiProxy systemUiProxy, Handler handler) {
+ SystemUiProxy systemUiProxy, Handler handler, AssistUtils assistUtils) {
mService = service;
mSystemUiProxy = systemUiProxy;
mHandler = handler;
+ mAssistUtils = assistUtils;
}
public void onButtonClick(@TaskbarButton int buttonType, View view) {
@@ -155,7 +161,7 @@
switch (buttonType) {
case BUTTON_HOME:
logEvent(LAUNCHER_TASKBAR_HOME_BUTTON_LONGPRESS);
- startAssistant();
+ onLongPressHome();
return true;
case BUTTON_A11Y:
logEvent(LAUNCHER_TASKBAR_A11Y_BUTTON_LONGPRESS);
@@ -267,6 +273,15 @@
private void navigateHome() {
TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY);
+
+ if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
+ DesktopVisibilityController desktopVisibilityController =
+ LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
+ if (desktopVisibilityController != null) {
+ desktopVisibilityController.onHomeActionTriggered();
+ }
+ }
+
mService.getOverviewCommandHelper().addCommand(OverviewCommandHelper.TYPE_HOME);
}
@@ -295,13 +310,16 @@
}
}
- private void startAssistant() {
+ private void onLongPressHome() {
if (mScreenPinned || !mAssistantLongPressEnabled) {
return;
}
- Bundle args = new Bundle();
- args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS);
- mSystemUiProxy.startAssistant(args);
+ // Attempt to start Assist with AssistUtils, otherwise fall back to SysUi's implementation.
+ if (!mAssistUtils.tryStartAssistOverride(INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS)) {
+ Bundle args = new Bundle();
+ args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS);
+ mSystemUiProxy.startAssistant(args);
+ }
}
private void showQuickSettings() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index 512b77a..a667dca 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.taskbar;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP;
import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
import android.content.Intent;
@@ -163,19 +162,9 @@
.filter(Objects::nonNull)
.collect(Collectors.toList());
- if (ENABLE_MATERIAL_U_POPUP.get()) {
- container = (PopupContainerWithArrow) context.getLayoutInflater().inflate(
- R.layout.popup_container_material_u, context.getDragLayer(), false);
- container.populateAndShowRowsMaterialU(icon, deepShortcutCount, systemShortcuts);
- } else {
- container = (PopupContainerWithArrow) context.getLayoutInflater().inflate(
+ container = (PopupContainerWithArrow) context.getLayoutInflater().inflate(
R.layout.popup_container, context.getDragLayer(), false);
- container.populateAndShow(
- icon,
- deepShortcutCount,
- mPopupDataProvider.getNotificationKeysForItem(item),
- systemShortcuts);
- }
+ container.populateAndShowRows(icon, deepShortcutCount, systemShortcuts);
container.addOnAttachStateChangeListener(
new PopupLiveUpdateHandler<BaseTaskbarContext>(context, container) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
index cdc6d59..e40757a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
@@ -70,6 +70,10 @@
invalidate();
}
+ protected float getScrimAlpha() {
+ return mRenderer.getPaint().getAlpha() / 255f;
+ }
+
/**
* Sets the roundness of the round corner above Taskbar.
* @param cornerRoundness 0 has no round corner, 1 has complete round corner.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
index 5ea00cf..a0ce976 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
@@ -15,14 +15,20 @@
*/
package com.android.launcher3.taskbar;
+import static android.view.View.VISIBLE;
+
+import static com.android.launcher3.taskbar.bubbles.BubbleBarController.BUBBLE_BAR_ENABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED;
+import static com.android.wm.shell.common.bubbles.BubbleConstants.BUBBLE_EXPANDED_SCRIM_ALPHA;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
import android.animation.ObjectAnimator;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import com.android.launcher3.anim.AnimatedFloat;
+import com.android.launcher3.util.DisplayController;
import com.android.quickstep.SystemUiProxy;
import java.io.PrintWriter;
@@ -33,13 +39,13 @@
public class TaskbarScrimViewController implements TaskbarControllers.LoggableTaskbarController,
TaskbarControllers.BackgroundRendererController {
- private static final float SCRIM_ALPHA = 0.6f;
-
private static final Interpolator SCRIM_ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
private static final Interpolator SCRIM_ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
private final TaskbarActivityContext mActivity;
private final TaskbarScrimView mScrimView;
+ private boolean mTaskbarVisible;
+ private int mSysUiStateFlags;
// Alpha property for the scrim.
private final AnimatedFloat mScrimAlpha = new AnimatedFloat(this::updateScrimAlpha);
@@ -60,31 +66,60 @@
}
/**
+ * Called when the taskbar visibility changes.
+ *
+ * @param visibility the current visibility of {@link TaskbarView}.
+ */
+ public void onTaskbarVisibilityChanged(int visibility) {
+ mTaskbarVisible = visibility == VISIBLE;
+ if (shouldShowScrim()) {
+ showScrim(true, getScrimAlpha(), false /* skipAnim */);
+ } else if (mScrimView.getScrimAlpha() > 0f) {
+ showScrim(false, 0, false /* skipAnim */);
+ }
+ }
+
+ /**
* Updates the scrim state based on the flags.
*/
public void updateStateForSysuiFlags(int stateFlags, boolean skipAnim) {
- final boolean bubblesExpanded = (stateFlags & SYSUI_STATE_BUBBLES_EXPANDED) != 0;
+ if (BUBBLE_BAR_ENABLED && DisplayController.isTransientTaskbar(mActivity)) {
+ // These scrims aren't used if bubble bar & transient taskbar are active.
+ return;
+ }
+ mSysUiStateFlags = stateFlags;
+ showScrim(shouldShowScrim(), getScrimAlpha(), skipAnim);
+ }
+
+ private boolean shouldShowScrim() {
+ final boolean bubblesExpanded = (mSysUiStateFlags & SYSUI_STATE_BUBBLES_EXPANDED) != 0;
+ boolean isShadeVisible = (mSysUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE) != 0;
+ return bubblesExpanded && !mControllers.navbarButtonsViewController.isImeVisible()
+ && !isShadeVisible
+ && !mControllers.taskbarStashController.isStashed()
+ && mTaskbarVisible;
+ }
+
+ private float getScrimAlpha() {
final boolean manageMenuExpanded =
- (stateFlags & SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED) != 0;
- final boolean showScrim = !mControllers.navbarButtonsViewController.isImeVisible()
- && bubblesExpanded
- && mControllers.taskbarStashController.isTaskbarVisibleAndNotStashing();
- final float scrimAlpha = manageMenuExpanded
+ (mSysUiStateFlags & SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED) != 0;
+ return manageMenuExpanded
// When manage menu shows there's the first scrim and second scrim so figure out
// what the total transparency would be.
- ? (SCRIM_ALPHA + (SCRIM_ALPHA * (1 - SCRIM_ALPHA)))
- : showScrim ? SCRIM_ALPHA : 0;
- showScrim(showScrim, scrimAlpha, skipAnim);
+ ? (BUBBLE_EXPANDED_SCRIM_ALPHA + (BUBBLE_EXPANDED_SCRIM_ALPHA
+ * (1 - BUBBLE_EXPANDED_SCRIM_ALPHA)))
+ : shouldShowScrim() ? BUBBLE_EXPANDED_SCRIM_ALPHA : 0;
}
private void showScrim(boolean showScrim, float alpha, boolean skipAnim) {
mScrimView.setOnClickListener(showScrim ? (view) -> onClick() : null);
mScrimView.setClickable(showScrim);
- ObjectAnimator anim = mScrimAlpha.animateToValue(showScrim ? alpha : 0);
- anim.setInterpolator(showScrim ? SCRIM_ALPHA_IN : SCRIM_ALPHA_OUT);
- anim.start();
if (skipAnim) {
- anim.end();
+ mScrimView.setScrimAlpha(alpha);
+ } else {
+ ObjectAnimator anim = mScrimAlpha.animateToValue(showScrim ? alpha : 0);
+ anim.setInterpolator(showScrim ? SCRIM_ALPHA_IN : SCRIM_ALPHA_OUT);
+ anim.start();
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
index 66ca7d9..abbd18b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
@@ -15,15 +15,28 @@
*/
package com.android.launcher3.taskbar;
+import static android.view.InsetsFrameProvider.SOURCE_DISPLAY;
+import static android.view.WindowInsets.Type.mandatorySystemGestures;
+import static android.view.WindowInsets.Type.navigationBars;
+import static android.view.WindowInsets.Type.systemGestures;
+import static android.view.WindowInsets.Type.tappableElement;
+
import static com.android.launcher3.taskbar.LauncherTaskbarUIController.DISPLAY_PROGRESS_COUNT;
import android.app.PendingIntent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.view.InsetsFrameProvider;
/**
* State shared across different taskbar instance
*/
public class TaskbarSharedState {
+ private final IBinder mInsetsOwner = new Binder();
+ private static int INDEX_LEFT = 0;
+ private static int INDEX_RIGHT = 1;
+
// TaskbarManager#onSystemUiFlagsChanged
public int sysuiStateFlags;
@@ -48,4 +61,14 @@
// Taskbar System Action
public PendingIntent taskbarSystemActionPendingIntent;
+
+ public final InsetsFrameProvider[] insetsFrameProviders = new InsetsFrameProvider[] {
+ new InsetsFrameProvider(mInsetsOwner, 0, navigationBars()),
+ new InsetsFrameProvider(mInsetsOwner, 0, tappableElement()),
+ new InsetsFrameProvider(mInsetsOwner, 0, mandatorySystemGestures()),
+ new InsetsFrameProvider(mInsetsOwner, INDEX_LEFT, systemGestures())
+ .setSource(SOURCE_DISPLAY),
+ new InsetsFrameProvider(mInsetsOwner, INDEX_RIGHT, systemGestures())
+ .setSource(SOURCE_DISPLAY)
+ };
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index daf9c47..f2b60b9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -18,21 +18,22 @@
import static android.view.HapticFeedbackConstants.LONG_PRESS;
import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.FINAL_FRAME;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING_KEY;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
-import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_PINNING;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_HIDE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_SHOW;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_HIDE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_SHOW;
import static com.android.launcher3.taskbar.TaskbarKeyguardController.MASK_ANY_SYSUI_LOCKED;
-import static com.android.launcher3.taskbar.TaskbarManager.SYSTEM_ACTION_ID_TASKBAR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.FlagDebugUtils.appendFlag;
import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange;
+import static com.android.quickstep.util.SystemActionConstants.SYSTEM_ACTION_ID_TASKBAR;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
@@ -96,6 +97,7 @@
public static final int FLAG_STASHED_IN_APP_AUTO = 1 << 9; // Autohide (transient taskbar).
public static final int FLAG_STASHED_SYSUI = 1 << 10; // app pinning,...
public static final int FLAG_STASHED_DEVICE_LOCKED = 1 << 11; // device is locked: keyguard, ...
+ public static final int FLAG_IN_OVERVIEW = 1 << 12; // launcher is in overview
// If any of these flags are enabled, isInApp should return true.
private static final int FLAGS_IN_APP = FLAG_IN_APP | FLAG_IN_SETUP;
@@ -257,14 +259,15 @@
private boolean mEnableBlockingTimeoutDuringTests = false;
// Evaluate whether the handle should be stashed
+ private final IntPredicate mIsStashedPredicate = flags -> {
+ boolean inApp = hasAnyFlag(flags, FLAGS_IN_APP);
+ boolean stashedInApp = hasAnyFlag(flags, FLAGS_STASHED_IN_APP);
+ boolean stashedLauncherState = hasAnyFlag(flags, FLAG_IN_STASHED_LAUNCHER_STATE);
+ boolean forceStashed = hasAnyFlag(flags, FLAGS_FORCE_STASHED);
+ return (inApp && stashedInApp) || (!inApp && stashedLauncherState) || forceStashed;
+ };
private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder(
- flags -> {
- boolean inApp = hasAnyFlag(flags, FLAGS_IN_APP);
- boolean stashedInApp = hasAnyFlag(flags, FLAGS_STASHED_IN_APP);
- boolean stashedLauncherState = hasAnyFlag(flags, FLAG_IN_STASHED_LAUNCHER_STATE);
- boolean forceStashed = hasAnyFlag(flags, FLAGS_FORCE_STASHED);
- return (inApp && stashedInApp) || (!inApp && stashedLauncherState) || forceStashed;
- });
+ mIsStashedPredicate);
private boolean mIsTaskbarSystemActionRegistered = false;
private TaskbarSharedState mTaskbarSharedState;
@@ -337,7 +340,6 @@
// us that we're paused until a bit later. This avoids flickering upon recreating taskbar.
updateStateForFlag(FLAG_IN_APP, true);
applyState(/* duration = */ 0);
-
notifyStashChange(/* visible */ false, /* stashed */ isStashedInApp());
}
@@ -504,9 +506,19 @@
}
/**
- * Stash or unstashes the transient taskbar.
+ * Stash or unstashes the transient taskbar, using the default TASKBAR_STASH_DURATION.
+ * If bubble bar exists, it will match taskbars stashing behavior.
*/
public void updateAndAnimateTransientTaskbar(boolean stash) {
+ updateAndAnimateTransientTaskbar(stash, /* shouldBubblesFollow= */ true);
+ }
+
+ /**
+ * Stash or unstashes the transient taskbar.
+ * @param stash whether transient taskbar should be stashed.
+ * @param shouldBubblesFollow whether bubbles should match taskbars behavior.
+ */
+ public void updateAndAnimateTransientTaskbar(boolean stash, boolean shouldBubblesFollow) {
if (!DisplayController.isTransientTaskbar(mActivity)) {
return;
}
@@ -525,6 +537,34 @@
updateStateForFlag(FLAG_STASHED_IN_APP_AUTO, stash);
applyState();
}
+
+ mControllers.bubbleControllers.ifPresent(controllers -> {
+ if (shouldBubblesFollow) {
+ final boolean willStash = mIsStashedPredicate.test(mState);
+ if (willStash != controllers.bubbleStashController.isStashed()) {
+ // Typically bubbles gets stashed / unstashed along with Taskbar, however, if
+ // taskbar is becoming stashed because bubbles is being expanded, we don't want
+ // to stash bubbles.
+ if (willStash) {
+ controllers.bubbleStashController.stashBubbleBar();
+ } else {
+ controllers.bubbleStashController.showBubbleBar(false /* expandBubbles */);
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * Stashes transient taskbar after it has timed out.
+ */
+ private void updateAndAnimateTransientTaskbarForTimeout() {
+ // If bubbles are expanded we shouldn't stash them when taskbar is hidden
+ // for the timeout.
+ boolean bubbleBarExpanded = mControllers.bubbleControllers.isPresent()
+ && mControllers.bubbleControllers.get().bubbleBarViewController.isExpanded();
+ updateAndAnimateTransientTaskbar(/* stash= */ true,
+ /* shouldBubblesFollow= */ !bubbleBarExpanded);
}
/**
@@ -636,7 +676,10 @@
.setDuration(duration));
mAnimator.play(mTaskbarImeBgAlpha.animateToValue(
hasAnyFlag(FLAG_STASHED_IN_APP_IME) ? 0 : 1).setDuration(duration));
- mAnimator.addListener(AnimatorListeners.forEndCallback(() -> mAnimator = null));
+ mAnimator.addListener(AnimatorListeners.forEndCallback(() -> {
+ mAnimator = null;
+ mIsStashed = isStashed;
+ }));
return;
}
@@ -830,8 +873,11 @@
.setDuration(isStashed ? duration / 2 : duration));
}
- private static void play(AnimatorSet as, Animator a, long startDelay, long duration,
+ private static void play(AnimatorSet as, @Nullable Animator a, long startDelay, long duration,
Interpolator interpolator) {
+ if (a == null) {
+ return;
+ }
a.setDuration(duration);
a.setStartDelay(startDelay);
a.setInterpolator(interpolator);
@@ -897,7 +943,7 @@
private void onIsStashedChanged(boolean isStashed) {
mControllers.runAfterInit(() -> {
mControllers.stashedHandleViewController.onIsStashedChanged(isStashed);
- mControllers.taskbarInsetsController.onTaskbarWindowHeightOrInsetsChanged();
+ mControllers.taskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
});
}
@@ -971,9 +1017,12 @@
updateStateForFlag(FLAG_STASHED_IN_APP_SYSUI, hasAnyFlag(systemUiStateFlags,
SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE));
- updateStateForFlag(FLAG_STASHED_SYSUI,
- hasAnyFlag(systemUiStateFlags, SYSUI_STATE_SCREEN_PINNING));
+ boolean stashForBubbles = hasAnyFlag(FLAG_IN_OVERVIEW)
+ && hasAnyFlag(systemUiStateFlags, SYSUI_STATE_BUBBLES_EXPANDED)
+ && DisplayController.isTransientTaskbar(mActivity);
+ updateStateForFlag(FLAG_STASHED_SYSUI,
+ hasAnyFlag(systemUiStateFlags, SYSUI_STATE_SCREEN_PINNING) || stashForBubbles);
boolean isLocked = hasAnyFlag(systemUiStateFlags, MASK_ANY_SYSUI_LOCKED)
&& !hasAnyFlag(systemUiStateFlags, SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY);
updateStateForFlag(FLAG_STASHED_DEVICE_LOCKED, isLocked);
@@ -1053,6 +1102,7 @@
TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_TRANSIENT_TASKBAR,
!hasAnyFlag(FLAG_STASHED_IN_APP_AUTO));
}
+ mActivity.applyForciblyShownFlagWhileTransientTaskbarUnstashed(!isStashedInApp());
}
private void notifyStashChange(boolean visible, boolean stashed) {
@@ -1147,7 +1197,7 @@
if (mControllers.taskbarAutohideSuspendController.isTransientTaskbarStashingSuspended()) {
return;
}
- updateAndAnimateTransientTaskbar(true);
+ updateAndAnimateTransientTaskbarForTimeout();
}
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt
index 1cc6672..deaf024 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt
@@ -16,9 +16,9 @@
package com.android.launcher3.taskbar
import android.view.MotionEvent
+import com.android.app.animation.Interpolators.LINEAR
import com.android.launcher3.R
import com.android.launcher3.Utilities
-import com.android.launcher3.anim.Interpolators.LINEAR
import com.android.launcher3.testing.shared.ResourceUtils
import com.android.launcher3.touch.SingleAxisSwipeDetector
import com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_NEGATIVE
@@ -108,7 +108,17 @@
}
override fun onControllerInterceptTouchEvent(ev: MotionEvent): Boolean {
- if (!enabled || controllers.taskbarStashController.isStashed) {
+ if (!enabled) {
+ return false
+ }
+ val bubbleControllers = controllers.bubbleControllers.orElse(null)
+ if (bubbleControllers != null && bubbleControllers.bubbleBarViewController.isExpanded) {
+ return false
+ }
+ if (
+ (bubbleControllers == null || bubbleControllers.bubbleStashController.isStashed) &&
+ controllers.taskbarStashController.isStashed
+ ) {
return false
}
@@ -122,7 +132,12 @@
return true
}
} else if (ev.action == MotionEvent.ACTION_DOWN) {
- if (screenCoordinatesEv.y < gestureHeightYThreshold) {
+ val isDownOnBubbleBar =
+ (bubbleControllers != null &&
+ bubbleControllers.bubbleBarViewController.isEventOverAnyItem(
+ screenCoordinatesEv
+ ))
+ if (!isDownOnBubbleBar && screenCoordinatesEv.y < gestureHeightYThreshold) {
controllers.taskbarStashController.updateAndAnimateTransientTaskbar(true)
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarThresholdUtils.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarThresholdUtils.java
new file mode 100644
index 0000000..5b6fbef
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarThresholdUtils.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar;
+
+import static com.android.launcher3.Utilities.dpToPx;
+import static com.android.launcher3.Utilities.dpiFromPx;
+
+import android.content.res.Resources;
+import android.util.DisplayMetrics;
+
+import androidx.core.content.res.ResourcesCompat;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
+
+/**
+ * Utility class that contains the different taskbar thresholds logic.
+ */
+public class TaskbarThresholdUtils {
+
+ // We divide the screen into this many parts, and use the result to scale the thresholds to
+ // any size device. Note that this value was calculated arbitrarily by using two tablet devices
+ // as data points.
+ private static final float SCREEN_UNITS = 1 / 80f;
+
+ private static int getThreshold(Resources r, DeviceProfile dp, int thresholdDimen,
+ int multiplierDimen) {
+ if (!FeatureFlags.ENABLE_DYNAMIC_TASKBAR_THRESHOLDS.get()) {
+ return r.getDimensionPixelSize(thresholdDimen);
+ }
+
+ float landscapeScreenHeight = dp.isLandscape ? dp.heightPx : dp.widthPx;
+ float screenPart = (landscapeScreenHeight * SCREEN_UNITS);
+ float defaultDp = dpiFromPx(screenPart, DisplayMetrics.DENSITY_DEVICE_STABLE);
+ float thisDp = dpToPx(defaultDp);
+ float multiplier = ResourcesCompat.getFloat(r, multiplierDimen);
+ float value = (thisDp) * multiplier;
+
+ return Math.round(value);
+ }
+
+ /**
+ * Returns the threshold that determines if we should show taskbar.
+ */
+ public static int getFromNavThreshold(Resources r, DeviceProfile dp) {
+ return getThreshold(r, dp, R.dimen.taskbar_from_nav_threshold,
+ R.dimen.taskbar_nav_threshold_mult);
+ }
+
+ /**
+ * Returns the threshold that we start moving the app window.
+ */
+ public static int getAppWindowThreshold(Resources r, DeviceProfile dp) {
+ return getThreshold(r, dp, R.dimen.taskbar_app_window_threshold,
+ R.dimen.taskbar_app_window_threshold_mult);
+ }
+
+ /**
+ * Returns the threshold for whether we land in home or overview.
+ */
+ public static int getHomeOverviewThreshold(Resources r, DeviceProfile dp) {
+ return getThreshold(r, dp, R.dimen.taskbar_home_overview_threshold,
+ R.dimen.taskbar_home_overview_threshold_mult);
+ }
+
+ /**
+ * Returns the threshold that we use to allow swipe to catch up to finger.
+ */
+ public static int getCatchUpThreshold(Resources r, DeviceProfile dp) {
+ return getThreshold(r, dp, R.dimen.taskbar_catch_up_threshold,
+ R.dimen.taskbar_catch_up_threshold_mult);
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
index 065d111..916b1e6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
@@ -26,8 +26,8 @@
import androidx.annotation.Nullable;
import androidx.dynamicanimation.animation.SpringForce;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.anim.AnimatedFloat;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.SpringAnimationBuilder;
import com.android.launcher3.util.DisplayController;
@@ -92,6 +92,10 @@
mControllers.stashedHandleViewController.setTranslationYForSwipe(transY);
mControllers.taskbarViewController.setTranslationYForSwipe(transY);
mControllers.taskbarDragLayerController.setTranslationYForSwipe(transY);
+ mControllers.bubbleControllers.ifPresent(controllers -> {
+ controllers.bubbleBarViewController.setTranslationYForSwipe(transY);
+ controllers.bubbleStashedHandleViewController.setTranslationYForSwipe(transY);
+ });
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 7154731..139e8f0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -40,8 +40,10 @@
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
+import com.android.systemui.shared.recents.model.Task;
import java.io.PrintWriter;
+import java.util.Collections;
import java.util.stream.Stream;
/**
@@ -204,9 +206,10 @@
return;
}
- recentsView.getSplitSelectController().findLastActiveTaskAndRunCallback(
- splitSelectSource.itemInfo.getComponentKey(),
- foundTask -> {
+ recentsView.getSplitSelectController().findLastActiveTasksAndRunCallback(
+ Collections.singletonList(splitSelectSource.itemInfo.getComponentKey()),
+ foundTasks -> {
+ @Nullable Task foundTask = foundTasks.get(0);
splitSelectSource.alreadyRunningTaskId = foundTask == null
? INVALID_TASK_ID
: foundTask.key.id;
@@ -221,9 +224,10 @@
*/
public void triggerSecondAppForSplit(ItemInfoWithIcon info, Intent intent, View startingView) {
RecentsView recents = getRecentsView();
- recents.getSplitSelectController().findLastActiveTaskAndRunCallback(
- info.getComponentKey(),
- foundTask -> {
+ recents.getSplitSelectController().findLastActiveTasksAndRunCallback(
+ Collections.singletonList(info.getComponentKey()),
+ foundTasks -> {
+ @Nullable Task foundTask = foundTasks.get(0);
if (foundTask != null) {
TaskView foundTaskView = recents.getTaskViewByTaskId(foundTask.key.id);
// TODO (b/266482558): This additional null check is needed because there
@@ -331,4 +335,7 @@
.stream()
.map(mControllers.taskbarPopupController::createSplitShortcutFactory);
}
+
+ /** Adjusts the hotseat for the bubble bar. */
+ public void adjustHotseatForBubbleBar(boolean isBubbleBarVisible) {}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index bf3b932..3dc30dc 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -18,6 +18,8 @@
import static android.content.pm.PackageManager.FEATURE_PC;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR;
+import static com.android.launcher3.config.FeatureFlags.enableCursorHoverStates;
import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
import android.content.Context;
@@ -32,6 +34,8 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
+import androidx.annotation.DimenRes;
+import androidx.annotation.DrawableRes;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -87,13 +91,13 @@
private @Nullable IconButtonView mAllAppsButton;
// Only non-null when device supports having an All Apps button.
- private @Nullable View mTaskbarDivider;
+ private @Nullable IconButtonView mTaskbarDivider;
- private View mQsb;
+ private final View mQsb;
- private float mTransientTaskbarMinWidth;
+ private final float mTransientTaskbarMinWidth;
- private float mTransientTaskbarAllAppsButtonTranslationXOffset;
+ private final float mTaskbarAllAppsButtonTranslationXOffset;
private boolean mShouldTryStartAlign;
@@ -119,12 +123,9 @@
boolean isTransientTaskbar = DisplayController.isTransientTaskbar(mActivityContext)
&& !TaskbarManager.isPhoneMode(mActivityContext.getDeviceProfile());
mIsRtl = Utilities.isRtl(resources);
- mTransientTaskbarMinWidth = mContext.getResources().getDimension(
- R.dimen.transient_taskbar_min_width);
- mTransientTaskbarAllAppsButtonTranslationXOffset =
- resources.getDimension(isTransientTaskbar
- ? R.dimen.transient_taskbar_all_apps_button_translation_x_offset
- : R.dimen.taskbar_all_apps_button_translation_x_offset);
+ mTransientTaskbarMinWidth = resources.getDimension(R.dimen.transient_taskbar_min_width);
+ mTaskbarAllAppsButtonTranslationXOffset =
+ resources.getDimension(getAllAppsButtonTranslationXOffset(isTransientTaskbar));
onDeviceProfileChanged(mActivityContext.getDeviceProfile());
@@ -148,17 +149,20 @@
if (!mActivityContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
mAllAppsButton = (IconButtonView) LayoutInflater.from(context)
.inflate(R.layout.taskbar_all_apps_button, this, false);
- mAllAppsButton.setIconDrawable(resources.getDrawable(isTransientTaskbar
- ? R.drawable.ic_transient_taskbar_all_apps_button
- : R.drawable.ic_taskbar_all_apps_button));
+ mAllAppsButton.setIconDrawable(resources.getDrawable(
+ getAllAppsButton(isTransientTaskbar)));
mAllAppsButton.setScaleX(mIsRtl ? -1 : 1);
mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
mAllAppsButton.setForegroundTint(
mActivityContext.getColor(R.color.all_apps_button_color));
if (FeatureFlags.ENABLE_TASKBAR_PINNING.get()) {
- mTaskbarDivider = LayoutInflater.from(context).inflate(R.layout.taskbar_divider,
+ mTaskbarDivider = (IconButtonView) LayoutInflater.from(context).inflate(
+ R.layout.taskbar_divider,
this, false);
+ mTaskbarDivider.setIconDrawable(
+ resources.getDrawable(R.drawable.taskbar_divider_button));
+ mTaskbarDivider.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
}
}
@@ -166,6 +170,39 @@
mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false);
}
+ @DrawableRes
+ private int getAllAppsButton(boolean isTransientTaskbar) {
+ if (ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
+ return isTransientTaskbar
+ ? R.drawable.ic_transient_taskbar_all_apps_search_button
+ : R.drawable.ic_taskbar_all_apps_search_button;
+ } else {
+ return isTransientTaskbar
+ ? R.drawable.ic_transient_taskbar_all_apps_button
+ : R.drawable.ic_taskbar_all_apps_button;
+ }
+ }
+
+ @DimenRes
+ private int getAllAppsButtonTranslationXOffset(boolean isTransientTaskbar) {
+ if (isTransientTaskbar) {
+ return R.dimen.transient_taskbar_all_apps_button_translation_x_offset;
+ } else {
+ return ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()
+ ? R.dimen.taskbar_all_apps_search_button_translation_x_offset
+ : R.dimen.taskbar_all_apps_button_translation_x_offset;
+ }
+ }
+
+ @Override
+ public void setVisibility(int visibility) {
+ boolean changed = getVisibility() != visibility;
+ super.setVisibility(visibility);
+ if (changed && mControllerCallbacks != null) {
+ mControllerCallbacks.notifyVisibilityChanged();
+ }
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -319,6 +356,9 @@
}
}
setClickAndLongClickListenersForIcon(hotseatView);
+ if (enableCursorHoverStates()) {
+ setHoverListenerForIcon(hotseatView);
+ }
nextViewIndex++;
}
// Remove remaining views
@@ -328,7 +368,7 @@
if (mAllAppsButton != null) {
mAllAppsButton.setTranslationXForTaskbarAllAppsIcon(getChildCount() > 0
- ? mTransientTaskbarAllAppsButtonTranslationXOffset : 0f);
+ ? mTaskbarAllAppsButtonTranslationXOffset : 0f);
addView(mAllAppsButton, mIsRtl ? getChildCount() : 0);
// if only all apps button present, don't include divider view.
@@ -366,16 +406,18 @@
icon.setOnLongClickListener(mIconLongClickListener);
}
+ /**
+ * Sets OnHoverListener for the given view.
+ */
+ private void setHoverListenerForIcon(View icon) {
+ icon.setOnHoverListener(mControllerCallbacks.getIconOnHoverListener(icon));
+ }
+
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int count = getChildCount();
DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
int spaceNeeded = getIconLayoutWidth();
- // We are removing the margin from taskbar divider item in taskbar,
- // so remove it from spacing also.
- if (FeatureFlags.ENABLE_TASKBAR_PINNING.get() && count > 1) {
- spaceNeeded -= mIconTouchSize;
- }
int navSpaceNeeded = deviceProfile.hotseatBarEndOffset;
boolean layoutRtl = isLayoutRtl();
int centerAlignIconEnd = right - (right - left - spaceNeeded) / 2;
@@ -496,7 +538,15 @@
if (deviceProfile.isQsbInline) {
countExcludingQsb--;
}
- return countExcludingQsb * (mItemMarginLeftRight * 2 + mIconTouchSize);
+ int iconLayoutBoundsWidth =
+ countExcludingQsb * (mItemMarginLeftRight * 2 + mIconTouchSize);
+
+ if (FeatureFlags.ENABLE_TASKBAR_PINNING.get() && countExcludingQsb > 1) {
+ // We are removing 4 * mItemMarginLeftRight as there should be no space between
+ // All Apps icon, divider icon, and first app icon in taskbar
+ iconLayoutBoundsWidth -= mItemMarginLeftRight * 4;
+ }
+ return iconLayoutBoundsWidth;
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 4abd995..b405320 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.taskbar;
+import static com.android.app.animation.Interpolators.FINAL_FRAME;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
@@ -22,9 +24,8 @@
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.anim.AnimatedFloat.VALUE;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP;
+import static com.android.launcher3.taskbar.TaskbarManager.isPhoneButtonNavMode;
import static com.android.launcher3.taskbar.TaskbarManager.isPhoneMode;
import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_TASKBAR_ALIGNMENT_ANIM;
@@ -45,6 +46,7 @@
import androidx.core.graphics.ColorUtils;
import androidx.core.view.OneShotPreDrawListener;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
@@ -53,7 +55,6 @@
import com.android.launcher3.anim.AlphaUpdateListener;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.RevealOutlineAnimation;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
@@ -133,7 +134,8 @@
mTaskbarView = taskbarView;
mTaskbarIconAlpha = new MultiValueAlpha(mTaskbarView, NUM_ALPHA_CHANNELS);
mTaskbarIconAlpha.setUpdateVisibility(true);
- mModelCallbacks = new TaskbarModelCallbacks(activity, mTaskbarView);
+ mModelCallbacks = TaskbarModelCallbacksFactory.newInstance(mActivity)
+ .create(mActivity, mTaskbarView);
mTaskbarBottomMargin = activity.getDeviceProfile().taskbarBottomMargin;
mStashedHandleHeight = activity.getResources()
.getDimensionPixelSize(R.dimen.taskbar_stashed_handle_height);
@@ -170,6 +172,13 @@
.getTaskbarNavButtonTranslationYForInAppDisplay();
mActivity.addOnDeviceProfileChangeListener(mDeviceProfileChangeListener);
+
+ if (TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW) {
+ // This gets modified in NavbarButtonsViewController, but the initial value it reads
+ // may be incorrect since it's state gets destroyed on taskbar recreate, so reset here
+ mTaskbarIconAlpha.get(ALPHA_INDEX_SMALL_SCREEN)
+ .animateToValue(isPhoneButtonNavMode(mActivity) ? 0 : 1).start();
+ }
}
/**
@@ -439,12 +448,22 @@
}
}
+ /** Resets the icon alignment controller so that it can be recreated again later. */
+ void resetIconAlignmentController() {
+ mIconAlignControllerLazy = null;
+ }
+
/**
* Creates an animation for aligning the Taskbar icons with the provided Launcher device profile
*/
private AnimatorPlaybackController createIconAlignmentController(DeviceProfile launcherDp) {
- mOnControllerPreCreateCallback.run();
PendingAnimation setter = new PendingAnimation(100);
+ if (TaskbarManager.isPhoneButtonNavMode(mActivity)) {
+ // No animation for icons in small-screen
+ return setter.createPlaybackController();
+ }
+
+ mOnControllerPreCreateCallback.run();
DeviceProfile taskbarDp = mActivity.getDeviceProfile();
Rect hotseatPadding = launcherDp.getHotseatLayoutPadding(mActivity);
float scaleUp = ((float) launcherDp.iconSizePx) / taskbarDp.taskbarIconSize;
@@ -550,9 +569,18 @@
continue;
}
- float hotseatIconCenter = hotseatPadding.left
- + (hotseatCellSize + borderSpacing) * positionInHotseat
- + hotseatCellSize / 2f;
+ float hotseatAdjustedBorderSpace =
+ launcherDp.getHotseatAdjustedBorderSpaceForBubbleBar(child.getContext());
+ float hotseatIconCenter;
+ if (bubbleBarHasBubbles() && hotseatAdjustedBorderSpace != 0) {
+ hotseatIconCenter = hotseatPadding.left + hotseatCellSize
+ + (hotseatCellSize + hotseatAdjustedBorderSpace) * positionInHotseat
+ + hotseatCellSize / 2f;
+ } else {
+ hotseatIconCenter = hotseatPadding.left
+ + (hotseatCellSize + borderSpacing) * positionInHotseat
+ + hotseatCellSize / 2f;
+ }
float childCenter = (child.getLeft() + child.getRight()) / 2f;
float toX = hotseatIconCenter - childCenter;
if (child instanceof Reorderable) {
@@ -574,6 +602,11 @@
return controller;
}
+ private boolean bubbleBarHasBubbles() {
+ return mControllers.bubbleControllers.isPresent()
+ && mControllers.bubbleControllers.get().bubbleBarViewController.hasBubbles();
+ }
+
public void onRotationChanged(DeviceProfile deviceProfile) {
if (!mControllers.uiController.isIconAlignedWithHotseat()) {
// We only translate on rotation when icon is aligned with hotseat
@@ -676,6 +709,11 @@
.updateAndAnimateIsManuallyStashedInApp(true);
}
+ /** Gets the hover listener for the provided icon view. */
+ public View.OnHoverListener getIconOnHoverListener(View icon) {
+ return new TaskbarHoverToolTipController(mActivity, mTaskbarView, icon);
+ }
+
/**
* Get the first chance to handle TaskbarView#onTouchEvent, and return whether we want to
* consume the touch so TaskbarView treats it as an ACTION_CANCEL.
@@ -718,5 +756,13 @@
public void notifyIconLayoutBoundsChanged() {
mControllers.uiController.onIconLayoutBoundsChanged();
}
+
+ /**
+ * Notifies the taskbar scrim when the visibility of taskbar changes.
+ */
+ public void notifyVisibilityChanged() {
+ mControllers.taskbarScrimViewController.onTaskbarVisibilityChanged(
+ mTaskbarView.getVisibility());
+ }
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt b/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
index 5eb240e..5a5ff8e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
@@ -192,13 +192,13 @@
removeOnAttachStateChangeListener(pendingAttachedToWindowListener)
pendingAttachedToWindowListener =
object : View.OnAttachStateChangeListener {
- override fun onViewAttachedToWindow(v: View?) {
+ override fun onViewAttachedToWindow(v: View) {
onAttachedToWindow()
removeOnAttachStateChangeListener(this)
pendingAttachedToWindowListener = null
}
- override fun onViewDetachedFromWindow(v: View?) {}
+ override fun onViewDetachedFromWindow(v: View) {}
}
addOnAttachStateChangeListener(pendingAttachedToWindowListener)
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
index b4b83f6..5d91acd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
@@ -47,9 +47,9 @@
}
@Override
- protected View inflateSearchBox() {
+ protected View inflateSearchBar() {
if (isSearchSupported()) {
- return super.inflateSearchBox();
+ return super.inflateSearchBar();
}
// Remove top padding of header, since we do not have any search
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
index e0a502b..c54bb7e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
@@ -15,11 +15,17 @@
*/
package com.android.launcher3.taskbar.allapps;
+import static com.android.launcher3.model.data.AppInfo.EMPTY_ARRAY;
+
+import android.view.View;
+
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.R;
import com.android.launcher3.appprediction.PredictionRowView;
+import com.android.launcher3.dragndrop.DragOptions.PreDragCondition;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.taskbar.TaskbarControllers;
@@ -30,7 +36,6 @@
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
-
/**
* Handles the all apps overlay window initialization, updates, and its data.
* <p>
@@ -45,13 +50,16 @@
public final class TaskbarAllAppsController {
private TaskbarControllers mControllers;
+ private @Nullable TaskbarOverlayContext mOverlayContext;
private @Nullable TaskbarAllAppsSlideInView mSlideInView;
private @Nullable TaskbarAllAppsContainerView mAppsView;
+ private @Nullable TaskbarSearchSessionController mSearchSessionController;
// Application data models.
- private AppInfo[] mApps;
+ private @NonNull AppInfo[] mApps = EMPTY_ARRAY;
private int mAppsModelFlags;
- private List<ItemInfo> mPredictedApps;
+ private @NonNull List<ItemInfo> mPredictedApps = Collections.emptyList();
+ private @Nullable List<ItemInfo> mZeroStateSearchSuggestions;
private boolean mDisallowGlobalDrag;
private boolean mDisallowLongClick;
@@ -70,9 +78,14 @@
}
}
+ /** Clean up the controller. */
+ public void onDestroy() {
+ cleanUpOverlay();
+ }
+
/** Updates the current {@link AppInfo} instances. */
- public void setApps(AppInfo[] apps, int flags, Map<PackageUserKey, Integer> map) {
- mApps = apps;
+ public void setApps(@Nullable AppInfo[] apps, int flags, Map<PackageUserKey, Integer> map) {
+ mApps = apps == null ? EMPTY_ARRAY : apps;
mAppsModelFlags = flags;
mPackageUserKeytoUidMap = map;
if (mAppsView != null) {
@@ -96,6 +109,14 @@
.findFixedRowByType(PredictionRowView.class)
.setPredictedApps(mPredictedApps);
}
+ if (mSearchSessionController != null) {
+ mSearchSessionController.setZeroStatePredictedItems(predictedApps);
+ }
+ }
+
+ /** Updates the current search suggestions. */
+ public void setZeroStateSearchSuggestions(List<ItemInfo> zeroStateSearchSuggestions) {
+ mZeroStateSearchSuggestions = zeroStateSearchSuggestions;
}
/** Updates the current notification dots. */
@@ -107,10 +128,19 @@
/** Toggles visibility of {@link TaskbarAllAppsContainerView} in the overlay window. */
public void toggle() {
+ toggle(false);
+ }
+
+ /** Toggles visibility of {@link TaskbarAllAppsContainerView} with the keyboard for search. */
+ public void toggleSearch() {
+ toggle(true);
+ }
+
+ private void toggle(boolean showKeyboard) {
if (isOpen()) {
mSlideInView.close(true);
} else {
- show(true);
+ show(true, showKeyboard);
}
}
@@ -120,6 +150,10 @@
}
private void show(boolean animate) {
+ show(animate, false);
+ }
+
+ private void show(boolean animate, boolean showKeyboard) {
if (mAppsView != null) {
return;
}
@@ -127,20 +161,35 @@
// to catch invalid states.
mControllers.getSharedState().allAppsVisible = true;
- TaskbarOverlayContext overlayContext =
- mControllers.taskbarOverlayController.requestWindow();
- mSlideInView = (TaskbarAllAppsSlideInView) overlayContext.getLayoutInflater().inflate(
- R.layout.taskbar_all_apps, overlayContext.getDragLayer(), false);
+ mOverlayContext = mControllers.taskbarOverlayController.requestWindow();
+
+ // Initialize search session for All Apps.
+ mSearchSessionController = TaskbarSearchSessionController.newInstance(mOverlayContext);
+ mOverlayContext.setSearchSessionController(mSearchSessionController);
+ mSearchSessionController.setZeroStatePredictedItems(mPredictedApps);
+ if (mZeroStateSearchSuggestions != null) {
+ mSearchSessionController.setZeroStateSearchSuggestions(mZeroStateSearchSuggestions);
+ }
+ mSearchSessionController.startLifecycle();
+
+ mSlideInView = (TaskbarAllAppsSlideInView) mOverlayContext.getLayoutInflater().inflate(
+ R.layout.taskbar_all_apps_sheet, mOverlayContext.getDragLayer(), false);
+ // Ensures All Apps gets touch events in case it is not the top floating view. Floating
+ // views above it may not be able to intercept the touch, so All Apps should try to.
+ mOverlayContext.getDragLayer().addTouchController(mSlideInView);
mSlideInView.addOnCloseListener(() -> {
mControllers.getSharedState().allAppsVisible = false;
- mSlideInView = null;
- mAppsView = null;
+ cleanUpOverlay();
});
TaskbarAllAppsViewController viewController = new TaskbarAllAppsViewController(
- overlayContext, mSlideInView, mControllers);
+ mOverlayContext,
+ mSlideInView,
+ mControllers,
+ mSearchSessionController,
+ showKeyboard);
viewController.show(animate);
- mAppsView = overlayContext.getAppsView();
+ mAppsView = mOverlayContext.getAppsView();
mAppsView.getAppsStore().setApps(mApps, mAppsModelFlags, mPackageUserKeytoUidMap);
mAppsView.getFloatingHeaderView()
.findFixedRowByType(PredictionRowView.class)
@@ -149,8 +198,29 @@
// 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);
+ mOverlayContext.getDragController().setDisallowGlobalDrag(mDisallowGlobalDrag);
+ mOverlayContext.getDragController().setDisallowLongClick(mDisallowLongClick);
+ }
+
+ private void cleanUpOverlay() {
+ // Floating search bar is added to the drag layer in ActivityAllAppsContainerView onAttach;
+ // removed here as this is a special case that we remove the all apps panel.
+ if (mAppsView != null && mOverlayContext != null
+ && mAppsView.getSearchUiDelegate().isSearchBarFloating()) {
+ mOverlayContext.getDragLayer().removeView(mAppsView.getSearchView());
+ mAppsView.getSearchUiDelegate().onDestroySearchBar();
+ }
+ if (mSearchSessionController != null) {
+ mSearchSessionController.onDestroy();
+ mSearchSessionController = null;
+ }
+ if (mOverlayContext != null) {
+ mOverlayContext.getDragLayer().removeTouchController(mSlideInView);
+ mOverlayContext.setSearchSessionController(null);
+ mOverlayContext = null;
+ }
+ mSlideInView = null;
+ mAppsView = null;
}
@VisibleForTesting
@@ -164,4 +234,12 @@
// Allow null-pointer since this should only be null if the apps view is not showing.
return mAppsView.getActiveRecyclerView().computeVerticalScrollOffset();
}
+
+ /** @see TaskbarSearchSessionController#createPreDragConditionForSearch(View) */
+ @Nullable
+ public PreDragCondition createPreDragConditionForSearch(View view) {
+ return mSearchSessionController != null
+ ? mSearchSessionController.createPreDragConditionForSearch(view)
+ : null;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
index cfa1027..c6c4f77 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -15,20 +15,27 @@
*/
package com.android.launcher3.taskbar.allapps;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
-import android.animation.PropertyValuesHolder;
+import android.animation.Animator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
import android.util.AttributeSet;
import android.view.MotionEvent;
+import android.view.View;
import android.view.animation.Interpolator;
import android.window.OnBackInvokedDispatcher;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
+import com.android.launcher3.anim.AnimatorListeners;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsViewController.TaskbarAllAppsCallbacks;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
@@ -37,8 +44,11 @@
/** Wrapper for taskbar all apps with slide-in behavior. */
public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarOverlayContext>
implements Insettable, DeviceProfile.OnDeviceProfileChangeListener {
+ private final Handler mHandler;
+
private TaskbarAllAppsContainerView mAppsView;
private float mShiftRange;
+ private @Nullable Runnable mShowOnFullyAttachedToWindowRunnable;
// Initialized in init.
private TaskbarAllAppsCallbacks mAllAppsCallbacks;
@@ -50,6 +60,7 @@
public TaskbarAllAppsSlideInView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
+ mHandler = new Handler(Looper.myLooper());
}
void init(TaskbarAllAppsCallbacks callbacks) {
@@ -58,20 +69,51 @@
/** Opens the all apps view. */
void show(boolean animate) {
- if (mIsOpen || mOpenCloseAnimator.isRunning()) {
+ if (mIsOpen || mOpenCloseAnimation.getAnimationPlayer().isRunning()) {
return;
}
mIsOpen = true;
- attachToContainer();
- if (animate) {
- mOpenCloseAnimator.setValues(
- PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
- mOpenCloseAnimator.setInterpolator(EMPHASIZED);
- mOpenCloseAnimator.setDuration(mAllAppsCallbacks.getOpenDuration()).start();
- } else {
+ addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ removeOnAttachStateChangeListener(this);
+ // Wait for view and its descendants to be fully attached before starting open.
+ mShowOnFullyAttachedToWindowRunnable = () -> showOnFullyAttachedToWindow(animate);
+ mHandler.post(mShowOnFullyAttachedToWindowRunnable);
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ removeOnAttachStateChangeListener(this);
+ }
+ });
+ attachToContainer();
+ }
+
+ private void showOnFullyAttachedToWindow(boolean animate) {
+ mAllAppsCallbacks.onAllAppsTransitionStart(true);
+ if (!animate) {
+ mAllAppsCallbacks.onAllAppsTransitionEnd(true);
mTranslationShift = TRANSLATION_SHIFT_OPENED;
+ return;
}
+
+ setUpOpenAnimation(mAllAppsCallbacks.getOpenDuration());
+ Animator animator = mOpenCloseAnimation.getAnimationPlayer();
+ animator.setInterpolator(EMPHASIZED);
+ animator.addListener(AnimatorListeners.forEndCallback(() -> {
+ if (mIsOpen) {
+ mAllAppsCallbacks.onAllAppsTransitionEnd(true);
+ }
+ }));
+ animator.start();
+ }
+
+ @Override
+ protected void onOpenCloseAnimationPending(PendingAnimation animation) {
+ mAllAppsCallbacks.onAllAppsAnimationPending(
+ animation, mToTranslationShift == TRANSLATION_SHIFT_OPENED);
}
/** The apps container inside this view. */
@@ -81,10 +123,23 @@
@Override
protected void handleClose(boolean animate) {
+ if (mShowOnFullyAttachedToWindowRunnable != null) {
+ mHandler.removeCallbacks(mShowOnFullyAttachedToWindowRunnable);
+ mShowOnFullyAttachedToWindowRunnable = null;
+ }
+ if (mIsOpen) {
+ mAllAppsCallbacks.onAllAppsTransitionStart(false);
+ }
handleClose(animate, mAllAppsCallbacks.getCloseDuration());
}
@Override
+ protected void onCloseComplete() {
+ mAllAppsCallbacks.onAllAppsTransitionEnd(false);
+ super.onCloseComplete();
+ }
+
+ @Override
protected Interpolator getIdleInterpolator() {
return EMPHASIZED;
}
@@ -165,7 +220,9 @@
@Override
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mNoIntercept = !mAppsView.shouldContainerScroll(ev);
+ mNoIntercept = !mAppsView.shouldContainerScroll(ev)
+ || getTopOpenViewWithType(
+ mActivityContext, TYPE_ACCESSIBLE & ~TYPE_TASKBAR_ALL_APPS) != null;
}
return super.onControllerInterceptTouchEvent(ev);
}
@@ -194,4 +251,11 @@
protected boolean isEventOverContent(MotionEvent ev) {
return getPopupContainer().isEventOverView(mAppsView.getVisibleContainerView(), ev);
}
+
+ @Override
+ public void onBackInvoked() {
+ if (!mAllAppsCallbacks.handleSearchBackInvoked()) {
+ super.onBackInvoked();
+ }
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
index 01342af..6d740c0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
@@ -19,8 +19,9 @@
import static com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT;
import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.allapps.AllAppsTransitionListener;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.appprediction.AppsDividerView;
-import com.android.launcher3.appprediction.PredictionRowView;
import com.android.launcher3.taskbar.NavbarButtonsViewController;
import com.android.launcher3.taskbar.TaskbarControllers;
import com.android.launcher3.taskbar.TaskbarStashController;
@@ -40,11 +41,14 @@
private final TaskbarStashController mTaskbarStashController;
private final NavbarButtonsViewController mNavbarButtonsViewController;
private final TaskbarOverlayController mOverlayController;
+ private final boolean mShowKeyboard;
TaskbarAllAppsViewController(
TaskbarOverlayContext context,
TaskbarAllAppsSlideInView slideInView,
- TaskbarControllers taskbarControllers) {
+ TaskbarControllers taskbarControllers,
+ TaskbarSearchSessionController searchSessionController,
+ boolean showKeyboard) {
mContext = context;
mSlideInView = slideInView;
@@ -52,9 +56,9 @@
mTaskbarStashController = taskbarControllers.taskbarStashController;
mNavbarButtonsViewController = taskbarControllers.navbarButtonsViewController;
mOverlayController = taskbarControllers.taskbarOverlayController;
+ mShowKeyboard = showKeyboard;
- mSlideInView.init(new TaskbarAllAppsCallbacks());
- setUpIconLongClick();
+ mSlideInView.init(new TaskbarAllAppsCallbacks(searchSessionController));
setUpAppDivider();
setUpTaskbarStashing();
}
@@ -69,15 +73,6 @@
mSlideInView.close(animate);
}
- private void setUpIconLongClick() {
- mAppsView.setOnIconLongClickListener(
- mContext.getDragController()::startDragOnLongClick);
- mAppsView.getFloatingHeaderView()
- .findFixedRowByType(PredictionRowView.class)
- .setOnIconLongClickListener(
- mContext.getDragController()::startDragOnLongClick);
- }
-
private void setUpAppDivider() {
mAppsView.getFloatingHeaderView()
.findFixedRowByType(AppsDividerView.class)
@@ -89,7 +84,7 @@
private void setUpTaskbarStashing() {
if (DisplayController.isTransientTaskbar(mContext)) {
mTaskbarStashController.updateStateForFlag(FLAG_STASHED_IN_TASKBAR_ALL_APPS, true);
- mTaskbarStashController.applyState(mOverlayController.getOpenDuration());
+ mTaskbarStashController.applyState();
}
mNavbarButtonsViewController.setSlideInViewVisible(true);
@@ -100,12 +95,18 @@
if (DisplayController.isTransientTaskbar(mContext)) {
mTaskbarStashController.updateStateForFlag(FLAG_STASHED_IN_TASKBAR_ALL_APPS, false);
- mTaskbarStashController.applyState(mOverlayController.getCloseDuration());
+ mTaskbarStashController.applyState();
}
});
}
- class TaskbarAllAppsCallbacks {
+ class TaskbarAllAppsCallbacks implements AllAppsTransitionListener {
+ private final TaskbarSearchSessionController mSearchSessionController;
+
+ private TaskbarAllAppsCallbacks(TaskbarSearchSessionController searchSessionController) {
+ mSearchSessionController = searchSessionController;
+ }
+
int getOpenDuration() {
return mOverlayController.getOpenDuration();
}
@@ -113,5 +114,29 @@
int getCloseDuration() {
return mOverlayController.getCloseDuration();
}
+
+ @Override
+ public void onAllAppsTransitionStart(boolean toAllApps) {
+ mSearchSessionController.onAllAppsTransitionStart(toAllApps);
+ }
+
+ @Override
+ public void onAllAppsTransitionEnd(boolean toAllApps) {
+ mSearchSessionController.onAllAppsTransitionEnd(toAllApps);
+ if (toAllApps
+ && mShowKeyboard
+ && mAppsView.getSearchUiManager().getEditText() != null) {
+ mAppsView.getSearchUiManager().getEditText().requestFocus();
+ }
+ }
+
+ /** Invoked on back press, returning {@code true} if the search session handled it. */
+ boolean handleSearchBackInvoked() {
+ return mSearchSessionController.handleBackInvoked();
+ }
+
+ void onAllAppsAnimationPending(PendingAnimation animation, boolean toAllApps) {
+ mSearchSessionController.onAllAppsAnimationPending(animation, toAllApps, mShowKeyboard);
+ }
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarSearchSessionController.kt b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarSearchSessionController.kt
new file mode 100644
index 0000000..3d15fbd
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarSearchSessionController.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar.allapps
+
+import android.content.Context
+import android.view.View
+import com.android.launcher3.R
+import com.android.launcher3.allapps.AllAppsTransitionListener
+import com.android.launcher3.anim.PendingAnimation
+import com.android.launcher3.config.FeatureFlags
+import com.android.launcher3.dragndrop.DragOptions.PreDragCondition
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.util.ResourceBasedOverride
+import com.android.launcher3.util.ResourceBasedOverride.Overrides
+
+/** Stub for managing the Taskbar search session. */
+open class TaskbarSearchSessionController : ResourceBasedOverride, AllAppsTransitionListener {
+
+ /** Start the search session lifecycle. */
+ open fun startLifecycle() = Unit
+
+ /** Destroy the search session. */
+ open fun onDestroy() = Unit
+
+ /** Updates the predicted items shown in the zero-state. */
+ open fun setZeroStatePredictedItems(items: List<ItemInfo>) = Unit
+
+ /** Updates the search suggestions shown in the zero-state. */
+ open fun setZeroStateSearchSuggestions(items: List<ItemInfo>) = Unit
+
+ override fun onAllAppsTransitionStart(toAllApps: Boolean) = Unit
+
+ override fun onAllAppsTransitionEnd(toAllApps: Boolean) = Unit
+
+ /** Creates a [PreDragCondition] for [view], if it is a search result that requires one. */
+ open fun createPreDragConditionForSearch(view: View): PreDragCondition? = null
+
+ open fun handleBackInvoked(): Boolean = false
+
+ open fun onAllAppsAnimationPending(
+ animation: PendingAnimation,
+ toAllApps: Boolean,
+ showKeyboard: Boolean,
+ ) = Unit
+
+ companion object {
+ @JvmStatic
+ fun newInstance(context: Context): TaskbarSearchSessionController {
+ if (!FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
+ return TaskbarSearchSessionController()
+ }
+
+ return Overrides.getObject(
+ TaskbarSearchSessionController::class.java,
+ context,
+ R.string.taskbar_search_session_controller_class,
+ )
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt
index 7397159..1e3f4f1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt
@@ -21,10 +21,10 @@
import android.graphics.Paint
import android.graphics.drawable.Drawable
import android.graphics.drawable.ShapeDrawable
+import com.android.app.animation.Interpolators
import com.android.launcher3.R
import com.android.launcher3.Utilities
import com.android.launcher3.Utilities.mapToRange
-import com.android.launcher3.anim.Interpolators
import com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound
import com.android.launcher3.taskbar.TaskbarActivityContext
import com.android.wm.shell.common.TriangleShape
@@ -48,6 +48,8 @@
private var showingArrow: Boolean = false
private var arrowDrawable: ShapeDrawable
+ var width: Float = 0f
+
init {
paint.color = context.getColor(R.color.taskbar_background)
paint.flags = Paint.ANTI_ALIAS_FLAG
@@ -59,8 +61,11 @@
pointerSize = res.getDimension(R.dimen.bubblebar_pointer_size)
shadowAlpha =
- if (Utilities.isDarkTheme(context)) DARK_THEME_SHADOW_ALPHA
- else LIGHT_THEME_SHADOW_ALPHA
+ if (Utilities.isDarkTheme(context)) {
+ DARK_THEME_SHADOW_ALPHA
+ } else {
+ LIGHT_THEME_SHADOW_ALPHA
+ }
arrowDrawable =
ShapeDrawable(TriangleShape.create(pointerSize, pointerSize, /* pointUp= */ true))
@@ -102,7 +107,7 @@
// Draw background.
val radius = backgroundHeight / 2f
canvas.drawRoundRect(
- 0f,
+ canvas.width.toFloat() - width,
0f,
canvas.width.toFloat(),
canvas.height.toFloat(),
@@ -132,4 +137,8 @@
override fun setColorFilter(colorFilter: ColorFilter?) {
paint.colorFilter = colorFilter
}
+
+ fun setArrowAlpha(alpha: Int) {
+ arrowDrawable.paint.alpha = alpha
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
index 6d19692..bd11efd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
@@ -31,18 +31,25 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
+import static java.lang.Math.abs;
+
import android.annotation.BinderThread;
import android.annotation.Nullable;
+import android.app.Notification;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
+import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Path;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
import android.os.Bundle;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -51,6 +58,8 @@
import android.util.PathParser;
import android.view.LayoutInflater;
+import androidx.appcompat.content.res.AppCompatResources;
+
import com.android.internal.graphics.ColorUtils;
import com.android.launcher3.R;
import com.android.launcher3.icons.BitmapInfo;
@@ -112,8 +121,10 @@
private final Executor mMainExecutor;
private final LauncherApps mLauncherApps;
private final BubbleIconFactory mIconFactory;
+ private final SystemUiProxy mSystemUiProxy;
- private BubbleBarBubble mSelectedBubble;
+ private BubbleBarItem mSelectedBubble;
+ private BubbleBarOverflow mOverflowBubble;
private BubbleBarViewController mBubbleBarViewController;
private BubbleStashController mBubbleStashController;
@@ -126,6 +137,7 @@
private static class BubbleBarViewUpdate {
boolean expandedChanged;
boolean expanded;
+ boolean shouldShowEducation;
String selectedBubbleKey;
String suppressedBubbleKey;
String unsuppressedBubbleKey;
@@ -140,6 +152,7 @@
BubbleBarViewUpdate(BubbleBarUpdate update) {
expandedChanged = update.expandedChanged;
expanded = update.expanded;
+ shouldShowEducation = update.shouldShowEducation;
selectedBubbleKey = update.selectedBubbleKey;
suppressedBubbleKey = update.suppressedBubbleKey;
unsuppressedBubbleKey = update.unsupressedBubbleKey;
@@ -152,8 +165,10 @@
mContext = context;
mBarView = bubbleView; // Need the view for inflating bubble views.
+ mSystemUiProxy = SystemUiProxy.INSTANCE.get(context);
+
if (BUBBLE_BAR_ENABLED) {
- SystemUiProxy.INSTANCE.get(context).setBubblesListener(this);
+ mSystemUiProxy.setBubblesListener(this);
}
mMainExecutor = MAIN_EXECUTOR;
mLauncherApps = context.getSystemService(LauncherApps.class);
@@ -166,7 +181,7 @@
}
public void onDestroy() {
- SystemUiProxy.INSTANCE.get(mContext).setBubblesListener(null);
+ mSystemUiProxy.setBubblesListener(null);
}
public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
@@ -175,12 +190,36 @@
mBubbleStashedHandleViewController = bubbleControllers.bubbleStashedHandleViewController;
bubbleControllers.runAfterInit(() -> {
- mBubbleBarViewController.setHiddenForBubbles(!BUBBLE_BAR_ENABLED);
- mBubbleStashedHandleViewController.setHiddenForBubbles(!BUBBLE_BAR_ENABLED);
+ mBubbleBarViewController.setHiddenForBubbles(
+ !BUBBLE_BAR_ENABLED || mBubbles.isEmpty());
+ mBubbleStashedHandleViewController.setHiddenForBubbles(
+ !BUBBLE_BAR_ENABLED || mBubbles.isEmpty());
+ mBubbleBarViewController.setUpdateSelectedBubbleAfterCollapse(
+ key -> setSelectedBubble(mBubbles.get(key)));
});
}
/**
+ * Creates and adds the overflow bubble to the bubble bar if it hasn't been created yet.
+ *
+ * <p>This should be called on the {@link #BUBBLE_STATE_EXECUTOR} executor to avoid inflating
+ * the overflow multiple times.
+ */
+ private void createAndAddOverflowIfNeeded() {
+ if (mOverflowBubble == null) {
+ BubbleBarOverflow overflow = createOverflow(mContext);
+ mMainExecutor.execute(() -> {
+ // we're on the main executor now, so check that the overflow hasn't been created
+ // again to avoid races.
+ if (mOverflowBubble == null) {
+ mBubbleBarViewController.addBubble(overflow);
+ mOverflowBubble = overflow;
+ }
+ });
+ }
+ }
+
+ /**
* Updates the bubble bar, handle bar, and stash controllers based on sysui state flags.
*/
public void updateStateForSysuiFlags(int flags) {
@@ -209,18 +248,23 @@
|| !update.currentBubbleList.isEmpty()) {
// We have bubbles to load
BUBBLE_STATE_EXECUTOR.execute(() -> {
+ createAndAddOverflowIfNeeded();
if (update.addedBubble != null) {
- viewUpdate.addedBubble = populateBubble(update.addedBubble, mContext, mBarView);
+ viewUpdate.addedBubble = populateBubble(mContext, update.addedBubble, mBarView,
+ null /* existingBubble */);
}
if (update.updatedBubble != null) {
+ BubbleBarBubble existingBubble = mBubbles.get(update.updatedBubble.getKey());
viewUpdate.updatedBubble =
- populateBubble(update.updatedBubble, mContext, mBarView);
+ populateBubble(mContext, update.updatedBubble, mBarView,
+ existingBubble);
}
if (update.currentBubbleList != null && !update.currentBubbleList.isEmpty()) {
List<BubbleBarBubble> currentBubbles = new ArrayList<>();
for (int i = 0; i < update.currentBubbleList.size(); i++) {
BubbleBarBubble b =
- populateBubble(update.currentBubbleList.get(i), mContext, mBarView);
+ populateBubble(mContext, update.currentBubbleList.get(i), mBarView,
+ null /* existingBubble */);
currentBubbles.add(b);
}
viewUpdate.currentBubbles = currentBubbles;
@@ -237,6 +281,7 @@
private void applyViewChanges(BubbleBarViewUpdate update) {
final boolean isCollapsed = (update.expandedChanged && !update.expanded)
|| (!update.expandedChanged && !mBubbleBarViewController.isExpanded());
+ BubbleBarItem previouslySelectedBubble = mSelectedBubble;
BubbleBarBubble bubbleToSelect = null;
if (!update.removedBubbles.isEmpty()) {
for (int i = 0; i < update.removedBubbles.size(); i++) {
@@ -281,10 +326,17 @@
mBubbleBarViewController.setHiddenForBubbles(mBubbles.isEmpty());
mBubbleStashedHandleViewController.setHiddenForBubbles(mBubbles.isEmpty());
+ if (mBubbles.isEmpty()) {
+ // all bubbles were removed. clear the selected bubble
+ mSelectedBubble = null;
+ }
+
if (update.updatedBubble != null) {
- // TODO: (b/269670235) handle updates:
- // (1) if content / icons change -- requires reload & add back in place
- // (2) if showing update dot changes -- tell the view to hide / show the dot
+ // Updates mean the dot state may have changed; any other changes were updated in
+ // the populateBubble step.
+ BubbleBarBubble bb = mBubbles.get(update.updatedBubble.getKey());
+ // If we're not stashed, we're visible so animate
+ bb.getView().updateDotVisibility(!mBubbleStashController.isStashed() /* animate */);
}
if (update.bubbleKeysInOrder != null && !update.bubbleKeysInOrder.isEmpty()) {
// Create the new list
@@ -301,8 +353,8 @@
// TODO: (b/273316505) handle suppression
}
if (update.selectedBubbleKey != null) {
- if (mSelectedBubble != null
- && !update.selectedBubbleKey.equals(mSelectedBubble.getKey())) {
+ if (mSelectedBubble == null
+ || !update.selectedBubbleKey.equals(mSelectedBubble.getKey())) {
BubbleBarBubble newlySelected = mBubbles.get(update.selectedBubbleKey);
if (newlySelected != null) {
bubbleToSelect = newlySelected;
@@ -314,6 +366,12 @@
}
if (bubbleToSelect != null) {
setSelectedBubble(bubbleToSelect);
+ if (previouslySelectedBubble == null) {
+ mBubbleStashController.animateToInitialState(update.expanded);
+ }
+ }
+ if (update.shouldShowEducation) {
+ mBubbleBarViewController.prepareToShowEducation();
}
if (update.expandedChanged) {
if (update.expanded != mBubbleBarViewController.isExpanded()) {
@@ -324,12 +382,38 @@
}
}
+ /** Tells WMShell to show the currently selected bubble. */
+ public void showSelectedBubble() {
+ if (getSelectedBubbleKey() != null) {
+ if (mSelectedBubble instanceof BubbleBarBubble) {
+ // Because we've visited this bubble, we should suppress the notification.
+ // This is updated on WMShell side when we show the bubble, but that update isn't
+ // passed to launcher, instead we apply it directly here.
+ BubbleInfo info = ((BubbleBarBubble) mSelectedBubble).getInfo();
+ info.setFlags(
+ info.getFlags() | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
+ mSelectedBubble.getView().updateDotVisibility(true /* animate */);
+ }
+ mSystemUiProxy.showBubble(getSelectedBubbleKey(),
+ getBubbleBarOffsetX(), getBubbleBarOffsetY());
+ } else {
+ Log.w(TAG, "Trying to show the selected bubble but it's null");
+ }
+ }
+
+ /** Updates the currently selected bubble for launcher views and tells WMShell to show it. */
+ public void showAndSelectBubble(BubbleBarItem b) {
+ if (DEBUG) Log.w(TAG, "showingSelectedBubble: " + b.getKey());
+ setSelectedBubble(b);
+ showSelectedBubble();
+ }
+
/**
* Sets the bubble that should be selected. This notifies the views, it does not notify
- * WMShell that the selection has changed, that should go through
- * {@link SystemUiProxy#showBubble}.
+ * WMShell that the selection has changed, that should go through either
+ * {@link #showSelectedBubble()} or {@link #showAndSelectBubble(BubbleBarItem)}.
*/
- public void setSelectedBubble(BubbleBarBubble b) {
+ private void setSelectedBubble(BubbleBarItem b) {
if (!Objects.equals(b, mSelectedBubble)) {
if (DEBUG) Log.w(TAG, "selectingBubble: " + b.getKey());
mSelectedBubble = b;
@@ -353,7 +437,8 @@
//
@Nullable
- private BubbleBarBubble populateBubble(BubbleInfo b, Context context, BubbleBarView bbv) {
+ private BubbleBarBubble populateBubble(Context context, BubbleInfo b, BubbleBarView bbv,
+ @Nullable BubbleBarBubble existingBubble) {
String appName;
Bitmap badgeBitmap;
Bitmap bubbleBitmap;
@@ -422,16 +507,68 @@
iconPath.transform(matrix);
dotPath = iconPath;
dotColor = ColorUtils.blendARGB(badgeBitmapInfo.color,
- Color.WHITE, WHITE_SCRIM_ALPHA);
+ Color.WHITE, WHITE_SCRIM_ALPHA / 255f);
+ if (existingBubble == null) {
+ LayoutInflater inflater = LayoutInflater.from(context);
+ BubbleView bubbleView = (BubbleView) inflater.inflate(
+ R.layout.bubblebar_item_view, bbv, false /* attachToRoot */);
+ BubbleBarBubble bubble = new BubbleBarBubble(b, bubbleView,
+ badgeBitmap, bubbleBitmap, dotColor, dotPath, appName);
+ bubbleView.setBubble(bubble);
+ return bubble;
+ } else {
+ // If we already have a bubble (so it already has an inflated view), update it.
+ existingBubble.setInfo(b);
+ existingBubble.setBadge(badgeBitmap);
+ existingBubble.setIcon(bubbleBitmap);
+ existingBubble.setDotColor(dotColor);
+ existingBubble.setDotPath(dotPath);
+ existingBubble.setAppName(appName);
+ return existingBubble;
+ }
+ }
+
+ private BubbleBarOverflow createOverflow(Context context) {
+ Bitmap bitmap = createOverflowBitmap(context);
LayoutInflater inflater = LayoutInflater.from(context);
BubbleView bubbleView = (BubbleView) inflater.inflate(
- R.layout.bubblebar_item_view, bbv, false /* attachToRoot */);
+ R.layout.bubblebar_item_view, mBarView, false /* attachToRoot */);
+ BubbleBarOverflow overflow = new BubbleBarOverflow(bubbleView);
+ bubbleView.setOverflow(overflow, bitmap);
+ return overflow;
+ }
- BubbleBarBubble bubble = new BubbleBarBubble(b, bubbleView,
- badgeBitmap, bubbleBitmap, dotColor, dotPath, appName);
- bubbleView.setBubble(bubble);
- return bubble;
+ private Bitmap createOverflowBitmap(Context context) {
+ Drawable iconDrawable = AppCompatResources.getDrawable(mContext,
+ R.drawable.bubble_ic_overflow_button);
+
+ final TypedArray ta = mContext.obtainStyledAttributes(
+ new int[]{
+ com.android.internal.R.attr.materialColorOnPrimaryFixed,
+ com.android.internal.R.attr.materialColorPrimaryFixed
+ });
+ int overflowIconColor = ta.getColor(0, Color.WHITE);
+ int overflowBackgroundColor = ta.getColor(1, Color.BLACK);
+ ta.recycle();
+
+ iconDrawable.setTint(overflowIconColor);
+
+ int inset = context.getResources().getDimensionPixelSize(R.dimen.bubblebar_overflow_inset);
+ Drawable foreground = new InsetDrawable(iconDrawable, inset);
+ Drawable drawable = new AdaptiveIconDrawable(new ColorDrawable(overflowBackgroundColor),
+ foreground);
+
+ return mIconFactory.createBadgedIconBitmap(drawable).icon;
+ }
+
+ private int getBubbleBarOffsetY() {
+ final int translation = (int) abs(mBubbleStashController.getBubbleBarTranslationY());
+ return translation + mBarView.getHeight();
+ }
+
+ private int getBubbleBarOffsetX() {
+ return mBarView.getWidth() + mBarView.getHorizontalMargin();
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubble.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarItem.kt
similarity index 65%
rename from quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubble.kt
rename to quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarItem.kt
index 3cd5f75..43e21f4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubble.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarItem.kt
@@ -19,16 +19,19 @@
import android.graphics.Path
import com.android.wm.shell.common.bubbles.BubbleInfo
+/** An entity in the bubble bar. */
+sealed class BubbleBarItem(open var key: String, open var view: BubbleView)
+
/** Contains state info about a bubble in the bubble bar as well as presentation information. */
data class BubbleBarBubble(
- val info: BubbleInfo,
- val view: BubbleView,
- val badge: Bitmap,
- val icon: Bitmap,
- val dotColor: Int,
- val dotPath: Path,
- val appName: String
-) {
+ var info: BubbleInfo,
+ override var view: BubbleView,
+ var badge: Bitmap,
+ var icon: Bitmap,
+ var dotColor: Int,
+ var dotPath: Path,
+ var appName: String
+) : BubbleBarItem(info.key, view)
- val key: String = info.key
-}
+/** Represents the overflow bubble in the bubble bar. */
+data class BubbleBarOverflow(override var view: BubbleView) : BubbleBarItem("Overflow", view)
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
index 0e1e0e1..c482911 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.taskbar.bubbles;
+import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
import android.content.Context;
@@ -31,6 +32,7 @@
import com.android.launcher3.views.ActivityContext;
import java.util.List;
+import java.util.function.Consumer;
/**
* The view that holds all the bubble views. Modifying this view should happen through
@@ -66,11 +68,15 @@
// if it's smaller than 5.
private static final int MAX_BUBBLES = 5;
private static final int ARROW_POSITION_ANIMATION_DURATION_MS = 200;
+ private static final int WIDTH_ANIMATION_DURATION_MS = 200;
- private final TaskbarActivityContext mActivityContext;
private final BubbleBarBackground mBubbleBarBackground;
- // The current bounds of all the bubble bar.
+ /**
+ * The current bounds of all the bubble bar. Note that these bounds may not account for
+ * translation. The bounds should be retrieved using {@link #getBubbleBarBounds()} which
+ * updates the bounds and accounts for translation.
+ */
private final Rect mBubbleBarBounds = new Rect();
// The amount the bubbles overlap when they are stacked in the bubble bar
private final float mIconOverlapAmount;
@@ -89,6 +95,12 @@
private View.OnClickListener mOnClickListener;
private final Rect mTempRect = new Rect();
+ private float mRelativePivotX = 1f;
+ private float mRelativePivotY = 1f;
+
+ // An animator that represents the expansion state of the bubble bar, where 0 corresponds to the
+ // collapsed state and 1 to the fully expanded state.
+ private final ValueAnimator mWidthAnimator = ValueAnimator.ofFloat(0, 1);
// We don't reorder the bubbles when they are expanded as it could be jarring for the user
// this runnable will be populated with any reordering of the bubbles that should be applied
@@ -96,6 +108,12 @@
@Nullable
private Runnable mReorderRunnable;
+ @Nullable
+ private Consumer<String> mUpdateSelectedBubbleAfterCollapse;
+
+ @Nullable
+ private BubbleView mDraggedBubbleView;
+
public BubbleBarView(Context context) {
this(context, null);
}
@@ -110,7 +128,7 @@
public BubbleBarView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- mActivityContext = ActivityContext.lookupContext(context);
+ TaskbarActivityContext activityContext = ActivityContext.lookupContext(context);
mIconOverlapAmount = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_overlap);
mIconSpacing = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_spacing);
@@ -118,9 +136,46 @@
mBubbleElevation = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_elevation);
setClipToPadding(false);
- mBubbleBarBackground = new BubbleBarBackground(mActivityContext,
+ mBubbleBarBackground = new BubbleBarBackground(activityContext,
getResources().getDimensionPixelSize(R.dimen.bubblebar_size));
setBackgroundDrawable(mBubbleBarBackground);
+
+ mWidthAnimator.setDuration(WIDTH_ANIMATION_DURATION_MS);
+ mWidthAnimator.addUpdateListener(animation -> {
+ updateChildrenRenderNodeProperties();
+ invalidate();
+ });
+ mWidthAnimator.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mBubbleBarBackground.showArrow(mIsBarExpanded);
+ if (!mIsBarExpanded && mReorderRunnable != null) {
+ mReorderRunnable.run();
+ mReorderRunnable = null;
+ }
+ // If the bar was just collapsed and the overflow was the last bubble that was
+ // selected, set the first bubble as selected.
+ if (!mIsBarExpanded && mUpdateSelectedBubbleAfterCollapse != null
+ && mSelectedBubbleView.getBubble() instanceof BubbleBarOverflow) {
+ BubbleView firstBubble = (BubbleView) getChildAt(0);
+ mUpdateSelectedBubbleAfterCollapse.accept(firstBubble.getBubble().getKey());
+ }
+ updateWidth();
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mBubbleBarBackground.showArrow(true);
+ }
+ });
}
@Override
@@ -131,63 +186,157 @@
mBubbleBarBounds.right = right;
mBubbleBarBounds.bottom = bottom;
- // The bubble bar handle is aligned to the bottom edge of the screen so scale towards that.
- setPivotX(getWidth());
- setPivotY(getHeight());
+ // The bubble bar handle is aligned according to the relative pivot,
+ // by default it's aligned to the bottom edge of the screen so scale towards that
+ setPivotX(mRelativePivotX * getWidth());
+ setPivotY(mRelativePivotY * getHeight());
// Position the views
updateChildrenRenderNodeProperties();
}
/**
- * Returns the bounds of the bubble bar.
+ * Updates the bounds with translation that may have been applied and returns the result.
*/
public Rect getBubbleBarBounds() {
+ mBubbleBarBounds.top = getTop() + (int) getTranslationY();
+ mBubbleBarBounds.bottom = getBottom() + (int) getTranslationY();
return mBubbleBarBounds;
}
- // TODO: (b/273592694) animate it
+ /**
+ * Set bubble bar relative pivot value for X and Y, applied as a fraction of view width/height
+ * respectively. If the value is not in range of 0 to 1 it will be normalized.
+ * @param x relative X pivot value in range 0..1
+ * @param y relative Y pivot value in range 0..1
+ */
+ public void setRelativePivot(float x, float y) {
+ mRelativePivotX = Float.max(Float.min(x, 1), 0);
+ mRelativePivotY = Float.max(Float.min(y, 1), 0);
+ requestLayout();
+ }
+
+ /**
+ * Get current relative pivot for X axis
+ */
+ public float getRelativePivotX() {
+ return mRelativePivotX;
+ }
+
+ /**
+ * Get current relative pivot for Y axis
+ */
+ public float getRelativePivotY() {
+ return mRelativePivotY;
+ }
+
+ // TODO: (b/280605790) animate it
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
if (getChildCount() + 1 > MAX_BUBBLES) {
- removeViewInLayout(getChildAt(getChildCount() - 1));
+ // the last child view is the overflow bubble and we shouldn't remove that. remove the
+ // second to last child view.
+ removeViewInLayout(getChildAt(getChildCount() - 2));
}
super.addView(child, index, params);
+ updateWidth();
+ }
+
+ // TODO: (b/283309949) animate it
+ @Override
+ public void removeView(View view) {
+ super.removeView(view);
+ updateWidth();
+ }
+
+ private void updateWidth() {
+ LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
+ lp.width = (int) (mIsBarExpanded ? expandedWidth() : collapsedWidth());
+ setLayoutParams(lp);
+ }
+
+ /** @return the horizontal margin between the bubble bar and the edge of the screen. */
+ int getHorizontalMargin() {
+ LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
+ return lp.getMarginEnd();
}
/**
* Updates the z order, positions, and badge visibility of the bubble views in the bar based
* on the expanded state.
*/
- // TODO: (b/273592694) animate it
private void updateChildrenRenderNodeProperties() {
+ final float widthState = (float) mWidthAnimator.getAnimatedValue();
+ final float currentWidth = getWidth();
+ final float expandedWidth = expandedWidth();
+ final float collapsedWidth = collapsedWidth();
int bubbleCount = getChildCount();
final float ty = (mBubbleBarBounds.height() - mIconSize) / 2f;
+ final boolean animate = getVisibility() == VISIBLE;
for (int i = 0; i < bubbleCount; i++) {
BubbleView bv = (BubbleView) getChildAt(i);
bv.setTranslationY(ty);
+
+ // the position of the bubble when the bar is fully expanded
+ final float expandedX = i * (mIconSize + mIconSpacing);
+ // the position of the bubble when the bar is fully collapsed
+ final float collapsedX = i == 0 ? 0 : mIconOverlapAmount;
+
if (mIsBarExpanded) {
- final float tx = i * (mIconSize + mIconSpacing);
- bv.setTranslationX(tx);
- bv.setZ(0);
- bv.showBadge();
+ // where the bubble will end up when the animation ends
+ final float targetX = currentWidth - expandedWidth + expandedX;
+ bv.setTranslationX(widthState * (targetX - collapsedX) + collapsedX);
+ // if we're fully expanded, set the z level to 0 or to bubble elevation if dragged
+ if (widthState == 1f) {
+ bv.setZ(bv == mDraggedBubbleView ? mBubbleElevation : 0);
+ }
+ // When we're expanded, we're not stacked so we're not behind the stack
+ bv.setBehindStack(false, animate);
+ bv.setAlpha(1);
} else {
+ final float targetX = currentWidth - collapsedWidth + collapsedX;
+ bv.setTranslationX(widthState * (expandedX - targetX) + targetX);
bv.setZ((MAX_BUBBLES * mBubbleElevation) - i);
- bv.setTranslationX(i * mIconOverlapAmount);
- if (i > 0) {
- bv.hideBadge();
- } else {
- bv.showBadge();
+ // If we're not the first bubble we're behind the stack
+ bv.setBehindStack(i > 0, animate);
+ // If we're fully collapsed, hide all bubbles except for the first 2. If there are
+ // only 2 bubbles, hide the second bubble as well because it's the overflow.
+ if (widthState == 0) {
+ if (i > 1) {
+ bv.setAlpha(0);
+ } else if (i == 1 && bubbleCount == 2) {
+ bv.setAlpha(0);
+ }
}
}
}
+
+ // update the arrow position
+ final float collapsedArrowPosition = arrowPositionForSelectedWhenCollapsed();
+ final float expandedArrowPosition = arrowPositionForSelectedWhenExpanded();
+ final float interpolatedWidth =
+ widthState * (expandedWidth - collapsedWidth) + collapsedWidth;
+ if (mIsBarExpanded) {
+ // when the bar is expanding, the selected bubble is always the first, so the arrow
+ // always shifts with the interpolated width.
+ final float arrowPosition = currentWidth - interpolatedWidth + collapsedArrowPosition;
+ mBubbleBarBackground.setArrowPosition(arrowPosition);
+ } else {
+ final float targetPosition = currentWidth - collapsedWidth + collapsedArrowPosition;
+ final float arrowPosition =
+ targetPosition + widthState * (expandedArrowPosition - targetPosition);
+ mBubbleBarBackground.setArrowPosition(arrowPosition);
+ }
+
+ mBubbleBarBackground.setArrowAlpha((int) (255 * widthState));
+ mBubbleBarBackground.setWidth(interpolatedWidth);
}
/**
* Reorders the views to match the provided list.
*/
public void reorder(List<BubbleView> viewOrder) {
- if (isExpanded()) {
+ if (isExpanded() || mWidthAnimator.isRunning()) {
mReorderRunnable = () -> doReorder(viewOrder);
} else {
doReorder(viewOrder);
@@ -199,7 +348,10 @@
if (!isExpanded()) {
for (int i = 0; i < viewOrder.size(); i++) {
View child = viewOrder.get(i);
- if (child != null) {
+ // this child view may have already been removed so verify that it still exists
+ // before reordering it, otherwise it will be re-added.
+ int indexOfChild = indexOfChild(child);
+ if (child != null && indexOfChild >= 0) {
removeViewInLayout(child);
addViewInLayout(child, i, child.getLayoutParams());
}
@@ -208,6 +360,11 @@
}
}
+ public void setUpdateSelectedBubbleAfterCollapse(
+ Consumer<String> updateSelectedBubbleAfterCollapse) {
+ mUpdateSelectedBubbleAfterCollapse = updateSelectedBubbleAfterCollapse;
+ }
+
/**
* Sets which bubble view should be shown as selected.
*/
@@ -217,6 +374,14 @@
}
/**
+ * Sets the dragged bubble view to correctly apply Z order. Dragged view should appear on top
+ */
+ public void setDraggedBubble(@Nullable BubbleView view) {
+ mDraggedBubbleView = view;
+ requestLayout();
+ }
+
+ /**
* Update the arrow position to match the selected bubble.
*
* @param shouldAnimate whether or not to animate the arrow. If the bar was just expanded, this
@@ -247,6 +412,16 @@
}
}
+ private float arrowPositionForSelectedWhenExpanded() {
+ final int index = indexOfChild(mSelectedBubbleView);
+ return getPaddingStart() + index * (mIconSize + mIconSpacing) + mIconSize / 2f;
+ }
+
+ private float arrowPositionForSelectedWhenCollapsed() {
+ final int index = indexOfChild(mSelectedBubbleView);
+ return getPaddingStart() + index * (mIconOverlapAmount) + mIconSize / 2f;
+ }
+
@Override
public void setOnClickListener(View.OnClickListener listener) {
mOnClickListener = listener;
@@ -264,18 +439,16 @@
/**
* Sets whether the bubble bar is expanded or collapsed.
*/
- // TODO: (b/273592694) animate it
public void setExpanded(boolean isBarExpanded) {
if (mIsBarExpanded != isBarExpanded) {
mIsBarExpanded = isBarExpanded;
updateArrowForSelected(/* shouldAnimate= */ false);
setOrUnsetClickListener();
- if (!isBarExpanded && mReorderRunnable != null) {
- mReorderRunnable.run();
- mReorderRunnable = null;
+ if (isBarExpanded) {
+ mWidthAnimator.start();
+ } else {
+ mWidthAnimator.reverse();
}
- mBubbleBarBackground.showArrow(mIsBarExpanded);
- requestLayout(); // trigger layout to reposition views & update size for expansion
}
}
@@ -286,19 +459,20 @@
return mIsBarExpanded;
}
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ private float expandedWidth() {
final int childCount = getChildCount();
- final float iconWidth = mIsBarExpanded
- ? (childCount * (mIconSize + mIconSpacing))
- : mIconSize + ((childCount - 1) * mIconOverlapAmount);
- final int totalWidth = (int) iconWidth + getPaddingStart() + getPaddingEnd();
- setMeasuredDimension(totalWidth, MeasureSpec.getSize(heightMeasureSpec));
+ final int horizontalPadding = getPaddingStart() + getPaddingEnd();
+ return childCount * (mIconSize + mIconSpacing) + horizontalPadding;
+ }
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- measureChild(child, (int) mIconSize, (int) mIconSize);
- }
+ private float collapsedWidth() {
+ final int childCount = getChildCount();
+ final int horizontalPadding = getPaddingStart() + getPaddingEnd();
+ // If there are more than 2 bubbles, the first 2 should be visible when collapsed.
+ // Otherwise just the first bubble should be visible because we don't show the overflow.
+ return childCount > 2
+ ? mIconSize + mIconOverlapAmount + horizontalPadding
+ : mIconSize + horizontalPadding;
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index 82494c6..065dd58 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -18,22 +18,28 @@
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
+import android.graphics.Point;
import android.graphics.Rect;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarControllers;
+import com.android.launcher3.taskbar.TaskbarInsetsController;
+import com.android.launcher3.taskbar.TaskbarStashController;
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.quickstep.SystemUiProxy;
import java.util.List;
import java.util.Objects;
+import java.util.function.Consumer;
/**
* Controller for {@link BubbleBarView}. Manages the visibility of the bubble bar as well as
@@ -51,6 +57,9 @@
// Initialized in init.
private BubbleStashController mBubbleStashController;
private BubbleBarController mBubbleBarController;
+ private BubbleDragController mBubbleDragController;
+ private TaskbarStashController mTaskbarStashController;
+ private TaskbarInsetsController mTaskbarInsetsController;
private View.OnClickListener mBubbleClickListener;
private View.OnClickListener mBubbleBarClickListener;
@@ -66,7 +75,8 @@
// Whether the bar is hidden for a sysui state.
private boolean mHiddenForSysui;
// Whether the bar is hidden because there are no bubbles.
- private boolean mHiddenForNoBubbles;
+ private boolean mHiddenForNoBubbles = true;
+ private boolean mShouldShowEducation;
public BubbleBarViewController(TaskbarActivityContext activity, BubbleBarView barView) {
mActivity = activity;
@@ -80,6 +90,9 @@
public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
mBubbleStashController = bubbleControllers.bubbleStashController;
mBubbleBarController = bubbleControllers.bubbleBarController;
+ mBubbleDragController = bubbleControllers.bubbleDragController;
+ mTaskbarStashController = controllers.taskbarStashController;
+ mTaskbarInsetsController = controllers.taskbarInsetsController;
mActivity.addOnDeviceProfileChangeListener(dp ->
mBarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarHeight
@@ -87,13 +100,16 @@
mBarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarHeight;
mBubbleBarScale.updateValue(1f);
mBubbleClickListener = v -> onBubbleClicked(v);
- mBubbleBarClickListener = v -> setExpanded(true);
+ mBubbleBarClickListener = v -> onBubbleBarClicked();
+ mBubbleDragController.setupBubbleBarView(mBarView);
mBarView.setOnClickListener(mBubbleBarClickListener);
- // TODO: when barView layout changes tell taskbarInsetsController the insets have changed.
+ mBarView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) ->
+ mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
+ );
}
private void onBubbleClicked(View v) {
- BubbleBarBubble bubble = ((BubbleView) v).getBubble();
+ BubbleBarItem bubble = ((BubbleView) v).getBubble();
if (bubble == null) {
Log.e(TAG, "bubble click listener, bubble was null");
}
@@ -103,9 +119,22 @@
setExpanded(false);
mBubbleStashController.stashBubbleBar();
} else {
- mBubbleBarController.setSelectedBubble(bubble);
- mSystemUiProxy.showBubble(bubble.getKey(),
- mBubbleStashController.isBubblesShowingOnHome());
+ mBubbleBarController.showAndSelectBubble(bubble);
+ }
+ }
+
+ private void onBubbleBarClicked() {
+ if (mShouldShowEducation) {
+ mShouldShowEducation = false;
+ // Get the bubble bar bounds on screen
+ Rect bounds = new Rect();
+ mBarView.getBoundsOnScreen(bounds);
+ // Calculate user education reference position in Screen coordinates
+ Point position = new Point(bounds.centerX(), bounds.top);
+ // Show user education relative to the reference point
+ mSystemUiProxy.showUserEducation(position);
+ } else {
+ setExpanded(true);
}
}
@@ -133,6 +162,11 @@
return mBarView.getVisibility() == VISIBLE;
}
+ /** Whether the bubble bar has bubbles. */
+ public boolean hasBubbles() {
+ return mBubbleBarController.getSelectedBubbleKey() != null;
+ }
+
/**
* The bounds of the bubble bar.
*/
@@ -140,6 +174,11 @@
return mBarView.getBubbleBarBounds();
}
+ /** The horizontal margin of the bubble bar from the edge of the screen. */
+ public int getHorizontalMargin() {
+ return mBarView.getHorizontalMargin();
+ }
+
/**
* When the bubble bar is not stashed, it can be collapsed (the icons are in a stack) or
* expanded (the icons are in a row). This indicates whether the bubble bar is expanded.
@@ -173,9 +212,16 @@
if (mHiddenForNoBubbles != hidden) {
mHiddenForNoBubbles = hidden;
updateVisibilityForStateChange();
+ mActivity.bubbleBarVisibilityChanged(!hidden);
}
}
+ /** Sets a callback that updates the selected bubble after the bubble bar collapses. */
+ public void setUpdateSelectedBubbleAfterCollapse(
+ Consumer<String> updateSelectedBubbleAfterCollapse) {
+ mBarView.setUpdateSelectedBubbleAfterCollapse(updateSelectedBubbleAfterCollapse);
+ }
+
/**
* Sets whether the bubble bar should be hidden due to SysUI state (e.g. on lockscreen).
*/
@@ -188,10 +234,12 @@
// TODO: (b/273592694) animate it
private void updateVisibilityForStateChange() {
- if (!mHiddenForSysui && !mBubbleStashController.isStashed() && !mHiddenForNoBubbles) {
+ if (!mHiddenForSysui && !mHiddenForNoBubbles) {
mBarView.setVisibility(VISIBLE);
} else {
mBarView.setVisibility(INVISIBLE);
+ mBarView.setAlpha(0);
+ mBarView.setExpanded(false);
}
}
@@ -228,7 +276,7 @@
/**
* Removes the provided bubble from the bubble bar.
*/
- public void removeBubble(BubbleBarBubble b) {
+ public void removeBubble(BubbleBarItem b) {
if (b != null) {
mBarView.removeView(b.getView());
} else {
@@ -239,10 +287,11 @@
/**
* Adds the provided bubble to the bubble bar.
*/
- public void addBubble(BubbleBarBubble b) {
+ public void addBubble(BubbleBarItem b) {
if (b != null) {
mBarView.addView(b.getView(), 0, new FrameLayout.LayoutParams(mIconSize, mIconSize));
b.getView().setOnClickListener(mBubbleClickListener);
+ mBubbleDragController.setupBubbleView(b.getView());
} else {
Log.w(TAG, "addBubble, bubble was null!");
}
@@ -260,7 +309,7 @@
/**
* Updates the selected bubble.
*/
- public void updateSelectedBubble(BubbleBarBubble newlySelected) {
+ public void updateSelectedBubble(BubbleBarItem newlySelected) {
mBarView.setSelectedBubble(newlySelected.getView());
}
@@ -276,14 +325,9 @@
if (!isExpanded) {
mSystemUiProxy.collapseBubbles();
} else {
- final String selectedKey = mBubbleBarController.getSelectedBubbleKey();
- if (selectedKey != null) {
- mSystemUiProxy.showBubble(selectedKey,
- mBubbleStashController.isBubblesShowingOnHome());
- } else {
- Log.w(TAG, "trying to expand bubbles when there isn't one selected");
- }
- // TODO: Tell taskbar stash controller to stash without bubbles following
+ mBubbleBarController.showSelectedBubble();
+ mTaskbarStashController.updateAndAnimateTransientTaskbar(true /* stash */,
+ false /* shouldBubblesFollow */);
}
}
}
@@ -299,4 +343,52 @@
mBubbleStashController.showBubbleBar(true /* expand the bubbles */);
}
}
+
+ /** Marks as should show education and shows the bubble bar in a collapsed state */
+ public void prepareToShowEducation() {
+ mShouldShowEducation = true;
+ mBubbleStashController.showBubbleBar(false /* expand the bubbles */);
+ }
+
+ /**
+ * Updates the dragged bubble view in the bubble bar view, and notifies SystemUI
+ * that a bubble is being dragged to dismiss.
+ * @param bubbleView dragged bubble view
+ */
+ public void onDragStart(@NonNull BubbleView bubbleView) {
+ if (bubbleView.getBubble() == null) return;
+ mSystemUiProxy.onBubbleDrag(bubbleView.getBubble().getKey(), /* isBeingDragged = */ true);
+ mBarView.setDraggedBubble(bubbleView);
+ }
+
+ /**
+ * Notifies SystemUI to expand the selected bubble when the bubble is released.
+ * @param bubbleView dragged bubble view
+ */
+ public void onDragRelease(@NonNull BubbleView bubbleView) {
+ if (bubbleView.getBubble() == null) return;
+ mSystemUiProxy.onBubbleDrag(bubbleView.getBubble().getKey(), /* isBeingDragged = */ false);
+ }
+
+ /**
+ * Removes the dragged bubble view in the bubble bar view
+ */
+ public void onDragEnd() {
+ mBarView.setDraggedBubble(null);
+ }
+
+ /**
+ * Called when bubble was dragged into the dismiss target. Notifies System
+ * @param bubble dismissed bubble item
+ */
+ public void onDismissBubbleWhileDragging(@NonNull BubbleBarItem bubble) {
+ mSystemUiProxy.removeBubble(bubble.getKey());
+ }
+
+ /**
+ * Called when bubble stack was dragged into the dismiss target
+ */
+ public void onDismissAllBubblesWhileDragging() {
+ mSystemUiProxy.removeAllBubbles();
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
index 6417f3c..c47427d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
@@ -27,6 +27,8 @@
public final BubbleBarViewController bubbleBarViewController;
public final BubbleStashController bubbleStashController;
public final BubbleStashedHandleViewController bubbleStashedHandleViewController;
+ public final BubbleDragController bubbleDragController;
+ public final BubbleDismissController bubbleDismissController;
private final RunnableList mPostInitRunnables = new RunnableList();
@@ -39,11 +41,15 @@
BubbleBarController bubbleBarController,
BubbleBarViewController bubbleBarViewController,
BubbleStashController bubbleStashController,
- BubbleStashedHandleViewController bubbleStashedHandleViewController) {
+ BubbleStashedHandleViewController bubbleStashedHandleViewController,
+ BubbleDragController bubbleDragController,
+ BubbleDismissController bubbleDismissController) {
this.bubbleBarController = bubbleBarController;
this.bubbleBarViewController = bubbleBarViewController;
this.bubbleStashController = bubbleStashController;
this.bubbleStashedHandleViewController = bubbleStashedHandleViewController;
+ this.bubbleDragController = bubbleDragController;
+ this.bubbleDismissController = bubbleDismissController;
}
/**
@@ -56,6 +62,8 @@
bubbleBarViewController.init(taskbarControllers, this);
bubbleStashedHandleViewController.init(taskbarControllers, this);
bubbleStashController.init(taskbarControllers, this);
+ bubbleDragController.init(/* bubbleControllers = */ this);
+ bubbleDismissController.init(/* bubbleControllers = */ this);
mPostInitRunnables.executeAllAndDestroy();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
new file mode 100644
index 0000000..41c3dec
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar.bubbles;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.dynamicanimation.animation.DynamicAnimation;
+
+import com.android.launcher3.R;
+import com.android.launcher3.taskbar.TaskbarActivityContext;
+import com.android.launcher3.taskbar.TaskbarDragLayer;
+import com.android.wm.shell.common.bubbles.DismissView;
+import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
+
+/**
+ * Controls dismiss view presentation for the bubble bar dismiss functionality.
+ * Provides the dragged view snapping to the target dismiss area and animates it.
+ * When the dragged bubble/bubble stack is released inside of the target area, it gets dismissed.
+ *
+ * @see BubbleDragController
+ */
+public class BubbleDismissController {
+ private static final String TAG = BubbleDismissController.class.getSimpleName();
+ private static final float FLING_TO_DISMISS_MIN_VELOCITY = 6000f;
+ private final TaskbarActivityContext mActivity;
+ private final TaskbarDragLayer mDragLayer;
+ @Nullable
+ private BubbleBarViewController mBubbleBarViewController;
+
+ // Dismiss view that's attached to drag layer. It consists of the scrim view and the circular
+ // dismiss view used as a dismiss target.
+ @Nullable
+ private DismissView mDismissView;
+
+ // The currently magnetized object, which is being dragged and will be attracted to the magnetic
+ // dismiss target. This is either the stack itself, or an individual bubble.
+ @Nullable
+ private MagnetizedObject<View> mMagnetizedObject;
+
+ // The MagneticTarget instance for our circular dismiss view. This is added to the
+ // MagnetizedObject instances for the stack and any dragged-out bubbles.
+ @Nullable
+ private MagnetizedObject.MagneticTarget mMagneticTarget;
+
+ // The bubble drag animator that synchronizes bubble drag and dismiss view animations
+ // A new instance is provided when the dismiss view is setup
+ @Nullable
+ private BubbleDragAnimator mAnimator;
+
+ public BubbleDismissController(TaskbarActivityContext activity, TaskbarDragLayer dragLayer) {
+ mActivity = activity;
+ mDragLayer = dragLayer;
+ }
+
+ /**
+ * Initializes dependencies when bubble controllers are created.
+ * Should be careful to only access things that were created in constructors for now, as some
+ * controllers may still be waiting for init().
+ */
+ public void init(@NonNull BubbleControllers bubbleControllers) {
+ mBubbleBarViewController = bubbleControllers.bubbleBarViewController;
+ }
+
+ /**
+ * Setup the dismiss view and magnetized object that will be attracted to magnetic target.
+ * Should be called before handling events or showing/hiding dismiss view.
+ *
+ * @param magnetizedView the view to be pulled into target dismiss area
+ * @param animator the bubble animator to be used for the magnetized view, it syncs bubble
+ * dragging and dismiss animations with the dismiss view provided.
+ */
+ public void setupDismissView(@NonNull View magnetizedView,
+ @NonNull BubbleDragAnimator animator) {
+ setupDismissView();
+ setupMagnetizedObject(magnetizedView);
+ if (mDismissView != null) {
+ animator.setDismissView(mDismissView);
+ mAnimator = animator;
+ }
+ }
+
+ /**
+ * Handle the touch event and pass it to the magnetized object.
+ * It should be called after {@code setupDismissView}
+ */
+ public boolean handleTouchEvent(@NonNull MotionEvent event) {
+ return mMagnetizedObject != null && mMagnetizedObject.maybeConsumeMotionEvent(event);
+ }
+
+ /**
+ * Show dismiss view with animation
+ * It should be called after {@code setupDismissView}
+ */
+ public void showDismissView() {
+ if (mDismissView == null) return;
+ mDismissView.show();
+ }
+
+ /**
+ * Hide dismiss view with animation
+ * It should be called after {@code setupDismissView}
+ */
+ public void hideDismissView() {
+ if (mDismissView == null) return;
+ mDismissView.hide();
+ }
+
+ /**
+ * Dismiss magnetized object when it's released in the dismiss target area
+ */
+ private void dismissMagnetizedObject() {
+ if (mMagnetizedObject == null || mBubbleBarViewController == null) return;
+ if (mMagnetizedObject.getUnderlyingObject() instanceof BubbleView) {
+ BubbleView bubbleView = (BubbleView) mMagnetizedObject.getUnderlyingObject();
+ if (bubbleView.getBubble() != null) {
+ mBubbleBarViewController.onDismissBubbleWhileDragging(bubbleView.getBubble());
+ }
+ } else if (mMagnetizedObject.getUnderlyingObject() instanceof BubbleBarView) {
+ mBubbleBarViewController.onDismissAllBubblesWhileDragging();
+ }
+ }
+
+ private void setupDismissView() {
+ if (mDismissView != null) return;
+ mDismissView = new DismissView(mActivity.getApplicationContext());
+ BubbleDismissViewUtils.setup(mDismissView);
+ mDragLayer.addView(mDismissView, /* index = */ 0,
+ new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
+ mDismissView.setElevation(mDismissView.getResources().getDimensionPixelSize(
+ R.dimen.bubblebar_elevation));
+ setupMagneticTarget(mDismissView.getCircle());
+ }
+
+ private void setupMagneticTarget(@NonNull View view) {
+ int magneticFieldRadius = mActivity.getResources().getDimensionPixelSize(
+ R.dimen.bubblebar_dismiss_target_size);
+ mMagneticTarget = new MagnetizedObject.MagneticTarget(view, magneticFieldRadius);
+ }
+
+ private void setupMagnetizedObject(@NonNull View magnetizedView) {
+ mMagnetizedObject = new MagnetizedObject<>(mActivity.getApplicationContext(),
+ magnetizedView, DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y) {
+ @Override
+ public float getWidth(@NonNull View underlyingObject) {
+ return underlyingObject.getWidth() * underlyingObject.getScaleX();
+ }
+
+ @Override
+ public float getHeight(@NonNull View underlyingObject) {
+ return underlyingObject.getHeight() * underlyingObject.getScaleY();
+ }
+
+ @Override
+ public void getLocationOnScreen(@NonNull View underlyingObject, @NonNull int[] loc) {
+ underlyingObject.getLocationOnScreen(loc);
+ }
+ };
+
+ mMagnetizedObject.setHapticsEnabled(true);
+ mMagnetizedObject.setFlingToTargetMinVelocity(FLING_TO_DISMISS_MIN_VELOCITY);
+ if (mMagneticTarget != null) {
+ mMagnetizedObject.addTarget(mMagneticTarget);
+ } else {
+ Log.e(TAG,"Requires MagneticTarget to add target to MagnetizedObject!");
+ }
+ mMagnetizedObject.setMagnetListener(new MagnetizedObject.MagnetListener() {
+ @Override
+ public void onStuckToTarget(@NonNull MagnetizedObject.MagneticTarget target) {
+ if (mAnimator == null) return;
+ mAnimator.animateDismissCaptured();
+ }
+
+ @Override
+ public void onUnstuckFromTarget(@NonNull MagnetizedObject.MagneticTarget target,
+ float velX, float velY, boolean wasFlungOut) {
+ if (mAnimator == null) return;
+ mAnimator.animateDismissReleased();
+ }
+
+ @Override
+ public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target) {
+ dismissMagnetizedObject();
+ }
+ });
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissViewExt.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissViewExt.kt
new file mode 100644
index 0000000..6c3f0d8
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissViewExt.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@file:JvmName("BubbleDismissViewUtils")
+
+package com.android.launcher3.taskbar.bubbles
+
+import com.android.launcher3.R
+import com.android.wm.shell.common.bubbles.DismissView
+
+/**
+ * Dismiss view is shared from WMShell. It requires setup with local resources.
+ *
+ * Usage:
+ * - Kotlin `dismissView.setup()`
+ * - Java `BubbleDismissViewUtils.setup(dismissView)`
+ */
+fun DismissView.setup() {
+ setup(
+ DismissView.Config(
+ dismissViewResId = R.id.dismiss_view,
+ targetSizeResId = R.dimen.bubblebar_dismiss_target_size,
+ iconSizeResId = R.dimen.bubblebar_dismiss_target_icon_size,
+ bottomMarginResId = R.dimen.bubblebar_dismiss_target_bottom_margin,
+ floatingGradientHeightResId = R.dimen.bubblebar_dismiss_floating_gradient_height,
+ floatingGradientColorResId = android.R.color.system_neutral1_900,
+ backgroundResId = R.drawable.bg_bubble_dismiss_circle,
+ iconResId = R.drawable.ic_bubble_dismiss_white
+ )
+ )
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
new file mode 100644
index 0000000..24dca5e
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar.bubbles;
+
+import static androidx.dynamicanimation.animation.SpringForce.DAMPING_RATIO_LOW_BOUNCY;
+import static androidx.dynamicanimation.animation.SpringForce.STIFFNESS_LOW;
+import static androidx.dynamicanimation.animation.SpringForce.STIFFNESS_MEDIUM;
+
+import android.content.res.Resources;
+import android.graphics.PointF;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.dynamicanimation.animation.DynamicAnimation;
+import androidx.dynamicanimation.animation.FloatPropertyCompat;
+
+import com.android.launcher3.R;
+import com.android.wm.shell.animation.PhysicsAnimator;
+import com.android.wm.shell.common.bubbles.DismissCircleView;
+import com.android.wm.shell.common.bubbles.DismissView;
+
+/**
+ * The animator performs the bubble animations while dragging and coordinates bubble and dismiss
+ * view animations when it gets magnetized, released or dismissed.
+ */
+public class BubbleDragAnimator {
+ private static final float SCALE_BUBBLE_FOCUSED = 1.2f;
+ private static final float SCALE_BUBBLE_CAPTURED = 0.9f;
+ private static final float SCALE_BUBBLE_BAR_FOCUSED = 1.1f;
+
+ private final PhysicsAnimator.SpringConfig mDefaultConfig =
+ new PhysicsAnimator.SpringConfig(STIFFNESS_LOW, DAMPING_RATIO_LOW_BOUNCY);
+ private final PhysicsAnimator.SpringConfig mTranslationConfig =
+ new PhysicsAnimator.SpringConfig(STIFFNESS_MEDIUM, DAMPING_RATIO_LOW_BOUNCY);
+ @NonNull
+ private final View mView;
+ @NonNull
+ private final PhysicsAnimator<View> mBubbleAnimator;
+ @Nullable
+ private DismissView mDismissView;
+ @Nullable
+ private PhysicsAnimator<DismissCircleView> mDismissAnimator;
+ private final float mBubbleFocusedScale;
+ private final float mBubbleCapturedScale;
+ private final float mDismissCapturedScale;
+
+ /**
+ * Should be initialised for each dragged view
+ *
+ * @param view the dragged view to animate
+ */
+ public BubbleDragAnimator(@NonNull View view) {
+ mView = view;
+ mBubbleAnimator = PhysicsAnimator.getInstance(view);
+ mBubbleAnimator.setDefaultSpringConfig(mDefaultConfig);
+
+ Resources resources = view.getResources();
+ final int collapsedSize = resources.getDimensionPixelSize(
+ R.dimen.bubblebar_dismiss_target_small_size);
+ final int expandedSize = resources.getDimensionPixelSize(
+ R.dimen.bubblebar_dismiss_target_size);
+ mDismissCapturedScale = (float) collapsedSize / expandedSize;
+
+ if (view instanceof BubbleBarView) {
+ mBubbleFocusedScale = SCALE_BUBBLE_BAR_FOCUSED;
+ mBubbleCapturedScale = mDismissCapturedScale;
+ } else {
+ mBubbleFocusedScale = SCALE_BUBBLE_FOCUSED;
+ mBubbleCapturedScale = SCALE_BUBBLE_CAPTURED;
+ }
+ }
+
+ /**
+ * Sets dismiss view to be animated alongside the dragged bubble
+ */
+ public void setDismissView(@NonNull DismissView dismissView) {
+ mDismissView = dismissView;
+ mDismissAnimator = PhysicsAnimator.getInstance(dismissView.getCircle());
+ mDismissAnimator.setDefaultSpringConfig(mDefaultConfig);
+ }
+
+ /**
+ * Animates the focused state of the bubble when the dragging starts
+ */
+ public void animateFocused() {
+ mBubbleAnimator.cancel();
+ mBubbleAnimator
+ .spring(DynamicAnimation.SCALE_X, mBubbleFocusedScale)
+ .spring(DynamicAnimation.SCALE_Y, mBubbleFocusedScale)
+ .start();
+ }
+
+ /**
+ * Animates the dragged bubble movement back to the initial position.
+ *
+ * @param initialPosition the position to animate to
+ * @param velocity the initial velocity to use for the spring animation
+ * @param endActions gets called when the animation completes or gets cancelled
+ */
+ public void animateToInitialState(@NonNull PointF initialPosition, @NonNull PointF velocity,
+ @Nullable Runnable endActions) {
+ mBubbleAnimator.cancel();
+ mBubbleAnimator
+ .spring(DynamicAnimation.SCALE_X, 1f)
+ .spring(DynamicAnimation.SCALE_Y, 1f)
+ .spring(DynamicAnimation.TRANSLATION_X, initialPosition.x, velocity.x,
+ mTranslationConfig)
+ .spring(DynamicAnimation.TRANSLATION_Y, initialPosition.y, velocity.y,
+ mTranslationConfig)
+ .addEndListener((View target, @NonNull FloatPropertyCompat<? super View> property,
+ boolean wasFling, boolean canceled, float finalValue, float finalVelocity,
+ boolean allRelevantPropertyAnimationsEnded) -> {
+ if (canceled || allRelevantPropertyAnimationsEnded) {
+ resetAnimatedViews(initialPosition);
+ if (endActions != null) {
+ endActions.run();
+ }
+ }
+ })
+ .start();
+ }
+
+ /**
+ * Animates the dragged view alongside the dismiss view when it gets captured in the dismiss
+ * target area.
+ */
+ public void animateDismissCaptured() {
+ mBubbleAnimator.cancel();
+ mBubbleAnimator
+ .spring(DynamicAnimation.SCALE_X, mBubbleCapturedScale)
+ .spring(DynamicAnimation.SCALE_Y, mBubbleCapturedScale)
+ .spring(DynamicAnimation.ALPHA, mDismissCapturedScale)
+ .start();
+
+ if (mDismissAnimator != null) {
+ mDismissAnimator.cancel();
+ mDismissAnimator
+ .spring(DynamicAnimation.SCALE_X, mDismissCapturedScale)
+ .spring(DynamicAnimation.SCALE_Y, mDismissCapturedScale)
+ .start();
+ }
+ }
+
+ /**
+ * Animates the dragged view alongside the dismiss view when it gets released from the dismiss
+ * target area.
+ */
+ public void animateDismissReleased() {
+ mBubbleAnimator.cancel();
+ mBubbleAnimator
+ .spring(DynamicAnimation.SCALE_X, mBubbleFocusedScale)
+ .spring(DynamicAnimation.SCALE_Y, mBubbleFocusedScale)
+ .spring(DynamicAnimation.ALPHA, 1f)
+ .start();
+
+ if (mDismissAnimator != null) {
+ mDismissAnimator.cancel();
+ mDismissAnimator
+ .spring(DynamicAnimation.SCALE_X, 1f)
+ .spring(DynamicAnimation.SCALE_Y, 1f)
+ .start();
+ }
+ }
+
+ /**
+ * Animates the dragged bubble dismiss when it's released in the dismiss target area.
+ *
+ * @param initialPosition the initial position to move the bubble too after animation finishes
+ * @param endActions gets called when the animation completes or gets cancelled
+ */
+ public void animateDismiss(@NonNull PointF initialPosition, @Nullable Runnable endActions) {
+ float dismissHeight = mDismissView != null ? mDismissView.getHeight() : 0f;
+ float translationY = mView.getTranslationY() + dismissHeight;
+ mBubbleAnimator
+ .spring(DynamicAnimation.TRANSLATION_Y, translationY)
+ .spring(DynamicAnimation.SCALE_X, 0f)
+ .spring(DynamicAnimation.SCALE_Y, 0f)
+ .spring(DynamicAnimation.ALPHA, 0f)
+ .addEndListener((View target, @NonNull FloatPropertyCompat<? super View> property,
+ boolean wasFling, boolean canceled, float finalValue, float finalVelocity,
+ boolean allRelevantPropertyAnimationsEnded) -> {
+ if (canceled || allRelevantPropertyAnimationsEnded) {
+ resetAnimatedViews(initialPosition);
+ if (endActions != null) endActions.run();
+ }
+ })
+ .start();
+ }
+
+ /**
+ * Reset the animated views to the initial state
+ *
+ * @param initialPosition position of the bubble
+ */
+ private void resetAnimatedViews(@NonNull PointF initialPosition) {
+ mView.setScaleX(1f);
+ mView.setScaleY(1f);
+ mView.setAlpha(1f);
+ mView.setTranslationX(initialPosition.x);
+ mView.setTranslationY(initialPosition.y);
+
+ if (mDismissView != null) {
+ mDismissView.getCircle().setScaleX(1f);
+ mDismissView.getCircle().setScaleY(1f);
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java
new file mode 100644
index 0000000..08fd681
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar.bubbles;
+
+import android.annotation.SuppressLint;
+import android.graphics.PointF;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.taskbar.TaskbarActivityContext;
+
+/**
+ * Controls bubble bar drag to dismiss interaction.
+ * Interacts with {@link BubbleDismissController}, used by {@link BubbleBarViewController}.
+ * Supported interactions:
+ * - Drag a single bubble view into dismiss target to remove it.
+ * - Drag the bubble stack into dismiss target to remove all.
+ * Restores initial position of dragged view if released outside of the dismiss target.
+ */
+public class BubbleDragController {
+ private final TaskbarActivityContext mActivity;
+ private BubbleBarViewController mBubbleBarViewController;
+ private BubbleDismissController mBubbleDismissController;
+
+ public BubbleDragController(TaskbarActivityContext activity) {
+ mActivity = activity;
+ }
+
+ /**
+ * Initializes dependencies when bubble controllers are created.
+ * Should be careful to only access things that were created in constructors for now, as some
+ * controllers may still be waiting for init().
+ */
+ public void init(@NonNull BubbleControllers bubbleControllers) {
+ mBubbleBarViewController = bubbleControllers.bubbleBarViewController;
+ mBubbleDismissController = bubbleControllers.bubbleDismissController;
+ }
+
+ /**
+ * Setup the bubble view for dragging and attach touch listener to it
+ */
+ @SuppressLint("ClickableViewAccessibility")
+ public void setupBubbleView(@NonNull BubbleView bubbleView) {
+ if (!(bubbleView.getBubble() instanceof BubbleBarBubble)) {
+ // Don't setup dragging for overflow bubble view
+ return;
+ }
+
+ bubbleView.setOnTouchListener(new BubbleTouchListener() {
+ @Override
+ void onDragStart() {
+ mBubbleBarViewController.onDragStart(bubbleView);
+ }
+
+ @Override
+ void onDragEnd() {
+ mBubbleBarViewController.onDragEnd();
+ }
+
+ @Override
+ protected void onDragRelease() {
+ mBubbleBarViewController.onDragRelease(bubbleView);
+ }
+ });
+ }
+
+ /**
+ * Setup the bubble bar view for dragging and attach touch listener to it
+ */
+ @SuppressLint("ClickableViewAccessibility")
+ public void setupBubbleBarView(@NonNull BubbleBarView bubbleBarView) {
+ PointF initialRelativePivot = new PointF();
+ bubbleBarView.setOnTouchListener(new BubbleTouchListener() {
+ @Override
+ protected boolean onTouchDown(@NonNull View view, @NonNull MotionEvent event) {
+ if (bubbleBarView.isExpanded()) return false;
+ return super.onTouchDown(view, event);
+ }
+
+ @Override
+ void onDragStart() {
+ initialRelativePivot.set(bubbleBarView.getRelativePivotX(),
+ bubbleBarView.getRelativePivotY());
+ // By default the bubble bar view pivot is in bottom right corner, while dragging
+ // it should be centered in order to align it with the dismiss target view
+ bubbleBarView.setRelativePivot(/* x = */ 0.5f, /* y = */ 0.5f);
+ }
+
+ @Override
+ void onDragEnd() {
+ // Restoring the initial pivot for the bubble bar view
+ bubbleBarView.setRelativePivot(initialRelativePivot.x, initialRelativePivot.y);
+ }
+ });
+ }
+
+ /**
+ * Bubble touch listener for handling a single bubble view or bubble bar view while dragging.
+ * The dragging starts after "shorter" long click (the long click duration might change):
+ * - When the touch gesture moves out of the {@code ACTION_DOWN} location the dragging
+ * interaction is cancelled.
+ * - When {@code ACTION_UP} happens before long click is registered and there was no significant
+ * movement the view will perform click.
+ * - When the listener registers long click it starts dragging interaction, all the subsequent
+ * {@code ACTION_MOVE} events will drag the view, and the interaction finishes when
+ * {@code ACTION_UP} or {@code ACTION_CANCEL} are received.
+ * Lifecycle methods can be overridden do add extra setup/clean up steps.
+ */
+ private abstract class BubbleTouchListener implements View.OnTouchListener {
+ /**
+ * The internal state of the touch listener
+ */
+ private enum State {
+ // Idle and ready for the touch events.
+ // Changes to:
+ // - TOUCHED, when the {@code ACTION_DOWN} is handled
+ IDLE,
+
+ // Touch down was handled and the lister is recognising the gestures.
+ // Changes to:
+ // - IDLE, when performs the click
+ // - DRAGGING, when registers the long click and starts dragging interaction
+ // - CANCELLED, when the touch events move out of the initial location before the long
+ // click is recognised
+
+ TOUCHED,
+
+ // The long click was registered and the view is being dragged.
+ // Changes to:
+ // - IDLE, when the gesture ends with the {@code ACTION_UP} or {@code ACTION_CANCEL}
+ DRAGGING,
+
+ // The dragging was cancelled.
+ // Changes to:
+ // - IDLE, when the current gesture completes
+ CANCELLED
+ }
+
+ private final PointF mTouchDownLocation = new PointF();
+ private final PointF mViewInitialPosition = new PointF();
+ private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
+ private final long mPressToDragTimeout = ViewConfiguration.getLongPressTimeout() / 2;
+ private State mState = State.IDLE;
+ private int mTouchSlop = -1;
+ private BubbleDragAnimator mAnimator;
+ @Nullable
+ private Runnable mLongClickRunnable;
+
+ /**
+ * Called when the dragging interaction has started
+ */
+ abstract void onDragStart();
+
+ /**
+ * Called when the dragging interaction has ended and all the animations have completed
+ */
+ abstract void onDragEnd();
+
+ /**
+ * Called when the dragged bubble is released outside of the dismiss target area and will
+ * move back to its initial position
+ */
+ protected void onDragRelease() {
+ }
+
+ /**
+ * Called when the dragged bubble is released inside of the dismiss target area and will get
+ * dismissed with animation
+ */
+ protected void onDragDismiss() {
+ }
+
+ @Override
+ @SuppressLint("ClickableViewAccessibility")
+ public boolean onTouch(@NonNull View view, @NonNull MotionEvent event) {
+ updateVelocity(event);
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ return onTouchDown(view, event);
+ case MotionEvent.ACTION_MOVE:
+ onTouchMove(view, event);
+ break;
+ case MotionEvent.ACTION_UP:
+ onTouchUp(view, event);
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ onTouchCancel(view, event);
+ break;
+ }
+ return true;
+ }
+
+ /**
+ * The touch down starts the interaction and schedules the long click handler.
+ *
+ * @param view the view that received the event
+ * @param event the motion event
+ * @return true if the gesture should be intercepted and handled, false otherwise. Note if
+ * the false is returned subsequent events in the gesture won't get reported.
+ */
+ protected boolean onTouchDown(@NonNull View view, @NonNull MotionEvent event) {
+ mState = State.TOUCHED;
+ mTouchSlop = ViewConfiguration.get(view.getContext()).getScaledTouchSlop();
+ mTouchDownLocation.set(event.getRawX(), event.getRawY());
+ mViewInitialPosition.set(view.getTranslationX(), view.getTranslationY());
+ setupLongClickHandler(view);
+ return true;
+ }
+
+ /**
+ * The move event drags the view or cancels the interaction if hasn't long clicked yet.
+ *
+ * @param view the view that received the event
+ * @param event the motion event
+ */
+ protected void onTouchMove(@NonNull View view, @NonNull MotionEvent event) {
+ final float dx = event.getRawX() - mTouchDownLocation.x;
+ final float dy = event.getRawY() - mTouchDownLocation.y;
+ switch (mState) {
+ case TOUCHED:
+ final boolean movedOut = Math.hypot(dx, dy) > mTouchSlop;
+ if (movedOut) {
+ // Moved out of the initial location before the long click was registered
+ mState = State.CANCELLED;
+ cleanUpLongClickHandler(view);
+ }
+ break;
+ case DRAGGING:
+ drag(view, event, dx, dy);
+ break;
+ }
+ }
+
+ /**
+ * On touch up performs click or finishes the dragging depending on the state.
+ *
+ * @param view the view that received the event
+ * @param event the motion event
+ */
+ protected void onTouchUp(@NonNull View view, @NonNull MotionEvent event) {
+ switch (mState) {
+ case TOUCHED:
+ view.performClick();
+ cleanUp(view);
+ break;
+ case DRAGGING:
+ stopDragging(view, event);
+ break;
+ default:
+ cleanUp(view);
+ break;
+ }
+ }
+
+ /**
+ * The gesture is cancelled and the interaction should clean up and complete.
+ *
+ * @param view the view that received the event
+ * @param event the motion event
+ */
+ protected void onTouchCancel(@NonNull View view, @NonNull MotionEvent event) {
+ if (mState == State.DRAGGING) {
+ stopDragging(view, event);
+ } else {
+ cleanUp(view);
+ }
+ }
+
+ private void startDragging(@NonNull View view) {
+ onDragStart();
+ mActivity.setTaskbarWindowFullscreen(true);
+ mAnimator = new BubbleDragAnimator(view);
+ mAnimator.animateFocused();
+ mBubbleDismissController.setupDismissView(view, mAnimator);
+ mBubbleDismissController.showDismissView();
+ }
+
+ private void drag(@NonNull View view, @NonNull MotionEvent event, float dx, float dy) {
+ if (mBubbleDismissController.handleTouchEvent(event)) return;
+ view.setTranslationX(mViewInitialPosition.x + dx);
+ view.setTranslationY(mViewInitialPosition.y + dy);
+ }
+
+ private void stopDragging(@NonNull View view, @NonNull MotionEvent event) {
+ Runnable onComplete = () -> {
+ mActivity.setTaskbarWindowFullscreen(false);
+ cleanUp(view);
+ onDragEnd();
+ };
+
+ if (mBubbleDismissController.handleTouchEvent(event)) {
+ onDragDismiss();
+ mAnimator.animateDismiss(mViewInitialPosition, onComplete);
+ } else {
+ onDragRelease();
+ mAnimator.animateToInitialState(mViewInitialPosition, getCurrentVelocity(),
+ onComplete);
+ }
+ mBubbleDismissController.hideDismissView();
+ }
+
+ private void setupLongClickHandler(@NonNull View view) {
+ cleanUpLongClickHandler(view);
+ mLongClickRunnable = () -> {
+ // Register long click and start dragging interaction
+ mState = State.DRAGGING;
+ startDragging(view);
+ };
+ view.getHandler().postDelayed(mLongClickRunnable, mPressToDragTimeout);
+ }
+
+ private void cleanUpLongClickHandler(@NonNull View view) {
+ if (mLongClickRunnable == null || view.getHandler() == null) return;
+ view.getHandler().removeCallbacks(mLongClickRunnable);
+ mLongClickRunnable = null;
+ }
+
+ private void cleanUp(@NonNull View view) {
+ cleanUpLongClickHandler(view);
+ mVelocityTracker.clear();
+ mState = State.IDLE;
+ }
+
+ private void updateVelocity(MotionEvent event) {
+ final float deltaX = event.getRawX() - event.getX();
+ final float deltaY = event.getRawY() - event.getY();
+ event.offsetLocation(deltaX, deltaY);
+ mVelocityTracker.addMovement(event);
+ event.offsetLocation(-deltaX, -deltaY);
+ }
+
+ private PointF getCurrentVelocity() {
+ mVelocityTracker.computeCurrentVelocity(/* units = */ 1000);
+ return new PointF(mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
index 0ab53b0..a5ea5a9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.taskbar.bubbles;
+import static java.lang.Math.abs;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -25,6 +27,7 @@
import com.android.launcher3.taskbar.StashedHandleViewController;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarControllers;
+import com.android.launcher3.taskbar.TaskbarInsetsController;
import com.android.launcher3.taskbar.TaskbarStashController;
import com.android.launcher3.util.MultiPropertyFactory;
@@ -50,6 +53,7 @@
// Initialized in init.
private TaskbarControllers mControllers;
+ private TaskbarInsetsController mTaskbarInsetsController;
private BubbleBarViewController mBarViewController;
private BubbleStashedHandleViewController mHandleViewController;
private TaskbarStashController mTaskbarStashController;
@@ -67,6 +71,7 @@
private int mUnstashedHeight;
private boolean mBubblesShowingOnHome;
private boolean mBubblesShowingOnOverview;
+ private boolean mIsSysuiLocked;
@Nullable
private AnimatorSet mAnimator;
@@ -77,6 +82,7 @@
public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
mControllers = controllers;
+ mTaskbarInsetsController = controllers.taskbarInsetsController;
mBarViewController = bubbleControllers.bubbleBarViewController;
mHandleViewController = bubbleControllers.bubbleStashedHandleViewController;
mTaskbarStashController = controllers.taskbarStashController;
@@ -90,14 +96,6 @@
mStashedHeight = mHandleViewController.getStashedHeight();
mUnstashedHeight = mHandleViewController.getUnstashedHeight();
-
- bubbleControllers.runAfterInit(() -> {
- if (mTaskbarStashController.isStashed()) {
- stashBubbleBar();
- } else {
- showBubbleBar(false /* expandBubbles */);
- }
- });
}
/**
@@ -115,13 +113,63 @@
}
/**
+ * Animates the bubble bar and handle to their initial state, transitioning from the state where
+ * both views are invisible. Called when the first bubble is added or when the device is
+ * unlocked.
+ *
+ * <p>Normally either the bubble bar or the handle is visible,
+ * and {@link #showBubbleBar(boolean)} and {@link #stashBubbleBar()} are used to transition
+ * between these two states. But the transition from the state where both the bar and handle
+ * are invisible is slightly different.
+ *
+ * <p>The initial state will depend on the current state of the device, i.e. overview, home etc
+ * and whether bubbles are requested to be expanded.
+ */
+ public void animateToInitialState(boolean expanding) {
+ AnimatorSet animatorSet = new AnimatorSet();
+ if (expanding || mBubblesShowingOnHome || mBubblesShowingOnOverview) {
+ mIsStashed = false;
+ animatorSet.playTogether(mIconScaleForStash.animateToValue(1),
+ mIconTranslationYForStash.animateToValue(getBubbleBarTranslationY()),
+ mIconAlphaForStash.animateToValue(1));
+ } else {
+ mIsStashed = true;
+ animatorSet.playTogether(mBubbleStashedHandleAlpha.animateToValue(1));
+ }
+
+ animatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ onIsStashedChanged();
+ }
+ });
+ animatorSet.setDuration(BAR_STASH_DURATION).start();
+ }
+
+ /**
* Called when launcher enters or exits the home page. Bubbles are unstashed on home.
*/
public void setBubblesShowingOnHome(boolean onHome) {
if (mBubblesShowingOnHome != onHome) {
mBubblesShowingOnHome = onHome;
+
+ if (!mBarViewController.hasBubbles()) {
+ // if there are no bubbles, there's nothing to show, so just return.
+ return;
+ }
+
if (mBubblesShowingOnHome) {
showBubbleBar(/* expanded= */ false);
+ // When transitioning from app to home the stash animator may already have been
+ // created, so we need to animate the bubble bar here to align with hotseat.
+ if (!mIsStashed) {
+ mIconTranslationYForStash.animateToValue(getBubbleBarTranslationYForHotseat())
+ .start();
+ }
+ // If the bubble bar is already unstashed, the taskbar touchable region won't be
+ // updated correctly, so force an update here.
+ mControllers.runAfterInit(() ->
+ mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged());
} else if (!mBarViewController.isExpanded()) {
stashBubbleBar();
}
@@ -140,18 +188,27 @@
mBubblesShowingOnOverview = onOverview;
if (!mBubblesShowingOnOverview && !mBarViewController.isExpanded()) {
stashBubbleBar();
+ } else {
+ // When transitioning to overview the stash animator may already have been
+ // created, so we need to animate the bubble bar here to align with taskbar.
+ mIconTranslationYForStash.animateToValue(getBubbleBarTranslationYForTaskbar())
+ .start();
}
}
}
+ /** Whether bubbles are showing on Overview. */
+ public boolean isBubblesShowingOnOverview() {
+ return mBubblesShowingOnOverview;
+ }
+
/** Called when sysui locked state changes, when locked, bubble bar is stashed. */
public void onSysuiLockedStateChange(boolean isSysuiLocked) {
- if (isSysuiLocked) {
- // TODO: should the normal path flip mBubblesOnHome / check if this is needed
- // If we're locked, we're no longer showing on home.
- mBubblesShowingOnHome = false;
- mBubblesShowingOnOverview = false;
- stashBubbleBar();
+ if (isSysuiLocked != mIsSysuiLocked) {
+ mIsSysuiLocked = isSysuiLocked;
+ if (!mIsSysuiLocked && mBarViewController.hasBubbles()) {
+ animateToInitialState(false /* expanding */);
+ }
}
}
@@ -230,9 +287,8 @@
firstHalfDurationScale = 0.5f;
secondHalfDurationScale = 0.75f;
- // If we're on home, adjust the translation so the bubble bar aligns with hotseat.
- final float hotseatTransY = mActivity.getDeviceProfile().getTaskbarOffsetY();
- final float translationY = mBubblesShowingOnHome ? hotseatTransY : 0;
+ final float translationY = getBubbleBarTranslationY();
+
fullLengthAnimatorSet.playTogether(
mIconScaleForStash.animateToValue(1),
mIconTranslationYForStash.animateToValue(translationY));
@@ -262,6 +318,7 @@
if (isStashed) {
mBarViewController.setExpanded(false);
}
+ mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
});
}
});
@@ -271,7 +328,26 @@
private void onIsStashedChanged() {
mControllers.runAfterInit(() -> {
mHandleViewController.onIsStashedChanged();
- // TODO: when stash changes tell taskbarInsetsController the insets have changed.
+ mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
});
}
+
+ private float getBubbleBarTranslationYForTaskbar() {
+ return -mActivity.getDeviceProfile().taskbarBottomMargin;
+ }
+
+ private float getBubbleBarTranslationYForHotseat() {
+ final float hotseatBottomSpace = mActivity.getDeviceProfile().hotseatBarBottomSpacePx;
+ final float hotseatCellHeight = mActivity.getDeviceProfile().hotseatCellHeightPx;
+ return -hotseatBottomSpace - hotseatCellHeight + mUnstashedHeight - abs(
+ hotseatCellHeight - mUnstashedHeight) / 2;
+ }
+
+ float getBubbleBarTranslationY() {
+ // If we're on home, adjust the translation so the bubble bar aligns with hotseat.
+ // Otherwise we're either showing in an app or in overview. In either case adjust it so
+ // the bubble bar aligns with the taskbar.
+ return mBubblesShowingOnHome ? getBubbleBarTranslationYForHotseat()
+ : getBubbleBarTranslationYForTaskbar();
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
index 2170a5d..fbab595 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
@@ -52,6 +52,7 @@
private BubbleStashController mBubbleStashController;
private RegionSamplingHelper mRegionSamplingHelper;
private int mBarSize;
+ private int mStashedTaskbarHeight;
private int mStashedHandleWidth;
private int mStashedHandleHeight;
@@ -92,7 +93,7 @@
mTaskbarStashedHandleAlpha.get(0).setValue(0);
- final int stashedTaskbarHeight = resources.getDimensionPixelSize(
+ mStashedTaskbarHeight = resources.getDimensionPixelSize(
R.dimen.bubblebar_stashed_size);
mStashedHandleView.setOutlineProvider(new ViewOutlineProvider() {
@Override
@@ -115,22 +116,27 @@
}
}, Executors.UI_HELPER_EXECUTOR);
- mStashedHandleView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) -> {
- // As more bubbles get added, the icon bounds become larger. To ensure a consistent
- // handle bar position, we pin it to the edge of the screen.
- Rect bubblebarRect = mBarViewController.getBubbleBarBounds();
- final int stashedCenterY = view.getHeight() - stashedTaskbarHeight / 2;
+ mStashedHandleView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) ->
+ updateBounds());
+ }
- mStashedHandleBounds.set(
- bubblebarRect.right - mStashedHandleWidth,
- stashedCenterY - mStashedHandleHeight / 2,
- bubblebarRect.right,
- stashedCenterY + mStashedHandleHeight / 2);
- mStashedHandleView.updateSampledRegion(mStashedHandleBounds);
+ private void updateBounds() {
+ // As more bubbles get added, the icon bounds become larger. To ensure a consistent
+ // handle bar position, we pin it to the edge of the screen.
+ final int right =
+ mActivity.getDeviceProfile().widthPx - mBarViewController.getHorizontalMargin();
- view.setPivotX(view.getWidth());
- view.setPivotY(view.getHeight() - stashedTaskbarHeight / 2f);
- });
+ final int stashedCenterY = mStashedHandleView.getHeight() - mStashedTaskbarHeight / 2;
+
+ mStashedHandleBounds.set(
+ right - mStashedHandleWidth,
+ stashedCenterY - mStashedHandleHeight / 2,
+ right,
+ stashedCenterY + mStashedHandleHeight / 2);
+ mStashedHandleView.updateSampledRegion(mStashedHandleBounds);
+
+ mStashedHandleView.setPivotX(mStashedHandleView.getWidth());
+ mStashedHandleView.setPivotY(mStashedHandleView.getHeight() - mStashedTaskbarHeight / 2f);
}
public void onDestroy() {
@@ -188,6 +194,7 @@
mStashedHandleView.setVisibility(VISIBLE);
} else {
mStashedHandleView.setVisibility(INVISIBLE);
+ mStashedHandleView.setAlpha(0);
}
updateRegionSampling();
}
@@ -203,12 +210,14 @@
private void updateRegionSampling() {
boolean handleVisible = mStashedHandleView.getVisibility() == VISIBLE
&& mBubbleStashController.isStashed();
- mRegionSamplingHelper.setWindowVisible(handleVisible);
- if (handleVisible) {
- mStashedHandleView.updateSampledRegion(mStashedHandleBounds);
- mRegionSamplingHelper.start(mStashedHandleView.getSampledRegion());
- } else {
- mRegionSamplingHelper.stop();
+ if (mRegionSamplingHelper != null) {
+ mRegionSamplingHelper.setWindowVisible(handleVisible);
+ if (handleVisible) {
+ mStashedHandleView.updateSampledRegion(mStashedHandleBounds);
+ mRegionSamplingHelper.start(mStashedHandleView.getSampledRegion());
+ } else {
+ mRegionSamplingHelper.stop();
+ }
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
index e22e63a..12cb8c5 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
@@ -18,7 +18,9 @@
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.Canvas;
import android.graphics.Outline;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -28,27 +30,59 @@
import androidx.constraintlayout.widget.ConstraintLayout;
import com.android.launcher3.R;
+import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.IconNormalizer;
+import com.android.wm.shell.animation.Interpolators;
+
+import java.util.EnumSet;
// TODO: (b/276978250) This is will be similar to WMShell's BadgedImageView, it'd be nice to share.
-// TODO: (b/269670235) currently this doesn't show the 'update dot'
+
/**
* View that displays a bubble icon, along with an app badge on either the left or
* right side of the view.
*/
public class BubbleView extends ConstraintLayout {
- // TODO: (b/269670235) currently we don't render the 'update dot', this will be used for that.
public static final int DEFAULT_PATH_SIZE = 100;
+ /**
+ * Flags that suppress the visibility of the 'new' dot or the app badge, for one reason or
+ * another. If any of these flags are set, the dot will not be shown.
+ * If {@link SuppressionFlag#BEHIND_STACK} then the app badge will not be shown.
+ */
+ enum SuppressionFlag {
+ // TODO: (b/277815200) implement flyout
+ // Suppressed because the flyout is visible - it will morph into the dot via animation.
+ FLYOUT_VISIBLE,
+ // Suppressed because this bubble is behind others in the collapsed stack.
+ BEHIND_STACK,
+ }
+
+ private final EnumSet<SuppressionFlag> mSuppressionFlags =
+ EnumSet.noneOf(SuppressionFlag.class);
+
private final ImageView mBubbleIcon;
private final ImageView mAppIcon;
private final int mBubbleSize;
+ private DotRenderer mDotRenderer;
+ private DotRenderer.DrawParams mDrawParams;
+ private int mDotColor;
+ private Rect mTempBounds = new Rect();
+
+ // Whether the dot is animating
+ private boolean mDotIsAnimating;
+ // What scale value the dot is animating to
+ private float mAnimatingToDotScale;
+ // The current scale value of the dot
+ private float mDotScale;
+
// TODO: (b/273310265) handle RTL
+ // Whether the bubbles are positioned on the left or right side of the screen
private boolean mOnLeft = false;
- private BubbleBarBubble mBubble;
+ private BubbleBarItem mBubble;
public BubbleView(Context context) {
this(context, null);
@@ -74,6 +108,8 @@
mBubbleIcon = findViewById(R.id.icon_view);
mAppIcon = findViewById(R.id.app_icon_view);
+ mDrawParams = new DotRenderer.DrawParams();
+
setFocusable(true);
setClickable(true);
setOutlineProvider(new ViewOutlineProvider() {
@@ -90,45 +126,147 @@
outline.setOval(inset, inset, inset + normalizedSize, inset + normalizedSize);
}
+ @Override
+ public void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+
+ if (!shouldDrawDot()) {
+ return;
+ }
+
+ getDrawingRect(mTempBounds);
+
+ mDrawParams.dotColor = mDotColor;
+ mDrawParams.iconBounds = mTempBounds;
+ mDrawParams.leftAlign = mOnLeft;
+ mDrawParams.scale = mDotScale;
+
+ mDotRenderer.draw(canvas, mDrawParams);
+ }
+
/** Sets the bubble being rendered in this view. */
void setBubble(BubbleBarBubble bubble) {
mBubble = bubble;
mBubbleIcon.setImageBitmap(bubble.getIcon());
mAppIcon.setImageBitmap(bubble.getBadge());
+ mDotColor = bubble.getDotColor();
+ mDotRenderer = new DotRenderer(mBubbleSize, bubble.getDotPath(), DEFAULT_PATH_SIZE);
+ }
+
+ /**
+ * Sets that this bubble represents the overflow. The overflow appears in the list of bubbles
+ * but does not represent app content, instead it shows recent bubbles that couldn't fit into
+ * the list of bubbles. It doesn't show an app icon because it is part of system UI / doesn't
+ * come from an app.
+ */
+ void setOverflow(BubbleBarOverflow overflow, Bitmap bitmap) {
+ mBubble = overflow;
+ mBubbleIcon.setImageBitmap(bitmap);
+ mAppIcon.setVisibility(GONE); // Overflow doesn't show the app badge
}
/** Returns the bubble being rendered in this view. */
@Nullable
- BubbleBarBubble getBubble() {
+ BubbleBarItem getBubble() {
return mBubble;
}
- /** Shows the app badge on this bubble. */
- void showBadge() {
- Bitmap appBadgeBitmap = mBubble.getBadge();
- if (appBadgeBitmap == null) {
- mAppIcon.setVisibility(GONE);
+ void updateDotVisibility(boolean animate) {
+ final float targetScale = shouldDrawDot() ? 1f : 0f;
+ if (animate) {
+ animateDotScale();
+ } else {
+ mDotScale = targetScale;
+ mAnimatingToDotScale = targetScale;
+ invalidate();
+ }
+ }
+
+ void updateBadgeVisibility() {
+ if (mBubble instanceof BubbleBarOverflow) {
+ // The overflow bubble does not have a badge, so just bail.
+ return;
+ }
+ BubbleBarBubble bubble = (BubbleBarBubble) mBubble;
+ Bitmap appBadgeBitmap = bubble.getBadge();
+ int translationX = mOnLeft
+ ? -(bubble.getIcon().getWidth() - appBadgeBitmap.getWidth())
+ : 0;
+ mAppIcon.setTranslationX(translationX);
+ mAppIcon.setVisibility(isBehindStack() ? GONE : VISIBLE);
+ }
+
+ /** Sets whether this bubble is in the stack & not the first bubble. **/
+ void setBehindStack(boolean behindStack, boolean animate) {
+ if (behindStack) {
+ mSuppressionFlags.add(SuppressionFlag.BEHIND_STACK);
+ } else {
+ mSuppressionFlags.remove(SuppressionFlag.BEHIND_STACK);
+ }
+ updateDotVisibility(animate);
+ updateBadgeVisibility();
+ }
+
+ /** Whether this bubble is in the stack & not the first bubble. **/
+ boolean isBehindStack() {
+ return mSuppressionFlags.contains(SuppressionFlag.BEHIND_STACK);
+ }
+
+ /** Whether the dot indicating unseen content in a bubble should be shown. */
+ private boolean shouldDrawDot() {
+ boolean bubbleHasUnseenContent = mBubble != null
+ && mBubble instanceof BubbleBarBubble
+ && mSuppressionFlags.isEmpty()
+ && !((BubbleBarBubble) mBubble).getInfo().isNotificationSuppressed();
+
+ // Always render the dot if it's animating, since it could be animating out. Otherwise, show
+ // it if the bubble wants to show it, and we aren't suppressing it.
+ return bubbleHasUnseenContent || mDotIsAnimating;
+ }
+
+ /** How big the dot should be, fraction from 0 to 1. */
+ private void setDotScale(float fraction) {
+ mDotScale = fraction;
+ invalidate();
+ }
+
+ /**
+ * Animates the dot to the given scale.
+ */
+ private void animateDotScale() {
+ float toScale = shouldDrawDot() ? 1f : 0f;
+ mDotIsAnimating = true;
+
+ // Don't restart the animation if we're already animating to the given value.
+ if (mAnimatingToDotScale == toScale || !shouldDrawDot()) {
+ mDotIsAnimating = false;
return;
}
- int translationX;
- if (mOnLeft) {
- translationX = -(mBubble.getIcon().getWidth() - appBadgeBitmap.getWidth());
- } else {
- translationX = 0;
- }
+ mAnimatingToDotScale = toScale;
- mAppIcon.setTranslationX(translationX);
- mAppIcon.setVisibility(VISIBLE);
+ final boolean showDot = toScale > 0f;
+
+ // Do NOT wait until after animation ends to setShowDot
+ // to avoid overriding more recent showDot states.
+ clearAnimation();
+ animate()
+ .setDuration(200)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .setUpdateListener((valueAnimator) -> {
+ float fraction = valueAnimator.getAnimatedFraction();
+ fraction = showDot ? fraction : 1f - fraction;
+ setDotScale(fraction);
+ }).withEndAction(() -> {
+ setDotScale(showDot ? 1f : 0f);
+ mDotIsAnimating = false;
+ }).start();
}
- /** Hides the app badge on this bubble. */
- void hideBadge() {
- mAppIcon.setVisibility(GONE);
- }
@Override
public String toString() {
- return "BubbleView{" + mBubble + "}";
+ String toString = mBubble != null ? mBubble.getKey() : "null";
+ return "BubbleView{" + toString + "}";
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/OWNERS b/quickstep/src/com/android/launcher3/taskbar/bubbles/OWNERS
new file mode 100644
index 0000000..7af0389
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/OWNERS
@@ -0,0 +1 @@
+madym@google.com
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
index 27a4988..b682081 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
@@ -17,10 +17,12 @@
package com.android.launcher3.taskbar.navbutton
import android.content.res.Resources
+import android.graphics.drawable.RotateDrawable
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import com.android.launcher3.R
+import com.android.launcher3.Utilities
import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.NavButtonLayoutter
/**
@@ -40,7 +42,18 @@
protected val endContextualContainer: ViewGroup,
protected val startContextualContainer: ViewGroup
) : NavButtonLayoutter {
- protected val homeButton: ImageView = navButtonContainer.findViewById(R.id.home)
- protected val recentsButton: ImageView = navButtonContainer.findViewById(R.id.recent_apps)
- protected val backButton: ImageView = navButtonContainer.findViewById(R.id.back)
+ protected val homeButton: ImageView? = navButtonContainer.findViewById(R.id.home)
+ protected val recentsButton: ImageView? = navButtonContainer.findViewById(R.id.recent_apps)
+ protected val backButton: ImageView? = navButtonContainer.findViewById(R.id.back)
+
+ init {
+ // setup back button drawable
+ if (backButton != null) {
+ val rotateDrawable = RotateDrawable()
+ rotateDrawable.drawable = backButton.context?.getDrawable(R.drawable.ic_sysbar_back)
+ rotateDrawable.fromDegrees = 0f
+ rotateDrawable.toDegrees = if (Utilities.isRtl(backButton.resources)) 90f else -90f
+ backButton.setImageDrawable(rotateDrawable)
+ }
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt
index 468a1a7..4a53c0c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/KidsNavLayoutter.kt
@@ -51,10 +51,10 @@
val paddingTop = (buttonHeight - iconSize) / 2
// Update icons
- backButton.setImageDrawable(backButton.context.getDrawable(DRAWABLE_SYSBAR_BACK_KIDS))
+ backButton!!.setImageDrawable(backButton.context.getDrawable(DRAWABLE_SYSBAR_BACK_KIDS))
backButton.scaleType = ImageView.ScaleType.FIT_CENTER
backButton.setPadding(paddingLeft, paddingTop, paddingLeft, paddingTop)
- homeButton.setImageDrawable(homeButton.getContext().getDrawable(DRAWABLE_SYSBAR_HOME_KIDS))
+ homeButton!!.setImageDrawable(homeButton.context.getDrawable(DRAWABLE_SYSBAR_HOME_KIDS))
homeButton.scaleType = ImageView.ScaleType.FIT_CENTER
homeButton.setPadding(paddingLeft, paddingTop, paddingLeft, paddingTop)
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
index 0668da9..931f692 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
@@ -17,6 +17,8 @@
package com.android.launcher3.taskbar.navbutton
import android.content.res.Resources
+import android.view.Surface.ROTATION_90
+import android.view.Surface.Rotation
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.LinearLayout
@@ -56,14 +58,17 @@
isKidsMode: Boolean,
isInSetup: Boolean,
isThreeButtonNav: Boolean,
- phoneMode: Boolean
+ phoneMode: Boolean,
+ @Rotation surfaceRotation: Int
): NavButtonLayoutter {
- val navButtonContainer = navButtonsView.findViewById<LinearLayout>(ID_END_NAV_BUTTONS)
+ val navButtonContainer =
+ navButtonsView.requireViewById<LinearLayout>(ID_END_NAV_BUTTONS)
val endContextualContainer =
- navButtonsView.findViewById<ViewGroup>(ID_END_CONTEXTUAL_BUTTONS)
+ navButtonsView.requireViewById<ViewGroup>(ID_END_CONTEXTUAL_BUTTONS)
val startContextualContainer =
- navButtonsView.findViewById<ViewGroup>(ID_START_CONTEXTUAL_BUTTONS)
+ navButtonsView.requireViewById<ViewGroup>(ID_START_CONTEXTUAL_BUTTONS)
val isPhoneNavMode = phoneMode && isThreeButtonNav
+ val isPhoneGestureMode = phoneMode && !isThreeButtonNav
return when {
isPhoneNavMode -> {
if (!deviceProfile.isLandscape) {
@@ -73,15 +78,30 @@
endContextualContainer,
startContextualContainer
)
- } else {
+ } else if (surfaceRotation == ROTATION_90) {
PhoneLandscapeNavLayoutter(
resources,
navButtonContainer,
endContextualContainer,
startContextualContainer
)
+ } else {
+ PhoneSeascapeNavLayoutter(
+ resources,
+ navButtonContainer,
+ endContextualContainer,
+ startContextualContainer
+ )
}
}
+ isPhoneGestureMode ->{
+ PhoneGestureLayoutter(
+ resources,
+ navButtonContainer,
+ endContextualContainer,
+ startContextualContainer
+ )
+ }
deviceProfile.isTaskbarPresent -> {
return when {
isInSetup -> {
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneGestureLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneGestureLayoutter.kt
new file mode 100644
index 0000000..8525c6c
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneGestureLayoutter.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.launcher3.taskbar.navbutton
+
+import android.content.res.Resources
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import com.android.launcher3.DeviceProfile
+
+/** Layoutter for showing gesture navigation on phone screen. No buttons here, no-op container */
+class PhoneGestureLayoutter(
+ resources: Resources,
+ navBarContainer: LinearLayout,
+ endContextualContainer: ViewGroup,
+ startContextualContainer: ViewGroup
+) :
+ AbstractNavButtonLayoutter(
+ resources,
+ navBarContainer,
+ endContextualContainer,
+ startContextualContainer
+ ) {
+
+ override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) {
+ // no-op
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt
index 201895f..2acd5d4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneLandscapeNavLayoutter.kt
@@ -27,7 +27,7 @@
import com.android.launcher3.taskbar.TaskbarManager
import com.android.launcher3.util.DimensionUtils
-class PhoneLandscapeNavLayoutter(
+open class PhoneLandscapeNavLayoutter(
resources: Resources,
navBarContainer: LinearLayout,
endContextualContainer: ViewGroup,
@@ -42,17 +42,15 @@
override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) {
// TODO(b/230395757): Polish pending, this is just to make it usable
- val navContainerParams = navButtonContainer.layoutParams as FrameLayout.LayoutParams
val endStartMargins = resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size)
- val taskbarDimensions =
- DimensionUtils.getTaskbarPhoneDimensions(dp, resources, TaskbarManager.isPhoneMode(dp))
+ val taskbarDimensions = DimensionUtils.getTaskbarPhoneDimensions(dp, resources,
+ TaskbarManager.isPhoneMode(dp))
navButtonContainer.removeAllViews()
navButtonContainer.orientation = LinearLayout.VERTICAL
+ val navContainerParams = FrameLayout.LayoutParams(
+ taskbarDimensions.x, ViewGroup.LayoutParams.MATCH_PARENT)
navContainerParams.apply {
- width = taskbarDimensions.x
- height = ViewGroup.LayoutParams.MATCH_PARENT
- gravity = Gravity.CENTER
topMargin = endStartMargins
bottomMargin = endStartMargins
marginEnd = 0
@@ -65,6 +63,7 @@
navButtonContainer.addView(backButton)
navButtonContainer.layoutParams = navContainerParams
+ navButtonContainer.gravity = Gravity.CENTER
// Add the spaces in between the nav buttons
val spaceInBetween: Int =
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt
index f7ac974..c763115 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhonePortraitNavLayoutter.kt
@@ -41,27 +41,31 @@
override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) {
// TODO(b/230395757): Polish pending, this is just to make it usable
- val navContainerParams = navButtonContainer.layoutParams as FrameLayout.LayoutParams
val taskbarDimensions =
- DimensionUtils.getTaskbarPhoneDimensions(dp, resources, TaskbarManager.isPhoneMode(dp))
+ DimensionUtils.getTaskbarPhoneDimensions(dp, resources,
+ TaskbarManager.isPhoneMode(dp))
val endStartMargins = resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size)
- navContainerParams.width = taskbarDimensions.x
- navContainerParams.height = ViewGroup.LayoutParams.MATCH_PARENT
- navContainerParams.gravity = Gravity.CENTER_VERTICAL
// Ensure order of buttons is correct
navButtonContainer.removeAllViews()
navButtonContainer.orientation = LinearLayout.HORIZONTAL
- navContainerParams.topMargin = 0
- navContainerParams.bottomMargin = 0
- navContainerParams.marginEnd = endStartMargins
- navContainerParams.marginStart = endStartMargins
+
+ val navContainerParams = FrameLayout.LayoutParams(
+ taskbarDimensions.x, ViewGroup.LayoutParams.MATCH_PARENT)
+ navContainerParams.apply {
+ topMargin = 0
+ bottomMargin = 0
+ marginEnd = endStartMargins
+ marginStart = endStartMargins
+ }
+
// Swap recents and back button in case we were landscape prior to this
navButtonContainer.addView(backButton)
navButtonContainer.addView(homeButton)
navButtonContainer.addView(recentsButton)
navButtonContainer.layoutParams = navContainerParams
+ navButtonContainer.gravity = Gravity.CENTER
// Add the spaces in between the nav buttons
val spaceInBetween =
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneSeascapeNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneSeascapeNavLayoutter.kt
new file mode 100644
index 0000000..f0fe581
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneSeascapeNavLayoutter.kt
@@ -0,0 +1,46 @@
+/*
+* Copyright (C) 2023 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License
+*/
+
+package com.android.launcher3.taskbar.navbutton
+
+import android.content.res.Resources
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import com.android.launcher3.DeviceProfile
+
+class PhoneSeascapeNavLayoutter(
+ resources: Resources,
+ navBarContainer: LinearLayout,
+ endContextualContainer: ViewGroup,
+ startContextualContainer: ViewGroup
+) :
+ PhoneLandscapeNavLayoutter(
+ resources,
+ navBarContainer,
+ endContextualContainer,
+ startContextualContainer
+ ) {
+
+ override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) {
+ // TODO(b/230395757): Polish pending, this is just to make it usable
+ super.layoutButtons(dp, isContextualButtonShowing)
+ navButtonContainer.removeAllViews()
+ // Flip ordering of back and recents buttons
+ navButtonContainer.addView(backButton)
+ navButtonContainer.addView(homeButton)
+ navButtonContainer.addView(recentsButton)
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt
index 5ec7ca0..8332b7d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt
@@ -40,7 +40,6 @@
override fun layoutButtons(dp: DeviceProfile, isContextualButtonShowing: Boolean) {
// Add spacing after the end of the last nav button
- val navButtonParams = navButtonContainer.layoutParams as FrameLayout.LayoutParams
var navMarginEnd = resources.getDimension(dp.inv.inlineNavButtonsEndSpacing).toInt()
val contextualWidth = endContextualContainer.width
// If contextual buttons are showing, we check if the end margin is enough for the
@@ -50,10 +49,10 @@
navMarginEnd += resources.getDimensionPixelSize(R.dimen.taskbar_hotseat_nav_spacing) / 2
}
+ val navButtonParams = FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT)
navButtonParams.apply {
- gravity = Gravity.END
- width = FrameLayout.LayoutParams.WRAP_CONTENT
- height = ViewGroup.LayoutParams.MATCH_PARENT
+ gravity = Gravity.END or Gravity.CENTER_VERTICAL
marginEnd = navMarginEnd
}
navButtonContainer.orientation = LinearLayout.HORIZONTAL
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
index a642693..64cc47c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
@@ -18,6 +18,8 @@
import android.content.Context;
import android.view.View;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.dot.DotInfo;
@@ -29,6 +31,7 @@
import com.android.launcher3.taskbar.TaskbarDragController;
import com.android.launcher3.taskbar.TaskbarUIController;
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView;
+import com.android.launcher3.taskbar.allapps.TaskbarSearchSessionController;
import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
/**
@@ -47,6 +50,8 @@
private final int mStashedTaskbarHeight;
private final TaskbarUIController mUiController;
+ private @Nullable TaskbarSearchSessionController mSearchSessionController;
+
public TaskbarOverlayContext(
Context windowContext,
TaskbarActivityContext taskbarContext,
@@ -62,6 +67,15 @@
mUiController = controllers.uiController;
}
+ public @Nullable TaskbarSearchSessionController getSearchSessionController() {
+ return mSearchSessionController;
+ }
+
+ public void setSearchSessionController(
+ @Nullable TaskbarSearchSessionController searchSessionController) {
+ mSearchSessionController = searchSessionController;
+ }
+
int getStashedTaskbarHeight() {
return mStashedTaskbarHeight;
}
@@ -112,6 +126,11 @@
}
@Override
+ public View.OnLongClickListener getAllAppsItemLongClickListener() {
+ return mDragController::startDragOnLongClick;
+ }
+
+ @Override
public PopupDataProvider getPopupDataProvider() {
return mTaskbarContext.getPopupDataProvider();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
index d4e2be9..c4eeea7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
@@ -23,7 +23,6 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import android.annotation.SuppressLint;
-import android.content.ComponentName;
import android.content.Context;
import android.graphics.PixelFormat;
import android.view.Gravity;
@@ -60,14 +59,26 @@
private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
@Override
- public void onTaskCreated(int taskId, ComponentName componentName) {
- // Created task will be below existing overlay, so move out of the way.
- hideWindow();
+ public void onTaskMovedToFront(int taskId) {
+ // New front task will be below existing overlay, so move out of the way.
+ hideWindowOnTaskStackChange();
}
@Override
- public void onTaskMovedToFront(int taskId) {
- // New front task will be below existing overlay, so move out of the way.
+ public void onTaskStackChanged() {
+ // The other callbacks are insufficient for All Apps, because there are many cases where
+ // it can relaunch the same task already behind it. However, this callback needs to be a
+ // no-op when only EDU is shown, because going between the EDU steps invokes this
+ // callback.
+ if (mControllers.getSharedState() != null
+ && mControllers.getSharedState().allAppsVisible) {
+ hideWindowOnTaskStackChange();
+ }
+ }
+
+ private void hideWindowOnTaskStackChange() {
+ // A task was launched while overlay window was open, so stash Taskbar.
+ mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
hideWindow();
}
};
@@ -199,8 +210,10 @@
@Override
protected void handleClose(boolean animate) {
- mTaskbarContext.getDragLayer().removeView(this);
- Optional.ofNullable(mOverlayContext).ifPresent(c -> closeAllOpenViews(c, animate));
+ if (mIsOpen) {
+ mTaskbarContext.getDragLayer().removeView(this);
+ Optional.ofNullable(mOverlayContext).ifPresent(c -> closeAllOpenViews(c, animate));
+ }
}
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
index add7279..e742a3d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.graphics.Insets;
+import android.media.permission.SafeCloseable;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
@@ -29,6 +30,7 @@
import androidx.annotation.NonNull;
+import com.android.app.viewcapture.SettingsAwareViewCapture;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
@@ -36,6 +38,7 @@
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
+import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -44,6 +47,7 @@
BaseDragLayer<TaskbarOverlayContext> implements
ViewTreeObserver.OnComputeInternalInsetsListener {
+ private SafeCloseable mViewCaptureCloseable;
private final List<OnClickListener> mOnClickListeners = new CopyOnWriteArrayList<>();
private final TouchController mClickListenerTouchController = new TouchController() {
@Override
@@ -66,6 +70,7 @@
return true;
}
};
+ private final List<TouchController> mTouchControllers = new ArrayList<>();
TaskbarOverlayDragLayer(Context context) {
super(context, null, 1);
@@ -77,20 +82,26 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getViewTreeObserver().addOnComputeInternalInsetsListener(this);
+ mViewCaptureCloseable = SettingsAwareViewCapture.getInstance(getContext())
+ .startCapture(getRootView(), ".TaskbarOverlay");
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
+ mViewCaptureCloseable.close();
}
@Override
public void recreateControllers() {
- mControllers = mOnClickListeners.isEmpty()
- ? new TouchController[]{mActivity.getDragController()}
- : new TouchController[] {
- mActivity.getDragController(), mClickListenerTouchController};
+ List<TouchController> controllers = new ArrayList<>();
+ controllers.add(mActivity.getDragController());
+ controllers.addAll(mTouchControllers);
+ if (!mOnClickListeners.isEmpty()) {
+ controllers.add(mClickListenerTouchController);
+ }
+ mControllers = controllers.toArray(new TouchController[0]);
}
@Override
@@ -177,6 +188,18 @@
});
}
+ /** Adds a {@link TouchController} to this drag layer. */
+ public void addTouchController(@NonNull TouchController touchController) {
+ mTouchControllers.add(touchController);
+ recreateControllers();
+ }
+
+ /** Removes a {@link TouchController} from this drag layer. */
+ public void removeTouchController(@NonNull TouchController touchController) {
+ mTouchControllers.remove(touchController);
+ recreateControllers();
+ }
+
/**
* Taskbar automatically stashes when opening all apps, but we don't report the insets as
* changing to avoid moving the underlying app. But internally, the apps view should still
diff --git a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
index a53dc15..475f465 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
@@ -16,13 +16,16 @@
package com.android.launcher3.uioverrides;
+import android.app.ActivityOptions;
import android.app.Person;
import android.content.Context;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
+import android.window.RemoteTransition;
import com.android.launcher3.Utilities;
+import com.android.quickstep.util.FadeOutRemoteTransition;
import java.util.Map;
@@ -41,4 +44,13 @@
public static Map<String, LauncherActivityInfo> getActivityOverrides(Context context) {
return context.getSystemService(LauncherApps.class).getActivityOverrides();
}
+
+ /**
+ * Creates an ActivityOptions to play fade-out animation on closing targets
+ */
+ public static ActivityOptions createFadeOutAnimOptions(Context context) {
+ ActivityOptions options = ActivityOptions.makeBasic();
+ options.setRemoteTransition(new RemoteTransition(new FadeOutRemoteTransition()));
+ return options;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index 955440b..d78ca88 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -16,40 +16,34 @@
package com.android.launcher3.uioverrides;
+import static com.android.app.animation.Interpolators.AGGRESSIVE_EASE_IN_OUT;
+import static com.android.app.animation.Interpolators.FINAL_FRAME;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.LauncherState.QUICK_SWITCH_FROM_HOME;
-import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
-import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SPLIT_SELECT_FLOATING_TASK_TRANSLATE_OFFSCREEN;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
-import static com.android.quickstep.views.FloatingTaskView.PRIMARY_TRANSLATE_OFFSCREEN;
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET;
import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
import static com.android.quickstep.views.RecentsView.TASK_THUMBNAIL_SPLASH_ALPHA;
-import android.graphics.Rect;
-import android.graphics.RectF;
import android.util.FloatProperty;
import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.Utilities;
import com.android.launcher3.anim.PendingAnimation;
-import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
-import com.android.quickstep.views.FloatingTaskView;
import com.android.quickstep.views.RecentsView;
/**
@@ -113,48 +107,19 @@
setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f,
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
- if (mRecentsView.isSplitSelectionActive()) {
- // TODO (b/238651489): Refactor state management to avoid need for double check
- FloatingTaskView floatingTask = mRecentsView.getFirstFloatingTaskView();
- if (floatingTask != null) {
- // We are in split selection state currently, transitioning to another state
- DragLayer dragLayer = mLauncher.getDragLayer();
- RectF onScreenRectF = new RectF();
- Utilities.getBoundsForViewInDragLayer(mLauncher.getDragLayer(), floatingTask,
- new Rect(0, 0, floatingTask.getWidth(), floatingTask.getHeight()),
- false, null, onScreenRectF);
- // Get the part of the floatingTask that intersects with the DragLayer (i.e. the
- // on-screen portion)
- onScreenRectF.intersect(
- dragLayer.getLeft(),
- dragLayer.getTop(),
- dragLayer.getRight(),
- dragLayer.getBottom()
- );
-
- setter.setFloat(
- mRecentsView.getFirstFloatingTaskView(),
- PRIMARY_TRANSLATE_OFFSCREEN,
- mRecentsView.getPagedOrientationHandler()
- .getFloatingTaskOffscreenTranslationTarget(
- floatingTask,
- onScreenRectF,
- floatingTask.getStagePosition(),
- mLauncher.getDeviceProfile()
- ),
- config.getInterpolator(
- ANIM_OVERVIEW_SPLIT_SELECT_FLOATING_TASK_TRANSLATE_OFFSCREEN,
- LINEAR
- ));
- setter.setViewAlpha(
- mRecentsView.getSplitInstructionsView(),
- 0,
- config.getInterpolator(
- ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE,
- LINEAR
- )
- );
- }
+ boolean exitingOverview = !FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()
+ && !toState.overviewUi;
+ if (mRecentsView.isSplitSelectionActive() && exitingOverview) {
+ setter.add(mRecentsView.getSplitSelectController().getSplitAnimationController()
+ .createPlaceholderDismissAnim(mLauncher));
+ setter.setViewAlpha(
+ mRecentsView.getSplitInstructionsView(),
+ 0,
+ config.getInterpolator(
+ ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE,
+ LINEAR
+ )
+ );
}
setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0,
diff --git a/quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java b/quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java
deleted file mode 100644
index d8aa235..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/**
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.uioverrides;
-
-import static android.os.IBinder.FLAG_ONEWAY;
-
-import android.os.Binder;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.util.Log;
-
-import androidx.annotation.MainThread;
-
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.function.BiConsumer;
-import java.util.function.Supplier;
-
-/**
- * A binder proxy transaction listener for tracking non-whitelisted binder calls.
- */
-public class DejankBinderTracker implements Binder.ProxyTransactListener {
- private static final String TAG = "DejankBinderTracker";
-
- private static final Object sLock = new Object();
- private static final HashSet<String> sWhitelistedFrameworkClasses = new HashSet<>();
- static {
- // Common IPCs that are ok to block the main thread.
- sWhitelistedFrameworkClasses.add("android.view.IWindowSession");
- sWhitelistedFrameworkClasses.add("android.os.IPowerManager");
- }
- private static boolean sTemporarilyIgnoreTracking = false;
-
- // Used by the client to limit binder tracking to specific regions
- private static boolean sTrackingAllowed = false;
-
- private BiConsumer<String, Integer> mUnexpectedTransactionCallback;
- private boolean mIsTracking = false;
-
- /**
- * Temporarily ignore blocking binder calls for the duration of this {@link Runnable}.
- */
- @MainThread
- public static void whitelistIpcs(Runnable runnable) {
- sTemporarilyIgnoreTracking = true;
- runnable.run();
- sTemporarilyIgnoreTracking = false;
- }
-
- /**
- * Temporarily ignore blocking binder calls for the duration of this {@link Supplier}.
- */
- @MainThread
- public static <T> T whitelistIpcs(Supplier<T> supplier) {
- sTemporarilyIgnoreTracking = true;
- T value = supplier.get();
- sTemporarilyIgnoreTracking = false;
- return value;
- }
-
- /**
- * Enables binder tracking during a test.
- */
- @MainThread
- public static void allowBinderTrackingInTests() {
- sTrackingAllowed = true;
- }
-
- /**
- * Disables binder tracking during a test.
- */
- @MainThread
- public static void disallowBinderTrackingInTests() {
- sTrackingAllowed = false;
- }
-
- public DejankBinderTracker(BiConsumer<String, Integer> unexpectedTransactionCallback) {
- mUnexpectedTransactionCallback = unexpectedTransactionCallback;
- }
-
- @MainThread
- public void startTracking() {
- if (!Build.TYPE.toLowerCase(Locale.ROOT).contains("debug")
- && !Build.TYPE.toLowerCase(Locale.ROOT).equals("eng")) {
- Log.wtf(TAG, "Unexpected use of binder tracker in non-debug build", new Exception());
- return;
- }
- if (mIsTracking) {
- return;
- }
- mIsTracking = true;
- Binder.setProxyTransactListener(this);
- }
-
- @MainThread
- public void stopTracking() {
- if (!mIsTracking) {
- return;
- }
- mIsTracking = false;
- Binder.setProxyTransactListener(null);
- }
-
- // Override the hidden Binder#onTransactStarted method
- public synchronized Object onTransactStarted(IBinder binder, int transactionCode, int flags) {
- if (!mIsTracking
- || !sTrackingAllowed
- || sTemporarilyIgnoreTracking
- || (flags & FLAG_ONEWAY) == FLAG_ONEWAY
- || !isMainThread()) {
- return null;
- }
-
- String descriptor;
- try {
- descriptor = binder.getInterfaceDescriptor();
- if (sWhitelistedFrameworkClasses.contains(descriptor)) {
- return null;
- }
- } catch (RemoteException e) {
- e.printStackTrace();
- descriptor = binder.getClass().getSimpleName();
- }
-
- mUnexpectedTransactionCallback.accept(descriptor, transactionCode);
- return null;
- }
-
- @Override
- public Object onTransactStarted(IBinder binder, int transactionCode) {
- // Do nothing
- return null;
- }
-
- @Override
- public void onTransactEnded(Object session) {
- // Do nothing
- }
-
- public static boolean isMainThread() {
- return Thread.currentThread() == Looper.getMainLooper().getThread();
- }
-}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
index a8b7698..2064fe2 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
@@ -15,7 +15,7 @@
*/
package com.android.launcher3.uioverrides;
-import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
+import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
import static com.android.launcher3.icons.BitmapInfo.FLAG_THEMED;
import static com.android.launcher3.icons.FastBitmapDrawable.getDisabledColorFilter;
@@ -189,7 +189,7 @@
} else {
float[] hctPlateColor = new float[3];
ColorUtils.colorToM3HCT(mDotParams.appColor, hctPlateColor);
- newPlateColor = ColorUtils.M3HCTtoColor(hctPlateColor[0], 36, 85);
+ newPlateColor = ColorUtils.M3HCTToColor(hctPlateColor[0], 36, 85);
}
if (!animate) {
@@ -260,8 +260,8 @@
Keyframe.ofFloat(0.82f, finalTrans - getOutlineOffsetY() / 2f), // Overshoot
Keyframe.ofFloat(1f, finalTrans) // Ease back into the final position
};
- keyframes[1].setInterpolator(ACCEL_DEACCEL);
- keyframes[2].setInterpolator(ACCEL_DEACCEL);
+ keyframes[1].setInterpolator(ACCELERATE_DECELERATE);
+ keyframes[2].setInterpolator(ACCELERATE_DECELERATE);
mSlotMachineAnim = ObjectAnimator.ofPropertyValuesHolder(this,
PropertyValuesHolder.ofKeyframe(SLOT_MACHINE_TRANSLATION_Y, keyframes));
@@ -337,7 +337,6 @@
if (getTag() instanceof WorkspaceItemInfo) {
WorkspaceItemInfo info = (WorkspaceItemInfo) getTag();
isBadged = !Process.myUserHandle().equals(info.user)
- || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
|| info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index b621a28..40909d5 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -20,23 +20,20 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_OPTIMIZE_MEASURE;
import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
import static com.android.launcher3.LauncherSettings.Animation.DEFAULT_NO_ICON;
import static com.android.launcher3.LauncherSettings.Animation.VIEW_BACKGROUND;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
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.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.NO_OFFSET;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;
-import static com.android.launcher3.config.FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition;
@@ -53,15 +50,13 @@
import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-import static com.android.launcher3.util.SplitConfigurationOptions.DEFAULT_SPLIT_RATIO;
import static com.android.quickstep.util.SplitAnimationTimings.TABLET_HOME_TO_SPLIT;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
-import android.animation.ValueAnimator;
-import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
@@ -71,20 +66,20 @@
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.RectF;
-import android.hardware.SensorManager;
-import android.hardware.devicestate.DeviceStateManager;
import android.hardware.display.DisplayManager;
import android.media.permission.SafeCloseable;
import android.os.Build;
import android.os.Bundle;
-import android.os.CancellationSignal;
import android.os.IBinder;
import android.os.SystemProperties;
import android.os.Trace;
+import android.util.AttributeSet;
+import android.util.Log;
import android.view.Display;
import android.view.HapticFeedbackConstants;
-import android.view.RemoteAnimationTarget;
import android.view.View;
+import android.widget.AnalogClock;
+import android.widget.TextClock;
import android.window.BackEvent;
import android.window.OnBackAnimationCallback;
import android.window.OnBackInvokedDispatcher;
@@ -111,7 +106,6 @@
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.appprediction.PredictionRowView;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.hybridhotseat.HotseatPredictionController;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.StatsLogManager;
@@ -119,9 +113,9 @@
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;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
@@ -153,6 +147,7 @@
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
+import com.android.launcher3.util.StartActivityParams;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.widget.LauncherWidgetHolder;
import com.android.quickstep.OverviewCommandHelper;
@@ -160,12 +155,10 @@
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.TouchInteractionService.TISBinder;
+import com.android.quickstep.util.AsyncClockEventDelegate;
import com.android.quickstep.util.GroupTask;
import com.android.quickstep.util.LauncherUnfoldAnimationController;
-import com.android.quickstep.util.ProxyScreenStatusProvider;
import com.android.quickstep.util.QuickstepOnboardingPrefs;
-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;
@@ -175,16 +168,14 @@
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.unfold.RemoteUnfoldSharedComponent;
-import com.android.systemui.unfold.UnfoldSharedComponent;
import com.android.systemui.unfold.UnfoldTransitionFactory;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig;
import com.android.systemui.unfold.config.UnfoldTransitionConfig;
import com.android.systemui.unfold.progress.RemoteUnfoldTransitionReceiver;
-import com.android.systemui.unfold.system.ActivityManagerActivityTypeProvider;
-import com.android.systemui.unfold.system.DeviceStateManagerFoldProvider;
import com.android.systemui.unfold.updates.RotationChangeProvider;
import java.io.FileDescriptor;
@@ -194,13 +185,17 @@
import java.util.Collections;
import java.util.List;
import java.util.Objects;
+import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class QuickstepLauncher extends Launcher {
+ private static final boolean TRACE_LAYOUTS =
+ SystemProperties.getBoolean("persist.debug.trace_layouts", false);
+ private static final String TRACE_RELAYOUT_CLASS =
+ SystemProperties.get("persist.debug.trace_request_layout_class", null);
- public static final boolean ENABLE_PIP_KEEP_CLEAR_ALGORITHM =
- SystemProperties.getBoolean("persist.wm.debug.enable_pip_keep_clear_algorithm", true);
+ private static final String TAG = "QuickstepLauncher";
public static final boolean GO_LOW_RAM_RECENTS_ENABLED = false;
@@ -213,11 +208,8 @@
private QuickstepTransitionManager mAppTransitionManager;
private OverviewActionsView mActionsView;
private TISBindHelper mTISBindHelper;
- private @Nullable TaskbarManager mTaskbarManager;
- private @Nullable OverviewCommandHelper mOverviewCommandHelper;
private @Nullable LauncherTaskbarUIController mTaskbarUIController;
// Will be updated when dragging from taskbar.
- private @Nullable DragOptions mNextWorkspaceDragOptions = null;
private @Nullable UnfoldTransitionProgressProvider mUnfoldTransitionProgressProvider;
private @Nullable LauncherUnfoldAnimationController mLauncherUnfoldAnimationController;
@@ -225,6 +217,8 @@
private SplitWithKeyboardShortcutController mSplitWithKeyboardShortcutController;
private SplitToWorkspaceController mSplitToWorkspaceController;
+ private AsyncClockEventDelegate mAsyncClockEventDelegate;
+
/**
* 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.
@@ -244,7 +238,8 @@
mSplitSelectStateController =
new SplitSelectStateController(this, mHandler, getStateManager(),
getDepthController(), getStatsLogManager(),
- SystemUiProxy.INSTANCE.get(this), RecentsModel.INSTANCE.get(this));
+ SystemUiProxy.INSTANCE.get(this), RecentsModel.INSTANCE.get(this),
+ () -> onStateBack());
overviewPanel.init(mActionsView, mSplitSelectStateController);
mSplitWithKeyboardShortcutController = new SplitWithKeyboardShortcutController(this,
mSplitSelectStateController);
@@ -260,11 +255,16 @@
mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
mDepthController = new DepthController(this);
mDesktopVisibilityController = new DesktopVisibilityController(this);
+ if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
+ mDesktopVisibilityController.registerSystemUiListener();
+ mSplitSelectStateController.initSplitFromDesktopController(this);
+ }
mHotseatPredictionController = new HotseatPredictionController(this);
mEnableWidgetDepth = SystemProperties.getBoolean("ro.launcher.depth.widget", true);
getWorkspace().addOverlayCallback(progress ->
onTaskbarInAppDisplayProgressUpdate(progress, MINUS_ONE_PAGE_PROGRESS_INDEX));
+ addBackAnimationCallback(mSplitSelectStateController.getSplitBackHandler());
}
@Override
@@ -281,7 +281,6 @@
if (mAllAppsPredictions != null
&& (info.itemType == ITEM_TYPE_APPLICATION
- || info.itemType == ITEM_TYPE_SHORTCUT
|| info.itemType == ITEM_TYPE_DEEP_SHORTCUT)) {
int count = mAllAppsPredictions.items.size();
for (int i = 0; i < count; i++) {
@@ -351,9 +350,7 @@
mHotseatPredictionController.setPauseUIUpdate(getTaskbarUIController() == null);
RunnableList result = super.startActivitySafely(v, intent, item);
if (result == null) {
- if (getTaskbarUIController() == null) {
- mHotseatPredictionController.setPauseUIUpdate(false);
- }
+ mHotseatPredictionController.setPauseUIUpdate(false);
} else {
result.add(() -> mHotseatPredictionController.setPauseUIUpdate(false));
}
@@ -408,8 +405,7 @@
}
private List<SystemShortcut.Factory<QuickstepLauncher>> getSplitShortcuts() {
-
- if (!ENABLE_SPLIT_FROM_WORKSPACE.get() || !mDeviceProfile.isTablet) {
+ if (!mDeviceProfile.isTablet || mSplitSelectStateController.isSplitSelectActive()) {
return Collections.emptyList();
}
RecentsView recentsView = getOverviewPanel();
@@ -437,12 +433,8 @@
boolean visible = (state == NORMAL || state == OVERVIEW)
&& (willUserBeActive || isUserActive())
&& !profile.isVerticalBarLayout();
- if (ENABLE_PIP_KEEP_CLEAR_ALGORITHM) {
- SystemUiProxy.INSTANCE.get(this)
- .setLauncherKeepClearAreaHeight(visible, profile.hotseatBarSizePx);
- } else {
- SystemUiProxy.INSTANCE.get(this).setShelfHeight(visible, profile.hotseatBarSizePx);
- }
+ SystemUiProxy.INSTANCE.get(this)
+ .setLauncherKeepClearAreaHeight(visible, profile.hotseatBarSizePx);
}
if (state == NORMAL && !inTransition) {
((RecentsView) getOverviewPanel()).setSwipeDownShouldLaunchApp(false);
@@ -451,6 +443,7 @@
@Override
public void bindExtraContainerItems(FixedContainerItems item) {
+ Log.d(TAG, "Bind extra container items");
if (item.containerId == Favorites.CONTAINER_PREDICTION) {
mAllAppsPredictions = item;
PredictionRowView<?> predictionRowView =
@@ -458,6 +451,7 @@
PredictionRowView.class);
predictionRowView.setPredictedApps(item.items);
} else if (item.containerId == Favorites.CONTAINER_HOTSEAT_PREDICTION) {
+ Log.d(TAG, "Bind extra container item is hotseat prediction");
mHotseatPredictionController.setPredictedItems(item);
} else if (item.containerId == Favorites.CONTAINER_WIDGETS_PREDICTION) {
getPopupDataProvider().setRecommendedWidgets(item.items);
@@ -474,26 +468,33 @@
public void onDestroy() {
mAppTransitionManager.onActivityDestroyed();
if (mUnfoldTransitionProgressProvider != null) {
- if (FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI.get()) {
- SystemUiProxy.INSTANCE.get(this).setUnfoldAnimationListener(null);
- }
-
+ SystemUiProxy.INSTANCE.get(this).setUnfoldAnimationListener(null);
mUnfoldTransitionProgressProvider.destroy();
}
mTISBindHelper.onDestroy();
- if (mTaskbarManager != null) {
- mTaskbarManager.clearActivity(this);
- }
if (mLauncherUnfoldAnimationController != null) {
mLauncherUnfoldAnimationController.onDestroy();
}
+ if (mDesktopVisibilityController != null) {
+ mDesktopVisibilityController.unregisterSystemUiListener();
+ }
+
+ if (mSplitSelectStateController != null) {
+ mSplitSelectStateController.onDestroy();
+ }
+
+ if (mAsyncClockEventDelegate != null) {
+ mAsyncClockEventDelegate.onDestroy();
+ }
+
super.onDestroy();
mHotseatPredictionController.destroy();
mSplitWithKeyboardShortcutController.onDestroy();
if (mViewCapture != null) mViewCapture.close();
+ removeBackAnimationCallback(mSplitSelectStateController.getSplitBackHandler());
}
@Override
@@ -523,7 +524,7 @@
}
case QUICK_SWITCH_STATE_ORDINAL: {
RecentsView rv = getOverviewPanel();
- TaskView tasktolaunch = rv.getTaskViewAt(0);
+ TaskView tasktolaunch = rv.getCurrentPageTaskView();
if (tasktolaunch != null) {
tasktolaunch.launchTask(success -> {
if (!success) {
@@ -547,11 +548,14 @@
ArrayList<TouchController> list = new ArrayList<>();
list.add(getDragController());
+ Consumer<AnimatorSet> splitAnimator = animatorSet ->
+ animatorSet.play(mSplitSelectStateController.getSplitAnimationController()
+ .createPlaceholderDismissAnim(this));
switch (mode) {
case NO_BUTTON:
list.add(new NoButtonQuickSwitchTouchController(this));
- list.add(new NavBarToHomeTouchController(this));
- list.add(new NoButtonNavbarToOverviewTouchController(this));
+ list.add(new NavBarToHomeTouchController(this, splitAnimator));
+ list.add(new NoButtonNavbarToOverviewTouchController(this, splitAnimator));
break;
case TWO_BUTTONS:
list.add(new TwoButtonNavbarTouchController(this));
@@ -561,8 +565,14 @@
list.add(new PortraitStatesTouchController(this));
break;
case THREE_BUTTONS:
+ list.add(new NoButtonQuickSwitchTouchController(this));
+ list.add(new NavBarToHomeTouchController(this, splitAnimator));
+ list.add(new NoButtonNavbarToOverviewTouchController(this, splitAnimator));
+ list.add(new PortraitStatesTouchController(this));
+ break;
default:
list.add(new PortraitStatesTouchController(this));
+ break;
}
if (!getDeviceProfile().isMultiWindowMode) {
@@ -603,6 +613,8 @@
mViewCapture = SettingsAwareViewCapture.getInstance(this).startCapture(getWindow());
}
getWindow().addPrivateFlags(PRIVATE_FLAG_OPTIMIZE_MEASURE);
+ View.setTraceLayoutSteps(TRACE_LAYOUTS);
+ View.setTracedRequestLayoutClassClass(TRACE_RELAYOUT_CLASS);
}
@Override
@@ -610,12 +622,14 @@
RecentsView recentsView = getOverviewPanel();
// Check if there is already an instance of this app running, if so, initiate the split
// using that.
- mSplitSelectStateController.findLastActiveTaskAndRunCallback(
- splitSelectSource.itemInfo.getComponentKey(),
- foundTask -> {
- splitSelectSource.alreadyRunningTaskId = foundTask == null
- ? INVALID_TASK_ID
- : foundTask.key.id;
+ mSplitSelectStateController.findLastActiveTasksAndRunCallback(
+ Collections.singletonList(splitSelectSource.itemInfo.getComponentKey()),
+ foundTasks -> {
+ @Nullable Task foundTask = foundTasks.get(0);
+ boolean taskWasFound = foundTask != null;
+ splitSelectSource.alreadyRunningTaskId = taskWasFound
+ ? foundTask.key.id
+ : INVALID_TASK_ID;
if (ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
startSplitToHome(splitSelectSource);
} else {
@@ -655,12 +669,20 @@
@Override
public void onAnimationCancel(Animator animation) {
getDragLayer().removeView(floatingTaskView);
+ mSplitSelectStateController.getSplitAnimationController()
+ .removeSplitInstructionsView(QuickstepLauncher.this);
mSplitSelectStateController.resetState();
}
});
+ anim.add(mSplitSelectStateController.getSplitAnimationController()
+ .getShowSplitInstructionsAnim(this).buildAnim());
anim.buildAnim().start();
}
+ @Override
+ protected boolean isSplitSelectionEnabled() {
+ return mSplitSelectStateController.isSplitSelectActive();
+ }
@Override
protected void onResume() {
@@ -678,14 +700,22 @@
}
super.onPause();
+
+ if (ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ // If Launcher pauses before both split apps are selected, exit split screen.
+ if (!mSplitSelectStateController.isBothSplitAppsConfirmed()) {
+ mSplitSelectStateController.getSplitAnimationController()
+ .playPlaceholderDismissAnim(this);
+ }
+ }
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
-
- if (mOverviewCommandHelper != null) {
- mOverviewCommandHelper.clearPendingCommands();
+ OverviewCommandHelper overviewCommandHelper = mTISBindHelper.getOverviewCommandHelper();
+ if (overviewCommandHelper != null) {
+ overviewCommandHelper.clearPendingCommands();
}
}
@@ -724,15 +754,6 @@
}
@Override
- protected void onScreenOnChanged(boolean isOn) {
- super.onScreenOnChanged(isOn);
- if (!isOn) {
- RecentsView recentsView = getOverviewPanel();
- recentsView.finishRecentsAnimation(true /* toRecents */, null);
- }
- }
-
- @Override
public void onAllAppsTransition(float progress) {
super.onAllAppsTransition(progress);
onTaskbarInAppDisplayProgressUpdate(progress, ALL_APPS_PAGE_PROGRESS_INDEX);
@@ -808,8 +829,9 @@
}
private void onTaskbarInAppDisplayProgressUpdate(float progress, int flag) {
- if (mTaskbarManager == null
- || mTaskbarManager.getCurrentActivityContext() == null
+ TaskbarManager taskbarManager = mTISBindHelper.getTaskbarManager();
+ if (taskbarManager == null
+ || taskbarManager.getCurrentActivityContext() == null
|| mTaskbarUIController == null) {
return;
}
@@ -853,7 +875,7 @@
if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
DesktopVisibilityController controller = mDesktopVisibilityController;
if (controller != null && controller.areFreeformTasksVisible()
- && !controller.isGestureInProgress()) {
+ && !controller.isRecentsGestureInProgress()) {
// Return early to skip setting activity to appear as resumed
// TODO(b/255649902): shouldn't be needed when we have a separate launcher state
// for desktop that we can use to control other parts of launcher
@@ -881,11 +903,10 @@
}
private void onTISConnected(TISBinder binder) {
- mTaskbarManager = binder.getTaskbarManager();
- if (mTaskbarManager != null) {
- mTaskbarManager.setActivity(this);
+ TaskbarManager taskbarManager = mTISBindHelper.getTaskbarManager();
+ if (taskbarManager != null) {
+ taskbarManager.setActivity(this);
}
- mOverviewCommandHelper = binder.getOverviewCommandHelper();
}
@Override
@@ -896,43 +917,10 @@
private void initUnfoldTransitionProgressProvider() {
final UnfoldTransitionConfig config = new ResourceUnfoldTransitionConfig();
if (config.isEnabled()) {
- if (RECEIVE_UNFOLD_EVENTS_FROM_SYSUI.get()) {
- initRemotelyCalculatedUnfoldAnimation(config);
- } else {
- initLocallyCalculatedUnfoldAnimation(config);
- }
-
+ initRemotelyCalculatedUnfoldAnimation(config);
}
}
- /** Registers hinge angle listener and calculates the animation progress in this process. */
- private void initLocallyCalculatedUnfoldAnimation(UnfoldTransitionConfig config) {
- UnfoldSharedComponent unfoldComponent =
- UnfoldTransitionFactory.createUnfoldSharedComponent(
- /* context= */ this,
- config,
- ProxyScreenStatusProvider.INSTANCE,
- new DeviceStateManagerFoldProvider(
- getSystemService(DeviceStateManager.class), /* context= */ this),
- new ActivityManagerActivityTypeProvider(
- getSystemService(ActivityManager.class)),
- getSystemService(SensorManager.class),
- getMainThreadHandler(),
- getMainExecutor(),
- /* backgroundExecutor= */ UI_HELPER_EXECUTOR,
- /* tracingTagPrefix= */ "launcher",
- getSystemService(DisplayManager.class)
- );
-
- mUnfoldTransitionProgressProvider = unfoldComponent.getUnfoldTransitionProvider()
- .orElseThrow(() -> new IllegalStateException(
- "Trying to create UnfoldTransitionProgressProvider when the "
- + "transition is disabled"));
-
- initUnfoldAnimationController(mUnfoldTransitionProgressProvider,
- unfoldComponent.getRotationChangeProvider());
- }
-
/** Receives animation progress from sysui process. */
private void initRemotelyCalculatedUnfoldAnimation(UnfoldTransitionConfig config) {
RemoteUnfoldSharedComponent unfoldComponent =
@@ -982,6 +970,13 @@
return mSplitToWorkspaceController;
}
+ @Override
+ protected void handleSplitAnimationGoingToHome() {
+ super.handleSplitAnimationGoingToHome();
+ mSplitSelectStateController.getSplitAnimationController()
+ .playPlaceholderDismissAnim(this);
+ }
+
public <T extends OverviewActionsView> T getActionsView() {
return (T) mActionsView;
}
@@ -1018,41 +1013,6 @@
}
@Override
- public DragOptions getDefaultWorkspaceDragOptions() {
- if (mNextWorkspaceDragOptions != null) {
- DragOptions options = mNextWorkspaceDragOptions;
- mNextWorkspaceDragOptions = null;
- return options;
- }
- return super.getDefaultWorkspaceDragOptions();
- }
-
- public void setNextWorkspaceDragOptions(DragOptions dragOptions) {
- mNextWorkspaceDragOptions = dragOptions;
- }
-
- @Override
- public void useFadeOutAnimationForLauncherStart(CancellationSignal signal) {
- QuickstepTransitionManager appTransitionManager = getAppTransitionManager();
- appTransitionManager.setRemoteAnimationProvider(new RemoteAnimationProvider() {
- @Override
- public AnimatorSet createWindowAnimation(RemoteAnimationTarget[] appTargets,
- RemoteAnimationTarget[] wallpaperTargets) {
-
- // On the first call clear the reference.
- signal.cancel();
-
- ValueAnimator fadeAnimation = ValueAnimator.ofFloat(1, 0);
- fadeAnimation.addUpdateListener(new RemoteFadeOutAnimationListener(appTargets,
- wallpaperTargets));
- AnimatorSet anim = new AnimatorSet();
- anim.play(fadeAnimation);
- return anim;
- }
- }, signal);
- }
-
- @Override
public float[] getNormalOverviewScaleAndOffset() {
return DisplayController.getNavigationMode(this).hasGestures
? new float[] {1, 1} : new float[] {1.1f, NO_OFFSET};
@@ -1102,6 +1062,8 @@
activityOptions.options.setLaunchDisplayId(
(v != null && v.getDisplay() != null) ? v.getDisplay().getDisplayId()
: Display.DEFAULT_DISPLAY);
+ activityOptions.options.setPendingIntentBackgroundActivityStartMode(
+ ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
addLaunchCookie(item, activityOptions.options);
return activityOptions;
}
@@ -1114,6 +1076,8 @@
Executors.MAIN_EXECUTOR.getHandler(), null,
elapsedRealTime -> callbacks.executeAllAndDestroy());
options.setSplashScreenStyle(splashScreenStyle);
+ options.setPendingIntentBackgroundActivityStartMode(
+ ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
return new ActivityOptionsWrapper(options, callbacks);
}
@@ -1161,7 +1125,6 @@
}
switch (info.itemType) {
case Favorites.ITEM_TYPE_APPLICATION:
- case Favorites.ITEM_TYPE_SHORTCUT:
case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
case Favorites.ITEM_TYPE_APPWIDGET:
// Fall through and continue if it's an app, shortcut, or widget
@@ -1270,8 +1233,9 @@
Trace.instantForTrack(TRACE_TAG_APP, "QuickstepLauncher#DeviceProfileChanged",
getDeviceProfile().toSmallString());
SystemUiProxy.INSTANCE.get(this).setLauncherAppIconSize(mDeviceProfile.iconSizePx);
- if (mTaskbarManager != null) {
- mTaskbarManager.debugWhyTaskbarNotDestroyed("QuickstepLauncher#onDeviceProfileChanged");
+ TaskbarManager taskbarManager = mTISBindHelper.getTaskbarManager();
+ if (taskbarManager != null) {
+ taskbarManager.debugWhyTaskbarNotDestroyed("QuickstepLauncher#onDeviceProfileChanged");
}
}
@@ -1293,13 +1257,33 @@
groupTask.task1.key.id,
groupTask.task2.key.id,
SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT,
- /* callback= */ success -> {},
+ /* callback= */ success -> mSplitSelectStateController.resetState(),
/* freezeTaskList= */ true,
groupTask.mSplitBounds == null
- ? DEFAULT_SPLIT_RATIO
- : groupTask.mSplitBounds.appsStackedVertically
- ? groupTask.mSplitBounds.topTaskPercent
- : groupTask.mSplitBounds.leftTaskPercent);
+ ? SNAP_TO_50_50
+ : groupTask.mSplitBounds.snapPosition);
+ }
+
+ /**
+ * Launches two apps as an app pair.
+ */
+ public void launchAppPair(WorkspaceItemInfo app1, WorkspaceItemInfo app2) {
+ mSplitSelectStateController.getAppPairsController().launchAppPair(app1, app2);
+ }
+
+ public boolean canStartHomeSafely() {
+ OverviewCommandHelper overviewCommandHelper = mTISBindHelper.getOverviewCommandHelper();
+ return overviewCommandHelper == null || overviewCommandHelper.canStartHomeSafely();
+ }
+
+ @Override
+ public boolean isBubbleBarEnabled() {
+ return (mTaskbarUIController != null && mTaskbarUIController.isBubbleBarEnabled());
+ }
+
+ @Override
+ public boolean hasBubbles() {
+ return (mTaskbarUIController != null && mTaskbarUIController.hasBubbles());
}
private static final class LauncherTaskViewController extends
@@ -1341,5 +1325,31 @@
if (mAppTransitionManager != null) {
mAppTransitionManager.dump(prefix + "\t" + RING_APPEAR_ANIMATION_PREFIX, writer);
}
+ if (mHotseatPredictionController != null) {
+ mHotseatPredictionController.dump(prefix, writer);
+ }
+ }
+
+ @Override
+ public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
+ switch (name) {
+ case "TextClock", "android.widget.TextClock" -> {
+ TextClock tc = new TextClock(context, attrs);
+ if (mAsyncClockEventDelegate == null) {
+ mAsyncClockEventDelegate = new AsyncClockEventDelegate(this);
+ }
+ tc.setClockEventDelegate(mAsyncClockEventDelegate);
+ return tc;
+ }
+ case "AnalogClock", "android.widget.AnalogClock" -> {
+ AnalogClock ac = new AnalogClock(context, attrs);
+ if (mAsyncClockEventDelegate == null) {
+ mAsyncClockEventDelegate = new AsyncClockEventDelegate(this);
+ }
+ ac.setClockEventDelegate(mAsyncClockEventDelegate);
+ return ac;
+ }
+ }
+ return super.onCreateView(parent, name, context, attrs);
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java
index 39543b0..f66bc60 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java
@@ -37,6 +37,7 @@
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.LauncherWidgetHolder;
+import com.android.launcher3.widget.custom.CustomWidgetManager;
import java.util.ArrayList;
import java.util.Collections;
@@ -237,12 +238,21 @@
@Override
public LauncherAppWidgetHostView createView(@NonNull Context context, int appWidgetId,
@NonNull LauncherAppWidgetProviderInfo appWidget) {
+
+ if (appWidget.isCustomWidget()) {
+ LauncherAppWidgetHostView lahv = new LauncherAppWidgetHostView(context);
+ lahv.setAppWidget(appWidgetId, appWidget);
+ CustomWidgetManager.INSTANCE.get(context).onViewCreated(lahv);
+ return lahv;
+ }
+
LauncherAppWidgetHostView widgetView = getPendingView(appWidgetId);
if (widgetView != null) {
removePendingView(appWidgetId);
} else {
widgetView = new LauncherAppWidgetHostView(context);
}
+ widgetView.setIsWidgetCachingDisabled(true);
widgetView.setInteractionHandler(mInteractionHandler);
widgetView.setAppWidget(appWidgetId, appWidget);
mViews.put(appWidgetId, widgetView);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index f16b43d..23e922c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -15,10 +15,10 @@
*/
package com.android.launcher3.uioverrides;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.LauncherState.CLEAR_ALL_BUTTON;
import static com.android.launcher3.LauncherState.OVERVIEW_ACTIONS;
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE;
import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
index b901a87..a76eb43 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
@@ -23,6 +23,7 @@
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
+import static com.android.launcher3.LauncherPrefs.ALL_APPS_OVERVIEW_THRESHOLD;
import static com.android.launcher3.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY;
import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.PLUGIN_CHANGED;
import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.pluginEnabledKey;
@@ -59,6 +60,7 @@
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder;
+import androidx.preference.SeekBarPreference;
import androidx.preference.SwitchPreference;
import com.android.launcher3.LauncherPrefs;
@@ -106,6 +108,9 @@
loadPluginPrefs();
maybeAddSandboxCategory();
addOnboardingPrefsCatergory();
+ if (FeatureFlags.ENABLE_ALL_APPS_FROM_OVERVIEW.get()) {
+ addAllAppsFromOverviewCatergory();
+ }
if (getActivity() != null) {
getActivity().setTitle("Developer Options");
@@ -393,6 +398,33 @@
}
}
+ private void addAllAppsFromOverviewCatergory() {
+ PreferenceCategory category = newCategory("All Apps from Overview Config");
+
+ SeekBarPreference thresholdPref = new SeekBarPreference(getContext());
+ thresholdPref.setTitle("Threshold to open All Apps from Overview");
+ thresholdPref.setSingleLineTitle(false);
+
+ // These values are 100x swipe up shift value (100 = where overview sits).
+ thresholdPref.setMax(500);
+ thresholdPref.setMin(105);
+ thresholdPref.setUpdatesContinuously(true);
+ thresholdPref.setIconSpaceReserved(false);
+ // Don't directly save to shared prefs, use LauncherPrefs instead.
+ thresholdPref.setPersistent(false);
+ thresholdPref.setOnPreferenceChangeListener((preference, newValue) -> {
+ LauncherPrefs.get(getContext()).put(ALL_APPS_OVERVIEW_THRESHOLD, newValue);
+ preference.setSummary(String.valueOf((int) newValue / 100f));
+ return true;
+ });
+ int value = LauncherPrefs.get(getContext()).get(ALL_APPS_OVERVIEW_THRESHOLD);
+ thresholdPref.setValue(value);
+ // For some reason the initial value is not triggering the summary update, so call manually.
+ thresholdPref.getOnPreferenceChangeListener().onPreferenceChange(thresholdPref, value);
+
+ category.addPreference(thresholdPref);
+ }
+
private String toName(String action) {
String str = action.replace("com.android.systemui.action.PLUGIN_", "")
.replace("com.android.launcher3.action.PLUGIN_", "");
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index 2a42175..ed0a0d5 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -15,14 +15,16 @@
*/
package com.android.launcher3.uioverrides.states;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.app.animation.Interpolators.DECELERATE_2;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
import android.content.Context;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
@@ -91,7 +93,7 @@
@Override
public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
PageAlphaProvider superPageAlphaProvider = super.getWorkspacePageAlphaProvider(launcher);
- return new PageAlphaProvider(DEACCEL_2) {
+ return new PageAlphaProvider(DECELERATE_2) {
@Override
public float getPageAlpha(int pageIndex) {
return launcher.getDeviceProfile().isTablet
@@ -103,14 +105,52 @@
@Override
public int getVisibleElements(Launcher launcher) {
- // Don't add HOTSEAT_ICONS for non-tablets in ALL_APPS state.
- return launcher.getDeviceProfile().isTablet ? ALL_APPS_CONTENT | HOTSEAT_ICONS
- : ALL_APPS_CONTENT;
+ int elements = ALL_APPS_CONTENT | FLOATING_SEARCH_BAR;
+ // Only add HOTSEAT_ICONS for tablets in ALL_APPS state.
+ if (launcher.getDeviceProfile().isTablet) {
+ elements |= HOTSEAT_ICONS;
+ }
+ return elements;
+ }
+
+ @Override
+ public int getFloatingSearchBarRestingMarginBottom(Launcher launcher) {
+ return 0;
+ }
+
+ @Override
+ public int getFloatingSearchBarRestingMarginStart(Launcher launcher) {
+ DeviceProfile dp = launcher.getDeviceProfile();
+ return dp.allAppsLeftRightMargin + dp.getAllAppsIconStartMargin();
+ }
+
+ @Override
+ public int getFloatingSearchBarRestingMarginEnd(Launcher launcher) {
+ DeviceProfile dp = launcher.getDeviceProfile();
+ return dp.allAppsLeftRightMargin + dp.getAllAppsIconStartMargin();
+ }
+
+ @Override
+ public boolean shouldFloatingSearchBarUsePillWhenUnfocused(Launcher launcher) {
+ DeviceProfile dp = launcher.getDeviceProfile();
+ return dp.isPhone && !dp.isLandscape;
}
@Override
public LauncherState getHistoryForState(LauncherState previousState) {
- return previousState == OVERVIEW ? OVERVIEW : NORMAL;
+ return previousState == BACKGROUND_APP ? QUICK_SWITCH_FROM_HOME
+ : previousState == OVERVIEW ? OVERVIEW : NORMAL;
+ }
+
+ @Override
+ public float[] getOverviewScaleAndOffset(Launcher launcher) {
+ if (!FeatureFlags.ENABLE_ALL_APPS_FROM_OVERVIEW.get()) {
+ return super.getOverviewScaleAndOffset(launcher);
+ }
+ // This handles the case of returning to the previous app from Overview -> All Apps gesture.
+ // This is the start scale/offset of overview that will be used for that transition.
+ // TODO (b/283336332): Translate in Y direction (ideally with overview resistance).
+ return new float[] {0.5f /* scale */, NO_OFFSET};
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
index b9221ee..3e7d45e 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
@@ -72,7 +72,7 @@
@Override
public boolean isTaskbarStashed(Launcher launcher) {
- if (FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get()) {
+ if (FeatureFlags.enableGridOnlyOverview()) {
return true;
}
return super.isTaskbarStashed(launcher);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 214679a..396d0ab 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -15,7 +15,7 @@
*/
package com.android.launcher3.uioverrides.states;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.app.animation.Interpolators.DECELERATE_2;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
import android.content.Context;
@@ -97,7 +97,7 @@
@Override
public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
- return new PageAlphaProvider(DEACCEL_2) {
+ return new PageAlphaProvider(DECELERATE_2) {
@Override
public float getPageAlpha(int pageIndex) {
return 0;
@@ -107,7 +107,32 @@
@Override
public int getVisibleElements(Launcher launcher) {
- return CLEAR_ALL_BUTTON | OVERVIEW_ACTIONS;
+ int elements = CLEAR_ALL_BUTTON | OVERVIEW_ACTIONS;
+ DeviceProfile dp = launcher.getDeviceProfile();
+ boolean showFloatingSearch;
+ if (dp.isPhone) {
+ // Only show search in phone overview in portrait mode.
+ showFloatingSearch = !dp.isLandscape;
+ } else {
+ // Only show search in tablet overview if taskbar is not visible.
+ showFloatingSearch = !dp.isTaskbarPresent || isTaskbarStashed(launcher);
+ }
+ if (showFloatingSearch) {
+ elements |= FLOATING_SEARCH_BAR;
+ }
+ return elements;
+ }
+
+ @Override
+ public int getFloatingSearchBarRestingMarginBottom(Launcher launcher) {
+ return areElementsVisible(launcher, FLOATING_SEARCH_BAR) ? 0
+ : super.getFloatingSearchBarRestingMarginBottom(launcher);
+ }
+
+ @Override
+ public boolean shouldFloatingSearchBarUsePillWhenUnfocused(Launcher launcher) {
+ DeviceProfile dp = launcher.getDeviceProfile();
+ return dp.isPhone && !dp.isLandscape;
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index a8d7538..e7b285a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -17,6 +17,20 @@
import static android.view.View.VISIBLE;
+import static com.android.app.animation.Interpolators.ACCELERATE;
+import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
+import static com.android.app.animation.Interpolators.DECELERATE;
+import static com.android.app.animation.Interpolators.DECELERATE_1_7;
+import static com.android.app.animation.Interpolators.DECELERATE_3;
+import static com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE;
+import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.app.animation.Interpolators.FINAL_FRAME;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.OVERSHOOT_0_75;
+import static com.android.app.animation.Interpolators.OVERSHOOT_1_2;
+import static com.android.app.animation.Interpolators.clampToProgress;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.HINT_STATE_TWO_BUTTON;
@@ -25,20 +39,6 @@
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
import static com.android.launcher3.QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION;
import static com.android.launcher3.WorkspaceStateTransitionAnimation.getWorkspaceSpringScaleAnimator;
-import static com.android.launcher3.anim.Interpolators.ACCEL;
-import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED_ACCELERATE;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-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.OVERSHOOT_1_2;
-import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_DEPTH;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE;
@@ -94,7 +94,6 @@
@Override
public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState,
StateAnimationConfig config) {
-
RecentsView overview = mActivity.getOverviewPanel();
if ((fromState == OVERVIEW || fromState == OVERVIEW_SPLIT_SELECT) && toState == NORMAL) {
overview.switchToScreenshot(() ->
@@ -112,8 +111,8 @@
fromState == OVERVIEW_SPLIT_SELECT
? clampToProgress(LINEAR, 0.33f, 1)
: LINEAR);
- config.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
- config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
+ config.setInterpolator(ANIM_WORKSPACE_SCALE, DECELERATE);
+ config.setInterpolator(ANIM_WORKSPACE_FADE, ACCELERATE);
if (DisplayController.getNavigationMode(mActivity).hasGestures
&& overview.getTaskViewCount() > 0) {
@@ -139,9 +138,9 @@
}
overview.snapToPage(DEFAULT_PAGE, Math.toIntExact(config.duration));
} else {
- config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL_DEACCEL);
- config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
- config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
+ config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCELERATE_DECELERATE);
+ config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCELERATE, 0, 0.9f));
+ config.setInterpolator(ANIM_OVERVIEW_FADE, DECELERATE_1_7);
}
Workspace<?> workspace = mActivity.getWorkspace();
@@ -167,8 +166,8 @@
|| fromState == HINT_STATE_TWO_BUTTON) && toState == OVERVIEW) {
if (DisplayController.getNavigationMode(mActivity).hasGestures) {
config.setInterpolator(ANIM_WORKSPACE_SCALE,
- fromState == NORMAL ? ACCEL : OVERSHOOT_1_2);
- config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
+ fromState == NORMAL ? ACCELERATE : OVERSHOOT_1_2);
+ config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCELERATE);
// Scrolling in tasks, so show straight away
if (overview.getTaskViewCount() > 0) {
@@ -196,7 +195,7 @@
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_2);
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, OVERSHOOT_1_2);
} else if (fromState == HINT_STATE && toState == NORMAL) {
- config.setInterpolator(ANIM_DEPTH, DEACCEL_3);
+ config.setInterpolator(ANIM_DEPTH, DECELERATE_3);
if (mHintToNormalDuration == -1) {
ValueAnimator va = getWorkspaceSpringScaleAnimator(mActivity,
mActivity.getWorkspace(),
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index 8cbd6e8..b266bcd 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -15,19 +15,22 @@
*/
package com.android.launcher3.uioverrides.touchcontrollers;
+import static com.android.app.animation.Interpolators.DECELERATE_3;
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL_APPS_EDU;
import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PULL_BACK_ALPHA;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PULL_BACK_TRANSLATION;
import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
+import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
+import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.view.MotionEvent;
import android.view.animation.Interpolator;
@@ -41,24 +44,29 @@
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.TouchController;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.OverviewToHomeAnim;
import com.android.quickstep.views.RecentsView;
+import java.util.function.Consumer;
+
/**
* Handles swiping up on the nav bar to go home from launcher, e.g. overview or all apps.
*/
public class NavBarToHomeTouchController implements TouchController,
SingleAxisSwipeDetector.Listener {
- private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL_3;
+ private static final Interpolator PULLBACK_INTERPOLATOR = DECELERATE_3;
// The min amount of overview scrim we keep during the transition.
private static final float OVERVIEW_TO_HOME_SCRIM_MULTIPLIER = 0.5f;
private final Launcher mLauncher;
+ private final Consumer<AnimatorSet> mCancelSplitRunnable;
private final SingleAxisSwipeDetector mSwipeDetector;
private final float mPullbackDistance;
@@ -67,8 +75,14 @@
private LauncherState mEndState = NORMAL;
private AnimatorPlaybackController mCurrentAnimation;
- public NavBarToHomeTouchController(Launcher launcher) {
+ /**
+ * @param cancelSplitRunnable Called when split placeholder view needs to be cancelled.
+ * Animation should be added to the provided AnimatorSet
+ */
+ public NavBarToHomeTouchController(Launcher launcher,
+ Consumer<AnimatorSet> cancelSplitRunnable) {
mLauncher = launcher;
+ mCancelSplitRunnable = cancelSplitRunnable;
mSwipeDetector = new SingleAxisSwipeDetector(mLauncher, this,
SingleAxisSwipeDetector.VERTICAL);
mPullbackDistance = mLauncher.getResources().getDimension(R.dimen.home_pullback_distance);
@@ -95,6 +109,10 @@
}
private boolean canInterceptTouch(MotionEvent ev) {
+ if (!isTrackpadMotionEvent(ev) && DisplayController.getNavigationMode(mLauncher)
+ == THREE_BUTTONS) {
+ return false;
+ }
boolean cameFromNavBar = (ev.getEdgeFlags() & Utilities.EDGE_NAV_BAR) != 0;
if (!cameFromNavBar) {
return false;
@@ -176,7 +194,10 @@
recentsView.switchToScreenshot(null,
() -> recentsView.finishRecentsAnimation(true /* toRecents */, null));
if (mStartState.overviewUi) {
- new OverviewToHomeAnim(mLauncher, () -> onSwipeInteractionCompleted(mEndState))
+ new OverviewToHomeAnim(mLauncher, () -> onSwipeInteractionCompleted(mEndState),
+ FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()
+ ? mCancelSplitRunnable
+ : null)
.animateWithVelocity(velocity);
} else {
mLauncher.getStateManager().goToState(mEndState, true,
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index b7bafd8..ca598c8 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -16,19 +16,22 @@
package com.android.launcher3.uioverrides.touchcontrollers;
+import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
-import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
+import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
import static com.android.launcher3.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.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.graphics.PointF;
@@ -43,6 +46,7 @@
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.taskbar.LauncherTaskbarUIController;
import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.VibratorWrapper;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.util.AnimatorControllerWithResistance;
@@ -50,6 +54,8 @@
import com.android.quickstep.util.OverviewToHomeAnim;
import com.android.quickstep.views.RecentsView;
+import java.util.function.Consumer;
+
/**
* Touch controller which handles swipe and hold from the nav bar to go to Overview. Swiping above
* the nav bar falls back to go to All Apps. Swiping from the nav bar without holding goes to the
@@ -64,6 +70,7 @@
private static final float TRANSLATION_ANIM_VELOCITY_DP_PER_MS = 0.8f;
private final VibratorWrapper mVibratorWrapper;
+ private final Consumer<AnimatorSet> mCancelSplitRunnable;
private final RecentsView mRecentsView;
private final MotionPauseDetector mMotionPauseDetector;
private final float mMotionPauseMinDisplacement;
@@ -79,16 +86,26 @@
// Normal to Hint animation has flag SKIP_OVERVIEW, so we update this scrim with this animator.
private ObjectAnimator mNormalToHintOverviewScrimAnimator;
- public NoButtonNavbarToOverviewTouchController(Launcher l) {
+ /**
+ * @param cancelSplitRunnable Called when split placeholder view needs to be cancelled.
+ * Animation should be added to the provided AnimatorSet
+ */
+ public NoButtonNavbarToOverviewTouchController(Launcher l,
+ Consumer<AnimatorSet> cancelSplitRunnable) {
super(l);
mRecentsView = l.getOverviewPanel();
mMotionPauseDetector = new MotionPauseDetector(l);
mMotionPauseMinDisplacement = ViewConfiguration.get(l).getScaledTouchSlop();
mVibratorWrapper = VibratorWrapper.INSTANCE.get(l.getApplicationContext());
+ mCancelSplitRunnable = cancelSplitRunnable;
}
@Override
protected boolean canInterceptTouch(MotionEvent ev) {
+ if (!isTrackpadMotionEvent(ev) && DisplayController.getNavigationMode(mLauncher)
+ == THREE_BUTTONS) {
+ return false;
+ }
mDidTouchStartInNavBar = (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0;
boolean isOneHandedModeActive = (SystemUiProxy.INSTANCE.get(mLauncher)
.getLastSystemUiStateFlags() & SYSUI_STATE_ONE_HANDED_ACTIVE) != 0;
@@ -102,9 +119,6 @@
protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) {
if (fromState == NORMAL && mDidTouchStartInNavBar) {
return HINT_STATE;
- } else if (fromState == OVERVIEW && isDragTowardPositive) {
- // Don't allow swiping up to all apps.
- return OVERVIEW;
}
return super.getTargetState(fromState, isDragTowardPositive);
}
@@ -190,6 +204,9 @@
// state, but since the hint state tracks the entire screen without a clear endpoint, we
// need to manually set the duration to a reasonable value.
animator.setDuration(HINT_STATE.getTransitionDuration(mLauncher, true /* isToState */));
+ AnimatorSet animatorSet = new AnimatorSet();
+ mCancelSplitRunnable.accept(animatorSet);
+ animatorSet.start();
}
if (FeatureFlags.ENABLE_PREMIUM_HAPTICS_ALL_APPS.get() &&
((mFromState == NORMAL && mToState == ALL_APPS)
@@ -261,7 +278,7 @@
private void goToOverviewOrHomeOnDragEnd(float velocity) {
boolean goToHomeInsteadOfOverview = !mMotionPauseDetector.isPaused();
if (goToHomeInsteadOfOverview) {
- new OverviewToHomeAnim(mLauncher, () -> onSwipeInteractionCompleted(NORMAL))
+ new OverviewToHomeAnim(mLauncher, () -> onSwipeInteractionCompleted(NORMAL), null)
.animateWithVelocity(velocity);
}
if (mReachedOverview) {
@@ -273,7 +290,7 @@
mRecentsView.animate()
.translationX(0)
.translationY(0)
- .setInterpolator(ACCEL_DEACCEL)
+ .setInterpolator(ACCELERATE_DECELERATE)
.setDuration(duration)
.withEndAction(goToHomeInsteadOfOverview
? null
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 80f5558..6f421eb 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -16,21 +16,21 @@
package com.android.launcher3.uioverrides.touchcontrollers;
import static android.view.MotionEvent.ACTION_DOWN;
-import static android.view.MotionEvent.ACTION_MOVE;
+import static com.android.app.animation.Interpolators.ACCELERATE_0_75;
+import static com.android.app.animation.Interpolators.DECELERATE_3;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_ACTIONS;
import static com.android.launcher3.LauncherState.QUICK_SWITCH_FROM_HOME;
import static com.android.launcher3.MotionEventsUtils.isTrackpadFourFingerSwipe;
+import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
import static com.android.launcher3.anim.AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_RIGHT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEDOWN;
@@ -46,6 +46,7 @@
import static com.android.launcher3.states.StateAnimationConfig.SKIP_SCRIM;
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT;
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP;
+import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET;
@@ -74,6 +75,7 @@
import com.android.launcher3.touch.BaseSwipeDetector;
import com.android.launcher3.touch.BothAxesSwipeDetector;
import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.util.VibratorWrapper;
import com.android.quickstep.SystemUiProxy;
@@ -84,6 +86,7 @@
import com.android.quickstep.views.DesktopTaskView;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
+import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
/**
* Handles quick switching to a recent task from the home screen. To give as much flexibility to
@@ -93,8 +96,8 @@
BothAxesSwipeDetector.Listener {
private static final float Y_ANIM_MIN_PROGRESS = 0.25f;
- private static final Interpolator FADE_OUT_INTERPOLATOR = DEACCEL_3;
- private static final Interpolator TRANSLATE_OUT_INTERPOLATOR = ACCEL_0_75;
+ private static final Interpolator FADE_OUT_INTERPOLATOR = DECELERATE_3;
+ private static final Interpolator TRANSLATE_OUT_INTERPOLATOR = ACCELERATE_0_75;
private static final Interpolator SCALE_DOWN_INTERPOLATOR = LINEAR;
private static final long ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW = 300;
@@ -110,7 +113,6 @@
newCancelListener(this::clearState);
private boolean mNoIntercept;
- private Boolean mIsTrackpadFourFingerSwipe;
private LauncherState mStartState;
private boolean mIsHomeScreenVisible = true;
@@ -136,9 +138,7 @@
@Override
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
- int action = ev.getActionMasked();
- if (action == ACTION_DOWN) {
- mIsTrackpadFourFingerSwipe = null;
+ if (ev.getActionMasked() == ACTION_DOWN) {
mNoIntercept = !canInterceptTouch(ev);
if (mNoIntercept) {
return false;
@@ -147,13 +147,6 @@
// Only detect horizontal swipe for intercept, then we will allow swipe up as well.
mSwipeDetector.setDetectableScrollConditions(DIRECTION_RIGHT,
false /* ignoreSlopWhenSettling */);
- } else if (isTrackpadMultiFingerSwipe(ev) && mIsTrackpadFourFingerSwipe == null
- && action == ACTION_MOVE) {
- mIsTrackpadFourFingerSwipe = isTrackpadFourFingerSwipe(ev);
- mNoIntercept = !mIsTrackpadFourFingerSwipe;
- if (mNoIntercept) {
- return false;
- }
}
if (mNoIntercept) {
@@ -170,6 +163,10 @@
}
private boolean canInterceptTouch(MotionEvent ev) {
+ if (!isTrackpadMotionEvent(ev) && DisplayController.getNavigationMode(mLauncher)
+ == THREE_BUTTONS) {
+ return false;
+ }
if (!mLauncher.isInState(LauncherState.NORMAL)) {
return false;
}
@@ -184,6 +181,9 @@
// TODO(b/268075592): add support for quickswitch to/from desktop
return false;
}
+ if (isTrackpadMultiFingerSwipe(ev)) {
+ return isTrackpadFourFingerSwipe(ev);
+ }
return true;
}
@@ -191,6 +191,9 @@
public void onDragStart(boolean start) {
mMotionPauseDetector.clear();
if (start) {
+ InteractionJankMonitorWrapper.begin(mRecentsView,
+ InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH);
+
mStartState = mLauncher.getStateManager().getState();
mMotionPauseDetector.setOnMotionPauseListener(this::onMotionPauseDetected);
@@ -325,6 +328,7 @@
if (mMotionPauseDetector.isPaused() && noFling) {
// Going to Overview.
cancelAnimations();
+ InteractionJankMonitorWrapper.cancel(InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH);
StateAnimationConfig config = new StateAnimationConfig();
config.duration = ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
@@ -441,6 +445,8 @@
RecentsView.SCROLL_VIBRATION_PRIMITIVE,
RecentsView.SCROLL_VIBRATION_PRIMITIVE_SCALE,
RecentsView.SCROLL_VIBRATION_FALLBACK);
+ } else {
+ InteractionJankMonitorWrapper.cancel(InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH);
}
nonOverviewAnim.setDuration(Math.max(xDuration, yDuration));
@@ -462,6 +468,11 @@
: targetState.ordinal > mStartState.ordinal
? LAUNCHER_UNKNOWN_SWIPEUP
: LAUNCHER_UNKNOWN_SWIPEDOWN));
+
+ if (targetState == QUICK_SWITCH_FROM_HOME) {
+ InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH);
+ }
+
mLauncher.getStateManager().goToState(targetState, false, forEndCallback(this::clearState));
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index 8368f9c..e30fe66 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -24,11 +24,12 @@
import android.view.MotionEvent;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.allapps.AllAppsTransitionController;
-import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.touch.AbstractStateChangeTouchController;
import com.android.launcher3.touch.AllAppsSwipeController;
@@ -92,9 +93,9 @@
@Override
protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) {
if (fromState == ALL_APPS && !isDragTowardPositive) {
- return NORMAL;
- } else if (fromState == OVERVIEW) {
- return isDragTowardPositive ? OVERVIEW : NORMAL;
+ return FeatureFlags.ENABLE_ALL_APPS_FROM_OVERVIEW.get()
+ ? mLauncher.getStateManager().getLastState()
+ : NORMAL;
} else if (fromState == NORMAL && isDragTowardPositive) {
return ALL_APPS;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
index f941b02..9a35bb2 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -15,12 +15,12 @@
*/
package com.android.launcher3.uioverrides.touchcontrollers;
+import static com.android.app.animation.Interpolators.ACCELERATE_2;
+import static com.android.app.animation.Interpolators.DECELERATE_2;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.QUICK_SWITCH_FROM_HOME;
-import static com.android.launcher3.anim.Interpolators.ACCEL_2;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
@@ -128,14 +128,14 @@
}
private void setupInterpolators(StateAnimationConfig stateAnimationConfig) {
- stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_2);
- stateAnimationConfig.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_2);
+ stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_FADE, DECELERATE_2);
+ stateAnimationConfig.setInterpolator(ANIM_ALL_APPS_FADE, DECELERATE_2);
if (DisplayController.getNavigationMode(mLauncher) == NavigationMode.NO_BUTTON) {
// Overview lives to the left of workspace, so translate down later than over
- stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL_2);
- stateAnimationConfig.setInterpolator(ANIM_VERTICAL_PROGRESS, ACCEL_2);
- stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_SCALE, ACCEL_2);
- stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, ACCEL_2);
+ stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCELERATE_2);
+ stateAnimationConfig.setInterpolator(ANIM_VERTICAL_PROGRESS, ACCELERATE_2);
+ stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_SCALE, ACCELERATE_2);
+ stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, ACCELERATE_2);
stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
} else {
stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_TRANSLATE, LINEAR);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java
index 395833f..26ab3d6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java
@@ -76,7 +76,7 @@
private void dispatchTouchEvent(MotionEvent ev) {
if (mSystemUiProxy.isActive()) {
mLastAction = ev.getActionMasked();
- mSystemUiProxy.onStatusBarMotionEvent(ev);
+ mSystemUiProxy.onStatusBarTouchEvent(ev);
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index eddc50c..3d94857 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -27,13 +27,13 @@
import android.view.View;
import android.view.animation.Interpolator;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.touch.BaseSwipeDetector;
import com.android.launcher3.touch.PagedOrientationHandler;
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 43db7c3..ca4f0ea 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -21,19 +21,19 @@
import static android.view.Surface.ROTATION_90;
import static android.widget.Toast.LENGTH_SHORT;
+import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
+import static com.android.app.animation.Interpolators.DECELERATE;
+import static com.android.app.animation.Interpolators.OVERSHOOT_1_2;
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
+import static com.android.launcher3.LauncherPrefs.ALL_APPS_OVERVIEW_THRESHOLD;
import static com.android.launcher3.PagedView.INVALID_PAGE;
-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.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;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_GESTURE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_LEFT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_RIGHT;
-import static com.android.launcher3.uioverrides.QuickstepLauncher.ENABLE_PIP_KEEP_CLEAR_ALGORITHM;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
@@ -94,6 +94,7 @@
import com.android.internal.util.LatencyTracker;
import com.android.launcher3.AbstractFloatingView;
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.AnimationSuccessListener;
@@ -101,14 +102,15 @@
import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
+import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.taskbar.TaskbarThresholdUtils;
import com.android.launcher3.taskbar.TaskbarUIController;
-import com.android.launcher3.tracing.InputConsumerProto;
-import com.android.launcher3.tracing.SwipeHandlerProto;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter;
import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.SafeCloseable;
import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.VibratorWrapper;
import com.android.launcher3.util.WindowBounds;
@@ -122,7 +124,6 @@
import com.android.quickstep.util.InputConsumerProxy;
import com.android.quickstep.util.InputProxyHandlerFactory;
import com.android.quickstep.util.MotionPauseDetector;
-import com.android.quickstep.util.ProtoTracer;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
@@ -133,6 +134,7 @@
import com.android.quickstep.views.DesktopTaskView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
+import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -149,6 +151,7 @@
import java.util.HashMap;
import java.util.Objects;
import java.util.Optional;
+import java.util.OptionalInt;
import java.util.function.Consumer;
/**
@@ -163,9 +166,6 @@
private static final ArrayList<String> STATE_NAMES = new ArrayList<>();
- /** Shift distance to transition to All Apps if ENABLE_ALL_APPS_FROM_OVERVIEW. */
- public static final float ALL_APPS_SHIFT_THRESHOLD = 2f;
-
protected final BaseActivityInterface<S, T> mActivityInterface;
protected final InputConsumerProxy mInputConsumerProxy;
protected final ActivityInitListener mActivityInitListener;
@@ -193,6 +193,7 @@
ActiveGestureLog.INSTANCE.addLog("Launcher destroyed", LAUNCHER_DESTROYED);
mRecentsView = null;
mActivity = null;
+ mStateCallback.clearState(STATE_LAUNCHER_PRESENT);
}
};
@@ -293,7 +294,8 @@
private boolean mContinuingLastGesture;
- private ThumbnailData mTaskSnapshot;
+ // Cache of recently-updated task snapshots, mapping task id to ThumbnailData
+ private HashMap<Integer, ThumbnailData> mTaskSnapshotCache = new HashMap<>();
// Used to control launcher components throughout the swipe gesture.
private AnimatorControllerWithResistance mLauncherTransitionController;
@@ -378,12 +380,12 @@
mTaskbarAlreadyOpen = controller != null && !controller.isTaskbarStashed();
mIsTaskbarAllAppsOpen = controller != null && controller.isTaskbarAllAppsOpen();
mTaskbarAppWindowThreshold =
- res.getDimensionPixelSize(R.dimen.taskbar_app_window_threshold);
+ TaskbarThresholdUtils.getAppWindowThreshold(res, mDp);
boolean swipeWillNotShowTaskbar = mTaskbarAlreadyOpen || mGestureState.isTrackpadGesture();
mTaskbarHomeOverviewThreshold = swipeWillNotShowTaskbar
? 0
- : res.getDimensionPixelSize(R.dimen.taskbar_home_overview_threshold);
- mTaskbarCatchUpThreshold = res.getDimensionPixelSize(R.dimen.taskbar_catch_up_threshold);
+ : TaskbarThresholdUtils.getHomeOverviewThreshold(res, mDp);
+ mTaskbarCatchUpThreshold = TaskbarThresholdUtils.getCatchUpThreshold(res, mDp);
}
@Nullable
@@ -516,20 +518,22 @@
// Set up a entire animation lifecycle callback to notify the current recents view when
// the animation is canceled
mGestureState.runOnceAtState(STATE_RECENTS_ANIMATION_CANCELED, () -> {
- HashMap<Integer, ThumbnailData> snapshots =
- mGestureState.consumeRecentsAnimationCanceledSnapshot();
- if (snapshots != null) {
- mRecentsView.switchToScreenshot(snapshots, () -> {
- if (mRecentsAnimationController != null) {
- mRecentsAnimationController.cleanupScreenshot();
- } else if (mDeferredCleanupRecentsAnimationController != null) {
- mDeferredCleanupRecentsAnimationController.cleanupScreenshot();
- mDeferredCleanupRecentsAnimationController = null;
- }
- });
- mRecentsView.onRecentsAnimationComplete();
- }
- });
+ if (mRecentsView == null) return;
+
+ HashMap<Integer, ThumbnailData> snapshots =
+ mGestureState.consumeRecentsAnimationCanceledSnapshot();
+ if (snapshots != null) {
+ mRecentsView.switchToScreenshot(snapshots, () -> {
+ if (mRecentsAnimationController != null) {
+ mRecentsAnimationController.cleanupScreenshot();
+ } else if (mDeferredCleanupRecentsAnimationController != null) {
+ mDeferredCleanupRecentsAnimationController.cleanupScreenshot();
+ mDeferredCleanupRecentsAnimationController = null;
+ }
+ });
+ mRecentsView.onRecentsAnimationComplete();
+ }
+ });
setupRecentsViewUi();
mRecentsView.runOnPageScrollsInitialized(this::linkRecentsViewScroll);
@@ -587,7 +591,7 @@
if (mWasLauncherAlreadyVisible) {
mStateCallback.setState(STATE_LAUNCHER_DRAWN);
} else {
- Object traceToken = TraceHelper.INSTANCE.beginSection("WTS-init");
+ SafeCloseable traceToken = TraceHelper.INSTANCE.beginAsyncSection("WTS-init");
View dragLayer = activity.getDragLayer();
dragLayer.getViewTreeObserver().addOnDrawListener(new OnDrawListener() {
boolean mHandled = false;
@@ -599,7 +603,7 @@
}
mHandled = true;
- TraceHelper.INSTANCE.endSection(traceToken);
+ traceToken.close();
dragLayer.post(() ->
dragLayer.getViewTreeObserver().removeOnDrawListener(this));
if (activity != mActivity) {
@@ -657,11 +661,12 @@
protected void notifyGestureAnimationStartToRecents() {
Task[] runningTasks;
+ TopTaskTracker.CachedTaskInfo cachedTaskInfo = mGestureState.getRunningTask();
if (mIsSwipeForSplit) {
int[] splitTaskIds = TopTaskTracker.INSTANCE.get(mContext).getRunningSplitTaskIds();
- runningTasks = mGestureState.getRunningTask().getPlaceholderTasks(splitTaskIds);
+ runningTasks = cachedTaskInfo.getPlaceholderTasks(splitTaskIds);
} else {
- runningTasks = mGestureState.getRunningTask().getPlaceholderTasks();
+ runningTasks = cachedTaskInfo.getPlaceholderTasks();
}
// Safeguard against any null tasks being sent to recents view, happens when quickswitching
@@ -681,11 +686,10 @@
private void initializeLauncherAnimationController() {
buildAnimationController();
- Object traceToken = TraceHelper.INSTANCE.beginSection("logToggleRecents",
- TraceHelper.FLAG_IGNORE_BINDERS);
- LatencyTracker.getInstance(mContext).logAction(LatencyTracker.ACTION_TOGGLE_RECENTS,
- (int) (mLauncherFrameDrawnTime - mTouchTimeMs));
- TraceHelper.INSTANCE.endSection(traceToken);
+ try (SafeCloseable c = TraceHelper.INSTANCE.allowIpcs("logToggleRecents")) {
+ LatencyTracker.getInstance(mContext).logAction(LatencyTracker.ACTION_TOGGLE_RECENTS,
+ (int) (mLauncherFrameDrawnTime - mTouchTimeMs));
+ }
// This method is only called when STATE_GESTURE_STARTED is set, so we can enable the
// high-res thumbnail loader here once we are sure that we will end up in an overview state
@@ -731,11 +735,15 @@
* @param moveRunningTask whether to move running task to front when attaching
*/
private void maybeUpdateRecentsAttachedState(boolean animate, boolean moveRunningTask) {
- if (!mDeviceState.isFullyGesturalNavMode() || mRecentsView == null) {
+ if ((!mDeviceState.isFullyGesturalNavMode() && !mGestureState.isTrackpadGesture())
+ || mRecentsView == null) {
return;
}
+ // looking at single target is fine here since either app of a split pair would
+ // have their "isInRecents" field set? (that's what this is used for below)
RemoteAnimationTarget runningTaskTarget = mRecentsAnimationTargets != null
- ? mRecentsAnimationTargets.findTask(mGestureState.getRunningTaskId())
+ ? mRecentsAnimationTargets
+ .findTask(mGestureState.getTopRunningTaskId())
: null;
final boolean recentsAttachedToAppWindow;
if (mIsInAllAppsRegion) {
@@ -810,6 +818,10 @@
VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC);
maybeUpdateRecentsAttachedState(true);
+ if (mActivity != null) {
+ mActivity.getAppsView().getSearchUiManager().prepareToFocusEditText(mIsInAllAppsRegion);
+ }
+
// Draw active task below Launcher so that All Apps can appear over it.
runActionOnRemoteHandles(remoteTargetHandle ->
remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(isInAllAppsRegion));
@@ -873,7 +885,8 @@
@UiThread
@Override
public void onCurrentShiftUpdated() {
- setIsInAllAppsRegion(mCurrentShift.value >= ALL_APPS_SHIFT_THRESHOLD);
+ float threshold = LauncherPrefs.get(mContext).get(ALL_APPS_OVERVIEW_THRESHOLD) / 100f;
+ setIsInAllAppsRegion(mCurrentShift.value >= threshold);
updateSysUiFlags(mCurrentShift.value);
applyScrollAndTransform();
@@ -1148,6 +1161,14 @@
mStateCallback.setState(STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT);
// Notify the SysUI to use fade-in animation when entering PiP
SystemUiProxy.INSTANCE.get(mContext).setPipAnimationTypeToAlpha();
+ if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
+ // Notify the SysUI to stash desktop apps if they are visible
+ DesktopVisibilityController desktopVisibilityController =
+ mActivityInterface.getDesktopVisibilityController();
+ if (desktopVisibilityController != null) {
+ desktopVisibilityController.onHomeActionTriggered();
+ }
+ }
break;
case RECENTS:
mStateCallback.setState(STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
@@ -1168,7 +1189,8 @@
break;
}
ActiveGestureLog.INSTANCE.addLog(
- /* event= */ "onSettledOnEndTarget " + endTarget,
+ new ActiveGestureLog.CompoundString("onSettledOnEndTarget ")
+ .append(endTarget.name()),
/* gestureEvent= */ ON_SETTLED_ON_END_TARGET);
}
@@ -1178,7 +1200,7 @@
return false;
}
boolean hasStartedTaskBefore = Arrays.stream(appearedTaskTarget).anyMatch(
- targetCompat -> targetCompat.taskId == mGestureState.getLastStartedTaskId());
+ mGestureState.mLastStartedTaskIdPredicate);
if (mStateCallback.hasStates(STATE_START_NEW_TASK) && hasStartedTaskBefore) {
reset();
return true;
@@ -1324,11 +1346,11 @@
Interpolator interpolator;
S state = mActivityInterface.stateFromGestureEndTarget(endTarget);
if (state.displayOverviewTasksAsGrid(mDp)) {
- interpolator = ACCEL_DEACCEL;
+ interpolator = ACCELERATE_DECELERATE;
} else if (endTarget == RECENTS) {
interpolator = OVERSHOOT_1_2;
} else {
- interpolator = DEACCEL;
+ interpolator = DECELERATE;
}
if (endTarget.isLauncher) {
@@ -1444,9 +1466,12 @@
@Override
public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
- if (task.taskId == mGestureState.getRunningTaskId()
- && task.configuration.windowConfiguration.getActivityType()
- != ACTIVITY_TYPE_HOME) {
+ boolean taskRunningAndNotHome = Arrays.stream(mGestureState
+ .getRunningTaskIds(true /*getMultipleTasks*/))
+ .anyMatch(taskId -> task.taskId == taskId
+ && task.configuration.windowConfiguration.getActivityType()
+ != ACTIVITY_TYPE_HOME);
+ if (taskRunningAndNotHome) {
// Since this is an edge case, just cancel and relaunch with default activity
// options (since we don't know if there's an associated app icon to launch from)
endRunningWindowAnim(true /* cancel */);
@@ -1488,8 +1513,12 @@
if (mGestureState.getEndTarget() == HOME) {
getOrientationHandler().adjustFloatingIconStartVelocity(velocityPxPerMs);
+ // Take first task ID, if there are multiple we don't have any special home
+ // animation so doesn't matter for splitscreen.. though the "allowEnterPip" might change
+ // depending on which task it is..
final RemoteAnimationTarget runningTaskTarget = mRecentsAnimationTargets != null
- ? mRecentsAnimationTargets.findTask(mGestureState.getRunningTaskId())
+ ? mRecentsAnimationTargets
+ .findTask(mGestureState.getTopRunningTaskId())
: null;
final ArrayList<IBinder> cookies = runningTaskTarget != null
? runningTaskTarget.taskInfo.launchCookies
@@ -1518,8 +1547,10 @@
// grab a screenshot before the PipContentOverlay gets parented on top of the task
UI_HELPER_EXECUTOR.execute(() -> {
- mTaskSnapshot = mRecentsAnimationController.screenshotTask(
- mGestureState.getRunningTaskId());
+ // Directly use top task, split to pip handled on shell side
+ final int taskId = mGestureState.getTopRunningTaskId();
+ mTaskSnapshotCache.put(taskId,
+ mRecentsAnimationController.screenshotTask(taskId));
});
// let SystemUi reparent the overlay leash as soon as possible
@@ -1725,11 +1756,6 @@
private Rect getKeepClearAreaForHotseat() {
Rect keepClearArea;
- if (!ENABLE_PIP_KEEP_CLEAR_ALGORITHM) {
- // make the height equal to hotseatBarSizePx only
- keepClearArea = new Rect(0, 0, 0, mDp.hotseatBarSizePx);
- return keepClearArea;
- }
// the keep clear area in global screen coordinates, in pixels
if (mDp.isPhone) {
if (mDp.isSeascape()) {
@@ -1908,7 +1934,7 @@
mActivityInitListener.unregister();
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(
mActivityRestartListener);
- mTaskSnapshot = null;
+ mTaskSnapshotCache.clear();
}
private void invalidateHandler() {
@@ -1926,7 +1952,7 @@
mActivityInitListener.unregister();
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(
mActivityRestartListener);
- mTaskSnapshot = null;
+ mTaskSnapshotCache.clear();
}
private void invalidateHandlerWithLauncher() {
@@ -1981,37 +2007,39 @@
// If there are no targets, then we don't need to capture anything
mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
} else {
- final int runningTaskId = mGestureState.getRunningTaskId();
boolean finishTransitionPosted = false;
+ // If we already have cached screenshot(s) from running tasks, skip update
+ boolean shouldUpdate = false;
+ int[] runningTaskIds = mGestureState.getRunningTaskIds(mIsSwipeForSplit);
+ for (int id : runningTaskIds) {
+ if (!mTaskSnapshotCache.containsKey(id)) {
+ shouldUpdate = true;
+ break;
+ }
+ }
+
if (mRecentsAnimationController != null) {
// Update the screenshot of the task
- if (mTaskSnapshot == null) {
+ if (shouldUpdate) {
UI_HELPER_EXECUTOR.execute(() -> {
if (mRecentsAnimationController == null) return;
- final ThumbnailData taskSnapshot =
- mRecentsAnimationController.screenshotTask(runningTaskId);
- // If split case, we should update all split tasks snapshot
- if (mIsSwipeForSplit) {
- int[] splitTaskIds = TopTaskTracker.INSTANCE.get(
- mContext).getRunningSplitTaskIds();
- for (int i = 0; i < splitTaskIds.length; i++) {
- // Skip running one because done above.
- if (splitTaskIds[i] == runningTaskId) continue;
-
- mRecentsAnimationController.screenshotTask(splitTaskIds[i]);
- }
+ for (int id : runningTaskIds) {
+ mTaskSnapshotCache.put(
+ id, mRecentsAnimationController.screenshotTask(id));
}
+
MAIN_EXECUTOR.execute(() -> {
- mTaskSnapshot = taskSnapshot;
- if (!updateThumbnail(runningTaskId, false /* refreshView */)) {
+ if (!updateThumbnail(false /* refreshView */)) {
setScreenshotCapturedState();
}
});
});
return;
}
- finishTransitionPosted = updateThumbnail(runningTaskId, false /* refreshView */);
+
+ finishTransitionPosted = updateThumbnail(false /* refreshView */);
}
+
if (!finishTransitionPosted) {
setScreenshotCapturedState();
}
@@ -2019,35 +2047,34 @@
}
// Returns whether finish transition was posted.
- private boolean updateThumbnail(int runningTaskId, boolean refreshView) {
- boolean finishTransitionPosted = false;
- final TaskView taskView;
+ private boolean updateThumbnail(boolean refreshView) {
if (mGestureState.getEndTarget() == HOME
|| mGestureState.getEndTarget() == NEW_TASK
|| mGestureState.getEndTarget() == ALL_APPS
|| mRecentsView == null) {
// Capture the screenshot before finishing the transition to home or quickswitching to
// ensure it's taken in the correct orientation, but no need to update the thumbnail.
- taskView = null;
- } else {
- taskView = mRecentsView.updateThumbnail(runningTaskId, mTaskSnapshot, refreshView);
+ return false;
}
- if (taskView != null && refreshView && !mCanceled) {
+
+ boolean finishTransitionPosted = false;
+ TaskView updatedTaskView = mRecentsView.updateThumbnail(mTaskSnapshotCache, refreshView);
+ if (updatedTaskView != null && refreshView && !mCanceled) {
// Defer finishing the animation until the next launcher frame with the
// new thumbnail
- finishTransitionPosted = ViewUtils.postFrameDrawn(taskView,
+ finishTransitionPosted = ViewUtils.postFrameDrawn(updatedTaskView,
() -> mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED),
this::isCanceled);
}
+
return finishTransitionPosted;
}
private void setScreenshotCapturedState() {
// If we haven't posted a draw callback, set the state immediately.
- Object traceToken = TraceHelper.INSTANCE.beginSection(SCREENSHOT_CAPTURED_EVT,
- TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS);
+ TraceHelper.INSTANCE.beginSection(SCREENSHOT_CAPTURED_EVT);
mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
}
private void finishCurrentTransitionToRecents() {
@@ -2188,16 +2215,28 @@
if (!mCanceled) {
TaskView nextTask = mRecentsView == null ? null : mRecentsView.getNextPageTaskView();
if (nextTask != null) {
- Task.TaskKey nextTaskKey = nextTask.getTask().key;
- int taskId = nextTaskKey.id;
- mGestureState.updateLastStartedTaskId(taskId);
- boolean hasTaskPreviouslyAppeared = mGestureState.getPreviouslyAppearedTaskIds()
- .contains(taskId);
+ int[] taskIds = nextTask.getTaskIds();
+ ActiveGestureLog.CompoundString nextTaskLog = new ActiveGestureLog.CompoundString(
+ "Launching task: ");
+ for (TaskIdAttributeContainer c : nextTask.getTaskIdAttributeContainers()) {
+ if (c == null) {
+ continue;
+ }
+ nextTaskLog
+ .append("[id: ")
+ .append(c.getTask().key.id)
+ .append(", pkg: ")
+ .append(c.getTask().key.getPackageName())
+ .append("] | ");
+ }
+ mGestureState.updateLastStartedTaskIds(taskIds);
+ boolean hasTaskPreviouslyAppeared = Arrays.stream(taskIds).anyMatch(
+ taskId -> mGestureState.getPreviouslyAppearedTaskIds()
+ .contains(taskId));
if (!hasTaskPreviouslyAppeared) {
ActiveGestureLog.INSTANCE.trackEvent(EXPECTING_TASK_APPEARED);
}
- ActiveGestureLog.INSTANCE.addLog("Launching task: id=" + taskId
- + " pkg=" + nextTaskKey.getPackageName());
+ ActiveGestureLog.INSTANCE.addLog(nextTaskLog);
nextTask.launchTask(success -> {
resultCallback.accept(success);
if (success) {
@@ -2267,21 +2306,23 @@
public void onTasksAppeared(RemoteAnimationTarget[] appearedTaskTargets) {
if (mRecentsAnimationController != null) {
boolean hasStartedTaskBefore = Arrays.stream(appearedTaskTargets).anyMatch(
- targetCompat -> targetCompat.taskId == mGestureState.getLastStartedTaskId());
+ mGestureState.mLastStartedTaskIdPredicate);
if (!mStateCallback.hasStates(STATE_GESTURE_COMPLETED) && !hasStartedTaskBefore) {
// This is a special case, if a task is started mid-gesture that wasn't a part of a
// previous quickswitch task launch, then cancel the animation back to the app
RemoteAnimationTarget appearedTaskTarget = appearedTaskTargets[0];
TaskInfo taskInfo = appearedTaskTarget.taskInfo;
- ActiveGestureLog.INSTANCE.addLog("Unexpected task appeared"
- + " id=" + taskInfo.taskId
- + " pkg=" + taskInfo.baseIntent.getComponent().getPackageName());
+ ActiveGestureLog.INSTANCE.addLog(
+ new ActiveGestureLog.CompoundString("Unexpected task appeared")
+ .append(" id=")
+ .append(taskInfo.taskId)
+ .append(" pkg=")
+ .append(taskInfo.baseIntent.getComponent().getPackageName()));
finishRecentsAnimationOnTasksAppeared(null /* onFinishComplete */);
} else if (handleTaskAppeared(appearedTaskTargets)) {
Optional<RemoteAnimationTarget> taskTargetOptional =
Arrays.stream(appearedTaskTargets)
- .filter(targetCompat ->
- targetCompat.taskId == mGestureState.getLastStartedTaskId())
+ .filter(mGestureState.mLastStartedTaskIdPredicate)
.findFirst();
if (!taskTargetOptional.isPresent()) {
ActiveGestureLog.INSTANCE.addLog("No appeared task matching started task id");
@@ -2350,11 +2391,16 @@
* resume if we finish the controller.
*/
protected int getLastAppearedTaskIndex() {
- return mRecentsView == null
- ? -1
- : mGestureState.getLastAppearedTaskId() != -1
- ? mRecentsView.getTaskIndexForId(mGestureState.getLastAppearedTaskId())
- : mRecentsView.getRunningTaskIndex();
+ if (mRecentsView == null) {
+ return -1;
+ }
+
+ OptionalInt firstValidTaskId = Arrays.stream(mGestureState.getLastAppearedTaskIds())
+ .filter(i -> i != -1)
+ .findFirst();
+ return firstValidTaskId.isPresent()
+ ? mRecentsView.getTaskIndexForId(firstValidTaskId.getAsInt())
+ : mRecentsView.getRunningTaskIndex();
}
/**
@@ -2362,7 +2408,7 @@
* but before that task appeared.
*/
protected boolean hasStartedNewTask() {
- return mGestureState.getLastStartedTaskId() != -1;
+ return mGestureState.getLastStartedTaskIds()[0] != -1;
}
/**
@@ -2406,7 +2452,6 @@
taskViewSimulator.apply(remoteHandle.getTransformParams());
}
}
- ProtoTracer.INSTANCE.get(mContext).scheduleFrameUpdate();
}
// Scaling of RecentsView during quick switch based on amount of recents scroll
@@ -2428,11 +2473,11 @@
if (scrollOffset < mQuickSwitchScaleScrollThreshold) {
scaleProgress = Utilities.mapToRange(scrollOffset, 0, mQuickSwitchScaleScrollThreshold,
- 0, maxScaleProgress, ACCEL_DEACCEL);
+ 0, maxScaleProgress, ACCELERATE_DECELERATE);
} else if (scrollOffset > (maxScrollOffset - mQuickSwitchScaleScrollThreshold)) {
scaleProgress = Utilities.mapToRange(scrollOffset,
(maxScrollOffset - mQuickSwitchScaleScrollThreshold), maxScrollOffset,
- maxScaleProgress, 0, ACCEL_DEACCEL);
+ maxScaleProgress, 0, ACCELERATE_DECELERATE);
}
return scaleProgress;
@@ -2461,7 +2506,7 @@
// "Catch up" with the displacement at mTaskbarCatchUpThreshold.
if (displacement < mTaskbarCatchUpThreshold) {
return Utilities.mapToRange(displacement, mTaskbarAppWindowThreshold,
- mTaskbarCatchUpThreshold, 0, mTaskbarCatchUpThreshold, ACCEL_DEACCEL);
+ mTaskbarCatchUpThreshold, 0, mTaskbarCatchUpThreshold, ACCELERATE_DECELERATE);
}
return displacement;
@@ -2476,26 +2521,6 @@
mRecentsAnimationTargets.nonApps, shown, null /* animatorHandler */);
}
- /**
- * Used for winscope tracing, see launcher_trace.proto
- * @see com.android.systemui.shared.tracing.ProtoTraceable#writeToProto
- * @param inputConsumerProto The parent of this proto message.
- */
- public void writeToProto(InputConsumerProto.Builder inputConsumerProto) {
- SwipeHandlerProto.Builder swipeHandlerProto = SwipeHandlerProto.newBuilder();
-
- mGestureState.writeToProto(swipeHandlerProto);
-
- swipeHandlerProto.setIsRecentsAttachedToAppWindow(
- mAnimationFactory.isRecentsAttachedToAppWindow());
- swipeHandlerProto.setScrollOffset(mRecentsView == null
- ? 0
- : mRecentsView.getScrollOffset());
- swipeHandlerProto.setAppToOverviewProgress(mCurrentShift.value);
-
- inputConsumerProto.setSwipeHandler(swipeHandlerProto);
- }
-
public interface Factory {
AbsSwipeUpHandler newHandler(GestureState gestureState, long touchTimeMs);
}
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 60083c6..3f88139 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -15,11 +15,11 @@
*/
package com.android.quickstep;
+import static com.android.app.animation.Interpolators.ACCELERATE_2;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
-import static com.android.launcher3.anim.Interpolators.ACCEL_2;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.AbsSwipeUpHandler.RECENTS_ATTACH_DURATION;
import static com.android.quickstep.GestureState.GestureEndTarget.LAST_TASK;
import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
@@ -239,7 +239,7 @@
public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect,
PagedOrientationHandler orientedState) {
if (dp.isTablet) {
- if (FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get()) {
+ if (FeatureFlags.enableGridOnlyOverview()) {
calculateGridTaskSize(context, dp, outRect, orientedState);
} else {
calculateFocusTaskSize(context, dp, outRect);
@@ -336,7 +336,7 @@
PagedOrientationHandler orientedState) {
Resources res = context.getResources();
Rect potentialTaskRect = new Rect();
- if (FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get()) {
+ if (FeatureFlags.enableGridOnlyOverview()) {
calculateGridSize(dp, potentialTaskRect);
} else {
calculateFocusTaskSize(context, dp, potentialTaskRect);
@@ -368,7 +368,7 @@
public final void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect,
PagedOrientationHandler orientedState) {
calculateTaskSize(context, dp, outRect, orientedState);
- boolean isGridOnlyOverview = dp.isTablet && FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get();
+ boolean isGridOnlyOverview = dp.isTablet && FeatureFlags.enableGridOnlyOverview();
int claimedSpaceBelow = isGridOnlyOverview
? dp.overviewActionsTopMarginPx + dp.overviewActionsHeight + dp.stashedTaskbarHeight
: (dp.heightPx - outRect.bottom - dp.getInsets().bottom);
@@ -437,11 +437,13 @@
}
protected void runOnInitBackgroundStateUI(Runnable callback) {
- mOnInitBackgroundStateUICallback = callback;
ACTIVITY_TYPE activity = getCreatedActivity();
if (activity != null && activity.getStateManager().getState() == mBackgroundState) {
+ callback.run();
onInitBackgroundStateUI();
+ return;
}
+ mOnInitBackgroundStateUICallback = callback;
}
private void onInitBackgroundStateUI() {
@@ -553,7 +555,7 @@
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.setInterpolator(attached ? INSTANT : ACCELERATE_2);
fadeAnim.setDuration(animationDuration);
animatorSet.play(fadeAnim);
diff --git a/quickstep/src/com/android/quickstep/BinderTracker.java b/quickstep/src/com/android/quickstep/BinderTracker.java
new file mode 100644
index 0000000..a876cd8
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/BinderTracker.java
@@ -0,0 +1,187 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep;
+
+import static android.os.IBinder.FLAG_ONEWAY;
+
+import android.os.Binder;
+import android.os.Binder.ProxyTransactListener;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.Trace;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.util.SafeCloseable;
+import com.android.launcher3.util.TraceHelper;
+
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.function.Consumer;
+
+import kotlin.random.Random;
+
+/**
+ * A binder proxy transaction listener for tracking binder calls on main thread.
+ */
+public class BinderTracker {
+
+ private static final String TAG = "BinderTracker";
+
+ // Common IPCs that are ok to block the main thread.
+ private static final Set<String> sAllowedFrameworkClasses = Set.of(
+ "android.view.IWindowSession",
+ "android.os.IPowerManager",
+ "android.os.IServiceManager");
+
+ /**
+ * Starts tracking binder class and returns a {@link SafeCloseable} to end tracking
+ */
+ public static SafeCloseable startTracking(Consumer<BinderCallSite> callback) {
+ TraceHelper current = TraceHelper.INSTANCE;
+
+ TraceHelperExtension helper = new TraceHelperExtension(callback);
+ TraceHelper.INSTANCE = helper;
+ Binder.setProxyTransactListener(helper);
+
+ return () -> {
+ Binder.setProxyTransactListener(null);
+ TraceHelper.INSTANCE = current;
+ };
+ }
+
+ private static final LinkedList<String> mMainThreadTraceStack = new LinkedList<>();
+ private static final LinkedList<String> mMainThreadIgnoreIpcStack = new LinkedList<>();
+
+ private static class TraceHelperExtension extends TraceHelper implements ProxyTransactListener {
+
+ private final Consumer<BinderCallSite> mUnexpectedTransactionCallback;
+
+ TraceHelperExtension(Consumer<BinderCallSite> unexpectedTransactionCallback) {
+ mUnexpectedTransactionCallback = unexpectedTransactionCallback;
+ }
+
+ @Override
+ public void beginSection(String sectionName) {
+ if (isMainThread()) {
+ mMainThreadTraceStack.add(sectionName);
+ }
+ super.beginSection(sectionName);
+ }
+
+ @Override
+ public SafeCloseable beginAsyncSection(String sectionName) {
+ if (!isMainThread()) {
+ return super.beginAsyncSection(sectionName);
+ }
+
+ mMainThreadTraceStack.add(sectionName);
+ int cookie = Random.Default.nextInt();
+ Trace.beginAsyncSection(sectionName, cookie);
+ return () -> {
+ Trace.endAsyncSection(sectionName, cookie);
+ mMainThreadTraceStack.remove(sectionName);
+ };
+ }
+
+ @Override
+ public void endSection() {
+ super.endSection();
+ if (isMainThread()) {
+ mMainThreadTraceStack.pollLast();
+ }
+ }
+
+ @Override
+ public SafeCloseable allowIpcs(String rpcName) {
+ if (!isMainThread()) {
+ return super.allowIpcs(rpcName);
+ }
+
+ mMainThreadTraceStack.add(rpcName);
+ mMainThreadIgnoreIpcStack.add(rpcName);
+ int cookie = Random.Default.nextInt();
+ Trace.beginAsyncSection(rpcName, cookie);
+ return () -> {
+ Trace.endAsyncSection(rpcName, cookie);
+ mMainThreadTraceStack.remove(rpcName);
+ mMainThreadIgnoreIpcStack.remove(rpcName);
+ };
+ }
+
+ @Override
+ public Object onTransactStarted(IBinder binder, int transactionCode, int flags) {
+ if (!isMainThread() || (flags & FLAG_ONEWAY) == FLAG_ONEWAY) {
+ return null;
+ }
+
+ String ipcBypass = mMainThreadIgnoreIpcStack.peekLast();
+ String descriptor;
+ try {
+ descriptor = binder.getInterfaceDescriptor();
+ if (sAllowedFrameworkClasses.contains(descriptor)) {
+ return null;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error getting IPC descriptor", e);
+ descriptor = binder.getClass().getSimpleName();
+ }
+
+ if (ipcBypass == null) {
+ mUnexpectedTransactionCallback.accept(new BinderCallSite(
+ mMainThreadTraceStack.peekLast(), descriptor, transactionCode));
+ } else {
+ Log.d(TAG, "MainThread-IPC " + descriptor + " ignored due to " + ipcBypass);
+ }
+ return null;
+ }
+
+ @Override
+ public Object onTransactStarted(IBinder binder, int transactionCode) {
+ // Do nothing
+ return null;
+ }
+
+ @Override
+ public void onTransactEnded(Object session) {
+ // Do nothing
+ }
+ }
+
+ private static boolean isMainThread() {
+ return Thread.currentThread() == Looper.getMainLooper().getThread();
+ }
+
+ /**
+ * Information about a binder call
+ */
+ public static class BinderCallSite {
+
+ @Nullable
+ public final String activeTrace;
+ public final String descriptor;
+ public final int transactionCode;
+
+ BinderCallSite(String activeTrace, String descriptor, int transactionCode) {
+ this.activeTrace = activeTrace;
+ this.descriptor = descriptor;
+ this.transactionCode = transactionCode;
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
index eff53f3..c5a88bc 100644
--- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -19,13 +19,13 @@
import static android.content.Intent.EXTRA_COMPONENT_NAME;
import static android.content.Intent.EXTRA_USER;
+import static com.android.app.animation.Interpolators.ACCELERATE;
import static com.android.launcher3.GestureNavContract.EXTRA_GESTURE_CONTRACT;
import static com.android.launcher3.GestureNavContract.EXTRA_ICON_POSITION;
import static com.android.launcher3.GestureNavContract.EXTRA_ICON_SURFACE;
import static com.android.launcher3.GestureNavContract.EXTRA_ON_FINISH_CALLBACK;
import static com.android.launcher3.GestureNavContract.EXTRA_REMOTE_CALLBACK;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.quickstep.OverviewComponentObserver.startHomeIntentSafely;
import android.animation.ObjectAnimator;
@@ -296,7 +296,7 @@
@Override
public AnimatorPlaybackController createActivityAnimationToHome() {
PendingAnimation pa = new PendingAnimation(mDuration);
- pa.setFloat(mRecentsAlpha, AnimatedFloat.VALUE, 0, ACCEL);
+ pa.setFloat(mRecentsAlpha, AnimatedFloat.VALUE, 0, ACCELERATE);
return pa.createPlaybackController();
}
@@ -324,7 +324,7 @@
@Override
public void playAtomicAnimation(float velocity) {
ObjectAnimator alphaAnim = mHomeAlpha.animateToValue(mHomeAlpha.value, 1);
- alphaAnim.setDuration(mDuration).setInterpolator(ACCEL);
+ alphaAnim.setDuration(mDuration).setInterpolator(ACCELERATE);
alphaAnim.start();
if (mRunningOverHome) {
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index 9d7ccb4..49ec85e 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -15,8 +15,9 @@
*/
package com.android.quickstep;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+
import static com.android.launcher3.MotionEventsUtils.isTrackpadFourFingerSwipe;
-import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
import static com.android.launcher3.MotionEventsUtils.isTrackpadThreeFingerSwipe;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
@@ -37,8 +38,6 @@
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StatefulActivity;
-import com.android.launcher3.tracing.GestureStateProto;
-import com.android.launcher3.tracing.SwipeHandlerProto;
import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
import com.android.quickstep.util.ActiveGestureErrorDetector;
import com.android.quickstep.util.ActiveGestureLog;
@@ -46,10 +45,12 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.function.Predicate;
/**
* Manages the state for an active system gesture, listens for events from the system and Launcher,
@@ -58,28 +59,37 @@
@TargetApi(Build.VERSION_CODES.R)
public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationListener {
+ final Predicate<RemoteAnimationTarget> mLastStartedTaskIdPredicate = new Predicate<>() {
+ @Override
+ public boolean test(RemoteAnimationTarget targetCompat) {
+ for (int taskId : mLastStartedTaskId) {
+ if (targetCompat.taskId == taskId) {
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+
/**
* Defines the end targets of a gesture and the associated state.
*/
public enum GestureEndTarget {
- HOME(true, LAUNCHER_STATE_HOME, false, GestureStateProto.GestureEndTarget.HOME),
+ HOME(true, LAUNCHER_STATE_HOME, false),
- RECENTS(true, LAUNCHER_STATE_OVERVIEW, true, GestureStateProto.GestureEndTarget.RECENTS),
+ RECENTS(true, LAUNCHER_STATE_OVERVIEW, true),
- NEW_TASK(false, LAUNCHER_STATE_BACKGROUND, true,
- GestureStateProto.GestureEndTarget.NEW_TASK),
+ NEW_TASK(false, LAUNCHER_STATE_BACKGROUND, true),
- LAST_TASK(false, LAUNCHER_STATE_BACKGROUND, true,
- GestureStateProto.GestureEndTarget.LAST_TASK),
+ LAST_TASK(false, LAUNCHER_STATE_BACKGROUND, true),
- ALL_APPS(true, LAUNCHER_STATE_ALLAPPS, false, GestureStateProto.GestureEndTarget.ALL_APPS);
+ ALL_APPS(true, LAUNCHER_STATE_ALLAPPS, false);
- GestureEndTarget(boolean isLauncher, int containerType, boolean recentsAttachedToAppWindow,
- GestureStateProto.GestureEndTarget protoEndTarget) {
+ GestureEndTarget(boolean isLauncher, int containerType,
+ boolean recentsAttachedToAppWindow) {
this.isLauncher = isLauncher;
this.containerType = containerType;
this.recentsAttachedToAppWindow = recentsAttachedToAppWindow;
- this.protoEndTarget = protoEndTarget;
}
/** Whether the target is in the launcher activity. Implicitly, if the end target is going
@@ -89,8 +99,6 @@
public final int containerType;
/** Whether RecentsView should be attached to the window as we animate to this target */
public final boolean recentsAttachedToAppWindow;
- /** The GestureStateProto enum value, used for winscope tracing. See launcher_trace.proto */
- public final GestureStateProto.GestureEndTarget protoEndTarget;
}
private static final String TAG = "GestureState";
@@ -150,15 +158,10 @@
public enum TrackpadGestureType {
NONE,
- // Assigned before we know whether it's a 3-finger or 4-finger gesture.
- MULTI_FINGER,
THREE_FINGER,
FOUR_FINGER;
public static TrackpadGestureType getTrackpadGestureType(MotionEvent event) {
- if (!isTrackpadMultiFingerSwipe(event)) {
- return TrackpadGestureType.NONE;
- }
if (isTrackpadThreeFingerSwipe(event)) {
return TrackpadGestureType.THREE_FINGER;
}
@@ -166,16 +169,16 @@
return TrackpadGestureType.FOUR_FINGER;
}
- return TrackpadGestureType.MULTI_FINGER;
+ return TrackpadGestureType.NONE;
}
}
private TrackpadGestureType mTrackpadGestureType = TrackpadGestureType.NONE;
private CachedTaskInfo mRunningTask;
private GestureEndTarget mEndTarget;
- private RemoteAnimationTarget mLastAppearedTaskTarget;
+ private RemoteAnimationTarget[] mLastAppearedTaskTargets;
private Set<Integer> mPreviouslyAppearedTaskIds = new HashSet<>();
- private int mLastStartedTaskId = -1;
+ private int[] mLastStartedTaskId = new int[]{INVALID_TASK_ID, INVALID_TASK_ID};
private RecentsAnimationController mRecentsAnimationController;
private HashMap<Integer, ThumbnailData> mRecentsAnimationCanceledSnapshots;
@@ -201,7 +204,7 @@
mGestureId = other.mGestureId;
mRunningTask = other.mRunningTask;
mEndTarget = other.mEndTarget;
- mLastAppearedTaskTarget = other.mLastAppearedTaskTarget;
+ mLastAppearedTaskTargets = other.mLastAppearedTaskTargets;
mPreviouslyAppearedTaskIds = other.mPreviouslyAppearedTaskIds;
mLastStartedTaskId = other.mLastStartedTaskId;
}
@@ -305,10 +308,29 @@
}
/**
- * @return the running task id for this gesture.
+ * @param getMultipleTasks Whether multiple tasks or not are to be returned (for split)
+ * @return the running task ids for this gesture.
*/
- public int getRunningTaskId() {
- return mRunningTask != null ? mRunningTask.getTaskId() : -1;
+ public int[] getRunningTaskIds(boolean getMultipleTasks) {
+ if (mRunningTask == null) {
+ return new int[]{INVALID_TASK_ID, INVALID_TASK_ID};
+ } else {
+ int cachedTasksSize = mRunningTask.mAllCachedTasks.size();
+ int count = Math.min(cachedTasksSize, getMultipleTasks ? 2 : 1);
+ int[] runningTaskIds = new int[count];
+ for (int i = 0; i < count; i++) {
+ runningTaskIds[i] = mRunningTask.mAllCachedTasks.get(i).taskId;
+ }
+ return runningTaskIds;
+ }
+ }
+
+ /**
+ * @see #getRunningTaskIds(boolean)
+ * @return the single top-most running taskId for this gesture
+ */
+ public int getTopRunningTaskId() {
+ return getRunningTaskIds(false /*getMultipleTasks*/)[0];
}
/**
@@ -321,18 +343,26 @@
/**
* Updates the last task that appeared during this gesture.
*/
- public void updateLastAppearedTaskTarget(RemoteAnimationTarget lastAppearedTaskTarget) {
- mLastAppearedTaskTarget = lastAppearedTaskTarget;
- if (lastAppearedTaskTarget != null) {
- mPreviouslyAppearedTaskIds.add(lastAppearedTaskTarget.taskId);
+ public void updateLastAppearedTaskTargets(RemoteAnimationTarget[] lastAppearedTaskTargets) {
+ mLastAppearedTaskTargets = lastAppearedTaskTargets;
+ for (RemoteAnimationTarget target : lastAppearedTaskTargets) {
+ if (target == null) {
+ continue;
+ }
+ mPreviouslyAppearedTaskIds.add(target.taskId);
}
}
/**
* @return The id of the task that appeared during this gesture.
*/
- public int getLastAppearedTaskId() {
- return mLastAppearedTaskTarget != null ? mLastAppearedTaskTarget.taskId : -1;
+ public int[] getLastAppearedTaskIds() {
+ if (mLastAppearedTaskTargets == null) {
+ return new int[]{INVALID_TASK_ID, INVALID_TASK_ID};
+ } else {
+ return Arrays.stream(mLastAppearedTaskTargets)
+ .mapToInt(target -> target != null ? target.taskId : INVALID_TASK_ID).toArray();
+ }
}
public void updatePreviouslyAppearedTaskIds(Set<Integer> previouslyAppearedTaskIds) {
@@ -346,7 +376,7 @@
/**
* Updates the last task that we started via startActivityFromRecents() during this gesture.
*/
- public void updateLastStartedTaskId(int lastStartedTaskId) {
+ public void updateLastStartedTaskIds(int[] lastStartedTaskId) {
mLastStartedTaskId = lastStartedTaskId;
}
@@ -354,7 +384,7 @@
* @return The id of the task that was most recently started during this gesture, or -1 if
* no task has been started yet (i.e. we haven't settled on a new task).
*/
- public int getLastStartedTaskId() {
+ public int[] getLastStartedTaskIds() {
return mLastStartedTaskId;
}
@@ -380,7 +410,8 @@
mEndTarget = target;
mStateCallback.setState(STATE_END_TARGET_SET);
ActiveGestureLog.INSTANCE.addLog(
- /* event= */ "setEndTarget " + mEndTarget,
+ new ActiveGestureLog.CompoundString("setEndTarget ")
+ .append(mEndTarget.name()),
/* gestureEvent= */ SET_END_TARGET);
switch (mEndTarget) {
case HOME:
@@ -490,21 +521,8 @@
pw.println(" gestureID=" + mGestureId);
pw.println(" runningTask=" + mRunningTask);
pw.println(" endTarget=" + mEndTarget);
- pw.println(" lastAppearedTaskTargetId=" + getLastAppearedTaskId());
- pw.println(" lastStartedTaskId=" + mLastStartedTaskId);
+ pw.println(" lastAppearedTaskTargetId=" + Arrays.toString(mLastAppearedTaskTargets));
+ pw.println(" lastStartedTaskId=" + Arrays.toString(mLastStartedTaskId));
pw.println(" isRecentsAnimationRunning=" + isRecentsAnimationRunning());
}
-
- /**
- * Used for winscope tracing, see launcher_trace.proto
- * @see com.android.systemui.shared.tracing.ProtoTraceable#writeToProto
- * @param swipeHandlerProto The parent of this proto message.
- */
- public void writeToProto(SwipeHandlerProto.Builder swipeHandlerProto) {
- GestureStateProto.Builder gestureStateProto = GestureStateProto.newBuilder();
- gestureStateProto.setEndTarget(mEndTarget == null
- ? GestureStateProto.GestureEndTarget.UNSET
- : mEndTarget.protoEndTarget);
- swipeHandlerProto.setGestureState(gestureStateProto);
- }
}
diff --git a/quickstep/src/com/android/quickstep/InputConsumer.java b/quickstep/src/com/android/quickstep/InputConsumer.java
index 6b189cf..23def14 100644
--- a/quickstep/src/com/android/quickstep/InputConsumer.java
+++ b/quickstep/src/com/android/quickstep/InputConsumer.java
@@ -21,9 +21,6 @@
import android.view.KeyEvent;
import android.view.MotionEvent;
-import com.android.launcher3.tracing.InputConsumerProto;
-import com.android.launcher3.tracing.TouchInteractionServiceProto;
-
@TargetApi(Build.VERSION_CODES.O)
public interface InputConsumer {
@@ -42,6 +39,7 @@
int TYPE_TASKBAR_STASH = 1 << 12;
int TYPE_STATUS_BAR = 1 << 13;
int TYPE_CURSOR_HOVER = 1 << 14;
+ int TYPE_NAV_HANDLE_LONG_PRESS = 1 << 15;
String[] NAMES = new String[] {
"TYPE_NO_OP", // 0
@@ -59,6 +57,7 @@
"TYPE_TASKBAR_STASH", // 12
"TYPE_STATUS_BAR", // 13
"TYPE_CURSOR_HOVER", // 14
+ "TYPE_NAV_HANDLE_LONG_PRESS", // 15
};
InputConsumer NO_OP = () -> TYPE_NO_OP;
@@ -127,21 +126,4 @@
}
return name.toString();
}
-
- /**
- * Used for winscope tracing, see launcher_trace.proto
- * @see com.android.systemui.shared.tracing.ProtoTraceable#writeToProto
- * @param serviceProto The parent of this proto message.
- */
- default void writeToProto(TouchInteractionServiceProto.Builder serviceProto) {
- InputConsumerProto.Builder inputConsumerProto = InputConsumerProto.newBuilder();
- inputConsumerProto.setName(getName());
- writeToProtoInternal(inputConsumerProto);
- serviceProto.setInputConsumer(inputConsumerProto);
- }
-
- /**
- * @see #writeToProto - allows subclasses to write additional info to the proto.
- */
- default void writeToProtoInternal(InputConsumerProto.Builder inputConsumerProto) {}
}
diff --git a/quickstep/src/com/android/quickstep/InstantAppResolverImpl.java b/quickstep/src/com/android/quickstep/InstantAppResolverImpl.java
index 7638541..33a2366 100644
--- a/quickstep/src/com/android/quickstep/InstantAppResolverImpl.java
+++ b/quickstep/src/com/android/quickstep/InstantAppResolverImpl.java
@@ -20,6 +20,9 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.os.Process;
+import android.os.UserHandle;
+import android.util.Log;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.util.InstantAppResolver;
@@ -49,4 +52,18 @@
ComponentName cn = info.getTargetComponent();
return cn != null && cn.getClassName().equals(COMPONENT_CLASS_MARKER);
}
+
+ @Override
+ public boolean isInstantApp(String packageName, int userId) {
+ if (!Process.myUserHandle().equals(UserHandle.of(userId))) {
+ // Instant app can only exist on current user
+ return false;
+ }
+ try {
+ return mPM.isInstantApp(packageName);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to determine whether package is instant app " + packageName, e);
+ return false;
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 0e0b022..5784c37 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -15,12 +15,13 @@
*/
package com.android.quickstep;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
+import static com.android.launcher3.LauncherState.FLOATING_SEARCH_BAR;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
@@ -267,7 +268,9 @@
@Override
public boolean allowAllAppsFromOverview() {
- return FeatureFlags.ENABLE_ALL_APPS_FROM_OVERVIEW.get();
+ return FeatureFlags.ENABLE_ALL_APPS_FROM_OVERVIEW.get()
+ // If floating search bar would not show in overview, don't allow all apps gesture.
+ && OVERVIEW.areElementsVisible(getCreatedActivity(), FLOATING_SEARCH_BAR);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
index c18ad5a..1f8ddf0 100644
--- a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
+++ b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
@@ -58,6 +58,8 @@
import com.android.quickstep.util.RectFSpringAnim;
import com.android.systemui.shared.system.QuickStepContract;
+import java.lang.ref.WeakReference;
+
/**
* Controls the animation of swiping back and returning to launcher.
*
@@ -105,7 +107,7 @@
private boolean mAnimatorSetInProgress = false;
private float mBackProgress = 0;
private boolean mBackInProgress = false;
- private IOnBackInvokedCallback mBackCallback;
+ private OnBackInvokedCallbackStub mBackCallback;
private IRemoteAnimationFinishedCallback mAnimationFinishedCallback;
private BackProgressAnimator mProgressAnimator = new BackProgressAnimator();
private SurfaceControl mScrimLayer;
@@ -129,7 +131,7 @@
mWindowMaxDeltaY = mLauncher.getResources().getDimensionPixelSize(
R.dimen.swipe_back_window_max_delta_y);
mCancelInterpolator =
- AnimationUtils.loadInterpolator(mLauncher, R.interpolator.back_cancel);
+ AnimationUtils.loadInterpolator(mLauncher, R.interpolator.standard_interpolator);
}
/**
@@ -137,65 +139,104 @@
* @param handler Handler to the thread to run the animations on.
*/
public void registerBackCallbacks(Handler handler) {
- mBackCallback = new IOnBackInvokedCallback.Stub() {
- @Override
- public void onBackCancelled() {
- handler.post(() -> {
+ mBackCallback = new OnBackInvokedCallbackStub(handler, mProgressAnimator, this);
+ SystemUiProxy.INSTANCE.get(mLauncher).setBackToLauncherCallback(mBackCallback,
+ new RemoteAnimationRunnerStub(this));
+ }
+
+ private static class OnBackInvokedCallbackStub extends IOnBackInvokedCallback.Stub {
+ private Handler mHandler;
+ private BackProgressAnimator mProgressAnimator;
+ // LauncherBackAnimationController has strong reference to Launcher activity, the binder
+ // callback should not hold strong reference to it to avoid memory leak.
+ private WeakReference<LauncherBackAnimationController> mControllerRef;
+
+ private OnBackInvokedCallbackStub(
+ Handler handler,
+ BackProgressAnimator progressAnimator,
+ LauncherBackAnimationController controller) {
+ mHandler = handler;
+ mProgressAnimator = progressAnimator;
+ mControllerRef = new WeakReference<>(controller);
+ }
+
+ @Override
+ public void onBackCancelled() {
+ mHandler.post(() -> {
+ LauncherBackAnimationController controller = mControllerRef.get();
+ if (controller != null) {
mProgressAnimator.onBackCancelled(
- LauncherBackAnimationController.this::resetPositionAnimated);
- });
- }
-
- @Override
- public void onBackInvoked() {
- handler.post(() -> {
- startTransition();
- mProgressAnimator.reset();
- });
- }
-
- @Override
- public void onBackProgressed(BackMotionEvent backEvent) {
- handler.post(() -> {
- mProgressAnimator.onBackProgressed(backEvent);
- });
- }
-
- @Override
- public void onBackStarted(BackMotionEvent backEvent) {
- handler.post(() -> {
- startBack(backEvent);
- mProgressAnimator.onBackStarted(backEvent, event -> {
- mBackProgress = event.getProgress();
- // TODO: Update once the interpolation curve spec is finalized.
- mBackProgress =
- 1 - (1 - mBackProgress) * (1 - mBackProgress) * (1
- - mBackProgress);
- updateBackProgress(mBackProgress, event);
- });
- });
- }
- };
-
- final IRemoteAnimationRunner runner = new IRemoteAnimationRunner.Stub() {
- @Override
- public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
- RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
- IRemoteAnimationFinishedCallback finishedCallback) {
- for (final RemoteAnimationTarget target : apps) {
- if (MODE_CLOSING == target.mode) {
- mBackTarget = target;
- break;
- }
+ controller::resetPositionAnimated);
}
- mAnimationFinishedCallback = finishedCallback;
+ });
+ }
+
+ @Override
+ public void onBackInvoked() {
+ mHandler.post(() -> {
+ LauncherBackAnimationController controller = mControllerRef.get();
+ if (controller != null) {
+ controller.startTransition();
+ }
+ mProgressAnimator.reset();
+ });
+ }
+
+ @Override
+ public void onBackProgressed(BackMotionEvent backMotionEvent) {
+ mHandler.post(() -> {
+ mProgressAnimator.onBackProgressed(backMotionEvent);
+ });
+ }
+
+ @Override
+ public void onBackStarted(BackMotionEvent backEvent) {
+ mHandler.post(() -> {
+ LauncherBackAnimationController controller = mControllerRef.get();
+ if (controller != null) {
+ controller.startBack(backEvent);
+ mProgressAnimator.onBackStarted(backEvent, event -> {
+ float backProgress = event.getProgress();
+ // TODO: Update once the interpolation curve spec is finalized.
+ controller.mBackProgress =
+ 1 - (1 - backProgress) * (1 - backProgress) * (1
+ - backProgress);
+ controller.updateBackProgress(controller.mBackProgress, event);
+ });
+ }
+ });
+ }
+ }
+
+ private static class RemoteAnimationRunnerStub extends IRemoteAnimationRunner.Stub {
+
+ // LauncherBackAnimationController has strong reference to Launcher activity, the binder
+ // callback should not hold strong reference to it to avoid memory leak.
+ private WeakReference<LauncherBackAnimationController> mControllerRef;
+
+ private RemoteAnimationRunnerStub(LauncherBackAnimationController controller) {
+ mControllerRef = new WeakReference<>(controller);
+ }
+
+ @Override
+ public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
+ RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
+ IRemoteAnimationFinishedCallback finishedCallback) {
+ LauncherBackAnimationController controller = mControllerRef.get();
+ if (controller == null) {
+ return;
}
+ for (final RemoteAnimationTarget target : apps) {
+ if (MODE_CLOSING == target.mode) {
+ controller.mBackTarget = target;
+ break;
+ }
+ }
+ controller.mAnimationFinishedCallback = finishedCallback;
+ }
- @Override
- public void onAnimationCancelled() {}
- };
-
- SystemUiProxy.INSTANCE.get(mLauncher).setBackToLauncherCallback(mBackCallback, runner);
+ @Override
+ public void onAnimationCancelled() {}
}
private void resetPositionAnimated() {
@@ -363,12 +404,16 @@
AbstractFloatingView.closeAllOpenViewsExcept(mLauncher, false, TYPE_REBIND_SAFE);
float cornerRadius = Utilities.mapRange(
mBackProgress, mWindowScaleStartCornerRadius, mWindowScaleEndCornerRadius);
+ final RectF resolveRectF = new RectF();
+ mQuickstepTransitionManager.transferRectToTargetCoordinate(
+ mBackTarget, mCurrentRect, true, resolveRectF);
+
Pair<RectFSpringAnim, AnimatorSet> pair =
mQuickstepTransitionManager.createWallpaperOpenAnimations(
new RemoteAnimationTarget[]{mBackTarget},
new RemoteAnimationTarget[0],
false /* fromUnlock */,
- mCurrentRect,
+ resolveRectF,
cornerRadius,
mBackInProgress /* fromPredictiveBack */);
startTransitionAnimations(pair.first, pair.second);
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index fd5c1a7..a9d8afc 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -15,10 +15,10 @@
*/
package com.android.quickstep;
+import static com.android.app.animation.Interpolators.EXAGGERATED_EASE;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.Utilities.mapBoundToRange;
-import static com.android.launcher3.anim.Interpolators.EXAGGERATED_EASE;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import static com.android.launcher3.views.FloatingIconView.getFloatingIconView;
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 07db194..833bf5f 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -37,7 +37,6 @@
import com.android.launcher3.taskbar.TaskbarUIController;
import com.android.launcher3.util.RunnableList;
import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
-import com.android.quickstep.views.DesktopTaskView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -79,6 +78,14 @@
*/
private int mTaskFocusIndexOverride = -1;
+ /**
+ * Whether we should incoming toggle commands while a previous toggle command is still ongoing.
+ * This serves as a rate-limiter to prevent overlapping animations that can clobber each other
+ * and prevent clean-up callbacks from running. This thus prevents a recurring set of bugs with
+ * janky recents animations and unresponsive home and overview buttons.
+ */
+ private boolean mWaitForToggleCommandComplete = false;
+
public OverviewCommandHelper(TouchInteractionService service,
OverviewComponentObserver observer,
TaskAnimationManager taskAnimationManager) {
@@ -141,6 +148,11 @@
mPendingCommands.clear();
}
+ @UiThread
+ public boolean canStartHomeSafely() {
+ return mPendingCommands.isEmpty() || mPendingCommands.get(0).type == TYPE_HOME;
+ }
+
@Nullable
private TaskView getNextTask(RecentsView view) {
final TaskView runningTaskView = view.getRunningTaskView();
@@ -156,15 +168,20 @@
private boolean launchTask(RecentsView recents, @Nullable TaskView taskView, CommandInfo cmd) {
RunnableList callbackList = null;
if (taskView != null) {
+ mWaitForToggleCommandComplete = true;
taskView.setEndQuickswitchCuj(true);
callbackList = taskView.launchTasks();
}
if (callbackList != null) {
- callbackList.add(() -> scheduleNextTask(cmd));
+ callbackList.add(() -> {
+ scheduleNextTask(cmd);
+ mWaitForToggleCommandComplete = false;
+ });
return false;
} else {
recents.startHome();
+ mWaitForToggleCommandComplete = false;
return true;
}
}
@@ -174,6 +191,9 @@
* task is deferred until {@link #scheduleNextTask} is called
*/
private <T extends StatefulActivity<?>> boolean executeCommand(CommandInfo cmd) {
+ if (mWaitForToggleCommandComplete && cmd.type == TYPE_TOGGLE) {
+ return true;
+ }
BaseActivityInterface<?, T> activityInterface =
mOverviewComponentObserver.getActivityInterface();
RecentsView recents = activityInterface.getVisibleRecentsView();
@@ -186,11 +206,6 @@
&& dp != null
&& (dp.isTablet || dp.isTwoPanels);
- if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
- // TODO(b/268075592): add support for quickswitch to/from desktop
- allowQuickSwitch = false;
- }
-
if (cmd.type == TYPE_HIDE) {
if (!allowQuickSwitch) {
return true;
@@ -360,6 +375,7 @@
pw.println(" pendingCommandType=" + mPendingCommands.get(0).type);
}
pw.println(" mTaskFocusIndexOverride=" + mTaskFocusIndexOverride);
+ pw.println(" mWaitForToggleCommandComplete=" + mWaitForToggleCommandComplete);
}
private static class CommandInfo {
diff --git a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
index a8f3c3a..60713cf 100644
--- a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
+++ b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
@@ -38,8 +38,6 @@
import androidx.annotation.Nullable;
import com.android.launcher3.R;
-import com.android.launcher3.tracing.OverviewComponentObserverProto;
-import com.android.launcher3.tracing.TouchInteractionServiceProto;
import com.android.launcher3.util.SimpleBroadcastReceiver;
import com.android.systemui.shared.system.PackageManagerWrapper;
@@ -276,19 +274,6 @@
}
/**
- * Used for winscope tracing, see launcher_trace.proto
- * @see com.android.systemui.shared.tracing.ProtoTraceable#writeToProto
- * @param serviceProto The parent of this proto message.
- */
- public void writeToProto(TouchInteractionServiceProto.Builder serviceProto) {
- OverviewComponentObserverProto.Builder overviewComponentObserver =
- OverviewComponentObserverProto.newBuilder();
- overviewComponentObserver.setOverviewActivityStarted(mActivityInterface.isStarted());
- overviewComponentObserver.setOverviewActivityResumed(mActivityInterface.isResumed());
- serviceProto.setOverviewComponentObvserver(overviewComponentObserver);
- }
-
- /**
* Starts the intent for the current home activity.
*/
public static void startHomeIntentSafely(@NonNull Context context, @Nullable Bundle options) {
diff --git a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
index 5f589bf..d1939ef 100644
--- a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
+++ b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
@@ -19,6 +19,8 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
+import android.os.Looper;
+import android.os.Trace;
import android.os.UserManager;
import android.util.Log;
import android.view.ThreadedRenderer;
@@ -60,5 +62,14 @@
// Elevate GPU priority for Quickstep and Remote animations.
ThreadedRenderer.setContextPriority(
ThreadedRenderer.EGL_CONTEXT_PRIORITY_HIGH_IMG);
+
+ // Enable Looper trace points.
+ // This allows us to see Handler callbacks on traces.
+ Looper.getMainLooper().setTraceTag(Trace.TRACE_TAG_APP);
+
+ if (BuildConfig.IS_STUDIO_BUILD) {
+ BinderTracker.startTracking(call -> Log.e("BinderCall",
+ call.descriptor + " called on mainthread under " + call.activeTrace));
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
index 4c9cf8b..9be9294 100644
--- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -44,9 +44,7 @@
}
case TestProtocol.REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT: {
- final float swipeHeight =
- LayoutUtils.getShelfTrackingDistance(mContext, mDeviceProfile,
- PagedOrientationHandler.PORTRAIT);
+ final float swipeHeight = mDeviceProfile.heightPx / 2f;
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
return response;
}
@@ -80,8 +78,7 @@
}
case TestProtocol.REQUEST_HAS_TIS: {
- response.putBoolean(
- TestProtocol.REQUEST_HAS_TIS, true);
+ response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD, true);
return response;
}
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index 38ac5bb..0a7344a 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -17,7 +17,8 @@
package com.android.quickstep;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-import static com.android.quickstep.views.DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED;
+import static com.android.quickstep.util.SplitScreenUtils.convertShellSplitBoundsToLauncher;
+import static com.android.quickstep.views.DesktopTaskView.DESKTOP_MODE_SUPPORTED;
import static com.android.wm.shell.util.GroupedRecentTaskInfo.TYPE_FREEFORM;
import android.annotation.TargetApi;
@@ -39,7 +40,6 @@
import com.android.systemui.shared.recents.model.Task;
import com.android.wm.shell.recents.IRecentTasksListener;
import com.android.wm.shell.util.GroupedRecentTaskInfo;
-import com.android.wm.shell.util.SplitBounds;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -270,7 +270,7 @@
TaskLoadResult allTasks = new TaskLoadResult(requestId, loadKeysOnly, rawTasks.size());
for (GroupedRecentTaskInfo rawTask : rawTasks) {
- if (DESKTOP_IS_PROTO2_ENABLED && rawTask.getType() == TYPE_FREEFORM) {
+ if (DESKTOP_MODE_SUPPORTED && rawTask.getType() == TYPE_FREEFORM) {
GroupTask desktopTask = createDesktopTask(rawTask);
allTasks.add(desktopTask);
continue;
@@ -293,7 +293,7 @@
task2.setLastSnapshotData(taskInfo2);
}
final SplitConfigurationOptions.SplitBounds launcherSplitBounds =
- convertSplitBounds(rawTask.getSplitBounds());
+ convertShellSplitBoundsToLauncher(rawTask.getSplitBounds());
allTasks.add(new GroupTask(task1, task2, launcherSplitBounds));
}
@@ -308,21 +308,11 @@
task.setLastSnapshotData(taskInfo);
task.positionInParent = taskInfo.positionInParent;
task.appBounds = taskInfo.configuration.windowConfiguration.getAppBounds();
- // TODO(b/244348395): tasks should be sorted from oldest to most recently used
tasks.add(task);
}
return new DesktopTask(tasks);
}
- private SplitConfigurationOptions.SplitBounds convertSplitBounds(
- SplitBounds shellSplitBounds) {
- return shellSplitBounds == null ?
- null :
- new SplitConfigurationOptions.SplitBounds(
- shellSplitBounds.leftTopBounds, shellSplitBounds.rightBottomBounds,
- shellSplitBounds.leftTopTaskId, shellSplitBounds.rightBottomTaskId);
- }
-
private ArrayList<GroupTask> copyOf(ArrayList<GroupTask> tasks) {
ArrayList<GroupTask> newTasks = new ArrayList<>();
for (int i = 0; i < tasks.size(); i++) {
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 39af7fd..d66421f 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -22,7 +22,6 @@
import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.QuickstepTransitionManager.STATUS_BAR_TRANSITION_DURATION;
import static com.android.launcher3.QuickstepTransitionManager.STATUS_BAR_TRANSITION_PRE_DELAY;
-import static com.android.launcher3.graphics.SysUiScrim.SYSUI_PROGRESS;
import static com.android.launcher3.testing.shared.TestProtocol.OVERVIEW_STATE_ORDINAL;
import static com.android.quickstep.OverviewComponentObserver.startHomeIntentSafely;
import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
@@ -38,6 +37,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Trace;
+import android.util.Log;
import android.view.Display;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
@@ -46,8 +46,10 @@
import android.window.RemoteTransition;
import android.window.SplashScreen;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
@@ -56,7 +58,6 @@
import com.android.launcher3.LauncherAnimationRunner.RemoteAnimationFactory;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.model.data.ItemInfo;
@@ -66,6 +67,7 @@
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.taskbar.FallbackTaskbarUIController;
import com.android.launcher3.taskbar.TaskbarManager;
+import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.ActivityTracker;
import com.android.launcher3.util.RunnableList;
@@ -107,7 +109,6 @@
private FallbackRecentsView mFallbackRecentsView;
private OverviewActionsView mActionsView;
private TISBindHelper mTISBindHelper;
- private @Nullable TaskbarManager mTaskbarManager;
private @Nullable FallbackTaskbarUIController mTaskbarUIController;
private StateManager<RecentsState> mStateManager;
@@ -119,6 +120,7 @@
// animation callback
private final Handler mHandler = new Handler();
private final Runnable mAnimationStartTimeoutRunnable = this::onAnimationStartTimeout;
+ private SplitSelectStateController mSplitSelectStateController;
/**
* Init drag layer and overview panel views.
@@ -130,22 +132,22 @@
mScrimView = findViewById(R.id.scrim_view);
mFallbackRecentsView = findViewById(R.id.overview_panel);
mActionsView = findViewById(R.id.overview_actions_view);
- SYSUI_PROGRESS.set(getRootView().getSysUiScrim(), 0f);
-
- SplitSelectStateController controller =
+ getRootView().getSysUiScrim().getSysUIProgress().updateValue(0);
+ mSplitSelectStateController =
new SplitSelectStateController(this, mHandler, getStateManager(),
- null /* depthController */, getStatsLogManager(),
- SystemUiProxy.INSTANCE.get(this), RecentsModel.INSTANCE.get(this));
+ null /* depthController */, getStatsLogManager(),
+ SystemUiProxy.INSTANCE.get(this), RecentsModel.INSTANCE.get(this),
+ null /*activityBackCallback*/);
mDragLayer.recreateControllers();
- mFallbackRecentsView.init(mActionsView, controller);
+ mFallbackRecentsView.init(mActionsView, mSplitSelectStateController);
mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
}
private void onTISConnected(TouchInteractionService.TISBinder binder) {
- mTaskbarManager = binder.getTaskbarManager();
- if (mTaskbarManager != null) {
- mTaskbarManager.setActivity(this);
+ TaskbarManager taskbarManager = binder.getTaskbarManager();
+ if (taskbarManager != null) {
+ taskbarManager.setActivity(this);
}
}
@@ -241,6 +243,11 @@
}
final TaskView taskView = (TaskView) v;
+ final RecentsView recentsView = taskView.getRecentsView();
+ if (recentsView == null) {
+ return super.getActivityLaunchOptions(v, item);
+ }
+
RunnableList onEndCallback = new RunnableList();
mActivityLaunchAnimationRunner = new RemoteAnimationFactory() {
@@ -249,7 +256,7 @@
RemoteAnimationTarget[] wallpaperTargets,
RemoteAnimationTarget[] nonAppTargets, AnimationResult result) {
mHandler.removeCallbacks(mAnimationStartTimeoutRunnable);
- AnimatorSet anim = composeRecentsLaunchAnimator(taskView, appTargets,
+ AnimatorSet anim = composeRecentsLaunchAnimator(recentsView, taskView, appTargets,
wallpaperTargets, nonAppTargets);
anim.addListener(resetStateListener());
result.setAnimation(anim, RecentsActivity.this, onEndCallback::executeAllAndDestroy,
@@ -277,6 +284,8 @@
activityOptions.options.setLaunchDisplayId(
(v != null && v.getDisplay() != null) ? v.getDisplay().getDisplayId()
: Display.DEFAULT_DISPLAY);
+ activityOptions.options.setPendingIntentBackgroundActivityStartMode(
+ ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
mHandler.postDelayed(mAnimationStartTimeoutRunnable, RECENTS_ANIMATION_TIMEOUT);
return activityOptions;
}
@@ -284,14 +293,16 @@
/**
* Composes the animations for a launch from the recents list if possible.
*/
- private AnimatorSet composeRecentsLaunchAnimator(TaskView taskView,
+ private AnimatorSet composeRecentsLaunchAnimator(
+ @NonNull RecentsView recentsView,
+ @NonNull TaskView taskView,
RemoteAnimationTarget[] appTargets,
RemoteAnimationTarget[] wallpaperTargets,
RemoteAnimationTarget[] nonAppTargets) {
AnimatorSet target = new AnimatorSet();
boolean activityClosing = taskIsATargetWithMode(appTargets, getTaskId(), MODE_CLOSING);
PendingAnimation pa = new PendingAnimation(RECENTS_LAUNCH_DURATION);
- createRecentsWindowAnimator(taskView, !activityClosing, appTargets,
+ createRecentsWindowAnimator(recentsView, taskView, !activityClosing, appTargets,
wallpaperTargets, nonAppTargets, null /* depthController */, pa);
target.play(pa.buildAnim());
@@ -299,7 +310,7 @@
if (activityClosing) {
Animator adjacentAnimation = mFallbackRecentsView
.createAdjacentPageAnimForTaskLaunch(taskView);
- adjacentAnimation.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
+ adjacentAnimation.setInterpolator(Interpolators.TOUCH_RESPONSE);
adjacentAnimation.setDuration(RECENTS_LAUNCH_DURATION);
adjacentAnimation.addListener(resetStateListener());
target.play(adjacentAnimation);
@@ -384,11 +395,8 @@
super.onDestroy();
ACTIVITY_TRACKER.onActivityDestroyed(this);
mActivityLaunchAnimationRunner = null;
-
+ mSplitSelectStateController.onDestroy();
mTISBindHelper.onDestroy();
- if (mTaskbarManager != null) {
- mTaskbarManager.clearActivity(this);
- }
}
@Override
@@ -398,6 +406,7 @@
}
public void startHome() {
+ Log.d(TestProtocol.INCORRECT_HOME_STATE, "start home from recents activity");
RecentsView recentsView = getOverviewPanel();
recentsView.switchToScreenshot(() -> recentsView.finishRecentsAnimation(true,
this::startHomeInternal));
@@ -471,4 +480,9 @@
}
};
}
+
+ public boolean canStartHomeSafely() {
+ OverviewCommandHelper overviewCommandHelper = mTISBindHelper.getOverviewCommandHelper();
+ return overviewCommandHelper == null || overviewCommandHelper.canStartHomeSafely();
+ }
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
index 2256cbf..3d332c2 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
@@ -19,10 +19,12 @@
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.CANCEL_RECENTS_ANIMATION;
-import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.START_RECENTS_ANIMATION;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.ON_CANCEL_RECENTS_ANIMATION;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.ON_FINISH_RECENTS_ANIMATION;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.ON_START_RECENTS_ANIMATION;
import android.graphics.Rect;
+import android.os.Bundle;
import android.util.ArraySet;
import android.view.RemoteAnimationTarget;
@@ -92,9 +94,9 @@
@Deprecated
public final void onAnimationStart(RecentsAnimationControllerCompat controller,
RemoteAnimationTarget[] appTargets, Rect homeContentInsets,
- Rect minimizedHomeBounds) {
+ Rect minimizedHomeBounds, Bundle extras) {
onAnimationStart(controller, appTargets, new RemoteAnimationTarget[0],
- homeContentInsets, minimizedHomeBounds);
+ homeContentInsets, minimizedHomeBounds, extras);
}
// Called only in R+ platform
@@ -102,7 +104,7 @@
public final void onAnimationStart(RecentsAnimationControllerCompat animationController,
RemoteAnimationTarget[] appTargets,
RemoteAnimationTarget[] wallpaperTargets,
- Rect homeContentInsets, Rect minimizedHomeBounds) {
+ Rect homeContentInsets, Rect minimizedHomeBounds, Bundle extras) {
long appCount = Arrays.stream(appTargets)
.filter(app -> app.mode == MODE_CLOSING)
.count();
@@ -111,7 +113,7 @@
ActiveGestureLog.INSTANCE.addLog(
/* event= */ "RecentsAnimationCallbacks.onAnimationStart (canceled)",
/* extras= */ 0,
- /* gestureEvent= */ START_RECENTS_ANIMATION);
+ /* gestureEvent= */ ON_START_RECENTS_ANIMATION);
notifyAnimationCanceled();
animationController.finish(false /* toHome */, false /* sendUserLeaveHint */);
return;
@@ -137,13 +139,14 @@
nonAppTargets = new RemoteAnimationTarget[0];
}
final RecentsAnimationTargets targets = new RecentsAnimationTargets(appTargets,
- wallpaperTargets, nonAppTargets, homeContentInsets, minimizedHomeBounds);
+ wallpaperTargets, nonAppTargets, homeContentInsets, minimizedHomeBounds,
+ extras);
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
ActiveGestureLog.INSTANCE.addLog(
/* event= */ "RecentsAnimationCallbacks.onAnimationStart",
/* extras= */ targets.apps.length,
- /* gestureEvent= */ START_RECENTS_ANIMATION);
+ /* gestureEvent= */ ON_START_RECENTS_ANIMATION);
for (RecentsAnimationListener listener : getListeners()) {
listener.onRecentsAnimationStart(mController, targets);
}
@@ -157,7 +160,7 @@
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
ActiveGestureLog.INSTANCE.addLog(
/* event= */ "RecentsAnimationCallbacks.onAnimationCanceled",
- /* gestureEvent= */ CANCEL_RECENTS_ANIMATION);
+ /* gestureEvent= */ ON_CANCEL_RECENTS_ANIMATION);
for (RecentsAnimationListener listener : getListeners()) {
listener.onRecentsAnimationCanceled(thumbnailDatas);
}
@@ -191,7 +194,8 @@
private final void onAnimationFinished(RecentsAnimationController controller) {
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
ActiveGestureLog.INSTANCE.addLog(
- /* event= */ "RecentsAnimationCallbacks.onAnimationFinished");
+ /* event= */ "RecentsAnimationCallbacks.onAnimationFinished",
+ ON_FINISH_RECENTS_ANIMATION);
for (RecentsAnimationListener listener : getListeners()) {
listener.onRecentsAnimationFinished(controller);
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
index f8e09e1..8972dc8 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
@@ -115,8 +115,8 @@
* {@link RecentsAnimationCallbacks#onTasksAppeared}}.
*/
@UiThread
- public void removeTaskTarget(@NonNull RemoteAnimationTarget target) {
- UI_HELPER_EXECUTOR.execute(() -> mController.removeTask(target.taskId));
+ public void removeTaskTarget(int targetTaskId) {
+ UI_HELPER_EXECUTOR.execute(() -> mController.removeTask(targetTaskId));
}
@UiThread
@@ -167,7 +167,6 @@
/* event= */ "finishRecentsAnimation",
/* extras= */ toRecents,
/* gestureEvent= */ FINISH_RECENTS_ANIMATION);
-
// Finish not yet requested
mFinishRequested = true;
mFinishTargetIsLauncher = toRecents;
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 64ec1d8..1448a52 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -17,7 +17,6 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.content.Intent.ACTION_USER_UNLOCKED;
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
@@ -52,10 +51,8 @@
import android.graphics.Region;
import android.inputmethodservice.InputMethodService;
import android.net.Uri;
-import android.os.Process;
import android.os.RemoteException;
import android.os.SystemProperties;
-import android.os.UserManager;
import android.provider.Settings;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
@@ -68,7 +65,6 @@
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;
@@ -116,15 +112,6 @@
private final boolean mIsOneHandedModeSupported;
private boolean mPipIsActive;
- private boolean mIsUserUnlocked;
- private final ArrayList<Runnable> mUserUnlockedActions = new ArrayList<>();
- 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();
private SystemGestureExclusionListenerCompat mExclusionListener;
@@ -150,14 +137,6 @@
runOnDestroy(mRotationTouchHelper::destroy);
}
- // Register for user unlocked if necessary
- mIsUserUnlocked = context.getSystemService(UserManager.class)
- .isUserUnlocked(Process.myUserHandle());
- if (!mIsUserUnlocked) {
- mUserUnlockedReceiver.register(mContext, ACTION_USER_UNLOCKED);
- }
- runOnDestroy(() -> mUserUnlockedReceiver.unregisterReceiverSafely(mContext));
-
// Register for exclusion updates
mExclusionListener = new SystemGestureExclusionListenerCompat(mDisplayId) {
@Override
@@ -317,39 +296,12 @@
}
/**
- * Adds a callback for when a user is unlocked. If the user is already unlocked, this listener
- * will be called back immediately.
- */
- public void runOnUserUnlocked(Runnable action) {
- if (mIsUserUnlocked) {
- action.run();
- } else {
- mUserUnlockedActions.add(action);
- }
- }
-
- /**
- * @return whether the user is unlocked.
- */
- public boolean isUserUnlocked() {
- return mIsUserUnlocked;
- }
-
- /**
* @return whether the user has completed setup wizard
*/
public boolean isUserSetupComplete() {
return mIsUserSetupComplete;
}
- private void notifyUserUnlocked() {
- for (Runnable action : mUserUnlockedActions) {
- action.run();
- }
- mUserUnlockedActions.clear();
- mUserUnlockedReceiver.unregisterReceiverSafely(mContext);
- }
-
/**
* Sets the task id where gestures should be blocked
*/
@@ -386,8 +338,16 @@
boolean canStartWithNavHidden = (mSystemUiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) == 0
|| (mSystemUiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0
|| mRotationTouchHelper.isTaskListFrozen();
- return canStartWithNavHidden
- && (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0
+ return canStartWithNavHidden && canStartTrackpadGesture();
+ }
+
+ /**
+ * @return whether SystemUI is in a state where we can start a system gesture from the trackpad.
+ * Trackpad gestures can start even when the nav bar / task bar is hidden in sticky immersive
+ * mode.
+ */
+ public boolean canStartTrackpadGesture() {
+ return (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0
&& (mSystemUiStateFlags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING) == 0
&& (mSystemUiStateFlags & SYSUI_STATE_QUICK_SETTINGS_EXPANDED) == 0
&& (mSystemUiStateFlags & SYSUI_STATE_MAGNIFICATION_OVERLAP) == 0
@@ -607,7 +567,6 @@
pw.println(" assistantAvailable=" + mAssistantAvailable);
pw.println(" assistantDisabled="
+ QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags));
- pw.println(" isUserUnlocked=" + mIsUserUnlocked);
pw.println(" isOneHandedModeEnabled=" + mIsOneHandedModeEnabled);
pw.println(" isSwipeToNotificationEnabled=" + mIsSwipeToNotificationEnabled);
pw.println(" deferredGestureRegion=" + mDeferredGestureRegion.getBounds());
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java b/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java
index 15e1365..67c56e3 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java
@@ -20,6 +20,7 @@
import android.app.WindowConfiguration;
import android.graphics.Rect;
+import android.os.Bundle;
import android.view.RemoteAnimationTarget;
import com.android.quickstep.views.DesktopTaskView;
@@ -35,8 +36,8 @@
public RecentsAnimationTargets(RemoteAnimationTarget[] apps,
RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
- Rect homeContentInsets, Rect minimizedHomeBounds) {
- super(apps, wallpapers, nonApps, MODE_CLOSING);
+ Rect homeContentInsets, Rect minimizedHomeBounds, Bundle extras) {
+ super(apps, wallpapers, nonApps, MODE_CLOSING, extras);
this.homeContentInsets = homeContentInsets;
this.minimizedHomeBounds = minimizedHomeBounds;
}
diff --git a/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java b/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java
index 80aaad0..e0c7403 100644
--- a/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java
+++ b/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
+import android.os.Bundle;
import android.view.RemoteAnimationTarget;
import java.util.ArrayList;
@@ -35,6 +36,7 @@
public final RemoteAnimationTarget[] apps;
public final RemoteAnimationTarget[] wallpapers;
public final RemoteAnimationTarget[] nonApps;
+ public final Bundle extras;
public final int targetMode;
public final boolean hasRecents;
@@ -42,7 +44,7 @@
public RemoteAnimationTargets(RemoteAnimationTarget[] apps,
RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
- int targetMode) {
+ int targetMode, Bundle extras) {
ArrayList<RemoteAnimationTarget> filteredApps = new ArrayList<>();
boolean hasRecents = false;
if (apps != null) {
@@ -61,6 +63,13 @@
this.targetMode = targetMode;
this.hasRecents = hasRecents;
this.nonApps = nonApps;
+ this.extras = extras;
+ }
+
+ public RemoteAnimationTargets(RemoteAnimationTarget[] apps,
+ RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
+ int targetMode) {
+ this(apps, wallpapers, nonApps, targetMode, new Bundle());
}
public RemoteAnimationTarget findTask(int taskId) {
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index 84246e9..3af5ab7 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -16,7 +16,9 @@
package com.android.quickstep;
-import android.app.WindowConfiguration;
+import static com.android.quickstep.util.SplitScreenUtils.convertShellSplitBoundsToLauncher;
+import static com.android.wm.shell.util.SplitBounds.KEY_EXTRA_SPLIT_BOUNDS;
+
import android.content.Context;
import android.graphics.Rect;
import android.util.Log;
@@ -24,11 +26,12 @@
import androidx.annotation.Nullable;
-import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds;
+import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.views.DesktopTaskView;
+import com.android.wm.shell.util.SplitBounds;
import java.util.ArrayList;
import java.util.Arrays;
@@ -43,7 +46,7 @@
private static final int DEFAULT_NUM_HANDLES = 2;
private RemoteTargetHandle[] mRemoteTargetHandles;
- private SplitBounds mSplitBounds;
+ private SplitConfigurationOptions.SplitBounds mSplitBounds;
/**
* Use this constructor if remote targets are split-screen independent
@@ -111,6 +114,16 @@
}
/**
+ * Calls {@link #assignTargetsForSplitScreen(RemoteAnimationTargets)} with SplitBounds
+ * information specified.
+ */
+ public RemoteTargetHandle[] assignTargetsForSplitScreen(RemoteAnimationTargets targets,
+ SplitConfigurationOptions.SplitBounds splitBounds) {
+ mSplitBounds = splitBounds;
+ return assignTargetsForSplitScreen(targets);
+ }
+
+ /**
* Similar to {@link #assignTargets(RemoteAnimationTargets)}, except this assigns the
* apps in {@code targets.apps} to the {@link #mRemoteTargetHandles} with index 0 will being
* the left/top task, index 1 right/bottom.
@@ -129,10 +142,17 @@
mRemoteTargetHandles = newHandles;
}
- boolean containsSplitTargets = Arrays.stream(targets.apps)
- .anyMatch(remoteAnimationTarget ->
- remoteAnimationTarget.windowConfiguration.getWindowingMode()
- == WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
+ // If we are in a true split screen case (2 apps running on screen), either:
+ // a) mSplitBounds was already set (from the clicked GroupedTaskView)
+ // b) A SplitBounds was passed up from shell (via AbsSwipeUpHandler)
+ // If both of these are null, we are in a 1-app or 1-app-plus-assistant case.
+ if (mSplitBounds == null) {
+ SplitBounds shellSplitBounds = targets.extras.getParcelable(KEY_EXTRA_SPLIT_BOUNDS,
+ SplitBounds.class);
+ mSplitBounds = convertShellSplitBoundsToLauncher(shellSplitBounds);
+ }
+
+ boolean containsSplitTargets = mSplitBounds != null;
Log.d(TAG, "containsSplitTargets? " + containsSplitTargets + " handleLength: " +
mRemoteTargetHandles.length + " appsLength: " + targets.apps.length);
@@ -154,40 +174,12 @@
}
} else {
// Split apps (+ maybe assistant)
- RemoteAnimationTarget topLeftTarget = Arrays.stream(targets.apps)
- .filter(remoteAnimationTarget ->
- remoteAnimationTarget.windowConfiguration.getWindowingMode()
- == WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW)
- .findFirst().get();
-
- // Fetch the adjacent target for split screen.
- RemoteAnimationTarget bottomRightTarget = null;
- for (int i = 0; i < targets.apps.length; i++) {
- final RemoteAnimationTarget target = targets.apps[i];
- if (target.windowConfiguration.getWindowingMode() !=
- WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW ||
- target == topLeftTarget) {
- continue;
- }
- Rect topLeftBounds = getStartBounds(topLeftTarget);
- Rect bounds = getStartBounds(target);
- if (topLeftBounds.left > bounds.right || topLeftBounds.top > bounds.bottom) {
- bottomRightTarget = topLeftTarget;
- topLeftTarget = target;
- break;
- } else if (topLeftBounds.right < bounds.left || topLeftBounds.bottom < bounds.top) {
- bottomRightTarget = target;
- break;
- }
- }
+ RemoteAnimationTarget topLeftTarget = targets.findTask(mSplitBounds.leftTopTaskId);
+ RemoteAnimationTarget bottomRightTarget = targets.findTask(
+ mSplitBounds.rightBottomTaskId);
// remoteTargetHandle[0] denotes topLeft task, so we pass in the bottomRight to exclude,
// vice versa
- mSplitBounds = new SplitBounds(
- getStartBounds(topLeftTarget),
- getStartBounds(bottomRightTarget),
- topLeftTarget.taskId,
- bottomRightTarget.taskId);
mRemoteTargetHandles[0].mTransformParams.setTargetSet(
createRemoteAnimationTargetsForTarget(targets, bottomRightTarget));
mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(topLeftTarget,
@@ -291,7 +283,7 @@
return mRemoteTargetHandles;
}
- public SplitBounds getSplitBounds() {
+ public SplitConfigurationOptions.SplitBounds getSplitBounds() {
return mSplitBounds;
}
diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
index 8626c40..2d47097 100644
--- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java
+++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
@@ -19,6 +19,7 @@
import static android.view.Surface.ROTATION_0;
import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
+import static com.android.launcher3.MotionEventsUtils.isTrackpadScroll;
import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
@@ -232,16 +233,18 @@
/**
* @return whether the coordinates of the {@param event} is in the swipe up gesture region.
*/
- public boolean isInSwipeUpTouchRegion(MotionEvent event, BaseActivityInterface activity) {
- return isInSwipeUpTouchRegion(event, 0, activity);
+ public boolean isInSwipeUpTouchRegion(MotionEvent event) {
+ return isInSwipeUpTouchRegion(event, 0);
}
/**
* @return whether the coordinates of the {@param event} with the given {@param pointerIndex}
* is in the swipe up gesture region.
*/
- public boolean isInSwipeUpTouchRegion(MotionEvent event, int pointerIndex,
- BaseActivityInterface activity) {
+ public boolean isInSwipeUpTouchRegion(MotionEvent event, int pointerIndex) {
+ if (isTrackpadScroll(event)) {
+ return false;
+ }
if (isTrackpadMultiFingerSwipe(event)) {
return true;
}
diff --git a/quickstep/src/com/android/quickstep/SplitSelectionListener.kt b/quickstep/src/com/android/quickstep/SplitSelectionListener.kt
new file mode 100644
index 0000000..5025c1c
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/SplitSelectionListener.kt
@@ -0,0 +1,17 @@
+package com.android.quickstep
+
+interface SplitSelectionListener {
+ /** Called when the first app has been selected with the intention to launch split screen */
+ fun onSplitSelectionActive()
+
+ /** Called when the second app has been selected with the intention to launch split screen */
+ fun onSplitSelectionConfirmed()
+
+ /**
+ * Called when the user no longer is in the process of selecting apps for split screen.
+ * [launchedSplit] will be true if selected apps have launched successfully (either in
+ * split screen or fullscreen), false if the user canceled/exited the selection process
+ */
+ fun onSplitSelectionExit(launchedSplit: Boolean) {
+ }
+}
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
index 25ac47a..e481165 100644
--- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -15,8 +15,8 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.ACCELERATE_1_5;
+import static com.android.app.animation.Interpolators.LINEAR;
import android.animation.Animator;
import android.content.Context;
@@ -218,7 +218,7 @@
if (progress >= end) {
return 0f;
}
- return Utilities.mapToRange(progress, start, end, 1, 0, ACCEL_1_5);
+ return Utilities.mapToRange(progress, start, end, 1, 0, ACCELERATE_1_5);
}
}
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 9350c72..170847d 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -19,6 +19,9 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
+import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.RECENT_TASKS_MISSING;
+import static com.android.quickstep.util.LogUtils.splitFailureMessage;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -30,6 +33,7 @@
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
+import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
@@ -60,7 +64,8 @@
import com.android.internal.view.AppearanceRegion;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.Preconditions;
-import com.android.launcher3.util.SplitConfigurationOptions;
+import com.android.quickstep.util.ActiveGestureLog;
+import com.android.quickstep.util.AssistUtils;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
@@ -73,7 +78,9 @@
import com.android.wm.shell.back.IBackAnimation;
import com.android.wm.shell.bubbles.IBubbles;
import com.android.wm.shell.bubbles.IBubblesListener;
+import com.android.wm.shell.common.split.SplitScreenConstants.SnapPosition;
import com.android.wm.shell.desktopmode.IDesktopMode;
+import com.android.wm.shell.desktopmode.IDesktopTaskListener;
import com.android.wm.shell.draganddrop.IDragAndDrop;
import com.android.wm.shell.onehanded.IOneHanded;
import com.android.wm.shell.pip.IPip;
@@ -82,6 +89,7 @@
import com.android.wm.shell.recents.IRecentTasksListener;
import com.android.wm.shell.splitscreen.ISplitScreen;
import com.android.wm.shell.splitscreen.ISplitScreenListener;
+import com.android.wm.shell.splitscreen.ISplitSelectListener;
import com.android.wm.shell.startingsurface.IStartingWindow;
import com.android.wm.shell.startingsurface.IStartingWindowListener;
import com.android.wm.shell.transition.IShellTransitions;
@@ -126,10 +134,12 @@
private IPipAnimationListener mPipAnimationListener;
private IBubblesListener mBubblesListener;
private ISplitScreenListener mSplitScreenListener;
+ private ISplitSelectListener mSplitSelectListener;
private IStartingWindowListener mStartingWindowListener;
private ILauncherUnlockAnimationController mLauncherUnlockAnimationController;
private IRecentTasksListener mRecentTasksListener;
private IUnfoldTransitionListener mUnfoldAnimationListener;
+ private IDesktopTaskListener mDesktopTaskListener;
private final LinkedHashMap<RemoteTransition, TransitionFilter> mRemoteTransitions =
new LinkedHashMap<>();
private IBinder mOriginalTransactionToken = null;
@@ -236,6 +246,7 @@
setPipAnimationListener(mPipAnimationListener);
setBubblesListener(mBubblesListener);
registerSplitScreenListener(mSplitScreenListener);
+ registerSplitSelectListener(mSplitSelectListener);
setStartingWindowListener(mStartingWindowListener);
setLauncherUnlockAnimationController(mLauncherUnlockAnimationController);
new LinkedHashMap<>(mRemoteTransitions).forEach(this::registerRemoteTransition);
@@ -243,6 +254,9 @@
registerRecentTasksListener(mRecentTasksListener);
setBackToLauncherCallback(mBackToLauncherCallback, mBackToLauncherRunner);
setUnfoldAnimationListener(mUnfoldAnimationListener);
+ setDesktopTaskListener(mDesktopTaskListener);
+ setAssistantOverridesRequested(
+ AssistUtils.newInstance(mContext).getSysUiAssistOverrideInvocationTypes());
}
/**
@@ -311,13 +325,24 @@
@MainThread
@Override
- public void onStatusBarMotionEvent(MotionEvent event) {
+ public void onStatusBarTouchEvent(MotionEvent event) {
Preconditions.assertUIThread();
if (mSystemUiProxy != null) {
try {
- mSystemUiProxy.onStatusBarMotionEvent(event);
+ mSystemUiProxy.onStatusBarTouchEvent(event);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call onStatusBarMotionEvent", e);
+ Log.w(TAG, "Failed call onStatusBarTouchEvent with arg: " + event, e);
+ }
+ }
+ }
+
+ @Override
+ public void onStatusBarTrackpadEvent(MotionEvent event) {
+ if (mSystemUiProxy != null) {
+ try {
+ mSystemUiProxy.onStatusBarTrackpadEvent(event);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call onStatusBarTrackpadEvent with arg: " + event, e);
}
}
}
@@ -356,6 +381,17 @@
}
@Override
+ public void setAssistantOverridesRequested(int[] invocationTypes) {
+ if (mSystemUiProxy != null) {
+ try {
+ mSystemUiProxy.setAssistantOverridesRequested(invocationTypes);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call setAssistantOverridesRequested", e);
+ }
+ }
+ }
+
+ @Override
public void notifyAccessibilityButtonClicked(int displayId) {
if (mSystemUiProxy != null) {
try {
@@ -631,13 +667,15 @@
/**
* Tells SysUI to show the bubble with the provided key.
* @param key the key of the bubble to show.
- * @param onLauncherHome whether the bubble is showing on launcher home or not (modifies where
- * the expanded bubble view is placed).
+ * @param bubbleBarOffsetX the offset of the bubble bar from the edge of the screen on the X
+ * axis.
+ * @param bubbleBarOffsetY the offset of the bubble bar from the edge of the screen on the Y
+ * axis.
*/
- public void showBubble(String key, boolean onLauncherHome) {
+ public void showBubble(String key, int bubbleBarOffsetX, int bubbleBarOffsetY) {
if (mBubbles != null) {
try {
- mBubbles.showBubble(key, onLauncherHome);
+ mBubbles.showBubble(key, bubbleBarOffsetX, bubbleBarOffsetY);
} catch (RemoteException e) {
Log.w(TAG, "Failed call showBubble");
}
@@ -645,6 +683,31 @@
}
/**
+ * Tells SysUI to remove the bubble with the provided key.
+ * @param key the key of the bubble to show.
+ */
+ public void removeBubble(String key) {
+ if (mBubbles == null) return;
+ try {
+ mBubbles.removeBubble(key);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call removeBubble");
+ }
+ }
+
+ /**
+ * Tells SysUI to remove all bubbles.
+ */
+ public void removeAllBubbles() {
+ if (mBubbles == null) return;
+ try {
+ mBubbles.removeAllBubbles();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call removeAllBubbles");
+ }
+ }
+
+ /**
* Tells SysUI to collapse the bubbles.
*/
public void collapseBubbles() {
@@ -657,6 +720,33 @@
}
}
+ /**
+ * Tells SysUI when the bubble is being dragged.
+ * Should be called only when the bubble bar is expanded.
+ * @param bubbleKey the key of the bubble to collapse/expand
+ * @param isBeingDragged whether the bubble is being dragged
+ */
+ public void onBubbleDrag(@Nullable String bubbleKey, boolean isBeingDragged) {
+ if (mBubbles == null) return;
+ try {
+ mBubbles.onBubbleDrag(bubbleKey, isBeingDragged);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call onBubbleDrag");
+ }
+ }
+
+ /**
+ * Tells SysUI to show user education relative to the reference point provided.
+ * @param position the bubble bar top center position in Screen coordinates.
+ */
+ public void showUserEducation(Point position) {
+ try {
+ mBubbles.showUserEducation(position.x, position.y);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call showUserEducation");
+ }
+ }
+
//
// Splitscreen
//
@@ -683,29 +773,52 @@
mSplitScreenListener = null;
}
+ public void registerSplitSelectListener(ISplitSelectListener listener) {
+ if (mSplitScreen != null) {
+ try {
+ mSplitScreen.registerSplitSelectListener(listener);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call registerSplitSelectListener");
+ }
+ }
+ mSplitSelectListener = listener;
+ }
+
+ public void unregisterSplitSelectListener(ISplitSelectListener listener) {
+ if (mSplitScreen != null) {
+ try {
+ mSplitScreen.unregisterSplitSelectListener(listener);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call unregisterSplitSelectListener");
+ }
+ }
+ mSplitSelectListener = null;
+ }
+
/** Start multiple tasks in split-screen simultaneously. */
public void startTasks(int taskId1, Bundle options1, int taskId2, Bundle options2,
- @SplitConfigurationOptions.StagePosition int splitPosition, float splitRatio,
+ @StagePosition int splitPosition, @SnapPosition int snapPosition,
RemoteTransition remoteTransition, InstanceId instanceId) {
if (mSystemUiProxy != null) {
try {
mSplitScreen.startTasks(taskId1, options1, taskId2, options2, splitPosition,
- splitRatio, remoteTransition, instanceId);
+ snapPosition, remoteTransition, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startTasks");
+ Log.w(TAG, splitFailureMessage("startTasks", "RemoteException"), e);
}
}
}
public void startIntentAndTask(PendingIntent pendingIntent, int userId1, Bundle options1,
- int taskId, Bundle options2, @SplitConfigurationOptions.StagePosition int splitPosition,
- float splitRatio, RemoteTransition remoteTransition, InstanceId instanceId) {
+ int taskId, Bundle options2, @StagePosition int splitPosition,
+ @SnapPosition int snapPosition, RemoteTransition remoteTransition,
+ InstanceId instanceId) {
if (mSystemUiProxy != null) {
try {
mSplitScreen.startIntentAndTask(pendingIntent, userId1, options1, taskId, options2,
- splitPosition, splitRatio, remoteTransition, instanceId);
+ splitPosition, snapPosition, remoteTransition, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startIntentAndTask");
+ Log.w(TAG, splitFailureMessage("startIntentAndTask", "RemoteException"), e);
}
}
}
@@ -713,28 +826,28 @@
public void startIntents(PendingIntent pendingIntent1, int userId1,
@Nullable ShortcutInfo shortcutInfo1, Bundle options1, PendingIntent pendingIntent2,
int userId2, @Nullable ShortcutInfo shortcutInfo2, Bundle options2,
- @SplitConfigurationOptions.StagePosition int splitPosition, float splitRatio,
+ @StagePosition int splitPosition, @SnapPosition int snapPosition,
RemoteTransition remoteTransition, InstanceId instanceId) {
if (mSystemUiProxy != null) {
try {
mSplitScreen.startIntents(pendingIntent1, userId1, shortcutInfo1, options1,
- pendingIntent2, userId2, shortcutInfo2, options2, splitPosition, splitRatio,
- remoteTransition, instanceId);
+ pendingIntent2, userId2, shortcutInfo2, options2, splitPosition,
+ snapPosition, remoteTransition, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startIntents");
+ Log.w(TAG, splitFailureMessage("startIntents", "RemoteException"), e);
}
}
}
public void startShortcutAndTask(ShortcutInfo shortcutInfo, Bundle options1, int taskId,
- Bundle options2, @SplitConfigurationOptions.StagePosition int splitPosition,
- float splitRatio, RemoteTransition remoteTransition, InstanceId instanceId) {
+ Bundle options2, @StagePosition int splitPosition, @SnapPosition int snapPosition,
+ RemoteTransition remoteTransition, InstanceId instanceId) {
if (mSystemUiProxy != null) {
try {
mSplitScreen.startShortcutAndTask(shortcutInfo, options1, taskId, options2,
- splitPosition, splitRatio, remoteTransition, instanceId);
+ splitPosition, snapPosition, remoteTransition, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startShortcutAndTask");
+ Log.w(TAG, splitFailureMessage("startShortcutAndTask", "RemoteException"), e);
}
}
}
@@ -743,41 +856,44 @@
* Start multiple tasks in split-screen simultaneously.
*/
public void startTasksWithLegacyTransition(int taskId1, Bundle options1, int taskId2,
- Bundle options2, @SplitConfigurationOptions.StagePosition int splitPosition,
- float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) {
+ Bundle options2, @StagePosition int splitPosition, @SnapPosition int snapPosition,
+ RemoteAnimationAdapter adapter, InstanceId instanceId) {
if (mSystemUiProxy != null) {
try {
mSplitScreen.startTasksWithLegacyTransition(taskId1, options1, taskId2, options2,
- splitPosition, splitRatio, adapter, instanceId);
+ splitPosition, snapPosition, adapter, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startTasksWithLegacyTransition");
+ Log.w(TAG, splitFailureMessage(
+ "startTasksWithLegacyTransition", "RemoteException"), e);
}
}
}
public void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, int userId1,
- Bundle options1, int taskId, Bundle options2,
- @SplitConfigurationOptions.StagePosition int splitPosition, float splitRatio,
- RemoteAnimationAdapter adapter, InstanceId instanceId) {
+ Bundle options1, int taskId, Bundle options2, @StagePosition int splitPosition,
+ @SnapPosition int snapPosition, RemoteAnimationAdapter adapter, InstanceId instanceId) {
if (mSystemUiProxy != null) {
try {
mSplitScreen.startIntentAndTaskWithLegacyTransition(pendingIntent, userId1,
- options1, taskId, options2, splitPosition, splitRatio, adapter, instanceId);
+ options1, taskId, options2, splitPosition, snapPosition, adapter,
+ instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startIntentAndTaskWithLegacyTransition");
+ Log.w(TAG, splitFailureMessage(
+ "startIntentAndTaskWithLegacyTransition", "RemoteException"), e);
}
}
}
public void startShortcutAndTaskWithLegacyTransition(ShortcutInfo shortcutInfo, Bundle options1,
- int taskId, Bundle options2, @SplitConfigurationOptions.StagePosition int splitPosition,
- float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) {
+ int taskId, Bundle options2, @StagePosition int splitPosition,
+ @SnapPosition int snapPosition, RemoteAnimationAdapter adapter, InstanceId instanceId) {
if (mSystemUiProxy != null) {
try {
mSplitScreen.startShortcutAndTaskWithLegacyTransition(shortcutInfo, options1,
- taskId, options2, splitPosition, splitRatio, adapter, instanceId);
+ taskId, options2, splitPosition, snapPosition, adapter, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startShortcutAndTaskWithLegacyTransition");
+ Log.w(TAG, splitFailureMessage(
+ "startShortcutAndTaskWithLegacyTransition", "RemoteException"), e);
}
}
}
@@ -789,15 +905,16 @@
public void startIntentsWithLegacyTransition(PendingIntent pendingIntent1, int userId1,
@Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
PendingIntent pendingIntent2, int userId2, @Nullable ShortcutInfo shortcutInfo2,
- @Nullable Bundle options2, @SplitConfigurationOptions.StagePosition int sidePosition,
- float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) {
+ @Nullable Bundle options2, @StagePosition int sidePosition,
+ @SnapPosition int snapPosition, RemoteAnimationAdapter adapter, InstanceId instanceId) {
if (mSystemUiProxy != null) {
try {
mSplitScreen.startIntentsWithLegacyTransition(pendingIntent1, userId1,
shortcutInfo1, options1, pendingIntent2, userId2, shortcutInfo2, options2,
- sidePosition, splitRatio, adapter, instanceId);
+ sidePosition, snapPosition, adapter, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startIntentsWithLegacyTransition");
+ Log.w(TAG, splitFailureMessage(
+ "startIntentsWithLegacyTransition", "RemoteException"), e);
}
}
}
@@ -809,7 +926,7 @@
mSplitScreen.startShortcut(packageName, shortcutId, position, options,
user, instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startShortcut");
+ Log.w(TAG, splitFailureMessage("startShortcut", "RemoteException"), e);
}
}
}
@@ -821,7 +938,7 @@
mSplitScreen.startIntent(intent, userId, fillInIntent, position, options,
instanceId);
} catch (RemoteException e) {
- Log.w(TAG, "Failed call startIntent");
+ Log.w(TAG, splitFailureMessage("startIntent", "RemoteException"), e);
}
}
}
@@ -1161,6 +1278,41 @@
}
}
+ /** Call shell to stash desktop apps */
+ public void stashDesktopApps(int displayId) {
+ if (mDesktopMode != null) {
+ try {
+ mDesktopMode.stashDesktopApps(displayId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call stashDesktopApps", e);
+ }
+ }
+ }
+
+ /** Call shell to hide desktop apps that may be stashed */
+ public void hideStashedDesktopApps(int displayId) {
+ if (mDesktopMode != null) {
+ try {
+ mDesktopMode.hideStashedDesktopApps(displayId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call hideStashedDesktopApps", e);
+ }
+ }
+ }
+
+ /**
+ * If task with the given id is on the desktop, bring it to front
+ */
+ public void showDesktopApp(int taskId) {
+ if (mDesktopMode != null) {
+ try {
+ mDesktopMode.showDesktopApp(taskId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call showDesktopApp", e);
+ }
+ }
+ }
+
/** Call shell to get number of visible freeform tasks */
public int getVisibleDesktopTaskCount(int displayId) {
if (mDesktopMode != null) {
@@ -1173,6 +1325,29 @@
return 0;
}
+ /** Set a listener on shell to get updates about desktop task state */
+ public void setDesktopTaskListener(@Nullable IDesktopTaskListener listener) {
+ mDesktopTaskListener = listener;
+ if (mDesktopMode != null) {
+ try {
+ mDesktopMode.setTaskListener(listener);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call setDesktopTaskListener", e);
+ }
+ }
+ }
+
+ /** Perform cleanup transactions after animation to split select is complete */
+ public void onDesktopSplitSelectAnimComplete(ActivityManager.RunningTaskInfo taskInfo) {
+ if (mDesktopMode != null) {
+ try {
+ mDesktopMode.onDesktopSplitSelectAnimComplete(taskInfo);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call onDesktopSplitSelectAnimComplete", e);
+ }
+ }
+ }
+
//
// Unfold transition
//
@@ -1201,15 +1376,21 @@
public boolean startRecentsActivity(Intent intent, ActivityOptions options,
RecentsAnimationListener listener) {
if (mRecentTasks == null) {
+ ActiveGestureLog.INSTANCE.trackEvent(RECENT_TASKS_MISSING);
return false;
}
final IRecentsAnimationRunner runner = new IRecentsAnimationRunner.Stub() {
@Override
public void onAnimationStart(IRecentsAnimationController controller,
RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
- Rect homeContentInsets, Rect minimizedHomeBounds) {
+ Rect homeContentInsets, Rect minimizedHomeBounds, Bundle extras) {
+ // Aidl bundles need to explicitly set class loader
+ // https://developer.android.com/guide/components/aidl#Bundles
+ if (extras != null) {
+ extras.setClassLoader(getClass().getClassLoader());
+ }
listener.onAnimationStart(new RecentsAnimationControllerCompat(controller), apps,
- wallpapers, homeContentInsets, minimizedHomeBounds);
+ wallpapers, homeContentInsets, minimizedHomeBounds, extras);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index eacca0d..f5a7ecc 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -38,6 +38,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
import com.android.quickstep.util.ActiveGestureLog;
@@ -61,7 +62,7 @@
private RecentsAnimationTargets mTargets;
// Temporary until we can hook into gesture state events
private GestureState mLastGestureState;
- private RemoteAnimationTarget mLastAppearedTaskTarget;
+ private RemoteAnimationTarget[] mLastAppearedTaskTargets;
private Runnable mLiveTileCleanUpHandler;
private Context mCtx;
@@ -124,13 +125,14 @@
// If mCallbacks still != null, that means we are getting this startRecentsAnimation()
// before the previous one got onRecentsAnimationStart(). In that case, cleanup the
// previous animation so it doesn't mess up/listen to state changes in this animation.
- cleanUpRecentsAnimation();
+ cleanUpRecentsAnimation(mCallbacks);
}
final BaseActivityInterface activityInterface = gestureState.getActivityInterface();
mLastGestureState = gestureState;
- mCallbacks = new RecentsAnimationCallbacks(SystemUiProxy.INSTANCE.get(mCtx),
- activityInterface.allowMinimizeSplitScreen());
+ RecentsAnimationCallbacks newCallbacks = new RecentsAnimationCallbacks(
+ SystemUiProxy.INSTANCE.get(mCtx), activityInterface.allowMinimizeSplitScreen());
+ mCallbacks = newCallbacks;
mCallbacks.addListener(new RecentsAnimationCallbacks.RecentsAnimationListener() {
@Override
public void onRecentsAnimationStart(RecentsAnimationController controller,
@@ -143,18 +145,25 @@
}
mController = controller;
mTargets = targets;
- mLastAppearedTaskTarget = mTargets.findTask(mLastGestureState.getRunningTaskId());
- mLastGestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget);
+ // TODO(b/236226779): We can probably get away w/ setting mLastAppearedTaskTargets
+ // to all appeared targets directly vs just looking at running ones
+ int[] runningTaskIds = mLastGestureState.getRunningTaskIds(targets.apps.length > 1);
+ mLastAppearedTaskTargets = new RemoteAnimationTarget[runningTaskIds.length];
+ for (int i = 0; i < runningTaskIds.length; i++) {
+ RemoteAnimationTarget task = mTargets.findTask(runningTaskIds[i]);
+ mLastAppearedTaskTargets[i] = task;
+ }
+ mLastGestureState.updateLastAppearedTaskTargets(mLastAppearedTaskTargets);
}
@Override
public void onRecentsAnimationCanceled(HashMap<Integer, ThumbnailData> thumbnailDatas) {
- cleanUpRecentsAnimation();
+ cleanUpRecentsAnimation(newCallbacks);
}
@Override
public void onRecentsAnimationFinished(RecentsAnimationController controller) {
- cleanUpRecentsAnimation();
+ cleanUpRecentsAnimation(newCallbacks);
}
@Override
@@ -172,6 +181,9 @@
RecentsView recentsView =
activityInterface.getCreatedActivity().getOverviewPanel();
if (recentsView != null) {
+ Log.d(TestProtocol.INCORRECT_HOME_STATE,
+ "finish recents animation on "
+ + compat.taskInfo.description);
recentsView.finishRecentsAnimation(true, null);
}
return;
@@ -189,8 +201,9 @@
RecentsView recentsView =
activityInterface.getCreatedActivity().getOverviewPanel();
if (recentsView != null) {
- ActiveGestureLog.INSTANCE.addLog("Launching side task id="
- + appearedTaskTarget.taskId);
+ ActiveGestureLog.INSTANCE.addLog(
+ new ActiveGestureLog.CompoundString("Launching side task id=")
+ .append(appearedTaskTarget.taskId));
recentsView.launchSideTaskInLiveTileMode(appearedTaskTarget.taskId,
appearedTaskTargets,
new RemoteAnimationTarget[0] /* wallpaper */,
@@ -204,14 +217,18 @@
true /*shown*/, null /* animatorHandler */);
}
if (mController != null) {
- if (mLastAppearedTaskTarget == null
- || appearedTaskTarget.taskId != mLastAppearedTaskTarget.taskId) {
- if (mLastAppearedTaskTarget != null) {
- mController.removeTaskTarget(mLastAppearedTaskTarget);
+ if (mLastAppearedTaskTargets != null) {
+ for (RemoteAnimationTarget lastTarget : mLastAppearedTaskTargets) {
+ for (RemoteAnimationTarget appearedTarget : appearedTaskTargets) {
+ if (lastTarget != null &&
+ appearedTarget.taskId != lastTarget.taskId) {
+ mController.removeTaskTarget(lastTarget.taskId);
+ }
+ }
}
- mLastAppearedTaskTarget = appearedTaskTarget;
- mLastGestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget);
}
+ mLastAppearedTaskTargets = appearedTaskTargets;
+ mLastGestureState.updateLastAppearedTaskTargets(mLastAppearedTaskTargets);
}
}
@@ -276,7 +293,7 @@
mCallbacks.addListener(gestureState);
gestureState.setState(STATE_RECENTS_ANIMATION_INITIALIZED
| STATE_RECENTS_ANIMATION_STARTED);
- gestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget);
+ gestureState.updateLastAppearedTaskTargets(mLastAppearedTaskTargets);
return mCallbacks;
}
@@ -315,11 +332,10 @@
* Finishes the running recents animation.
* @param forceFinish will synchronously finish the controller
*/
- private void finishRunningRecentsAnimation(boolean toHome, boolean forceFinish) {
+ public void finishRunningRecentsAnimation(boolean toHome, boolean forceFinish) {
if (mController != null) {
ActiveGestureLog.INSTANCE.addLog(
/* event= */ "finishRunningRecentsAnimation", toHome);
- mCallbacks.notifyAnimationCanceled();
if (forceFinish) {
mController.finishController(toHome, null, false /* sendUserLeaveHint */,
true /* forceFinish */);
@@ -328,7 +344,6 @@
? mController::finishAnimationToHome
: mController::finishAnimationToApp);
}
- cleanUpRecentsAnimation();
}
}
@@ -355,7 +370,12 @@
/**
* Cleans up the recents animation entirely.
*/
- private void cleanUpRecentsAnimation() {
+ private void cleanUpRecentsAnimation(RecentsAnimationCallbacks targetCallbacks) {
+ if (mCallbacks != targetCallbacks) {
+ ActiveGestureLog.INSTANCE.addLog(
+ /* event= */ "cleanUpRecentsAnimation skipped due to wrong callbacks");
+ return;
+ }
ActiveGestureLog.INSTANCE.addLog(/* event= */ "cleanUpRecentsAnimation");
if (mLiveTileCleanUpHandler != null) {
mLiveTileCleanUpHandler.run();
@@ -377,7 +397,7 @@
mCallbacks = null;
mTargets = null;
mLastGestureState = null;
- mLastAppearedTaskTarget = null;
+ mLastAppearedTaskTargets = null;
}
@Nullable
diff --git a/quickstep/src/com/android/quickstep/TaskIconCache.java b/quickstep/src/com/android/quickstep/TaskIconCache.java
index 7c05a10..164a366 100644
--- a/quickstep/src/com/android/quickstep/TaskIconCache.java
+++ b/quickstep/src/com/android/quickstep/TaskIconCache.java
@@ -15,7 +15,6 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.uioverrides.QuickstepLauncher.GO_LOW_RAM_RECENTS_ENABLED;
import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
import android.annotation.Nullable;
@@ -182,17 +181,14 @@
}
}
- // Loading content descriptions if accessibility or low RAM recents is enabled.
- if (GO_LOW_RAM_RECENTS_ENABLED || mAccessibilityManager.isEnabled()) {
- // Skip loading the content description if the activity no longer exists
- if (activityInfo == null) {
- activityInfo = PackageManagerWrapper.getInstance().getActivityInfo(
- key.getComponent(), key.userId);
- }
- if (activityInfo != null) {
- entry.contentDescription = getBadgedContentDescription(
- activityInfo, task.key.userId, task.taskDescription);
- }
+ // Skip loading the content description if the activity no longer exists
+ if (activityInfo == null) {
+ activityInfo = PackageManagerWrapper.getInstance().getActivityInfo(
+ key.getComponent(), key.userId);
+ }
+ if (activityInfo != null) {
+ entry.contentDescription = getBadgedContentDescription(
+ activityInfo, task.key.userId, task.taskDescription);
}
mIconCache.put(task.key, entry);
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 1744b08..bd3ccb7 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -80,7 +80,7 @@
boolean isInLandscape = orientedState.getTouchRotation() != ROTATION_0;
boolean isTablet = activity.getDeviceProfile().isTablet;
- boolean isGridOnlyOverview = isTablet && FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get();
+ boolean isGridOnlyOverview = isTablet && FeatureFlags.enableGridOnlyOverview();
// Add overview actions to the menu when in in-place rotate landscape mode, or in
// grid-only overview.
if ((!canLauncherRotate && isInLandscape) || isGridOnlyOverview) {
@@ -122,6 +122,12 @@
public void removeListeners() {
}
+ /**
+ * Clears any active state outside of the TaskOverlay lifecycle which might have built
+ * up over time
+ */
+ public void clearAllActiveState() { }
+
/** Note that these will be shown in order from top to bottom, if available for the task. */
private static final TaskShortcutFactory[] MENU_OPTIONS = new TaskShortcutFactory[]{
TaskShortcutFactory.APP_INFO,
@@ -159,6 +165,10 @@
return mActionsView;
}
+ public TaskThumbnailView getThumbnailView() {
+ return mThumbnailView;
+ }
+
/**
* Called when the current task is interactive for the user
*/
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index 208f99a..2adc790 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -30,6 +30,7 @@
import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemProperties;
+import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.WindowInsets;
@@ -140,6 +141,7 @@
@Override
public void onClick(View view) {
+ dismissTaskMenuView(mTarget);
((RecentsView) mTarget.getOverviewPanel())
.getSplitSelectController().getAppPairsController().saveAppPair(mTaskView);
}
@@ -344,8 +346,9 @@
}
private boolean isAvailable(BaseDraggingActivity activity, int displayId) {
- return ActivityManagerWrapper.getInstance().supportsFreeformMultiWindow(activity)
- && !SystemProperties.getBoolean("persist.wm.debug.desktop_mode", false)
+ return Settings.Global.getInt(
+ activity.getContentResolver(),
+ Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0
&& !SystemProperties.getBoolean("persist.wm.debug.desktop_mode_2", false);
}
};
@@ -396,11 +399,12 @@
@Override
public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
TaskIdAttributeContainer taskContainer) {
- return InstantAppResolver.newInstance(activity).isInstantApp(activity,
- taskContainer.getTask().getTopComponent().getPackageName()) ?
- Collections.singletonList(new SystemShortcut.Install(activity,
- taskContainer.getItemInfo(), taskContainer.getTaskView())) :
- null;
+ Task t = taskContainer.getTask();
+ return InstantAppResolver.newInstance(activity).isInstantApp(
+ t.getTopComponent().getPackageName(), t.getKey().userId)
+ ? Collections.singletonList(new SystemShortcut.Install(activity,
+ taskContainer.getItemInfo(), taskContainer.getTaskView()))
+ : null;
}
};
diff --git a/quickstep/src/com/android/quickstep/TaskUtils.java b/quickstep/src/com/android/quickstep/TaskUtils.java
index 67360c4..80a449b 100644
--- a/quickstep/src/com/android/quickstep/TaskUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskUtils.java
@@ -33,6 +33,7 @@
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.util.TraceHelper;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -51,7 +52,8 @@
* TODO: remove this once we switch to getting the icon and label from IconCache.
*/
public static CharSequence getTitle(Context context, Task task) {
- return getTitle(context, task.key.userId, task.getTopComponent().getPackageName());
+ return TraceHelper.allowIpcs("TaskUtils.getTitle", () ->
+ getTitle(context, task.key.userId, task.getTopComponent().getPackageName()));
}
public static CharSequence getTitle(
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 1238819..34965df 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -21,6 +21,9 @@
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.TOUCH_RESPONSE;
+import static com.android.app.animation.Interpolators.clampToProgress;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
@@ -35,9 +38,6 @@
import static com.android.launcher3.QuickstepTransitionManager.SPLIT_DIVIDER_ANIM_DURATION;
import static com.android.launcher3.QuickstepTransitionManager.SPLIT_LAUNCH_DURATION;
import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
-import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
import static com.android.quickstep.views.DesktopTaskView.DESKTOP_MODE_SUPPORTED;
@@ -61,12 +61,12 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.statehandlers.DepthController;
@@ -160,13 +160,14 @@
}
public static void createRecentsWindowAnimator(
- @NonNull TaskView v, boolean skipViewChanges,
+ @NonNull RecentsView recentsView,
+ @NonNull TaskView v,
+ boolean skipViewChanges,
@NonNull RemoteAnimationTarget[] appTargets,
@NonNull RemoteAnimationTarget[] wallpaperTargets,
@NonNull RemoteAnimationTarget[] nonAppTargets,
@Nullable DepthController depthController,
PendingAnimation out) {
- RecentsView recentsView = v.getRecentsView();
boolean isQuickSwitch = v.isEndQuickswitchCuj();
v.setEndQuickswitchCuj(false);
@@ -190,7 +191,8 @@
if (forDesktop) {
remoteTargetHandles = gluer.assignTargetsForDesktop(targets);
} else if (v.containsMultipleTasks()) {
- remoteTargetHandles = gluer.assignTargetsForSplitScreen(targets);
+ remoteTargetHandles = gluer.assignTargetsForSplitScreen(targets,
+ ((GroupedTaskView) v).getSplitBoundsConfig());
} else {
remoteTargetHandles = gluer.assignTargets(targets);
}
@@ -237,12 +239,12 @@
for (RemoteTargetHandle targetHandle : remoteTargetHandles) {
TaskViewSimulator tvsLocal = targetHandle.getTaskViewSimulator();
out.setFloat(tvsLocal.fullScreenProgress,
- AnimatedFloat.VALUE, 1, TOUCH_RESPONSE_INTERPOLATOR);
+ AnimatedFloat.VALUE, 1, TOUCH_RESPONSE);
out.setFloat(tvsLocal.recentsViewScale,
AnimatedFloat.VALUE, tvsLocal.getFullScreenScale(),
- TOUCH_RESPONSE_INTERPOLATOR);
+ TOUCH_RESPONSE);
out.setFloat(tvsLocal.recentsViewScroll, AnimatedFloat.VALUE, 0,
- TOUCH_RESPONSE_INTERPOLATOR);
+ TOUCH_RESPONSE);
out.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
@@ -355,9 +357,9 @@
float fullScreenScale =
topMostSimulators[i].getTaskViewSimulator().getFullScreenScale();
out.addFloat(ttv, VIEW_TRANSLATE_Y, translationY,
- translationY / fullScreenScale, TOUCH_RESPONSE_INTERPOLATOR);
+ translationY / fullScreenScale, TOUCH_RESPONSE);
out.addFloat(ttv, VIEW_TRANSLATE_X, translationX,
- translationX / fullScreenScale, TOUCH_RESPONSE_INTERPOLATOR);
+ translationX / fullScreenScale, TOUCH_RESPONSE);
}
Matrix[] k0i = new Matrix[matrixSize];
@@ -405,25 +407,19 @@
if (depthController != null) {
out.setFloat(depthController.stateDepth, MULTI_PROPERTY_VALUE,
- BACKGROUND_APP.getDepth(baseActivity), TOUCH_RESPONSE_INTERPOLATOR);
+ BACKGROUND_APP.getDepth(baseActivity), TOUCH_RESPONSE);
}
}
/**
- * TODO: This doesn't animate at present. Feel free to blow out everyhing in this method
- * if needed
+ * If {@param launchingTaskView} is not null, then this will play the tasks launch animation
+ * from the position of the GroupedTaskView (when user taps on the TaskView to start it).
+ * Technically this case should be taken care of by
+ * {@link #composeRecentsSplitLaunchAnimatorLegacy} below, but the way we launch tasks whether
+ * it's a single task or multiple tasks results in different entry-points.
*
- * We could manually try to animate the just the bounds for the leashes we get back, but we try
- * to do it through TaskViewSimulator(TVS) since that handles a lot of the recents UI stuff for
- * us.
- *
- * First you have to call TVS#setPreview() to indicate which leash it will operate one
- * Then operations happen in TVS#apply() on each frame callback.
- *
- * TVS uses DeviceProfile to try to figure out things like task height and such based on if the
- * device is in multiWindowMode or not. It's unclear given the two calls to startTask() when the
- * device is considered in multiWindowMode and things like insets and stuff change
- * and calculations have to be adjusted in the animations for that
+ * If it is null, then it will simply fade in the starting apps and fade out launcher (for the
+ * case where launcher handles animating starting split tasks from app icon)
*/
public static void composeRecentsSplitLaunchAnimator(GroupedTaskView launchingTaskView,
@NonNull StateManager stateManager, @Nullable DepthController depthController,
@@ -457,12 +453,14 @@
return;
}
- // TODO: consider initialTaskPendingIntent
TransitionInfo.Change splitRoot1 = null;
TransitionInfo.Change splitRoot2 = null;
+ final ArrayList<SurfaceControl> openingTargets = new ArrayList<>();
for (int i = 0; i < transitionInfo.getChanges().size(); ++i) {
final TransitionInfo.Change change = transitionInfo.getChanges().get(i);
- if (change.getTaskInfo() == null) continue;
+ if (change.getTaskInfo() == null) {
+ continue;
+ }
final int taskId = change.getTaskInfo().taskId;
final int mode = change.getMode();
@@ -477,31 +475,48 @@
if (taskId == initialTaskId) {
splitRoot1 = change.getParent() == null ? change :
transitionInfo.getChange(change.getParent());
+ openingTargets.add(splitRoot1.getLeash());
}
if (taskId == secondTaskId) {
splitRoot2 = change.getParent() == null ? change :
transitionInfo.getChange(change.getParent());
+ openingTargets.add(splitRoot2.getLeash());
}
}
- // This is where we should animate the split roots. For now, though, just make them visible.
- animateSplitRoot(t, splitRoot1);
- animateSplitRoot(t, splitRoot2);
+ SurfaceControl.Transaction animTransaction = new SurfaceControl.Transaction();
+ ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
+ animator.setDuration(SPLIT_LAUNCH_DURATION);
+ animator.addUpdateListener(valueAnimator -> {
+ float progress = valueAnimator.getAnimatedFraction();
+ for (SurfaceControl leash: openingTargets) {
+ animTransaction.setAlpha(leash, progress);
+ }
+ animTransaction.apply();
+ });
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ for (SurfaceControl leash: openingTargets) {
+ animTransaction.show(leash)
+ .setAlpha(leash, 0.0f);
+ }
+ animTransaction.apply();
+ }
- // This contains the initial state (before animation), so apply this at the beginning of
- // the animation.
- t.apply();
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ finishCallback.run();
+ }
+ });
- // Once there is an animation, this should be called AFTER the animation completes.
- finishCallback.run();
- }
-
- private static void animateSplitRoot(SurfaceControl.Transaction t,
- TransitionInfo.Change splitRoot) {
- if (splitRoot != null) {
- t.show(splitRoot.getLeash());
- t.setAlpha(splitRoot.getLeash(), 1.f);
+ if (splitRoot1 != null && splitRoot1.getParent() != null) {
+ // Set the highest level split root alpha; we could technically use the parent of either
+ // splitRoot1 or splitRoot2
+ t.setAlpha(transitionInfo.getChange(splitRoot1.getParent()).getLeash(), 1f);
}
+ t.apply();
+ animator.start();
}
/**
@@ -514,7 +529,9 @@
* it's a single task or multiple tasks results in different entry-points.
*
* If it is null, then it will simply fade in the starting apps and fade out launcher (for the
- * case where launcher handles animating starting split tasks from app icon) */
+ * case where launcher handles animating starting split tasks from app icon)
+ * @deprecated with shell transitions
+ */
public static void composeRecentsSplitLaunchAnimatorLegacy(
@Nullable GroupedTaskView launchingTaskView, int initialTaskId, int secondTaskId,
@NonNull RemoteAnimationTarget[] appTargets,
@@ -606,8 +623,8 @@
TaskView taskView = findTaskViewToLaunch(recentsView, v, appTargets);
PendingAnimation pa = new PendingAnimation(RECENTS_LAUNCH_DURATION);
- createRecentsWindowAnimator(taskView, skipLauncherChanges, appTargets, wallpaperTargets,
- nonAppTargets, depthController, pa);
+ createRecentsWindowAnimator(recentsView, taskView, skipLauncherChanges, appTargets,
+ wallpaperTargets, nonAppTargets, depthController, pa);
if (launcherClosing) {
// TODO(b/182592057): differentiate between "restore split" vs "launch fullscreen app"
TaskViewUtils.createSplitAuxiliarySurfacesAnimator(nonAppTargets, true /*shown*/,
@@ -637,7 +654,7 @@
raController.setWillFinishToHome(false);
}
launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView);
- launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
+ launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE);
launcherAnim.setDuration(RECENTS_LAUNCH_DURATION);
windowAnimEndListener = new AnimatorListenerAdapter() {
diff --git a/quickstep/src/com/android/quickstep/TopTaskTracker.java b/quickstep/src/com/android/quickstep/TopTaskTracker.java
index d34cddf..01baed3 100644
--- a/quickstep/src/com/android/quickstep/TopTaskTracker.java
+++ b/quickstep/src/com/android/quickstep/TopTaskTracker.java
@@ -210,7 +210,7 @@
@Nullable
private final RunningTaskInfo mTopTask;
- private final List<RunningTaskInfo> mAllCachedTasks;
+ public final List<RunningTaskInfo> mAllCachedTasks;
CachedTaskInfo(List<RunningTaskInfo> allCachedTasks) {
mAllCachedTasks = allCachedTasks;
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index d6a468d..4c3f738 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -24,8 +24,11 @@
import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.Launcher.INTENT_ACTION_ALL_APPS_TOGGLE;
+import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
+import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TRACKPAD_GESTURE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WIDTH;
import static com.android.quickstep.GestureState.DEFAULT_STATE;
import static com.android.quickstep.GestureState.TrackpadGestureType.getTrackpadGestureType;
import static com.android.quickstep.InputConsumer.TYPE_CURSOR_HOVER;
@@ -37,10 +40,8 @@
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER;
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_BUBBLES;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE;
@@ -56,6 +57,8 @@
import android.app.PendingIntent;
import android.app.RemoteAction;
import android.app.Service;
+import android.content.IIntentReceiver;
+import android.content.IIntentSender;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
@@ -66,8 +69,10 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.SystemClock;
+import android.os.Trace;
import android.util.Log;
import android.view.Choreographer;
+import android.view.InputDevice;
import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.SurfaceControl;
@@ -82,27 +87,27 @@
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.AnimatedFloat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.provider.RestoreDbTask;
-import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarManager;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.testing.shared.TestProtocol;
-import com.android.launcher3.tracing.LauncherTraceProto;
-import com.android.launcher3.tracing.TouchInteractionServiceProto;
import com.android.launcher3.uioverrides.flags.FlagsFactory;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.LockedUserState;
import com.android.launcher3.util.OnboardingPrefs;
+import com.android.launcher3.util.SafeCloseable;
+import com.android.launcher3.util.ScreenOnTracker;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
import com.android.quickstep.inputconsumers.AssistantInputConsumer;
import com.android.quickstep.inputconsumers.DeviceLockedInputConsumer;
+import com.android.quickstep.inputconsumers.NavHandleLongPressInputConsumer;
import com.android.quickstep.inputconsumers.OneHandedModeInputConsumer;
import com.android.quickstep.inputconsumers.OtherActivityInputConsumer;
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
@@ -110,13 +115,13 @@
import com.android.quickstep.inputconsumers.ProgressDelegateInputConsumer;
import com.android.quickstep.inputconsumers.ResetGestureInputConsumer;
import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
-import com.android.quickstep.inputconsumers.StatusBarInputConsumer;
import com.android.quickstep.inputconsumers.SysUiOverlayInputConsumer;
import com.android.quickstep.inputconsumers.TaskbarUnstashInputConsumer;
+import com.android.quickstep.inputconsumers.TrackpadStatusBarInputConsumer;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.ActiveGestureLog.CompoundString;
-import com.android.quickstep.util.ProtoTracer;
-import com.android.quickstep.util.ProxyScreenStatusProvider;
+import com.android.quickstep.util.AssistStateManager;
+import com.android.quickstep.util.AssistUtils;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -124,7 +129,6 @@
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
-import com.android.systemui.shared.tracing.ProtoTraceable;
import com.android.systemui.unfold.progress.IUnfoldAnimation;
import com.android.wm.shell.back.IBackAnimation;
import com.android.wm.shell.bubbles.IBubbles;
@@ -140,8 +144,6 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
-import java.util.Arrays;
-import java.util.LinkedList;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -149,8 +151,7 @@
* Service connected by system-UI for handling touch interaction.
*/
@TargetApi(Build.VERSION_CODES.R)
-public class TouchInteractionService extends Service
- implements ProtoTraceable<LauncherTraceProto.Builder> {
+public class TouchInteractionService extends Service {
private static final String SUBSTRING_PREFIX = "; ";
private static final String NEWLINE_PREFIX = "\n\t\t\t-> ";
@@ -284,6 +285,20 @@
}));
}
+ /**
+ * Sent when the assistant has been invoked with the given type (defined in AssistManager)
+ * and should be shown. This method is used if SystemUiProxy#setAssistantOverridesRequested
+ * was previously called including this invocation type.
+ */
+ @Override
+ public void onAssistantOverrideInvoked(int invocationType) {
+ executeForTouchInteractionService(tis -> {
+ if (!AssistUtils.newInstance(tis).tryStartAssistOverride(invocationType)) {
+ Log.w(TAG, "Failed to invoke Assist override");
+ }
+ });
+ }
+
@Override
public void onNavigationBarSurface(SurfaceControl surface) {
// TODO: implement
@@ -306,24 +321,6 @@
@BinderThread
@Override
- public void onScreenTurnedOn() {
- MAIN_EXECUTOR.execute(ProxyScreenStatusProvider.INSTANCE::onScreenTurnedOn);
- }
-
- @BinderThread
- @Override
- public void onScreenTurningOn() {
- MAIN_EXECUTOR.execute(ProxyScreenStatusProvider.INSTANCE::onScreenTurningOn);
- }
-
- @BinderThread
- @Override
- public void onScreenTurningOff() {
- MAIN_EXECUTOR.execute(ProxyScreenStatusProvider.INSTANCE::onScreenTurningOff);
- }
-
- @BinderThread
- @Override
public void enterStageSplitFromRunningApp(boolean leftOrTop) {
executeForTouchInteractionService(tis -> {
StatefulActivity activity =
@@ -456,6 +453,8 @@
private final AbsSwipeUpHandler.Factory mFallbackSwipeHandlerFactory =
this::createFallbackSwipeHandler;
+ private final ScreenOnTracker.ScreenOnListener mScreenOnListener = this::onScreenOnChanged;
+
private ActivityManagerWrapper mAM;
private OverviewCommandHelper mOverviewCommandHelper;
private OverviewComponentObserver mOverviewComponentObserver;
@@ -488,12 +487,12 @@
BootAwarePreloader.start(this);
// Call runOnUserUnlocked() before any other callbacks to ensure everything is initialized.
- mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
- mDeviceState.runOnUserUnlocked(mTaskbarManager::onUserUnlocked);
+ LockedUserState.get(this).runOnUserUnlocked(this::onUserUnlocked);
+ LockedUserState.get(this).runOnUserUnlocked(mTaskbarManager::onUserUnlocked);
mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
-
- ProtoTracer.INSTANCE.get(this).add(this);
sConnected = true;
+
+ ScreenOnTracker.INSTANCE.get(this).addListener(mScreenOnListener);
}
private void disposeEventHandlers(String reason) {
@@ -511,7 +510,7 @@
private void initInputMonitor(String reason) {
disposeEventHandlers("Initializing input monitor due to: " + reason);
- if (mDeviceState.isButtonNavMode()) {
+ if (mDeviceState.isButtonNavMode() && !ENABLE_TRACKPAD_GESTURE.get()) {
return;
}
@@ -559,7 +558,7 @@
}
private void resetHomeBounceSeenOnQuickstepEnabledFirstTime() {
- if (!mDeviceState.isUserUnlocked() || mDeviceState.isButtonNavMode()) {
+ if (!LockedUserState.get(this).isUserUnlocked() || mDeviceState.isButtonNavMode()) {
// Skip if not yet unlocked (can't read user shared prefs) or if the current navigation
// mode doesn't have gestures
return;
@@ -579,15 +578,7 @@
AccessibilityManager am = getSystemService(AccessibilityManager.class);
if (isHomeAndOverviewSame) {
- Intent intent = new Intent(mOverviewComponentObserver.getHomeIntent())
- .setAction(INTENT_ACTION_ALL_APPS_TOGGLE);
- RemoteAction allAppsAction = new RemoteAction(
- Icon.createWithResource(this, R.drawable.ic_apps),
- getString(R.string.all_apps_label),
- getString(R.string.all_apps_label),
- PendingIntent.getActivity(this, GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS, intent,
- PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE));
- am.registerSystemAction(allAppsAction, GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
+ am.registerSystemAction(createAllAppsAction(), GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
} else {
am.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
}
@@ -600,26 +591,43 @@
mTISBinder.onOverviewTargetChange();
}
+ private RemoteAction createAllAppsAction() {
+ final Intent homeIntent = new Intent(mOverviewComponentObserver.getHomeIntent())
+ .setAction(INTENT_ACTION_ALL_APPS_TOGGLE);
+ final PendingIntent actionPendingIntent;
+
+ if (FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
+ actionPendingIntent = new PendingIntent(new IIntentSender.Stub() {
+ @Override
+ public void send(int code, Intent intent, String resolvedType,
+ IBinder allowlistToken, IIntentReceiver finishedReceiver,
+ String requiredPermission, Bundle options) {
+ MAIN_EXECUTOR.execute(() -> mTaskbarManager.toggleAllApps(homeIntent));
+ }
+ });
+ } else {
+ actionPendingIntent = PendingIntent.getActivity(
+ this,
+ GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS,
+ homeIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+ }
+
+ return new RemoteAction(
+ Icon.createWithResource(this, R.drawable.ic_apps),
+ getString(R.string.all_apps_label),
+ getString(R.string.all_apps_label),
+ actionPendingIntent);
+ }
+
@UiThread
private void onSystemUiFlagsChanged(int lastSysUIFlags) {
- if (mDeviceState.isUserUnlocked()) {
+ if (LockedUserState.get(this).isUserUnlocked()) {
int systemUiStateFlags = mDeviceState.getSystemUiStateFlags();
SystemUiProxy.INSTANCE.get(this).setLastSystemUiStateFlags(systemUiStateFlags);
mOverviewComponentObserver.onSystemUiStateChanged();
mTaskbarManager.onSystemUiFlagsChanged(systemUiStateFlags);
- boolean wasFreeformActive =
- (lastSysUIFlags & SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE) != 0;
- boolean isFreeformActive =
- (systemUiStateFlags & SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE) != 0;
- if (wasFreeformActive != isFreeformActive) {
- DesktopVisibilityController controller =
- LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
- if (controller != null) {
- controller.setFreeformTasksVisible(isFreeformActive);
- }
- }
-
int isShadeExpandedFlag =
SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
boolean wasExpanded = (lastSysUIFlags & isShadeExpandedFlag) != 0;
@@ -629,25 +637,12 @@
// overview.
mTaskAnimationManager.endLiveTile();
}
-
- if ((lastSysUIFlags & SYSUI_STATE_TRACING_ENABLED) !=
- (systemUiStateFlags & SYSUI_STATE_TRACING_ENABLED)) {
- // Update the tracing state
- if ((systemUiStateFlags & SYSUI_STATE_TRACING_ENABLED) != 0) {
- Log.d(TAG, "Starting tracing.");
- ProtoTracer.INSTANCE.get(this).start();
- } else {
- Log.d(TAG, "Stopping tracing. Dumping to file="
- + ProtoTracer.INSTANCE.get(this).getTraceFile());
- ProtoTracer.INSTANCE.get(this).stop();
- }
- }
}
}
@UiThread
private void onAssistantVisibilityChanged() {
- if (mDeviceState.isUserUnlocked()) {
+ if (LockedUserState.get(this).isUserUnlocked()) {
mOverviewComponentObserver.getActivityInterface().onAssistantVisibilityChanged(
mDeviceState.getAssistantVisibility());
}
@@ -657,21 +652,21 @@
public void onDestroy() {
Log.d(TAG, "Touch service destroyed: user=" + getUserId());
sIsInitialized = false;
- if (mDeviceState.isUserUnlocked()) {
+ if (LockedUserState.get(this).isUserUnlocked()) {
mInputConsumer.unregisterInputConsumer();
mOverviewComponentObserver.onDestroy();
}
disposeEventHandlers("TouchInteractionService onDestroy()");
mDeviceState.destroy();
SystemUiProxy.INSTANCE.get(this).clearProxy();
- ProtoTracer.INSTANCE.get(this).stop();
- ProtoTracer.INSTANCE.get(this).remove(this);
getSystemService(AccessibilityManager.class)
.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
mTaskbarManager.destroy();
sConnected = false;
+
+ ScreenOnTracker.INSTANCE.get(this).removeListener(mScreenOnListener);
super.onDestroy();
}
@@ -681,6 +676,17 @@
return mTISBinder;
}
+ protected void onScreenOnChanged(boolean isOn) {
+ if (isOn) {
+ return;
+ }
+ long currentTime = SystemClock.uptimeMillis();
+ MotionEvent cancelEvent = MotionEvent.obtain(
+ currentTime, currentTime, ACTION_CANCEL, 0f, 0f, 0);
+ onInputEvent(cancelEvent);
+ cancelEvent.recycle();
+ }
+
private void onInputEvent(InputEvent ev) {
if (!(ev instanceof MotionEvent)) {
Log.e(TAG, "Unknown event " + ev);
@@ -691,12 +697,12 @@
TestLogging.recordMotionEvent(
TestProtocol.SEQUENCE_TIS, "TouchInteractionService.onInputEvent", event);
- if (!mDeviceState.isUserUnlocked()) {
+ if (!LockedUserState.get(this).isUserUnlocked() || (mDeviceState.isButtonNavMode()
+ && !isTrackpadMotionEvent(event))) {
return;
}
- Object traceToken = TraceHelper.INSTANCE.beginFlagsOverride(
- TraceHelper.FLAG_ALLOW_BINDER_TRACKING);
+ SafeCloseable traceToken = TraceHelper.INSTANCE.allowIpcs("TIS.onInputEvent");
final int action = event.getActionMasked();
// Note this will create a new consumer every mouse click, as after ACTION_UP from the click
@@ -707,8 +713,7 @@
mRotationTouchHelper.setOrientationTransformIfNeeded(event);
if ((!mDeviceState.isOneHandedModeActive()
- && mRotationTouchHelper.isInSwipeUpTouchRegion(event,
- mOverviewComponentObserver.getActivityInterface()))
+ && mRotationTouchHelper.isInSwipeUpTouchRegion(event))
|| isHoverActionWithoutConsumer) {
// Clone the previous gesture state since onConsumerAboutToBeSwitched might trigger
// onConsumerInactive and wipe the previous gesture state
@@ -720,7 +725,8 @@
mGestureState = newGestureState;
mConsumer = newConsumer(prevGestureState, mGestureState, event);
mUncheckedConsumer = mConsumer;
- } else if (mDeviceState.isUserUnlocked() && mDeviceState.isFullyGesturalNavMode()
+ } else if (LockedUserState.get(this).isUserUnlocked()
+ && (mDeviceState.isFullyGesturalNavMode() || isTrackpadMultiFingerSwipe(event))
&& mDeviceState.canTriggerAssistantAction(event)) {
mGestureState = createGestureState(mGestureState,
getTrackpadGestureType(event));
@@ -744,29 +750,42 @@
}
if (mUncheckedConsumer != InputConsumer.NO_OP) {
- switch (event.getActionMasked()) {
+ switch (action) {
case ACTION_DOWN:
// fall through
case ACTION_UP:
ActiveGestureLog.INSTANCE.addLog(
- /* event= */ "onMotionEvent(" + (int) event.getRawX() + ", "
- + (int) event.getRawY() + "): "
- + MotionEvent.actionToString(event.getActionMasked()) + ", "
- + MotionEvent.classificationToString(event.getClassification()),
- /* gestureEvent= */ event.getActionMasked() == ACTION_DOWN
+ new CompoundString("onMotionEvent(")
+ .append((int) event.getRawX())
+ .append(", ")
+ .append((int) event.getRawY())
+ .append("): ")
+ .append(MotionEvent.actionToString(action))
+ .append(", ")
+ .append(MotionEvent.classificationToString(
+ event.getClassification())),
+ /* gestureEvent= */ action == ACTION_DOWN
? MOTION_DOWN
: MOTION_UP);
break;
case ACTION_MOVE:
- ActiveGestureLog.INSTANCE.addLog("onMotionEvent: "
- + MotionEvent.actionToString(event.getActionMasked()) + ","
- + MotionEvent.classificationToString(event.getClassification())
- + ", pointerCount: " + event.getPointerCount(), MOTION_MOVE);
+ ActiveGestureLog.INSTANCE.addLog(
+ new CompoundString("onMotionEvent: ")
+ .append(MotionEvent.actionToString(action))
+ .append(",")
+ .append(MotionEvent.classificationToString(
+ event.getClassification()))
+ .append(", pointerCount: ")
+ .append(event.getPointerCount()),
+ MOTION_MOVE);
break;
default: {
- ActiveGestureLog.INSTANCE.addLog("onMotionEvent: "
- + MotionEvent.actionToString(event.getActionMasked()) + ","
- + MotionEvent.classificationToString(event.getClassification()));
+ ActiveGestureLog.INSTANCE.addLog(
+ new CompoundString("onMotionEvent: ")
+ .append(MotionEvent.actionToString(action))
+ .append(",")
+ .append(MotionEvent.classificationToString(
+ event.getClassification())));
}
}
}
@@ -783,10 +802,7 @@
if (mGestureState.isTrackpadGesture() && (action == ACTION_POINTER_DOWN
|| action == ACTION_POINTER_UP)) {
// Skip ACTION_POINTER_DOWN and ACTION_POINTER_UP events from trackpad.
- if (action == ACTION_POINTER_DOWN) {
- mGestureState.setTrackpadGestureType(getTrackpadGestureType(event));
- }
- } else if (event.isHoverEvent()) {
+ } else if (isCursorHoverEvent(event)) {
mUncheckedConsumer.onHoverEvent(event);
} else {
mUncheckedConsumer.onMotionEvent(event);
@@ -795,8 +811,12 @@
if (cleanUpConsumer) {
reset();
}
- TraceHelper.INSTANCE.endFlagsOverride(traceToken);
- ProtoTracer.INSTANCE.get(this).scheduleFrameUpdate();
+ traceToken.close();
+ }
+
+ // Talkback generates hover events on touch, which we do not want to consume.
+ private boolean isCursorHoverEvent(MotionEvent event) {
+ return event.isHoverEvent() && event.getSource() == InputDevice.SOURCE_MOUSE;
}
private InputConsumer tryCreateAssistantInputConsumer(
@@ -830,7 +850,7 @@
ActiveGestureLog.INSTANCE.getLogId());
taskInfo = previousGestureState.getRunningTask();
gestureState.updateRunningTask(taskInfo);
- gestureState.updateLastStartedTaskId(previousGestureState.getLastStartedTaskId());
+ gestureState.updateLastStartedTaskIds(previousGestureState.getLastStartedTaskIds());
gestureState.updatePreviouslyAppearedTaskIds(
previousGestureState.getPreviouslyAppearedTaskIds());
} else {
@@ -862,9 +882,11 @@
return consumer;
}
- boolean canStartSystemGesture = mDeviceState.canStartSystemGesture();
+ boolean canStartSystemGesture =
+ mGestureState.isTrackpadGesture() ? mDeviceState.canStartTrackpadGesture()
+ : mDeviceState.canStartSystemGesture();
- if (!mDeviceState.isUserUnlocked()) {
+ if (!LockedUserState.get(this).isUserUnlocked()) {
CompoundString reasonString = newCompoundString("device locked");
InputConsumer consumer;
if (canStartSystemGesture) {
@@ -897,11 +919,12 @@
.append(", trying to use default input consumer");
base = getDefaultInputConsumer(reasonString);
}
- if (mDeviceState.isGesturalNavMode()) {
+ if (mDeviceState.isGesturalNavMode() || newGestureState.isTrackpadGesture()) {
handleOrientationSetup(base);
}
- if (mDeviceState.isFullyGesturalNavMode()) {
- String reasonPrefix = "device is in gesture navigation mode";
+ if (mDeviceState.isFullyGesturalNavMode() || newGestureState.isTrackpadGesture()) {
+ String reasonPrefix = "device is in gesture navigation mode or 3-button mode with a"
+ + "trackpad gesture";
if (mDeviceState.canTriggerAssistantAction(event)) {
reasonString.append(NEWLINE_PREFIX)
.append(reasonPrefix)
@@ -924,8 +947,12 @@
.append(SUBSTRING_PREFIX)
.append("TaskbarActivityContext != null, "
+ "using TaskbarUnstashInputConsumer");
- base = new TaskbarUnstashInputConsumer(this, base, mInputMonitorCompat, tac);
+ base = new TaskbarUnstashInputConsumer(this, base, mInputMonitorCompat, tac,
+ mOverviewCommandHelper);
}
+ } else if (canStartSystemGesture && FeatureFlags.ENABLE_LONG_PRESS_NAV_HANDLE.get()
+ && !previousGestureState.isRecentsAnimationRunning()) {
+ base = new NavHandleLongPressInputConsumer(this, base, mInputMonitorCompat);
}
if (mDeviceState.isBubblesExpanded()) {
@@ -945,11 +972,12 @@
}
if (ENABLE_TRACKPAD_GESTURE.get() && mGestureState.isTrackpadGesture()
- && !previousGestureState.isRecentsAnimationRunning()) {
+ && canStartSystemGesture && !previousGestureState.isRecentsAnimationRunning()) {
reasonString = newCompoundString(reasonPrefix)
.append(SUBSTRING_PREFIX)
- .append("Trackpad 3-finger gesture, using StatusBarInputConsumer");
- base = new StatusBarInputConsumer(getBaseContext(), base, mInputMonitorCompat);
+ .append("Trackpad 3-finger gesture, using TrackpadStatusBarInputConsumer");
+ base = new TrackpadStatusBarInputConsumer(getBaseContext(), base,
+ mInputMonitorCompat);
}
if (mDeviceState.isScreenPinningActive()) {
@@ -1037,6 +1065,7 @@
}
reasonString.append(SUBSTRING_PREFIX).append("keyguard is not showing occluded");
+
// Use overview input consumer for sharesheets on top of home.
boolean forceOverviewInputConsumer = gestureState.getActivityInterface().isStarted()
&& gestureState.getRunningTask() != null
@@ -1112,17 +1141,21 @@
private InputConsumer createDeviceLockedInputConsumer(
GestureState gestureState, CompoundString reasonString) {
- if (mDeviceState.isFullyGesturalNavMode() && gestureState.getRunningTask() != null) {
+ if ((mDeviceState.isFullyGesturalNavMode() || gestureState.isTrackpadGesture())
+ && gestureState.getRunningTask() != null) {
reasonString.append(SUBSTRING_PREFIX)
- .append("device is in gesture nav mode and running task != null")
+ .append("device is in gesture nav mode or 3-button mode with a trackpad gesture"
+ + "and running task != null")
.append(", using DeviceLockedInputConsumer");
return new DeviceLockedInputConsumer(
this, mDeviceState, mTaskAnimationManager, gestureState, mInputMonitorCompat);
} else {
return getDefaultInputConsumer(reasonString
.append(SUBSTRING_PREFIX)
- .append(mDeviceState.isFullyGesturalNavMode()
- ? "running task == null" : "device is not in gesture nav mode")
+ .append((mDeviceState.isFullyGesturalNavMode()
+ || gestureState.isTrackpadGesture())
+ ? "running task == null"
+ : "device is not in gesture nav mode and it's not a trackpad gesture")
.append(", trying to use default input consumer"));
}
}
@@ -1211,11 +1244,13 @@
}
private void preloadOverview(boolean fromInit) {
+ Trace.beginSection("preloadOverview(fromInit=" + fromInit + ")");
preloadOverview(fromInit, false);
+ Trace.endSection();
}
private void preloadOverview(boolean fromInit, boolean forSUWAllSet) {
- if (!mDeviceState.isUserUnlocked()) {
+ if (!LockedUserState.get(this).isUserUnlocked()) {
return;
}
@@ -1251,7 +1286,7 @@
@Override
public void onConfigurationChanged(Configuration newConfig) {
- if (!mDeviceState.isUserUnlocked()) {
+ if (!LockedUserState.get(this).isUserUnlocked()) {
return;
}
final BaseActivityInterface activityInterface =
@@ -1261,7 +1296,10 @@
// We only care about the existing background activity.
return;
}
- if (mOverviewComponentObserver.canHandleConfigChanges(activity.getComponentName(),
+ Configuration oldConfig = activity.getResources().getConfiguration();
+ boolean isFoldUnfold = isTablet(oldConfig) != isTablet(newConfig);
+ if (!isFoldUnfold && mOverviewComponentObserver.canHandleConfigChanges(
+ activity.getComponentName(),
activity.getResources().getConfiguration().diff(newConfig))) {
// Since navBar gestural height are different between portrait and landscape,
// can handle orientation changes and refresh navigation gestural region through
@@ -1276,82 +1314,47 @@
preloadOverview(false /* fromInit */);
}
+ private static boolean isTablet(Configuration config) {
+ return config.smallestScreenWidthDp >= MIN_TABLET_WIDTH;
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] rawArgs) {
- if (rawArgs.length > 0 && Utilities.IS_DEBUG_DEVICE) {
- LinkedList<String> args = new LinkedList(Arrays.asList(rawArgs));
- switch (args.pollFirst()) {
- case "cmd":
- if (args.peekFirst() == null) {
- printAvailableCommands(pw);
- } else {
- onCommand(pw, args);
- }
- break;
- }
- } else {
- // Dump everything
- FlagsFactory.dump(pw);
- if (mDeviceState.isUserUnlocked()) {
- PluginManagerWrapper.INSTANCE.get(getBaseContext()).dump(pw);
- }
- mDeviceState.dump(pw);
- if (mOverviewComponentObserver != null) {
- mOverviewComponentObserver.dump(pw);
- }
- if (mOverviewCommandHelper != null) {
- mOverviewCommandHelper.dump(pw);
- }
- if (mGestureState != null) {
- mGestureState.dump(pw);
- }
- pw.println("Input state:");
- pw.println(" mInputMonitorCompat=" + mInputMonitorCompat);
- pw.println(" mInputEventReceiver=" + mInputEventReceiver);
- DisplayController.INSTANCE.get(this).dump(pw);
- pw.println("TouchState:");
- BaseDraggingActivity createdOverviewActivity = mOverviewComponentObserver == null ? null
- : mOverviewComponentObserver.getActivityInterface().getCreatedActivity();
- boolean resumed = mOverviewComponentObserver != null
- && mOverviewComponentObserver.getActivityInterface().isResumed();
- pw.println(" createdOverviewActivity=" + createdOverviewActivity);
- pw.println(" resumed=" + resumed);
- pw.println(" mConsumer=" + mConsumer.getName());
- ActiveGestureLog.INSTANCE.dump("", pw);
- RecentsModel.INSTANCE.get(this).dump("", pw);
- pw.println("ProtoTrace:");
- pw.println(" file=" + ProtoTracer.INSTANCE.get(this).getTraceFile());
- if (createdOverviewActivity != null) {
- createdOverviewActivity.getDeviceProfile().dump(this, "", pw);
- }
- mTaskbarManager.dumpLogs("", pw);
+ // Dump everything
+ FlagsFactory.dump(pw);
+ if (LockedUserState.get(this).isUserUnlocked()) {
+ PluginManagerWrapper.INSTANCE.get(getBaseContext()).dump(pw);
}
- }
-
- private void printAvailableCommands(PrintWriter pw) {
- pw.println("Available commands:");
- pw.println(" clear-touch-log: Clears the touch interaction log");
- pw.println(" print-gesture-log: only prints the ActiveGestureLog dump");
- }
-
- private void onCommand(PrintWriter pw, LinkedList<String> args) {
- String cmd = args.pollFirst();
- if (cmd == null) {
- pw.println("Command missing");
- printAvailableCommands(pw);
- return;
+ mDeviceState.dump(pw);
+ if (mOverviewComponentObserver != null) {
+ mOverviewComponentObserver.dump(pw);
}
- switch (cmd) {
- case "clear-touch-log":
- ActiveGestureLog.INSTANCE.clear();
- break;
- case "print-gesture-log":
- ActiveGestureLog.INSTANCE.dump("", pw);
- break;
- default:
- pw.println("Command does not exist: " + cmd);
- printAvailableCommands(pw);
+ if (mOverviewCommandHelper != null) {
+ mOverviewCommandHelper.dump(pw);
}
+ if (mGestureState != null) {
+ mGestureState.dump(pw);
+ }
+ pw.println("Input state:");
+ pw.println(" mInputMonitorCompat=" + mInputMonitorCompat);
+ pw.println(" mInputEventReceiver=" + mInputEventReceiver);
+ DisplayController.INSTANCE.get(this).dump(pw);
+ pw.println("TouchState:");
+ BaseDraggingActivity createdOverviewActivity = mOverviewComponentObserver == null ? null
+ : mOverviewComponentObserver.getActivityInterface().getCreatedActivity();
+ boolean resumed = mOverviewComponentObserver != null
+ && mOverviewComponentObserver.getActivityInterface().isResumed();
+ pw.println(" createdOverviewActivity=" + createdOverviewActivity);
+ pw.println(" resumed=" + resumed);
+ pw.println(" mConsumer=" + mConsumer.getName());
+ ActiveGestureLog.INSTANCE.dump("", pw);
+ RecentsModel.INSTANCE.get(this).dump("", pw);
+ if (createdOverviewActivity != null) {
+ createdOverviewActivity.getDeviceProfile().dump(this, "", pw);
+ }
+ mTaskbarManager.dumpLogs("", pw);
+ pw.println("AssistStateManager:");
+ AssistStateManager.INSTANCE.get(this).dump(" ", pw);
}
private AbsSwipeUpHandler createLauncherSwipeHandler(
@@ -1367,18 +1370,4 @@
gestureState, touchTimeMs, mTaskAnimationManager.isRecentsAnimationRunning(),
mInputConsumer);
}
-
- @Override
- public void writeToProto(LauncherTraceProto.Builder proto) {
- TouchInteractionServiceProto.Builder serviceProto =
- TouchInteractionServiceProto.newBuilder();
- serviceProto.setServiceConnected(true);
-
- if (mOverviewComponentObserver != null) {
- mOverviewComponentObserver.writeToProto(serviceProto);
- }
- mConsumer.writeToProto(serviceProto);
-
- proto.setTouchInteractionService(serviceProto);
- }
}
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index 11b1ab8..8a9e04e 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -15,9 +15,9 @@
*/
package com.android.quickstep.fallback;
-import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.FINAL_FRAME;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 074aedd..95d88cd 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -35,6 +35,7 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.util.SplitConfigurationOptions;
@@ -79,11 +80,16 @@
}
@Override
- public void startHome(boolean animated) {
+ protected void handleStartHome(boolean animated) {
mActivity.startHome();
AbstractFloatingView.closeAllOpenViews(mActivity, mActivity.isStarted());
}
+ @Override
+ protected boolean canStartHomeSafely() {
+ return mActivity.canStartHomeSafely();
+ }
+
/**
* When starting gesture interaction from home, we add a temporary invisible tile corresponding
* to the home task. This allows us to handle quick-switch similarly to a quick-switching
@@ -246,7 +252,11 @@
setOverviewSelectEnabled(false);
}
if (finalState != OVERVIEW_SPLIT_SELECT) {
- resetFromSplitSelectionState();
+ if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ mSplitSelectStateController.resetState();
+ } else {
+ resetFromSplitSelectionState();
+ }
}
if (isOverlayEnabled) {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
index 6a36d9f..2abc7ba 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
@@ -103,8 +103,7 @@
if (mState == STATE_INACTIVE) {
int pointerIndex = ev.getActionIndex();
if (mDeviceState.getRotationTouchHelper().isInSwipeUpTouchRegion(ev,
- pointerIndex, mGestureState.getActivityInterface())
- && mDelegate.allowInterceptByParent()) {
+ pointerIndex) && mDelegate.allowInterceptByParent()) {
setActive(ev);
mActivePointerId = ev.getPointerId(pointerIndex);
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
index 162ace4..a209b3b 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
@@ -42,9 +42,9 @@
import android.view.MotionEvent;
import android.view.ViewConfiguration;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
-import com.android.launcher3.anim.Interpolators;
import com.android.quickstep.BaseActivityInterface;
import com.android.quickstep.GestureState;
import com.android.quickstep.InputConsumer;
@@ -209,7 +209,7 @@
SystemUiProxy.INSTANCE.get(mContext).onAssistantProgress(0f);
}
});
- animator.setInterpolator(Interpolators.DEACCEL_2);
+ animator.setInterpolator(Interpolators.DECELERATE_2);
animator.start();
}
mPassedSlop = false;
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
index 03f8eef..858999e 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
@@ -4,7 +4,6 @@
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
-import com.android.launcher3.tracing.InputConsumerProto;
import com.android.quickstep.InputConsumer;
import com.android.systemui.shared.system.InputMonitorCompat;
@@ -54,9 +53,4 @@
mDelegate.onMotionEvent(event);
event.recycle();
}
-
- @Override
- public void writeToProtoInternal(InputConsumerProto.Builder inputConsumerProto) {
- mDelegate.writeToProtoInternal(inputConsumerProto);
- }
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index 59a9582..2a35584 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -39,9 +39,9 @@
import android.view.RemoteAnimationTarget;
import android.view.VelocityTracker;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatedFloat;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.DisplayController;
@@ -153,8 +153,7 @@
if (!mThresholdCrossed) {
// Cancel interaction in case of multi-touch interaction
int ptrIdx = ev.getActionIndex();
- if (!mDeviceState.getRotationTouchHelper().isInSwipeUpTouchRegion(ev, ptrIdx,
- mGestureState.getActivityInterface())) {
+ if (!mDeviceState.getRotationTouchHelper().isInSwipeUpTouchRegion(ev, ptrIdx)) {
int action = ev.getAction();
ev.setAction(ACTION_CANCEL);
finishTouchTracking(ev);
@@ -204,7 +203,7 @@
// Animate back to fullscreen before finishing
ObjectAnimator animator = mProgress.animateToValue(mProgress.value, 0);
animator.setDuration(100);
- animator.setInterpolator(Interpolators.ACCEL);
+ animator.setInterpolator(Interpolators.ACCELERATE);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
new file mode 100644
index 0000000..7a2b343
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.inputconsumers;
+
+import android.content.Context;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.R;
+import com.android.launcher3.util.ResourceBasedOverride;
+
+/**
+ * Class for extending nav handle long press behavior
+ */
+public class NavHandleLongPressHandler implements ResourceBasedOverride {
+
+ /** Creates NavHandleLongPressHandler as specified by overrides */
+ public static NavHandleLongPressHandler newInstance(Context context) {
+ return Overrides.getObject(NavHandleLongPressHandler.class, context,
+ R.string.nav_handle_long_press_handler_class);
+ }
+
+ /**
+ * Called when nav handle is long pressed to get the Runnable that should be executed by the
+ * caller to invoke long press behavior. If null is returned that means long press couldn't be
+ * handled.
+ * <p>
+ * A Runnable is returned here to ensure the InputConsumer can call
+ * {@link android.view.InputMonitor#pilferPointers()} before invoking the long press behavior
+ * since pilfering can break the long press behavior.
+ */
+ public @Nullable Runnable getLongPressRunnable() {
+ return null;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
new file mode 100644
index 0000000..0b11b00
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.inputconsumers;
+
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
+import android.content.Context;
+import android.view.GestureDetector;
+import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.MotionEvent;
+
+import com.android.launcher3.R;
+import com.android.launcher3.util.DisplayController;
+import com.android.quickstep.InputConsumer;
+import com.android.systemui.shared.system.InputMonitorCompat;
+
+/**
+ * Listens for a long press
+ */
+public class NavHandleLongPressInputConsumer extends DelegateInputConsumer {
+
+ private final GestureDetector mLongPressDetector;
+ private final NavHandleLongPressHandler mNavHandleLongPressHandler;
+ private final float mNavHandleWidth;
+ private final float mScreenWidth;
+
+ public NavHandleLongPressInputConsumer(Context context, InputConsumer delegate,
+ InputMonitorCompat inputMonitor) {
+ super(delegate, inputMonitor);
+ mNavHandleWidth = context.getResources().getDimensionPixelSize(
+ R.dimen.navigation_home_handle_width);
+ mScreenWidth = DisplayController.INSTANCE.get(context).getInfo().currentSize.x;
+
+ mNavHandleLongPressHandler = NavHandleLongPressHandler.newInstance(context);
+
+ mLongPressDetector = new GestureDetector(context, new SimpleOnGestureListener() {
+ @Override
+ public void onLongPress(MotionEvent motionEvent) {
+ if (isInArea(motionEvent.getRawX())) {
+ Runnable longPressRunnable = mNavHandleLongPressHandler.getLongPressRunnable();
+ if (longPressRunnable != null) {
+ setActive(motionEvent);
+
+ MAIN_EXECUTOR.post(longPressRunnable);
+ }
+ }
+ }
+ });
+ }
+
+ @Override
+ public int getType() {
+ return TYPE_NAV_HANDLE_LONG_PRESS | mDelegate.getType();
+ }
+
+ @Override
+ public void onMotionEvent(MotionEvent ev) {
+ mLongPressDetector.onTouchEvent(ev);
+ if (mState != STATE_ACTIVE) {
+ mDelegate.onMotionEvent(ev);
+ }
+ }
+
+ protected boolean isInArea(float x) {
+ float areaFromMiddle = mNavHandleWidth / 2.0f;
+ float distFromMiddle = Math.abs(mScreenWidth / 2.0f - x);
+
+ return distFromMiddle < areaFromMiddle;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index f9cd4ee..7e61167 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -28,7 +28,6 @@
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.Utilities.squaredHypot;
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;
import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
@@ -49,7 +48,6 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
-import com.android.launcher3.tracing.InputConsumerProto;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.AbsSwipeUpHandler;
@@ -229,8 +227,7 @@
// Until we detect the gesture, handle events as we receive them
mInputEventReceiver.setBatchingEnabled(false);
- Object traceToken = TraceHelper.INSTANCE.beginSection(DOWN_EVT,
- FLAG_CHECK_FOR_RACE_CONDITIONS);
+ TraceHelper.INSTANCE.beginSection(DOWN_EVT);
mActivePointerId = ev.getPointerId(0);
mDownPos.set(ev.getX(), ev.getY());
mLastPos.set(mDownPos);
@@ -241,15 +238,14 @@
startTouchTrackingForWindowAnimation(ev.getEventTime());
}
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
break;
}
case ACTION_POINTER_DOWN: {
if (!mPassedPilferInputSlop) {
// Cancel interaction in case of multi-touch interaction
int ptrIdx = ev.getActionIndex();
- if (!mRotationTouchHelper.isInSwipeUpTouchRegion(ev, ptrIdx,
- mActivityInterface)) {
+ if (!mRotationTouchHelper.isInSwipeUpTouchRegion(ev, ptrIdx)) {
forceCancelGesture(ev);
}
}
@@ -282,7 +278,8 @@
if (!mIsDeferredDownTarget) {
// Normal gesture, ensure we pass the drag slop before we start tracking
// the gesture
- if (Math.abs(displacement) > mTouchSlop) {
+ if (mGestureState.isTrackpadGesture() || Math.abs(displacement)
+ > mTouchSlop) {
mPassedWindowMoveSlop = true;
mStartDisplacement = Math.min(displacement, -mTouchSlop);
}
@@ -291,8 +288,8 @@
float horizontalDist = Math.abs(displacementX);
float upDist = -displacement;
- boolean passedSlop = squaredHypot(displacementX, displacementY)
- >= mSquaredTouchSlop;
+ boolean passedSlop = mGestureState.isTrackpadGesture() || squaredHypot(
+ displacementX, displacementY) >= mSquaredTouchSlop;
if (!mPassedSlopOnThisGesture && passedSlop) {
mPassedSlopOnThisGesture = true;
@@ -352,7 +349,8 @@
mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
}
- if (mDeviceState.isFullyGesturalNavMode()) {
+ if (mDeviceState.isFullyGesturalNavMode()
+ || mGestureState.isTrackpadGesture()) {
boolean minSwipeMet = upDist >= Math.max(mMotionPauseMinDisplacement,
mInteractionHandler.getThresholdToAllowMotionPause());
mInteractionHandler.setCanSlowSwipeGoHome(minSwipeMet);
@@ -417,11 +415,11 @@
* the animation can still be running.
*/
private void finishTouchTracking(MotionEvent ev) {
- Object traceToken = TraceHelper.INSTANCE.beginSection(UP_EVT,
- FLAG_CHECK_FOR_RACE_CONDITIONS);
+ TraceHelper.INSTANCE.beginSection(UP_EVT);
+ boolean isCanceled = ev.getActionMasked() == ACTION_CANCEL;
if (mPassedWindowMoveSlop && mInteractionHandler != null) {
- if (ev.getActionMasked() == ACTION_CANCEL) {
+ if (isCanceled) {
mInteractionHandler.onGestureCancelled();
} else {
mVelocityTracker.computeCurrentVelocity(PX_PER_MS);
@@ -443,8 +441,10 @@
if (mActiveCallbacks != null && mInteractionHandler != null) {
if (mTaskAnimationManager.isRecentsAnimationRunning()) {
// The animation started, but with no movement, in this case, there will be no
- // animateToProgress so we have to manually finish here.
- mTaskAnimationManager.finishRunningRecentsAnimation(false /* toHome */);
+ // animateToProgress so we have to manually finish here. In the case of
+ // ACTION_CANCEL, someone else may be doing something so finish synchronously.
+ mTaskAnimationManager.finishRunningRecentsAnimation(false /* toHome */,
+ isCanceled /* forceFinish */);
} else {
// The animation hasn't started yet, so insert a replacement handler into the
// callbacks which immediately finishes the animation after it starts.
@@ -455,7 +455,7 @@
onInteractionGestureFinished();
}
cleanupAfterGesture();
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
}
private void cleanupAfterGesture() {
@@ -512,13 +512,6 @@
return !mPassedPilferInputSlop;
}
- @Override
- public void writeToProtoInternal(InputConsumerProto.Builder inputConsumerProto) {
- if (mInteractionHandler != null) {
- mInteractionHandler.writeToProto(inputConsumerProto);
- }
- }
-
/**
* A listener which just finishes the animation immediately after starting. Replaces
* AbsSwipeUpHandler if the gesture itself finishes before the animation even starts.
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java
index eac09ad..c9c64b6 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java
@@ -15,7 +15,7 @@
*/
package com.android.quickstep.inputconsumers;
-import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
+import static com.android.app.animation.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.touch.BaseSwipeDetector.calculateDuration;
import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_POSITIVE;
import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL;
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
index fbe7fde..200b37d 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
@@ -19,7 +19,7 @@
import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
import static com.android.launcher3.Utilities.squaredHypot;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_CURSOR_HOVER_STATES;
+import static com.android.launcher3.config.FeatureFlags.enableCursorHoverStates;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_TOUCHING;
import android.content.Context;
@@ -28,6 +28,7 @@
import android.graphics.Rect;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.InputDevice;
import android.view.MotionEvent;
import androidx.annotation.Nullable;
@@ -36,10 +37,13 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.taskbar.TaskbarActivityContext;
+import com.android.launcher3.taskbar.TaskbarThresholdUtils;
import com.android.launcher3.taskbar.TaskbarTranslationController.TransitionCallback;
+import com.android.launcher3.taskbar.bubbles.BubbleControllers;
import com.android.launcher3.touch.OverScroll;
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.InputConsumer;
+import com.android.quickstep.OverviewCommandHelper;
import com.android.systemui.shared.system.InputMonitorCompat;
/**
@@ -50,6 +54,7 @@
public class TaskbarUnstashInputConsumer extends DelegateInputConsumer {
private final TaskbarActivityContext mTaskbarActivityContext;
+ private final OverviewCommandHelper mOverviewCommandHelper;
private final GestureDetector mLongPressDetector;
private final float mSquaredTouchSlop;
@@ -62,6 +67,7 @@
private final int mTaskbarNavThresholdY;
private final boolean mIsTaskbarAllAppsOpen;
private boolean mHasPassedTaskbarNavThreshold;
+ private boolean mIsInBubbleBarArea;
private final PointF mDownPos = new PointF();
private final PointF mLastPos = new PointF();
@@ -78,16 +84,19 @@
private final @Nullable TransitionCallback mTransitionCallback;
public TaskbarUnstashInputConsumer(Context context, InputConsumer delegate,
- InputMonitorCompat inputMonitor, TaskbarActivityContext taskbarActivityContext) {
+ InputMonitorCompat inputMonitor, TaskbarActivityContext taskbarActivityContext,
+ OverviewCommandHelper overviewCommandHelper) {
super(delegate, inputMonitor);
mTaskbarActivityContext = taskbarActivityContext;
+ mOverviewCommandHelper = overviewCommandHelper;
// TODO(b/270395798): remove this when cleaning up old Persistent Taskbar code.
mSquaredTouchSlop = Utilities.squaredTouchSlop(context);
mScreenWidth = taskbarActivityContext.getDeviceProfile().widthPx;
Resources res = context.getResources();
mUnstashArea = res.getDimensionPixelSize(R.dimen.taskbar_unstash_input_area);
- mTaskbarNavThreshold = res.getDimensionPixelSize(R.dimen.taskbar_from_nav_threshold);
+ mTaskbarNavThreshold = TaskbarThresholdUtils.getFromNavThreshold(res,
+ taskbarActivityContext.getDeviceProfile());
mTaskbarNavThresholdY = taskbarActivityContext.getDeviceProfile().heightPx
- mTaskbarNavThreshold;
mIsTaskbarAllAppsOpen =
@@ -121,7 +130,11 @@
public void onMotionEvent(MotionEvent ev) {
mLongPressDetector.onTouchEvent(ev);
if (mState != STATE_ACTIVE) {
- mDelegate.onMotionEvent(ev);
+ boolean isStashedTaskbarHovered = isMouseEvent(ev)
+ && isStashedTaskbarHovered((int) ev.getX(), (int) ev.getY());
+ if (!isStashedTaskbarHovered) {
+ mDelegate.onMotionEvent(ev);
+ }
// Only show the transient task bar if the touch events are on the screen.
if (mTaskbarActivityContext != null && !isTrackpadMotionEvent(ev)) {
@@ -136,7 +149,7 @@
mHasPassedTaskbarNavThreshold = false;
mTaskbarActivityContext.setAutohideSuspendFlag(
FLAG_AUTOHIDE_SUSPEND_TOUCHING, true);
- if (isInArea(x)) {
+ if (isInTaskbarArea(x)) {
if (!mIsTransientTaskbar) {
mLongPressDownX = x;
mLongPressDownY = y;
@@ -145,10 +158,12 @@
mCanceledUnstashHint = false;
}
}
-
if (mTransitionCallback != null && !mIsTaskbarAllAppsOpen) {
mTransitionCallback.onActionDown();
}
+ if (mIsTransientTaskbar && isInBubbleBarArea(x)) {
+ mIsInBubbleBarArea = true;
+ }
break;
case MotionEvent.ACTION_POINTER_UP:
int ptrIdx = ev.getActionIndex();
@@ -185,7 +200,11 @@
if (!mHasPassedTaskbarNavThreshold && passedTaskbarNavThreshold) {
mHasPassedTaskbarNavThreshold = true;
- mTaskbarActivityContext.onSwipeToUnstashTaskbar();
+ if (mIsInBubbleBarArea) {
+ mTaskbarActivityContext.onSwipeToOpenBubblebar();
+ } else {
+ mTaskbarActivityContext.onSwipeToUnstashTaskbar();
+ }
}
if (dY < 0) {
@@ -208,21 +227,37 @@
mTransitionCallback.onActionEnd();
}
mHasPassedTaskbarNavThreshold = false;
+ mIsInBubbleBarArea = false;
+ break;
+ case MotionEvent.ACTION_BUTTON_RELEASE:
+ if (isStashedTaskbarHovered) {
+ mOverviewCommandHelper.addCommand(OverviewCommandHelper.TYPE_HOME);
+ }
break;
}
}
}
}
- private boolean isInArea(float x) {
+ private boolean isInTaskbarArea(float x) {
float areaFromMiddle = mUnstashArea / 2.0f;
float distFromMiddle = Math.abs(mScreenWidth / 2.0f - x);
return distFromMiddle < areaFromMiddle;
}
+ private boolean isInBubbleBarArea(float x) {
+ if (mTaskbarActivityContext != null && mIsTransientTaskbar) {
+ BubbleControllers controllers = mTaskbarActivityContext.getBubbleControllers();
+ if (controllers == null) return false;
+ Rect bubbleBarBounds = controllers.bubbleBarViewController.getBubbleBarBounds();
+ return x >= bubbleBarBounds.left && x <= bubbleBarBounds.right;
+ }
+ return false;
+ }
+
private void onLongPressDetected(MotionEvent motionEvent) {
if (mTaskbarActivityContext != null
- && isInArea(motionEvent.getRawX())
+ && isInTaskbarArea(motionEvent.getRawX())
&& !mIsTransientTaskbar) {
boolean taskBarPressed = mTaskbarActivityContext.onLongPressToUnstashTaskbar();
if (taskBarPressed) {
@@ -241,7 +276,7 @@
*/
@Override
public void onHoverEvent(MotionEvent ev) {
- if (!ENABLE_CURSOR_HOVER_STATES.get() || mTaskbarActivityContext == null
+ if (!enableCursorHoverStates() || mTaskbarActivityContext == null
|| !mTaskbarActivityContext.isTaskbarStashed()) {
return;
}
@@ -255,19 +290,17 @@
private void updateHoveredTaskbarState(int x, int y) {
DeviceProfile dp = mTaskbarActivityContext.getDeviceProfile();
- mStashedTaskbarHandleBounds.set(
+ mBottomEdgeBounds.set(
(dp.widthPx - (int) mUnstashArea) / 2,
- dp.heightPx - dp.stashedTaskbarHeight,
+ dp.heightPx - mStashedTaskbarBottomEdge,
(int) (((dp.widthPx - mUnstashArea) / 2) + mUnstashArea),
dp.heightPx);
- mBottomEdgeBounds.set(mStashedTaskbarHandleBounds);
- mBottomEdgeBounds.top = dp.heightPx - mStashedTaskbarBottomEdge;
if (mBottomEdgeBounds.contains(x, y)) {
// If hovering stashed taskbar and then hover screen bottom edge, unstash it.
mTaskbarActivityContext.onSwipeToUnstashTaskbar();
mIsStashedTaskbarHovered = false;
- } else if (!mStashedTaskbarHandleBounds.contains(x, y)) {
+ } else if (!isStashedTaskbarHovered(x, y)) {
// If exit hovering stashed taskbar, remove hint.
startStashedTaskbarHover(/* isHovered = */ false);
}
@@ -275,18 +308,13 @@
private void updateUnhoveredTaskbarState(int x, int y) {
DeviceProfile dp = mTaskbarActivityContext.getDeviceProfile();
- mStashedTaskbarHandleBounds.set(
- (dp.widthPx - (int) mUnstashArea) / 2,
- dp.heightPx - dp.stashedTaskbarHeight,
- (int) (((dp.widthPx - mUnstashArea) / 2) + mUnstashArea),
- dp.heightPx);
mBottomEdgeBounds.set(
0,
dp.heightPx - mBottomScreenEdge,
dp.widthPx,
dp.heightPx);
- if (mStashedTaskbarHandleBounds.contains(x, y)) {
+ if (isStashedTaskbarHovered(x, y)) {
// If enter hovering stashed taskbar, start hint.
startStashedTaskbarHover(/* isHovered = */ true);
} else if (mBottomEdgeBounds.contains(x, y)) {
@@ -299,4 +327,23 @@
mTaskbarActivityContext.startTaskbarUnstashHint(isHovered, /* forceUnstash = */ true);
mIsStashedTaskbarHovered = isHovered;
}
+
+ private boolean isStashedTaskbarHovered(int x, int y) {
+ if (!mTaskbarActivityContext.isTaskbarStashed()
+ || mTaskbarActivityContext.isTaskbarAllAppsOpen()
+ || !enableCursorHoverStates()) {
+ return false;
+ }
+ DeviceProfile dp = mTaskbarActivityContext.getDeviceProfile();
+ mStashedTaskbarHandleBounds.set(
+ (dp.widthPx - (int) mUnstashArea) / 2,
+ dp.heightPx - dp.stashedTaskbarHeight,
+ (int) (((dp.widthPx - mUnstashArea) / 2) + mUnstashArea),
+ dp.heightPx);
+ return mStashedTaskbarHandleBounds.contains(x, y);
+ }
+
+ private boolean isMouseEvent(MotionEvent event) {
+ return event.getSource() == InputDevice.SOURCE_MOUSE;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/StatusBarInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TrackpadStatusBarInputConsumer.java
similarity index 91%
rename from quickstep/src/com/android/quickstep/inputconsumers/StatusBarInputConsumer.java
rename to quickstep/src/com/android/quickstep/inputconsumers/TrackpadStatusBarInputConsumer.java
index 898aa86..7ff9982 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/StatusBarInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TrackpadStatusBarInputConsumer.java
@@ -27,15 +27,15 @@
import com.android.quickstep.SystemUiProxy;
import com.android.systemui.shared.system.InputMonitorCompat;
-/** Allows the status bar to be pull down for notification shade */
-public class StatusBarInputConsumer extends DelegateInputConsumer {
+/** Allows the status bar to be pull down for notification shade using the trackpad. */
+public class TrackpadStatusBarInputConsumer extends DelegateInputConsumer {
private final SystemUiProxy mSystemUiProxy;
private final float mTouchSlop;
private final PointF mDown = new PointF();
private boolean mHasPassedTouchSlop;
- public StatusBarInputConsumer(Context context, InputConsumer delegate,
+ public TrackpadStatusBarInputConsumer(Context context, InputConsumer delegate,
InputMonitorCompat inputMonitor) {
super(delegate, inputMonitor);
@@ -79,7 +79,7 @@
private void dispatchTouchEvent(MotionEvent ev) {
if (mSystemUiProxy.isActive()) {
- mSystemUiProxy.onStatusBarMotionEvent(ev);
+ mSystemUiProxy.onStatusBarTrackpadEvent(ev);
}
}
}
diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
index 6619dd8..49814df 100644
--- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -15,10 +15,10 @@
*/
package com.android.quickstep.interaction;
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.Utilities.mapBoundToRange;
import static com.android.launcher3.Utilities.mapRange;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.OverviewComponentObserver.startHomeIntentSafely;
import android.animation.Animator;
@@ -95,11 +95,10 @@
private static final float ANIMATION_PAUSE_ALPHA_THRESHOLD = 0.1f;
- private TISBindHelper mTISBindHelper;
- private TISBinder mBinder;
- @Nullable private TaskbarManager mTaskbarManager = null;
-
private final AnimatedFloat mSwipeProgress = new AnimatedFloat(this::onSwipeProgressUpdate);
+
+ private TISBindHelper mTISBindHelper;
+
private BgDrawable mBackground;
private View mRootView;
private float mSwipeUpShift;
@@ -174,7 +173,7 @@
LOTTIE_TERTIARY_COLOR_TOKEN, R.color.all_set_bg_tertiary),
getTheme());
- startBackgroundAnimation();
+ startBackgroundAnimation(dp.isTablet);
}
private void runOnUiHelperThread(Runnable runnable) {
@@ -185,7 +184,7 @@
Executors.UI_HELPER_EXECUTOR.execute(runnable);
}
- private void startBackgroundAnimation() {
+ private void startBackgroundAnimation(boolean forTablet) {
if (!Utilities.ATLEAST_S || mVibrator == null) {
return;
}
@@ -201,7 +200,7 @@
.addPrimitive(supportsThud
? VibrationEffect.Composition.PRIMITIVE_THUD
: VibrationEffect.Composition.PRIMITIVE_TICK,
- /* scale= */ 1.0f,
+ /* scale= */ forTablet ? 1.0f : 0.3f,
/* delay= */ 50)
.compose();
@@ -233,29 +232,30 @@
}
private void setSetupUIVisible(boolean visible) {
- if (mBinder == null || mTaskbarManager == null) return;
- mTaskbarManager.setSetupUIVisible(visible);
+ TaskbarManager taskbarManager = mTISBindHelper.getTaskbarManager();
+ if (taskbarManager == null) return;
+ taskbarManager.setSetupUIVisible(visible);
}
@Override
protected void onResume() {
super.onResume();
maybeResumeOrPauseBackgroundAnimation();
- if (mBinder != null) {
+ TISBinder binder = mTISBindHelper.getBinder();
+ if (binder != null) {
setSetupUIVisible(true);
- mBinder.setSwipeUpProxy(this::createSwipeUpProxy);
+ binder.setSwipeUpProxy(this::createSwipeUpProxy);
}
}
private void onTISConnected(TISBinder binder) {
- mBinder = binder;
- mTaskbarManager = mBinder.getTaskbarManager();
setSetupUIVisible(isResumed());
- mBinder.setSwipeUpProxy(isResumed() ? this::createSwipeUpProxy : null);
- mBinder.setOverviewTargetChangeListener(mBinder::preloadOverviewForSUWAllSet);
- mBinder.preloadOverviewForSUWAllSet();
- if (mTaskbarManager != null) {
- mLauncherStartAnim = mTaskbarManager.createLauncherStartFromSuwAnim(MAX_SWIPE_DURATION);
+ binder.setSwipeUpProxy(isResumed() ? this::createSwipeUpProxy : null);
+ binder.setOverviewTargetChangeListener(binder::preloadOverviewForSUWAllSet);
+ binder.preloadOverviewForSUWAllSet();
+ TaskbarManager taskbarManager = binder.getTaskbarManager();
+ if (taskbarManager != null) {
+ mLauncherStartAnim = taskbarManager.createLauncherStartFromSuwAnim(MAX_SWIPE_DURATION);
}
}
@@ -271,10 +271,11 @@
}
private void clearBinderOverride() {
- if (mBinder != null) {
+ TISBinder binder = mTISBindHelper.getBinder();
+ if (binder != null) {
setSetupUIVisible(false);
- mBinder.setSwipeUpProxy(null);
- mBinder.setOverviewTargetChangeListener(null);
+ binder.setSwipeUpProxy(null);
+ binder.setOverviewTargetChangeListener(null);
}
}
@@ -302,7 +303,7 @@
}
private AnimatedFloat createSwipeUpProxy(GestureState state) {
- if (state.getRunningTaskId() != getTaskId()) {
+ if (state.getTopRunningTaskId() != getTaskId()) {
return null;
}
mSwipeProgress.updateValue(0);
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
index 5d25279..631cff7 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
@@ -23,9 +23,9 @@
import android.graphics.PointF;
import android.view.View;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.Interpolators;
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult;
import com.android.quickstep.util.LottieAnimationColorUtils;
@@ -154,7 +154,7 @@
@Override
public void onBackGestureAttempted(BackGestureResult result) {
- if (skipGestureAttempt()) {
+ if (isGestureCompleted()) {
return;
}
switch (mTutorialType) {
@@ -172,7 +172,7 @@
@Override
public void onBackGestureProgress(float diffx, float diffy, boolean isLeftGesture) {
- if (skipGestureAttempt()) {
+ if (isGestureCompleted()) {
return;
}
@@ -183,7 +183,7 @@
/* upperBound = */ 1f,
/* toMin = */ 1f,
/* toMax = */ EXITING_APP_MIN_SIZE_PERCENTAGE,
- Interpolators.DEACCEL);
+ Interpolators.DECELERATE);
// shrink the exiting app as we progress through the back gesture
mExitingAppView.setPivotX(isLeftGesture ? mScreenWidth : 0);
@@ -197,7 +197,7 @@
/* upperBound = */ 1f,
/* toMin = */ 0,
/* toMax = */ mExitingAppMargin,
- Interpolators.DEACCEL)
+ Interpolators.DECELERATE)
* (isLeftGesture ? -1 : 1));
// round the corners of the exiting app as we progress through the back gesture
@@ -241,7 +241,7 @@
@Override
public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) {
- if (skipGestureAttempt()) {
+ if (isGestureCompleted()) {
return;
}
if (mTutorialType == BACK_NAVIGATION_COMPLETE) {
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java
index a16b239..b379baa 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java
@@ -42,6 +42,12 @@
super(fromTutorialMenu);
}
+ @NonNull
+ @Override
+ TutorialType getDefaultTutorialType() {
+ return TutorialType.BACK_NAVIGATION;
+ }
+
@Nullable
@Override
Integer getEdgeAnimationResId() {
diff --git a/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java b/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java
index 8eb4059..a9dcad8 100644
--- a/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java
+++ b/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java
@@ -40,8 +40,8 @@
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.R;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.util.VibratorWrapper;
diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
index 62726a0..d102502 100644
--- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
@@ -53,18 +53,15 @@
static final String KEY_USE_TUTORIAL_MENU = "use_tutorial_menu";
@Nullable private TutorialType[] mTutorialSteps;
- private GestureSandboxFragment mFragment;
+ private GestureSandboxFragment mCurrentFragment;
+ private GestureSandboxFragment mPendingFragment;
private int mCurrentStep;
private int mNumSteps;
- private boolean mShowRotationPrompt;
private SharedPreferences mSharedPrefs;
private StatsLogManager mStatsLogManager;
-
- private View mRotationPrompt;
private TISBindHelper mTISBindHelper;
- private TISBinder mBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -83,7 +80,7 @@
&& args.getBoolean(KEY_USE_TUTORIAL_MENU, false)) {
mTutorialSteps = null;
TutorialType tutorialTypeOverride = (TutorialType) args.get(KEY_TUTORIAL_TYPE);
- mFragment = tutorialTypeOverride == null
+ mCurrentFragment = tutorialTypeOverride == null
? new MenuFragment()
: makeTutorialFragment(
tutorialTypeOverride,
@@ -91,16 +88,15 @@
/* fromMenu= */ true);
} else {
mTutorialSteps = getTutorialSteps(args);
- mFragment = makeTutorialFragment(
+ mCurrentFragment = makeTutorialFragment(
mTutorialSteps[mCurrentStep - 1],
gestureComplete,
/* fromMenu= */ false);
}
getSupportFragmentManager().beginTransaction()
- .add(R.id.gesture_tutorial_fragment_container, mFragment)
+ .add(R.id.gesture_tutorial_fragment_container, mCurrentFragment)
.commit();
- mRotationPrompt = findViewById(R.id.rotation_prompt);
if (FeatureFlags.ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) {
correctUserOrientation();
}
@@ -128,34 +124,45 @@
DeviceProfile deviceProfile = InvariantDeviceProfile.INSTANCE.get(
getApplicationContext()).getDeviceProfile(this);
if (deviceProfile.isTablet) {
- mShowRotationPrompt = getResources().getConfiguration().orientation
+ boolean showRotationPrompt = getResources().getConfiguration().orientation
== ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
- updateVisibility(mRotationPrompt, mShowRotationPrompt ? View.VISIBLE : View.GONE);
+
+ GestureSandboxFragment recreatedFragment =
+ showRotationPrompt || mPendingFragment == null
+ ? null : mPendingFragment.recreateFragment();
+ showFragment(showRotationPrompt
+ ? new RotationPromptFragment()
+ : recreatedFragment == null
+ ? mCurrentFragment : recreatedFragment);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
- void updateVisibility(View view, int visibility) {
- if (view == null || view.getVisibility() == visibility) {
- return;
+ private void showFragment(@NonNull GestureSandboxFragment fragment) {
+ if (mCurrentFragment.recreateFragment() != null) {
+ mPendingFragment = mCurrentFragment;
}
- view.setVisibility(visibility);
+ mCurrentFragment = fragment;
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.gesture_tutorial_fragment_container, mCurrentFragment)
+ .runOnCommit(() -> mCurrentFragment.onAttachedToWindow())
+ .commit();
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
- if (mFragment.shouldDisableSystemGestures()) {
+ if (mCurrentFragment.shouldDisableSystemGestures()) {
disableSystemGestures();
}
- mFragment.onAttachedToWindow();
+ mCurrentFragment.onAttachedToWindow();
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
- mFragment.onDetachedFromWindow();
+ mCurrentFragment.onDetachedFromWindow();
}
@Override
@@ -170,14 +177,10 @@
protected void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
savedInstanceState.putStringArray(KEY_TUTORIAL_STEPS, getTutorialStepNames());
savedInstanceState.putInt(KEY_CURRENT_STEP, mCurrentStep);
- mFragment.onSaveInstanceState(savedInstanceState);
+ mCurrentFragment.onSaveInstanceState(savedInstanceState);
super.onSaveInstanceState(savedInstanceState);
}
- protected boolean isRotationPromptShowing() {
- return mShowRotationPrompt;
- }
-
protected SharedPreferences getSharedPrefs() {
return mSharedPrefs;
}
@@ -206,7 +209,7 @@
*/
public void continueTutorial() {
if (isTutorialComplete() || mTutorialSteps == null) {
- mFragment.close();
+ mCurrentFragment.close();
return;
}
launchTutorialStep(mTutorialSteps[mCurrentStep], false);
@@ -225,20 +228,12 @@
* the menu when complete.
*/
public void launchTutorialStep(@NonNull TutorialType tutorialType, boolean fromMenu) {
- mFragment = makeTutorialFragment(tutorialType, false, fromMenu);
- getSupportFragmentManager().beginTransaction()
- .replace(R.id.gesture_tutorial_fragment_container, mFragment)
- .runOnCommit(() -> mFragment.onAttachedToWindow())
- .commit();
+ showFragment(makeTutorialFragment(tutorialType, false, fromMenu));
}
/** Launches the gesture nav tutorial menu page */
public void launchTutorialMenu() {
- mFragment = new MenuFragment();
- getSupportFragmentManager().beginTransaction()
- .replace(R.id.gesture_tutorial_fragment_container, mFragment)
- .runOnCommit(() -> mFragment.onAttachedToWindow())
- .commit();
+ showFragment(new MenuFragment());
}
private String[] getTutorialStepNames() {
@@ -321,7 +316,6 @@
}
private void onTISConnected(TISBinder binder) {
- mBinder = binder;
updateServiceState(isResumed());
}
@@ -332,8 +326,9 @@
}
private void updateServiceState(boolean isEnabled) {
- if (mBinder != null) {
- mBinder.setGestureBlockedTaskId(isEnabled ? getTaskId() : -1);
+ TISBinder binder = mTISBindHelper.getBinder();
+ if (binder != null) {
+ binder.setGestureBlockedTaskId(isEnabled ? getTaskId() : -1);
}
}
diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxFragment.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxFragment.java
index d52f19a..08f2989 100644
--- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxFragment.java
@@ -17,6 +17,7 @@
import android.app.Activity;
+import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
@@ -27,6 +28,11 @@
void onDetachedFromWindow() {}
+ @Nullable
+ GestureSandboxFragment recreateFragment() {
+ return null;
+ }
+
boolean shouldDisableSystemGestures() {
return true;
}
diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
index 0aa80d3..daac99b 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
@@ -147,7 +147,7 @@
@Override
public void onBackGestureAttempted(BackGestureResult result) {
- if (skipGestureAttempt()) {
+ if (isGestureCompleted()) {
return;
}
switch (mTutorialType) {
@@ -174,7 +174,7 @@
@Override
public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) {
- if (skipGestureAttempt()) {
+ if (isGestureCompleted()) {
return;
}
switch (mTutorialType) {
diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java
index bced8c4..3e924d7 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java
@@ -41,6 +41,12 @@
super(fromTutorialMenu);
}
+ @NonNull
+ @Override
+ TutorialType getDefaultTutorialType() {
+ return TutorialType.HOME_NAVIGATION;
+ }
+
@Nullable
@Override
Integer getEdgeAnimationResId() {
diff --git a/quickstep/src/com/android/quickstep/interaction/MenuFragment.java b/quickstep/src/com/android/quickstep/interaction/MenuFragment.java
index 46f79b1..dbf141b 100644
--- a/quickstep/src/com/android/quickstep/interaction/MenuFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/MenuFragment.java
@@ -19,7 +19,6 @@
import static com.android.quickstep.interaction.GestureSandboxActivity.KEY_TUTORIAL_TYPE;
import static com.android.quickstep.interaction.GestureSandboxActivity.KEY_USE_TUTORIAL_MENU;
-import android.graphics.Rect;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -28,33 +27,23 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.R;
/** Displays the gesture nav tutorial menu. */
public final class MenuFragment extends GestureSandboxFragment {
- @NonNull private Rect mInsets = new Rect();
-
+ @NonNull
@Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mInsets = InvariantDeviceProfile.INSTANCE.get(getContext())
- .getDeviceProfile(getContext()).getInsets();
+ GestureSandboxFragment recreateFragment() {
+ return new MenuFragment();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
- View root = inflater.inflate(
+ final View root = inflater.inflate(
R.layout.gesture_tutorial_step_menu, container, false);
- root.setPadding(
- root.getPaddingLeft() + mInsets.left,
- root.getPaddingTop() + mInsets.top,
- root.getPaddingRight() + mInsets.right,
- root.getPaddingBottom() + mInsets.bottom);
-
root.findViewById(R.id.gesture_tutorial_menu_home_button).setOnClickListener(
v -> launchTutorialStep(TutorialController.TutorialType.HOME_NAVIGATION));
root.findViewById(R.id.gesture_tutorial_menu_back_button).setOnClickListener(
diff --git a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
index 6cee690..c4a2216 100644
--- a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
+++ b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
@@ -60,12 +60,11 @@
NavBarGestureHandler(Context context) {
mContext = context;
DisplayController.Info displayInfo = DisplayController.INSTANCE.get(mContext).getInfo();
- final int displayRotation = displayInfo.rotation;
Point currentSize = displayInfo.currentSize;
mDisplaySize.set(currentSize.x, currentSize.y);
mSwipeUpTouchTracker =
new TriggerSwipeUpTouchTracker(context, true /*disableHorizontalSwipe*/,
- new NavBarPosition(NavigationMode.NO_BUTTON, displayRotation),
+ new NavBarPosition(NavigationMode.NO_BUTTON, displayInfo),
null /*onInterceptTouch*/, this);
mMotionPauseDetector = new MotionPauseDetector(context);
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
index 454dd17..afdc1e5 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
@@ -15,7 +15,7 @@
*/
package com.android.quickstep.interaction;
-import static com.android.launcher3.anim.Interpolators.ACCEL;
+import static com.android.app.animation.Interpolators.ACCELERATE;
import static com.android.launcher3.config.FeatureFlags.ENABLE_NEW_GESTURE_NAV_TUTORIAL;
import android.animation.Animator;
@@ -179,7 +179,7 @@
@Override
public void onBackGestureAttempted(BackGestureResult result) {
- if (skipGestureAttempt()) {
+ if (isGestureCompleted()) {
return;
}
switch (mTutorialType) {
@@ -206,7 +206,7 @@
@Override
public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) {
- if (skipGestureAttempt()) {
+ if (isGestureCompleted()) {
return;
}
switch (mTutorialType) {
@@ -254,7 +254,7 @@
public void animateTaskViewToOverview(boolean animateDelayedSuccessFeedback) {
PendingAnimation anim = new PendingAnimation(TASK_VIEW_END_ANIMATION_DURATION_MILLIS);
anim.setFloat(mTaskViewSwipeUpAnimation
- .getCurrentShift(), AnimatedFloat.VALUE, 1, ACCEL);
+ .getCurrentShift(), AnimatedFloat.VALUE, 1, ACCELERATE);
if (animateDelayedSuccessFeedback) {
anim.addListener(new AnimatorListenerAdapter() {
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
index 01074dd..ee1c460 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
@@ -41,6 +41,12 @@
super(fromTutorialMenu);
}
+ @NonNull
+ @Override
+ TutorialType getDefaultTutorialType() {
+ return TutorialType.OVERVIEW_NAVIGATION;
+ }
+
@Nullable
@Override
Integer getEdgeAnimationResId() {
diff --git a/quickstep/src/com/android/quickstep/interaction/RotationPromptFragment.java b/quickstep/src/com/android/quickstep/interaction/RotationPromptFragment.java
new file mode 100644
index 0000000..89af647
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/interaction/RotationPromptFragment.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.interaction;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.R;
+
+/** Displays the prompt requesting that the user rotates their device. */
+public class RotationPromptFragment extends GestureSandboxFragment {
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.gesture_tutorial_rotation_prompt, container, false);
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index 558d5dc..87defc5 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -18,7 +18,7 @@
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
-import static com.android.launcher3.anim.Interpolators.ACCEL;
+import static com.android.app.animation.Interpolators.ACCELERATE;
import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import static com.android.quickstep.AbsSwipeUpHandler.MAX_SWIPE_DURATION;
@@ -171,14 +171,14 @@
PendingAnimation anim = new PendingAnimation(300);
if (toOverviewFirst) {
anim.setFloat(mTaskViewSwipeUpAnimation
- .getCurrentShift(), AnimatedFloat.VALUE, 1, ACCEL);
+ .getCurrentShift(), AnimatedFloat.VALUE, 1, ACCELERATE);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation, boolean isReverse) {
PendingAnimation fadeAnim =
new PendingAnimation(TASK_VIEW_END_ANIMATION_DURATION_MILLIS);
fadeAnim.setFloat(mTaskViewSwipeUpAnimation
- .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCEL);
+ .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCELERATE);
if (resetViews) {
fadeAnim.addListener(mResetTaskView);
}
@@ -213,7 +213,7 @@
});
} else {
anim.setFloat(mTaskViewSwipeUpAnimation
- .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCEL);
+ .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCELERATE);
if (resetViews) {
anim.addListener(mResetTaskView);
}
@@ -239,8 +239,8 @@
mFakeTaskView.setVisibility(View.VISIBLE);
PendingAnimation anim = new PendingAnimation(300);
anim.setFloat(mTaskViewSwipeUpAnimation
- .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCEL);
- anim.setViewAlpha(mFakeTaskView, 1, ACCEL);
+ .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCELERATE);
+ anim.setViewAlpha(mFakeTaskView, 1, ACCELERATE);
anim.addListener(mResetTaskView);
AnimatorSet animset = anim.buildAnim();
if (animateTaskbar) {
@@ -260,7 +260,7 @@
mTaskViewSwipeUpAnimation.handleSwipeUpToHome(finalVelocity);
// After home animation finishes, fade out and run onEndRunnable.
PendingAnimation fadeAnim = new PendingAnimation(300);
- fadeAnim.setViewAlpha(mFakeIconView, 0, ACCEL);
+ fadeAnim.setViewAlpha(mFakeIconView, 0, ACCELERATE);
final View hotseatIconView = mHotseatIconView;
if (hotseatIconView != null) {
hotseatIconView.setVisibility(INVISIBLE);
@@ -282,7 +282,7 @@
@Override
public void setNavBarGestureProgress(@Nullable Float displacement) {
- if (skipGestureAttempt()) {
+ if (isGestureCompleted()) {
return;
}
if (mTutorialType == HOME_NAVIGATION_COMPLETE
@@ -303,7 +303,7 @@
@Override
public void onMotionPaused(boolean unused) {
- if (skipGestureAttempt()) {
+ if (isGestureCompleted()) {
return;
}
if (mShowTasks) {
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index 4a1fec3..545a94d 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -226,13 +226,11 @@
return;
}
Matrix scaleMatrix = new Matrix();
- float pivotX = mScreenWidth / 2f;
- float pivotY = mScreenHeight;
float scaleFactor = mScreenWidth / animationBoundsRect.width();
+ float heightTranslate = (mScreenHeight - (scaleFactor * animationBoundsRect.height()));
- scaleMatrix.postScale(scaleFactor, scaleFactor, pivotX, pivotY);
- scaleMatrix.postTranslate(0,
- mTutorialFragment.getDeviceProfile().heightPx - animationBoundsRect.height());
+ scaleMatrix.postScale(scaleFactor, scaleFactor);
+ scaleMatrix.postTranslate(0, heightTranslate);
mAnimatedGestureDemonstration.setImageMatrix(scaleMatrix);
}
@@ -489,10 +487,6 @@
return mGestureCompleted;
}
- public boolean skipGestureAttempt() {
- return isGestureCompleted() || mTutorialFragment.isRotationPromptShowing();
- }
-
void hideFeedback() {
if (mFeedbackView.getVisibility() != View.VISIBLE) {
return;
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index 84326f5..a28cf58 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -100,6 +100,19 @@
return fragment;
}
+ @Nullable
+ @Override
+ GestureSandboxFragment recreateFragment() {
+ TutorialType tutorialType = mTutorialController == null
+ ? (mTutorialType == null
+ ? getDefaultTutorialType() : mTutorialType)
+ : mTutorialController.mTutorialType;
+ return newInstance(tutorialType, isGestureComplete(), mFromTutorialMenu);
+ }
+
+ @NonNull
+ abstract TutorialType getDefaultTutorialType();
+
TutorialFragment(boolean fromTutorialMenu) {
mFromTutorialMenu = fromTutorialMenu;
}
@@ -498,11 +511,6 @@
return activity != null ? activity.getStatsLogManager() : null;
}
- protected boolean isRotationPromptShowing() {
- GestureSandboxActivity activity = getGestureSandboxActivity();
- return activity != null && activity.isRotationPromptShowing();
- }
-
@Nullable
private SharedPreferences getSharedPreferences() {
GestureSandboxActivity activity = getGestureSandboxActivity();
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 6288937..b1daac4 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -62,14 +62,11 @@
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;
@@ -90,6 +87,7 @@
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 boolean DEBUG = !Utilities.isRunningInTestHarness();
private static final InstanceId DEFAULT_INSTANCE_ID = InstanceId.fakeInstanceId(0);
// LauncherAtom.ItemInfo.getDefaultInstance() should be used but until launcher proto migrates
// from nano to lite, bake constant to prevent robo test failure.
@@ -110,8 +108,6 @@
public static final CopyOnWriteArrayList<StatsLogConsumer> LOGS_CONSUMER =
new CopyOnWriteArrayList<>();
- private final Context mContext;
-
public StatsLogCompatManager(Context context) {
mContext = context;
}
@@ -331,6 +327,11 @@
if (!Utilities.ATLEAST_R) {
return;
}
+ if (DEBUG) {
+ String name = (event instanceof Enum) ? ((Enum) event).name() :
+ event.getId() + "";
+ Log.d(TAG, name);
+ }
LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
if (mSlice == null && mSliceItem != null) {
@@ -566,14 +567,16 @@
* Helps to construct and log statsd compatible impression events.
*/
private static class StatsCompatImpressionLogger implements StatsImpressionLogger {
- private int[] mResultTypeList = new int[]{};
- private int[] mResultCountList = new int[]{};
- private final List<Boolean> mAboveKeyboardList = new ArrayList<>();
- private int[] mUidList = new int[]{};
private InstanceId mInstanceId = DEFAULT_INSTANCE_ID;
private State mLauncherState = State.UNKNOWN;
private int mQueryLength = -1;
+ // Fields used for Impression Logging V2.
+ private int mResultType;
+ private boolean mAboveKeyboard = false;
+ private int mUid;
+ private int mResultSource;
+
@Override
public StatsImpressionLogger withInstanceId(InstanceId instanceId) {
this.mInstanceId = instanceId;
@@ -593,69 +596,60 @@
}
@Override
- public StatsImpressionLogger withResultType(IntArray resultType) {
- mResultTypeList = resultType.toArray();
+ public StatsImpressionLogger withResultType(int resultType) {
+ mResultType = resultType;
+ return this;
+ }
+
+
+ @Override
+ public StatsImpressionLogger withAboveKeyboard(boolean aboveKeyboard) {
+ mAboveKeyboard = aboveKeyboard;
return this;
}
@Override
- public StatsImpressionLogger withResultCount(IntArray resultCount) {
- mResultCountList = resultCount.toArray();
+ public StatsImpressionLogger withUid(int uid) {
+ mUid = uid;
return this;
}
@Override
- public StatsImpressionLogger withAboveKeyboard(List<Boolean> aboveKeyboard) {
- mAboveKeyboardList.clear();
- this.mAboveKeyboardList.addAll(aboveKeyboard);
- return this;
- }
-
- @Override
- public StatsImpressionLogger withUids(IntArray uid) {
- mUidList = uid.toArray();
+ public StatsImpressionLogger withResultSource(int resultSource) {
+ mResultSource = resultSource;
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.length; i++) {
- logStringBuilder.append(String.format(
- "\n ResultType = %s with ResultCount = %s with is_above_keyboard = %s"
- + " with uid = %s",
- mResultTypeList[i], mResultCountList[i],
- mAboveKeyboard[i], mUidList[i]));
- }
+ logStringBuilder.append(String.format("\n\tLauncherState = %s ", mLauncherState));
+ logStringBuilder.append(String.format("\tQueryLength = %s ", mQueryLength));
+ logStringBuilder.append(String.format(
+ "\n\t ResultType = %s is_above_keyboard = %s"
+ + " uid = %s result_source = %s",
+ mResultType,
+ mAboveKeyboard, mUid, mResultSource));
+
Log.d(IMPRESSION_TAG, logStringBuilder.toString());
}
-
- SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_IMPRESSION_EVENT,
+ SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_IMPRESSION_EVENT_V2,
event.getId(), // event_id
mInstanceId.getId(), // instance_id
mLauncherState.getLauncherState(), // state
mQueryLength, // query_length
- //result type list
- mResultTypeList,
- // result count list
- mResultCountList,
- // above keyboard list
- mAboveKeyboard,
- // uid list
- mUidList
+ mResultType, //result type
+ mAboveKeyboard, // above keyboard
+ mUid, // uid
+ mResultSource // result source
+
);
}
}
diff --git a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
index 8335523..4d7a5bb 100644
--- a/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
+++ b/quickstep/src/com/android/quickstep/util/ActiveGestureErrorDetector.java
@@ -34,10 +34,11 @@
public enum GestureEvent {
MOTION_DOWN, MOTION_UP, MOTION_MOVE, SET_END_TARGET, SET_END_TARGET_HOME,
SET_END_TARGET_NEW_TASK, SET_END_TARGET_ALL_APPS, ON_SETTLED_ON_END_TARGET,
+ ON_START_RECENTS_ANIMATION, ON_FINISH_RECENTS_ANIMATION, ON_CANCEL_RECENTS_ANIMATION,
START_RECENTS_ANIMATION, FINISH_RECENTS_ANIMATION, CANCEL_RECENTS_ANIMATION,
SET_ON_PAGE_TRANSITION_END_CALLBACK, CANCEL_CURRENT_ANIMATION, CLEANUP_SCREENSHOT,
SCROLLER_ANIMATION_ABORTED, TASK_APPEARED, EXPECTING_TASK_APPEARED,
- FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER, LAUNCHER_DESTROYED,
+ FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER, LAUNCHER_DESTROYED, RECENT_TASKS_MISSING,
/**
* These GestureEvents are specifically associated to state flags that get set in
@@ -218,6 +219,40 @@
+ "set before/without startRecentsAnimation.",
writer);
break;
+ case RECENT_TASKS_MISSING:
+ errorDetected |= printErrorIfTrue(
+ true,
+ prefix,
+ /* errorMessage= */ "SystemUiProxy.mRecentTasks missing,"
+ + " couldn't start the recents activity",
+ writer);
+ break;
+ case ON_START_RECENTS_ANIMATION:
+ errorDetected |= printErrorIfTrue(
+ !encounteredEvents.contains(GestureEvent.START_RECENTS_ANIMATION),
+ prefix,
+ /* errorMessage= */ "ON_START_RECENTS_ANIMATION "
+ + "onAnimationStart callback ran before startRecentsAnimation",
+ writer);
+ break;
+ case ON_CANCEL_RECENTS_ANIMATION:
+ errorDetected |= printErrorIfTrue(
+ !encounteredEvents.contains(GestureEvent.ON_START_RECENTS_ANIMATION),
+ prefix,
+ /* errorMessage= */ "ON_CANCEL_RECENTS_ANIMATION "
+ + "onAnimationCanceled callback ran before onAnimationStart "
+ + "callback",
+ writer);
+ break;
+ case ON_FINISH_RECENTS_ANIMATION:
+ errorDetected |= printErrorIfTrue(
+ !encounteredEvents.contains(GestureEvent.ON_START_RECENTS_ANIMATION),
+ prefix,
+ /* errorMessage= */ "ON_FINISH_RECENTS_ANIMATION "
+ + "onAnimationFinished callback ran before onAnimationStart "
+ + "callback",
+ writer);
+ break;
case MOTION_DOWN:
case SET_END_TARGET:
case SET_END_TARGET_HOME:
@@ -349,6 +384,30 @@
/* errorMessage= */ "onTaskAppeared was expected to be called but wasn't.",
writer);
+ errorDetected |= printErrorIfTrue(
+ /* condition= */ encounteredEvents.contains(GestureEvent.START_RECENTS_ANIMATION)
+ && !encounteredEvents.contains(GestureEvent.ON_START_RECENTS_ANIMATION),
+ prefix,
+ /* errorMessage= */
+ "startRecentAnimation was called but onAnimationStart callback was not",
+ writer);
+ errorDetected |= printErrorIfTrue(
+ /* condition= */
+ encounteredEvents.contains(GestureEvent.FINISH_RECENTS_ANIMATION)
+ && !encounteredEvents.contains(GestureEvent.ON_FINISH_RECENTS_ANIMATION),
+ prefix,
+ /* errorMessage= */
+ "finishController was called but onAnimationFinished callback was not",
+ writer);
+ errorDetected |= printErrorIfTrue(
+ /* condition= */
+ encounteredEvents.contains(GestureEvent.CANCEL_RECENTS_ANIMATION)
+ && !encounteredEvents.contains(GestureEvent.ON_CANCEL_RECENTS_ANIMATION),
+ prefix,
+ /* errorMessage= */
+ "onRecentsAnimationCanceled was called but onAnimationCanceled was not",
+ writer);
+
if (!errorDetected) {
writer.println(prefix + "\tNo errors detected.");
}
diff --git a/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java b/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
index 409bf9c..d6a2e93 100644
--- a/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
+++ b/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
@@ -18,12 +18,9 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.config.FeatureFlags;
-
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
@@ -49,7 +46,7 @@
private static final int TYPE_INTEGER = 2;
private static final int TYPE_BOOL_TRUE = 3;
private static final int TYPE_BOOL_FALSE = 4;
- private static final int TYPE_INPUT_CONSUMER = 5;
+ private static final int TYPE_COMPOUND_STRING = 5;
private static final int TYPE_GESTURE_EVENT = 6;
private final EventLog[] logs;
@@ -84,7 +81,13 @@
}
public void addLog(CompoundString compoundString) {
- addLog(TYPE_INPUT_CONSUMER, "", 0, compoundString, null);
+ addLog(TYPE_COMPOUND_STRING, "", 0, compoundString, null);
+ }
+
+ public void addLog(
+ CompoundString compoundString,
+ @Nullable ActiveGestureErrorDetector.GestureEvent gestureEvent) {
+ addLog(TYPE_COMPOUND_STRING, "", 0, compoundString, gestureEvent);
}
/**
@@ -150,10 +153,6 @@
lastEventEntries.add(eventEntry);
}
- public void clear() {
- Arrays.fill(logs, null);
- }
-
public void dump(String prefix, PrintWriter writer) {
writer.println(prefix + "ActiveGestureErrorDetector:");
for (int i = 0; i < logs.length; i++) {
@@ -192,7 +191,7 @@
case TYPE_INTEGER:
msg.append(": ").append((int) eventEntry.extras);
break;
- case TYPE_INPUT_CONSUMER:
+ case TYPE_COMPOUND_STRING:
msg.append(eventEntry.mCompoundString);
break;
case TYPE_GESTURE_EVENT:
@@ -321,6 +320,15 @@
return this;
}
+ public CompoundString append(int num) {
+ if (mIsNoOp) {
+ return this;
+ }
+ mSubstrings.add(Integer.toString(num));
+
+ return this;
+ }
+
@Override
public String toString() {
if (mIsNoOp) {
diff --git a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
index a92ab2a..cb35ec8 100644
--- a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
+++ b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
@@ -15,9 +15,9 @@
*/
package com.android.quickstep.util;
-import static com.android.launcher3.anim.Interpolators.DEACCEL;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.quickstep.AbsSwipeUpHandler.ALL_APPS_SHIFT_THRESHOLD;
+import static com.android.app.animation.Interpolators.DECELERATE;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.launcher3.LauncherPrefs.ALL_APPS_OVERVIEW_THRESHOLD;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
@@ -34,6 +34,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
@@ -55,7 +56,7 @@
private enum RecentsResistanceParams {
FROM_APP(0.75f, 0.5f, 1f, false),
- FROM_APP_TO_ALL_APPS(0.75f, 0.5f, 0.8f, false),
+ FROM_APP_TO_ALL_APPS(1f, 0.6f, 0.8f, false),
FROM_APP_TABLET(1f, 0.7f, 1f, true),
FROM_APP_TO_ALL_APPS_TABLET(1f, 0.5f, 0.5f, false),
FROM_OVERVIEW(1f, 0.75f, 0.5f, false);
@@ -91,7 +92,7 @@
public final boolean stopScalingAtTop;
}
- private static final TimeInterpolator RECENTS_SCALE_RESIST_INTERPOLATOR = DEACCEL;
+ private static final TimeInterpolator RECENTS_SCALE_RESIST_INTERPOLATOR = DECELERATE;
private static final TimeInterpolator RECENTS_TRANSLATE_RESIST_INTERPOLATOR = LINEAR;
private static final Rect TEMP_RECT = new Rect();
@@ -188,7 +189,8 @@
recentsOrientedState.getOrientationHandler());
float dragLengthFactor = (float) dp.heightPx / transitionDragLength;
// -1s are because 0-1 is reserved for the normal transition.
- return (ALL_APPS_SHIFT_THRESHOLD - 1) / (dragLengthFactor - 1);
+ float threshold = LauncherPrefs.get(context).get(ALL_APPS_OVERVIEW_THRESHOLD) / 100f;
+ return (threshold - 1) / (dragLengthFactor - 1);
}
/**
diff --git a/quickstep/src/com/android/quickstep/util/AppPairsController.java b/quickstep/src/com/android/quickstep/util/AppPairsController.java
index cbde257..1a7099d 100644
--- a/quickstep/src/com/android/quickstep/util/AppPairsController.java
+++ b/quickstep/src/com/android/quickstep/util/AppPairsController.java
@@ -17,19 +17,30 @@
package com.android.quickstep.util;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_PAIR_LAUNCH;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import android.app.ActivityTaskManager;
import android.content.Context;
+import android.content.Intent;
+
+import androidx.annotation.Nullable;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.icons.IconCache;
+import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.recents.model.Task;
+
+import java.util.Arrays;
/**
* Mini controller class that handles app pair interactions: saving, modifying, deleting, etc.
@@ -52,10 +63,13 @@
private final Context mContext;
private final SplitSelectStateController mSplitSelectStateController;
+ private final StatsLogManager mStatsLogManager;
public AppPairsController(Context context,
- SplitSelectStateController splitSelectStateController) {
+ SplitSelectStateController splitSelectStateController,
+ StatsLogManager statsLogManager) {
mContext = context;
mSplitSelectStateController = splitSelectStateController;
+ mStatsLogManager = statsLogManager;
}
/**
@@ -84,11 +98,51 @@
LauncherAccessibilityDelegate delegate =
Launcher.getLauncher(mContext).getAccessibilityDelegate();
if (delegate != null) {
- MAIN_EXECUTOR.execute(() -> delegate.addToWorkspace(newAppPair, true));
+ delegate.addToWorkspace(newAppPair, true);
+ mStatsLogManager.logger().withItemInfo(newAppPair)
+ .log(StatsLogManager.LauncherEvent.LAUNCHER_APP_PAIR_SAVE);
}
});
});
+ }
+ /**
+ * Launches an app pair by searching the RecentsModel for running instances of each app, and
+ * staging either those running instances or launching the apps as new Intents.
+ */
+ public void launchAppPair(WorkspaceItemInfo app1, WorkspaceItemInfo app2) {
+ ComponentKey app1Key = new ComponentKey(app1.getTargetComponent(), app1.user);
+ ComponentKey app2Key = new ComponentKey(app2.getTargetComponent(), app2.user);
+ mSplitSelectStateController.findLastActiveTasksAndRunCallback(
+ Arrays.asList(app1Key, app2Key),
+ foundTasks -> {
+ @Nullable Task foundTask1 = foundTasks.get(0);
+ Intent task1Intent;
+ int task1Id;
+ if (foundTask1 != null) {
+ task1Id = foundTask1.key.id;
+ task1Intent = null;
+ } else {
+ task1Id = ActivityTaskManager.INVALID_TASK_ID;
+ task1Intent = app1.intent;
+ }
+
+ mSplitSelectStateController.setInitialTaskSelect(task1Intent,
+ SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT,
+ app1,
+ LAUNCHER_APP_PAIR_LAUNCH,
+ task1Id);
+
+ @Nullable Task foundTask2 = foundTasks.get(1);
+ if (foundTask2 != null) {
+ mSplitSelectStateController.setSecondTask(foundTask2);
+ } else {
+ mSplitSelectStateController.setSecondTask(
+ app2.intent, app2.user);
+ }
+
+ mSplitSelectStateController.launchSplitTasks();
+ });
}
/**
diff --git a/quickstep/src/com/android/quickstep/util/AssistStateManager.java b/quickstep/src/com/android/quickstep/util/AssistStateManager.java
new file mode 100644
index 0000000..d4923b8
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/AssistStateManager.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
+
+import com.android.launcher3.R;
+import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.ResourceBasedOverride;
+
+import java.io.PrintWriter;
+
+/** Class to manage Assistant states. */
+public class AssistStateManager implements ResourceBasedOverride {
+
+ public static final MainThreadInitializedObject<AssistStateManager> INSTANCE =
+ forOverride(AssistStateManager.class, R.string.assist_state_manager_class);
+
+ public AssistStateManager() {}
+
+ /** Whether search is available. */
+ public boolean isSearchAvailable() {
+ return false;
+ }
+
+ /** Dump states. */
+ public void dump(String prefix, PrintWriter writer) {}
+}
diff --git a/quickstep/src/com/android/quickstep/util/AssistUtils.java b/quickstep/src/com/android/quickstep/util/AssistUtils.java
new file mode 100644
index 0000000..11b6ea7
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/AssistUtils.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import android.content.Context;
+
+import com.android.launcher3.R;
+import com.android.launcher3.util.ResourceBasedOverride;
+
+/** Utilities to work with Assistant functionality. */
+public class AssistUtils implements ResourceBasedOverride {
+
+ public AssistUtils() {}
+
+ /** Creates AssistUtils as specified by overrides */
+ public static AssistUtils newInstance(Context context) {
+ return Overrides.getObject(AssistUtils.class, context, R.string.assist_utils_class);
+ }
+
+ /** @return Array of AssistUtils.INVOCATION_TYPE_* that we want to handle instead of SysUI. */
+ public int[] getSysUiAssistOverrideInvocationTypes() {
+ return new int[0];
+ }
+
+ /**
+ * @return {@code true} if the override was handled, i.e. an assist surface was shown or the
+ * request should be ignored. {@code false} means the caller should start assist another way.
+ */
+ public boolean tryStartAssistOverride(int invocationType) {
+ return false;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/AsyncClockEventDelegate.java b/quickstep/src/com/android/quickstep/util/AsyncClockEventDelegate.java
new file mode 100644
index 0000000..0dee5b3
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/AsyncClockEventDelegate.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import static android.content.Intent.ACTION_TIMEZONE_CHANGED;
+import static android.content.Intent.ACTION_TIME_CHANGED;
+
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+import android.util.ArrayMap;
+import android.widget.TextClock.ClockEventDelegate;
+
+import androidx.annotation.WorkerThread;
+
+import com.android.launcher3.util.SettingsCache;
+import com.android.launcher3.util.SettingsCache.OnChangeListener;
+import com.android.launcher3.util.SimpleBroadcastReceiver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Extension of {@link ClockEventDelegate} to support async event registration
+ */
+public class AsyncClockEventDelegate extends ClockEventDelegate implements OnChangeListener {
+
+ private final Context mContext;
+ private final SimpleBroadcastReceiver mReceiver =
+ new SimpleBroadcastReceiver(this::onClockEventReceived);
+
+ private final ArrayMap<BroadcastReceiver, Handler> mTimeEventReceivers = new ArrayMap<>();
+ private final List<ContentObserver> mFormatObservers = new ArrayList<>();
+ private final Uri mFormatUri = Settings.System.getUriFor(Settings.System.TIME_12_24);
+
+ private boolean mFormatRegistered = false;
+ private boolean mDestroyed = false;
+
+ public AsyncClockEventDelegate(Context context) {
+ super(context);
+ mContext = context;
+
+ UI_HELPER_EXECUTOR.execute(() ->
+ mReceiver.register(mContext, ACTION_TIME_CHANGED, ACTION_TIMEZONE_CHANGED));
+ }
+
+ @Override
+ public void registerTimeChangeReceiver(BroadcastReceiver receiver, Handler handler) {
+ synchronized (mTimeEventReceivers) {
+ mTimeEventReceivers.put(receiver, handler == null ? new Handler() : handler);
+ }
+ }
+
+ @Override
+ public void unregisterTimeChangeReceiver(BroadcastReceiver receiver) {
+ synchronized (mTimeEventReceivers) {
+ mTimeEventReceivers.remove(receiver);
+ }
+ }
+
+ @Override
+ public void registerFormatChangeObserver(ContentObserver observer, int userHandle) {
+ synchronized (mFormatObservers) {
+ if (!mFormatRegistered && !mDestroyed) {
+ SettingsCache.INSTANCE.get(mContext).register(mFormatUri, this);
+ mFormatRegistered = true;
+ }
+ mFormatObservers.add(observer);
+ }
+ }
+
+ @Override
+ public void unregisterFormatChangeObserver(ContentObserver observer) {
+ synchronized (mFormatObservers) {
+ mFormatObservers.remove(observer);
+ }
+ }
+
+ @Override
+ public void onSettingsChanged(boolean isEnabled) {
+ if (mDestroyed) {
+ return;
+ }
+ synchronized (mFormatObservers) {
+ mFormatObservers.forEach(o -> o.dispatchChange(false, mFormatUri));
+ }
+ }
+ @WorkerThread
+ private void onClockEventReceived(Intent intent) {
+ if (mDestroyed) {
+ return;
+ }
+ synchronized (mReceiver) {
+ mTimeEventReceivers.forEach((r, h) -> h.post(() -> r.onReceive(mContext, intent)));
+ }
+ }
+
+ /**
+ * Unregisters all system callbacks and destroys this delegate
+ */
+ public void onDestroy() {
+ mDestroyed = true;
+ SettingsCache.INSTANCE.get(mContext).unregister(mFormatUri, this);
+ UI_HELPER_EXECUTOR.execute(() -> mReceiver.unregisterReceiverSafely(mContext));
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/BaseDepthController.java b/quickstep/src/com/android/quickstep/util/BaseDepthController.java
index 931e468..99f564c 100644
--- a/quickstep/src/com/android/quickstep/util/BaseDepthController.java
+++ b/quickstep/src/com/android/quickstep/util/BaseDepthController.java
@@ -18,6 +18,7 @@
import android.app.WallpaperManager;
import android.os.IBinder;
import android.util.FloatProperty;
+import android.util.Log;
import android.view.AttachedSurfaceControl;
import android.view.SurfaceControl;
@@ -50,6 +51,9 @@
private static final int DEPTH_INDEX_WIDGET = 1;
private static final int DEPTH_INDEX_COUNT = 2;
+ // b/291401432
+ private static final String TAG = "BaseDepthController";
+
protected final Launcher mLauncher;
/** Property to set the depth for state transition. */
public final MultiProperty stateDepth;
@@ -88,7 +92,7 @@
*/
protected boolean mInEarlyWakeUp;
- private boolean mWaitingOnSurfaceValidity;
+ protected boolean mWaitingOnSurfaceValidity;
public BaseDepthController(Launcher activity) {
mLauncher = activity;
@@ -133,9 +137,11 @@
return;
}
if (mSurface == null) {
+ Log.d(TAG, "mSurface is null and mCurrentBlur is: " + mCurrentBlur);
return;
}
if (!mSurface.isValid()) {
+ Log.d(TAG, "mSurface is not valid");
mWaitingOnSurfaceValidity = true;
onInvalidSurface();
return;
@@ -186,6 +192,8 @@
protected void setSurface(SurfaceControl surface) {
if (mSurface != surface || mWaitingOnSurfaceValidity) {
mSurface = surface;
+ Log.d(TAG, "setSurface:\n\tmWaitingOnSurfaceValidity: " + mWaitingOnSurfaceValidity
+ + "\n\tmSurface: " + mSurface);
applyDepthAndBlur();
}
}
diff --git a/quickstep/src/com/android/quickstep/util/BinderTracker.java b/quickstep/src/com/android/quickstep/util/BinderTracker.java
deleted file mode 100644
index cb04e5b..0000000
--- a/quickstep/src/com/android/quickstep/util/BinderTracker.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.quickstep.util;
-
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Looper;
-import android.util.Log;
-
-import com.android.launcher3.config.FeatureFlags;
-
-/**
- * Utility class to test and check binder calls during development.
- */
-public class BinderTracker {
-
- private static final String TAG = "BinderTracker";
-
- public static void start() {
- if (!FeatureFlags.IS_STUDIO_BUILD) {
- Log.wtf(TAG, "Accessing tracker in released code.", new Exception());
- return;
- }
-
- Binder.setProxyTransactListener(new Tracker());
- }
-
- public static void stop() {
- if (!FeatureFlags.IS_STUDIO_BUILD) {
- Log.wtf(TAG, "Accessing tracker in released code.", new Exception());
- return;
- }
- Binder.setProxyTransactListener(null);
- }
-
- private static class Tracker implements Binder.ProxyTransactListener {
-
- @Override
- public Object onTransactStarted(IBinder iBinder, int code) {
- if (Looper.myLooper() == Looper.getMainLooper()) {
- Log.e(TAG, "Binder call on ui thread", new Exception());
- }
- return null;
- }
-
- @Override
- public void onTransactEnded(Object session) { }
- }
-}
diff --git a/quickstep/src/com/android/quickstep/util/BorderAnimator.java b/quickstep/src/com/android/quickstep/util/BorderAnimator.java
index 011d45c..7563187 100644
--- a/quickstep/src/com/android/quickstep/util/BorderAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/BorderAnimator.java
@@ -29,9 +29,9 @@
import androidx.annotation.NonNull;
import androidx.annotation.Px;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.AnimatorListeners;
-import com.android.launcher3.anim.Interpolators;
/**
* Utility class for drawing a rounded-rect border around a view.
diff --git a/quickstep/src/com/android/quickstep/util/FadeOutRemoteTransition.kt b/quickstep/src/com/android/quickstep/util/FadeOutRemoteTransition.kt
new file mode 100644
index 0000000..59ff81d
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/FadeOutRemoteTransition.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util
+
+import android.animation.ValueAnimator
+import android.os.IBinder
+import android.os.RemoteException
+import android.view.SurfaceControl
+import android.view.SurfaceControl.Transaction
+import android.window.IRemoteTransition
+import android.window.IRemoteTransitionFinishedCallback
+import android.window.TransitionInfo
+import com.android.launcher3.anim.AnimatorListeners.forEndCallback
+import com.android.launcher3.util.Executors
+import com.android.wm.shell.util.TransitionUtil
+
+/** Remote animation which fades out the closing targets */
+class FadeOutRemoteTransition : IRemoteTransition.Stub() {
+
+ override fun mergeAnimation(
+ iBinder: IBinder,
+ transitionInfo: TransitionInfo,
+ transaction: Transaction,
+ mergeTarget: IBinder,
+ finishCB: IRemoteTransitionFinishedCallback
+ ) {
+
+ try {
+ finishCB.onTransitionFinished(null, Transaction())
+ } catch (e: RemoteException) {
+ // Ignore
+ }
+ }
+
+ override fun startAnimation(
+ transition: IBinder,
+ info: TransitionInfo,
+ startT: Transaction,
+ finishCB: IRemoteTransitionFinishedCallback
+ ) {
+ val anim = ValueAnimator.ofFloat(1f, 0f)
+
+ val closingControls: MutableList<SurfaceControl> = mutableListOf()
+ for (chg in info.changes) {
+ startT.show(chg.leash)
+ if (TransitionUtil.isClosingType(chg.mode)) {
+ closingControls.add(chg.leash)
+ }
+ }
+ startT.apply()
+
+ anim.addUpdateListener {
+ val t = Transaction()
+ closingControls.forEach { t.setAlpha(it, anim.animatedValue as Float) }
+ t.apply()
+ }
+ anim.addListener(
+ forEndCallback(
+ Runnable {
+ val t = Transaction()
+ closingControls.forEach { t.hide(it) }
+ try {
+ finishCB.onTransitionFinished(null, t)
+ } catch (e: RemoteException) {
+ // Ignore
+ }
+ }
+ )
+ )
+
+ Executors.MAIN_EXECUTOR.execute { anim.start() }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/GroupTask.java b/quickstep/src/com/android/quickstep/util/GroupTask.java
index 2be4f0a..9c49647 100644
--- a/quickstep/src/com/android/quickstep/util/GroupTask.java
+++ b/quickstep/src/com/android/quickstep/util/GroupTask.java
@@ -37,6 +37,10 @@
@TaskView.Type
public final int taskViewType;
+ public GroupTask(@NonNull Task task) {
+ this(task, null, null);
+ }
+
public GroupTask(@NonNull Task t1, @Nullable Task t2, @Nullable SplitBounds splitBounds) {
this(t1, t2, splitBounds, t2 != null ? TaskView.Type.GROUPED : TaskView.Type.SINGLE);
}
diff --git a/quickstep/src/com/android/quickstep/util/LogUtils.kt b/quickstep/src/com/android/quickstep/util/LogUtils.kt
index 23a41f6..e34c4ec 100644
--- a/quickstep/src/com/android/quickstep/util/LogUtils.kt
+++ b/quickstep/src/com/android/quickstep/util/LogUtils.kt
@@ -20,6 +20,11 @@
import com.android.launcher3.logging.InstanceId
object LogUtils {
+ @JvmStatic
+ fun splitFailureMessage(caller: String, reason: String): String {
+ return "($caller) Splitscreen aborted: $reason"
+ }
+
/**
* @return a [Pair] of two InstanceIds but with different types, one that can be used by
* framework (if needing to pass through an intent or such) and one used in Launcher
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index 4bc41bc..a8a96ce 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -15,6 +15,8 @@
*/
package com.android.quickstep.util;
+import static com.android.launcher3.testing.shared.TestProtocol.PAUSE_DETECTED_MESSAGE;
+
import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
@@ -201,7 +203,8 @@
ActiveGestureLog.INSTANCE.addLog(logString);
boolean isFirstDetectedPause = !mHasEverBeenPaused && mIsPaused;
if (mIsPaused) {
- AccessibilityManagerCompat.sendPauseDetectedEventToTest(mContext);
+ AccessibilityManagerCompat.sendTestProtocolEventToTest(mContext,
+ PAUSE_DETECTED_MESSAGE);
mHasEverBeenPaused = true;
}
if (mOnMotionPauseListener != null) {
diff --git a/quickstep/src/com/android/quickstep/util/NavBarPosition.java b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
index 59c8263..9418512 100644
--- a/quickstep/src/com/android/quickstep/util/NavBarPosition.java
+++ b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
@@ -27,25 +27,22 @@
*/
public class NavBarPosition {
+ private final boolean mIsTablet;
private final NavigationMode mMode;
private final int mDisplayRotation;
public NavBarPosition(NavigationMode mode, Info info) {
+ mIsTablet = info.isTablet(info.realBounds);
mMode = mode;
mDisplayRotation = info.rotation;
}
- public NavBarPosition(NavigationMode mode, int displayRotation) {
- mMode = mode;
- mDisplayRotation = displayRotation;
- }
-
public boolean isRightEdge() {
- return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90;
+ return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90 && !mIsTablet;
}
public boolean isLeftEdge() {
- return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270;
+ return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270 && !mIsTablet;
}
public float getRotation() {
diff --git a/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java b/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java
index 3cec1a4..6d9ecd9 100644
--- a/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java
+++ b/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java
@@ -22,12 +22,16 @@
import android.animation.AnimatorSet;
import android.util.Log;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.states.StateAnimationConfig;
+import java.util.function.Consumer;
+
/**
* Runs an animation from overview to home. Currently, this animation is just a wrapper around the
* normal state transition and may play a {@link WorkspaceRevealAnim} if we're starting from an
@@ -39,14 +43,18 @@
private final Launcher mLauncher;
private final Runnable mOnReachedHome;
+ @Nullable
+ private final Consumer<AnimatorSet> mSplitCancelConsumer;
// Only run mOnReachedHome when both of these are true.
private boolean mIsHomeStaggeredAnimFinished;
private boolean mIsOverviewHidden;
- public OverviewToHomeAnim(Launcher launcher, Runnable onReachedHome) {
+ public OverviewToHomeAnim(Launcher launcher, Runnable onReachedHome,
+ @Nullable Consumer<AnimatorSet> splitCancelConsumer) {
mLauncher = launcher;
mOnReachedHome = onReachedHome;
+ mSplitCancelConsumer = splitCancelConsumer;
}
/**
@@ -92,6 +100,11 @@
maybeOverviewToHomeAnimComplete();
}
});
+
+ if (mSplitCancelConsumer != null) {
+ // Clear split state when swiping to home
+ mSplitCancelConsumer.accept(anim);
+ }
anim.play(stateAnim);
stateManager.setCurrentAnimation(anim, NORMAL);
anim.start();
diff --git a/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java b/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java
index e189a66..3027f79 100644
--- a/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java
+++ b/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java
@@ -16,8 +16,8 @@
package com.android.quickstep.util;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.INSTANT;
import android.view.animation.Interpolator;
diff --git a/quickstep/src/com/android/quickstep/util/PhoneOverviewToSplitTimings.java b/quickstep/src/com/android/quickstep/util/PhoneOverviewToSplitTimings.java
index f1dde53..a38f437 100644
--- a/quickstep/src/com/android/quickstep/util/PhoneOverviewToSplitTimings.java
+++ b/quickstep/src/com/android/quickstep/util/PhoneOverviewToSplitTimings.java
@@ -16,7 +16,7 @@
package com.android.quickstep.util;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
import android.view.animation.Interpolator;
diff --git a/quickstep/src/com/android/quickstep/util/ProtoTracer.java b/quickstep/src/com/android/quickstep/util/ProtoTracer.java
deleted file mode 100644
index ef9586d..0000000
--- a/quickstep/src/com/android/quickstep/util/ProtoTracer.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2019 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.tracing.LauncherTraceFileProto.MagicNumber.MAGIC_NUMBER_H_VALUE;
-import static com.android.launcher3.tracing.LauncherTraceFileProto.MagicNumber.MAGIC_NUMBER_L_VALUE;
-
-import android.content.Context;
-import android.os.SystemClock;
-
-import android.os.Trace;
-import com.android.launcher3.tracing.LauncherTraceProto;
-import com.android.launcher3.tracing.LauncherTraceEntryProto;
-import com.android.launcher3.tracing.LauncherTraceFileProto;
-import com.android.launcher3.util.MainThreadInitializedObject;
-import com.android.systemui.shared.tracing.FrameProtoTracer;
-import com.android.systemui.shared.tracing.FrameProtoTracer.ProtoTraceParams;
-import com.android.systemui.shared.tracing.ProtoTraceable;
-import com.google.protobuf.MessageLite;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Queue;
-
-
-/**
- * Controller for coordinating winscope proto tracing.
- */
-public class ProtoTracer implements ProtoTraceParams<MessageLite.Builder,
- LauncherTraceFileProto.Builder, LauncherTraceEntryProto.Builder,
- LauncherTraceProto.Builder> {
-
- public static final MainThreadInitializedObject<ProtoTracer> INSTANCE =
- new MainThreadInitializedObject<>(ProtoTracer::new);
-
- private static final String TAG = "ProtoTracer";
- private static final long MAGIC_NUMBER_VALUE =
- ((long) MAGIC_NUMBER_H_VALUE << 32) | MAGIC_NUMBER_L_VALUE;
-
- private final Context mContext;
- private final FrameProtoTracer<MessageLite.Builder, LauncherTraceFileProto.Builder,
- LauncherTraceEntryProto.Builder, LauncherTraceProto.Builder> mProtoTracer;
-
- public ProtoTracer(Context context) {
- mContext = context;
- mProtoTracer = new FrameProtoTracer<>(this);
- }
-
- @Override
- public File getTraceFile() {
- return new File(mContext.getFilesDir(), "launcher_trace.pb");
- }
-
- @Override
- public LauncherTraceFileProto.Builder getEncapsulatingTraceProto() {
- return LauncherTraceFileProto.newBuilder();
- }
-
- @Override
- public LauncherTraceEntryProto.Builder updateBufferProto(
- LauncherTraceEntryProto.Builder reuseObj,
- ArrayList<ProtoTraceable<LauncherTraceProto.Builder>> traceables) {
- Trace.beginSection("ProtoTracer.updateBufferProto");
- LauncherTraceEntryProto.Builder proto = LauncherTraceEntryProto.newBuilder();
- proto.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
- LauncherTraceProto.Builder launcherProto = LauncherTraceProto.newBuilder();
- for (ProtoTraceable t : traceables) {
- t.writeToProto(launcherProto);
- }
- proto.setLauncher(launcherProto);
- Trace.endSection();
- return proto;
- }
-
- @Override
- public byte[] serializeEncapsulatingProto(LauncherTraceFileProto.Builder encapsulatingProto,
- Queue<LauncherTraceEntryProto.Builder> buffer) {
- Trace.beginSection("ProtoTracer.serializeEncapsulatingProto");
- encapsulatingProto.setMagicNumber(MAGIC_NUMBER_VALUE);
- for (LauncherTraceEntryProto.Builder entry : buffer) {
- encapsulatingProto.addEntry(entry);
- }
- byte[] bytes = encapsulatingProto.build().toByteArray();
- Trace.endSection();
- return bytes;
- }
-
- @Override
- public byte[] getProtoBytes(MessageLite.Builder proto) {
- return proto.build().toByteArray();
- }
-
- @Override
- public int getProtoSize(MessageLite.Builder proto) {
- return proto.build().getSerializedSize();
- }
-
- public void start() {
- mProtoTracer.start();
- }
-
- public void stop() {
- mProtoTracer.stop();
- }
-
- public void add(ProtoTraceable<LauncherTraceProto.Builder> traceable) {
- mProtoTracer.add(traceable);
- }
-
- public void remove(ProtoTraceable<LauncherTraceProto.Builder> traceable) {
- mProtoTracer.remove(traceable);
- }
-
- public void scheduleFrameUpdate() {
- mProtoTracer.scheduleFrameUpdate();
- }
-
- public void update() {
- mProtoTracer.update();
- }
-}
diff --git a/quickstep/src/com/android/quickstep/util/ProxyScreenStatusProvider.java b/quickstep/src/com/android/quickstep/util/ProxyScreenStatusProvider.java
deleted file mode 100644
index 8f79ccf..0000000
--- a/quickstep/src/com/android/quickstep/util/ProxyScreenStatusProvider.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.util;
-
-import androidx.annotation.NonNull;
-
-import com.android.systemui.unfold.updates.screen.ScreenStatusProvider;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Screen status provider implementation that exposes methods to provide screen
- * status updates to listeners. It is used to receive screen turned on event from
- * SystemUI to Launcher.
- */
-public class ProxyScreenStatusProvider implements ScreenStatusProvider {
-
- public static final ProxyScreenStatusProvider INSTANCE = new ProxyScreenStatusProvider();
- private final List<ScreenListener> mListeners = new ArrayList<>();
-
- /**
- * Called when the screen is on and ready (windows are drawn and screen blocker is removed)
- */
- public void onScreenTurnedOn() {
- mListeners.forEach(ScreenListener::onScreenTurnedOn);
- }
-
- /** Called when the screen is starting to turn on. */
- public void onScreenTurningOn() {
- mListeners.forEach(ScreenListener::onScreenTurningOn);
- }
-
- /** Called when the screen is starting to turn off. */
- public void onScreenTurningOff() {
- mListeners.forEach(ScreenListener::onScreenTurningOff);
- }
-
- @Override
- public void addCallback(@NonNull ScreenListener listener) {
- mListeners.add(listener);
- }
-
- @Override
- public void removeCallback(@NonNull ScreenListener listener) {
- mListeners.remove(listener);
- }
-}
diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
deleted file mode 100644
index 10f2eaa..0000000
--- a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.util;
-
-import android.animation.AnimatorSet;
-import android.view.RemoteAnimationTarget;
-
-public abstract class RemoteAnimationProvider {
-
- public abstract AnimatorSet createWindowAnimation(RemoteAnimationTarget[] appTargets,
- RemoteAnimationTarget[] wallpaperTargets);
-
- /**
- * @return the target with the lowest opaque layer for a certain app animation, or null.
- */
- public static RemoteAnimationTarget findLowestOpaqueLayerTarget(
- RemoteAnimationTarget[] appTargets, int mode) {
- int lowestLayer = Integer.MAX_VALUE;
- int lowestLayerIndex = -1;
- for (int i = appTargets.length - 1; i >= 0; i--) {
- RemoteAnimationTarget target = appTargets[i];
- if (target.mode == mode && !target.isTranslucent) {
- int layer = target.prefixOrderIndex;
- if (layer < lowestLayer) {
- lowestLayer = layer;
- lowestLayerIndex = i;
- }
- }
- }
- return lowestLayerIndex != -1
- ? appTargets[lowestLayerIndex]
- : null;
- }
-}
diff --git a/quickstep/src/com/android/quickstep/util/RemoteFadeOutAnimationListener.java b/quickstep/src/com/android/quickstep/util/RemoteFadeOutAnimationListener.java
deleted file mode 100644
index 382cf79..0000000
--- a/quickstep/src/com/android/quickstep/util/RemoteFadeOutAnimationListener.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.util;
-
-import static android.view.RemoteAnimationTarget.MODE_CLOSING;
-
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.view.RemoteAnimationTarget;
-import android.view.SurfaceControl.Transaction;
-
-import com.android.quickstep.RemoteAnimationTargets;
-
-/**
- * Animation listener which fades out the closing targets
- */
-public class RemoteFadeOutAnimationListener implements AnimatorUpdateListener {
-
- private final RemoteAnimationTargets mTarget;
- private boolean mFirstFrame = true;
-
- public RemoteFadeOutAnimationListener(RemoteAnimationTarget[] appTargets,
- RemoteAnimationTarget[] wallpaperTargets) {
- mTarget = new RemoteAnimationTargets(appTargets, wallpaperTargets,
- new RemoteAnimationTarget[0], MODE_CLOSING);
- }
-
- @Override
- public void onAnimationUpdate(ValueAnimator valueAnimator) {
- Transaction t = new Transaction();
- if (mFirstFrame) {
- for (RemoteAnimationTarget target : mTarget.unfilteredApps) {
- t.show(target.leash);
- }
- mFirstFrame = false;
- }
-
- float alpha = 1 - valueAnimator.getAnimatedFraction();
- for (RemoteAnimationTarget app : mTarget.apps) {
- t.setAlpha(app.leash, alpha);
- }
- t.apply();
- }
-}
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
index b76fe5c..c3774eb 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
@@ -17,14 +17,26 @@
package com.android.quickstep.util
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.graphics.Bitmap
+import android.graphics.Rect
+import android.graphics.RectF
import android.graphics.drawable.Drawable
import android.view.View
+import com.android.app.animation.Interpolators
import com.android.launcher3.DeviceProfile
+import com.android.launcher3.Utilities
import com.android.launcher3.anim.PendingAnimation
+import com.android.launcher3.statemanager.StatefulActivity
import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource
+import com.android.launcher3.views.BaseDragLayer
+import com.android.quickstep.views.FloatingTaskView
import com.android.quickstep.views.IconView
+import com.android.quickstep.views.RecentsView
+import com.android.quickstep.views.SplitInstructionsView
import com.android.quickstep.views.TaskThumbnailView
import com.android.quickstep.views.TaskView
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
@@ -176,4 +188,91 @@
TaskThumbnailView.SPLIT_SELECT_TRANSLATE_X, 0f))
}
}
+
+ /** Does not play any animation if user is not currently in split selection state. */
+ fun playPlaceholderDismissAnim(launcher: StatefulActivity<*>) {
+ if (!splitSelectStateController.isSplitSelectActive) {
+ return
+ }
+
+ val anim = createPlaceholderDismissAnim(launcher)
+ anim.start()
+ }
+
+ /** Returns [AnimatorSet] which slides initial split placeholder view offscreen. */
+ fun createPlaceholderDismissAnim(launcher: StatefulActivity<*>) : AnimatorSet {
+ val animatorSet = AnimatorSet()
+ val recentsView : RecentsView<*, *> = launcher.getOverviewPanel()
+ val floatingTask: FloatingTaskView = splitSelectStateController.firstFloatingTaskView
+ ?: return animatorSet
+
+ // We are in split selection state currently, transitioning to another state
+ val dragLayer: BaseDragLayer<*> = launcher.dragLayer
+ val onScreenRectF = RectF()
+ Utilities.getBoundsForViewInDragLayer(dragLayer, floatingTask,
+ Rect(0, 0, floatingTask.width, floatingTask.height),
+ false, null, onScreenRectF)
+ // Get the part of the floatingTask that intersects with the DragLayer (i.e. the
+ // on-screen portion)
+ onScreenRectF.intersect(
+ dragLayer.left.toFloat(),
+ dragLayer.top.toFloat(),
+ dragLayer.right.toFloat(),
+ dragLayer.bottom
+ .toFloat()
+ )
+ animatorSet.play(ObjectAnimator.ofFloat(floatingTask,
+ FloatingTaskView.PRIMARY_TRANSLATE_OFFSCREEN,
+ recentsView.pagedOrientationHandler
+ .getFloatingTaskOffscreenTranslationTarget(
+ floatingTask,
+ onScreenRectF,
+ floatingTask.stagePosition,
+ launcher.deviceProfile
+ )))
+ animatorSet.addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ splitSelectStateController.resetState()
+ safeRemoveViewFromDragLayer(launcher,
+ splitSelectStateController.splitInstructionsView)
+ }
+ })
+ return animatorSet
+ }
+
+ /**
+ * Returns a [PendingAnimation] to animate in the chip to instruct a user to select a second
+ * app for splitscreen
+ */
+ fun getShowSplitInstructionsAnim(launcher: StatefulActivity<*>) : PendingAnimation {
+ safeRemoveViewFromDragLayer(launcher, splitSelectStateController.splitInstructionsView)
+ val splitInstructionsView = SplitInstructionsView.getSplitInstructionsView(launcher)
+ splitSelectStateController.splitInstructionsView = splitInstructionsView
+ val timings = AnimUtils.getDeviceOverviewToSplitTimings(launcher.deviceProfile.isTablet)
+ val anim = PendingAnimation(100 /*duration */)
+ anim.setViewAlpha(splitInstructionsView, 1f,
+ Interpolators.clampToProgress(Interpolators.LINEAR,
+ timings.instructionsContainerFadeInStartOffset,
+ timings.instructionsContainerFadeInEndOffset))
+ anim.setViewAlpha(splitInstructionsView!!.textView, 1f,
+ Interpolators.clampToProgress(Interpolators.LINEAR,
+ timings.instructionsTextFadeInStartOffset,
+ timings.instructionsTextFadeInEndOffset))
+ anim.addFloat(splitInstructionsView, SplitInstructionsView.UNFOLD, 0.1f, 1f,
+ Interpolators.clampToProgress(Interpolators.EMPHASIZED_DECELERATE,
+ timings.instructionsUnfoldStartOffset,
+ timings.instructionsUnfoldEndOffset))
+ return anim
+ }
+
+ /** Removes the split instructions view from [launcher] drag layer. */
+ fun removeSplitInstructionsView(launcher: StatefulActivity<*>) {
+ safeRemoveViewFromDragLayer(launcher, splitSelectStateController.splitInstructionsView)
+ }
+
+ private fun safeRemoveViewFromDragLayer(launcher: StatefulActivity<*>, view: View?) {
+ if (view != null) {
+ launcher.dragLayer.removeView(view)
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java b/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
index 7dc1b32..93f2255 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
@@ -16,7 +16,7 @@
package com.android.quickstep.util;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.LINEAR;
import android.view.animation.Interpolator;
diff --git a/quickstep/src/com/android/quickstep/util/SplitScreenUtils.kt b/quickstep/src/com/android/quickstep/util/SplitScreenUtils.kt
new file mode 100644
index 0000000..596bb47
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/SplitScreenUtils.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.util
+
+import com.android.launcher3.util.SplitConfigurationOptions
+import com.android.wm.shell.util.SplitBounds
+
+class SplitScreenUtils {
+ companion object {
+ // TODO(b/254378592): Remove these methods when the two classes are reunited
+ /** Converts the shell version of SplitBounds to the launcher version */
+ @JvmStatic
+ fun convertShellSplitBoundsToLauncher(
+ shellSplitBounds: SplitBounds?
+ ): SplitConfigurationOptions.SplitBounds? {
+ return if (shellSplitBounds == null) {
+ null
+ } else {
+ SplitConfigurationOptions.SplitBounds(
+ shellSplitBounds.leftTopBounds, shellSplitBounds.rightBottomBounds,
+ shellSplitBounds.leftTopTaskId, shellSplitBounds.rightBottomTaskId,
+ shellSplitBounds.snapPosition
+ )
+ }
+ }
+
+ /** Converts the launcher version of SplitBounds to the shell version */
+ @JvmStatic
+ fun convertLauncherSplitBoundsToShell(
+ launcherSplitBounds: SplitConfigurationOptions.SplitBounds?
+ ): SplitBounds? {
+ return if (launcherSplitBounds == null) {
+ null
+ } else {
+ SplitBounds(
+ launcherSplitBounds.leftTopBounds,
+ launcherSplitBounds.rightBottomBounds,
+ launcherSplitBounds.leftTopTaskId,
+ launcherSplitBounds.rightBottomTaskId,
+ launcherSplitBounds.snapPosition
+ )
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt b/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt
index e073264..95f1fbf 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectDataHolder.kt
@@ -45,7 +45,11 @@
*
* After setting the correct fields for initial/second.* variables, this converts them into the
* correct [PendingIntent] and [ShortcutInfo] objects where applicable and sends the necessary
- * data back via [getSplitLaunchData].
+ * data back via [getSplitLaunchData]. Note: there should be only one "initial" field and one
+ * "second" field set, with the rest remaining null. (Exception: [Intent] and [UserHandle] are
+ * always passed in together as a set, and are converted to a single [PendingIntent] or
+ * [ShortcutInfo]+[PendingIntent] before launch.)
+ *
* [SplitLaunchType] indicates the type of tasks/apps/intents being launched given the provided
* state
*/
@@ -80,21 +84,21 @@
const val SPLIT_SINGLE_SHORTCUT_FULLSCREEN = 8
}
-
@StagePosition
private var initialStagePosition: Int = STAGE_POSITION_UNDEFINED
- private var initialTaskId: Int = INVALID_TASK_ID
- private var secondTaskId: Int = INVALID_TASK_ID
- private var initialUser: UserHandle? = null
- private var secondUser: UserHandle? = null
- private var initialIntent: Intent? = null
- private var secondIntent: Intent? = null
- private var secondPendingIntent: PendingIntent? = null
private var itemInfo: ItemInfo? = null
private var splitEvent: EventEnum? = null
+
+ private var initialTaskId: Int = INVALID_TASK_ID
+ private var secondTaskId: Int = INVALID_TASK_ID
+ private var initialIntent: Intent? = null
+ private var secondIntent: Intent? = null
+ private var initialUser: UserHandle? = null
+ private var secondUser: UserHandle? = null
+ private var initialPendingIntent: PendingIntent? = null
+ private var secondPendingIntent: PendingIntent? = null
private var initialShortcut: ShortcutInfo? = null
private var secondShortcut: ShortcutInfo? = null
- private var initialPendingIntent: PendingIntent? = null
/**
* @param alreadyRunningTask if set to [android.app.ActivityTaskManager.INVALID_TASK_ID]
@@ -156,18 +160,23 @@
*/
fun setSecondTask(pendingIntent: PendingIntent) {
secondPendingIntent = pendingIntent
- secondUser = pendingIntent.creatorUserHandle!!
+ secondUser = pendingIntent.creatorUserHandle
}
private fun getShortcutInfo(intent: Intent?, user: UserHandle?): ShortcutInfo? {
- if (intent?.getPackage() == null) {
+ val intentPackage = intent?.getPackage()
+ if (intentPackage == null) {
return null
}
val shortcutId = intent.getStringExtra(ShortcutKey.EXTRA_SHORTCUT_ID)
?: return null
try {
- val context: Context = context.createPackageContextAsUser(
- intent.getPackage(), 0 /* flags */, user)
+ val context: Context =
+ if (user != null) {
+ context.createPackageContextAsUser(intentPackage, 0 /* flags */, user)
+ } else {
+ context.createPackageContext(intentPackage, 0 /* *flags */)
+ }
return ShortcutInfo.Builder(context, shortcutId).build()
} catch (e: PackageManager.NameNotFoundException) {
Log.w(TAG, "Failed to create a ShortcutInfo for " + intent.getPackage())
@@ -217,7 +226,7 @@
* split task in fullscreen
*/
fun getFullscreenLaunchData() : SplitLaunchData {
- // Convert all intents to shortcut infos to see if determine if we launch shortcut or intent
+ // Convert all intents to shortcut infos to determine if we launch shortcut or intent
convertIntentsToFinalTypes()
val splitLaunchType = getFullscreenLaunchType()
@@ -359,7 +368,8 @@
}
private fun isInitialTaskIntentSet(): Boolean {
- return initialTaskId != INVALID_TASK_ID || initialIntent != null
+ return initialTaskId != INVALID_TASK_ID || initialIntent != null ||
+ initialPendingIntent != null
}
fun getInitialTaskId(): Int {
@@ -370,6 +380,18 @@
return secondTaskId
}
+ fun getSplitEvent(): EventEnum? {
+ return splitEvent
+ }
+
+ fun getInitialStagePosition(): Int {
+ return initialStagePosition
+ }
+
+ fun getItemInfo(): ItemInfo? {
+ return itemInfo
+ }
+
private fun isSecondTaskIntentSet(): Boolean {
return secondTaskId != INVALID_TASK_ID || secondIntent != null
|| secondPendingIntent != null
@@ -383,6 +405,7 @@
secondUser = null
initialIntent = null
secondIntent = null
+ initialPendingIntent = null
secondPendingIntent = null
itemInfo = null
splitEvent = null
@@ -405,4 +428,4 @@
writer.println("$prefix\tinitialShortcut= $initialShortcut")
writer.println("$prefix\tsecondShortcut= $secondShortcut")
}
-}
\ No newline at end of file
+}
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index f25619d..c8831c7 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -16,14 +16,13 @@
package com.android.quickstep.util;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static android.app.PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT;
-import static android.app.PendingIntent.FLAG_MUTABLE;
-
import static com.android.launcher3.Utilities.postAsyncCallback;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DESKTOP_MODE_SPLIT_LEFT_TOP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DESKTOP_MODE_SPLIT_RIGHT_BOTTOM;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.launcher3.util.SplitConfigurationOptions.DEFAULT_SPLIT_RATIO;
-import static com.android.launcher3.util.SplitConfigurationOptions.getOppositeStagePosition;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_PENDINGINTENT_PENDINGINTENT;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_PENDINGINTENT_TASK;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_SHORTCUT_TASK;
@@ -33,20 +32,26 @@
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_PENDINGINTENT;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_SHORTCUT;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_TASK;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ActivityThread;
import android.app.PendingIntent;
-import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;
@@ -61,28 +66,45 @@
import androidx.annotation.Nullable;
import com.android.internal.logging.InstanceId;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.icons.IconProvider;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.StateManager;
+import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
+import com.android.launcher3.util.BackPressHandler;
import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
+import com.android.quickstep.OverviewComponentObserver;
+import com.android.quickstep.RecentsAnimationCallbacks;
+import com.android.quickstep.RecentsAnimationController;
+import com.android.quickstep.RecentsAnimationDeviceState;
+import com.android.quickstep.RecentsAnimationTargets;
import com.android.quickstep.RecentsModel;
+import com.android.quickstep.SplitSelectionListener;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskAnimationManager;
import com.android.quickstep.TaskViewUtils;
import com.android.quickstep.views.FloatingTaskView;
import com.android.quickstep.views.GroupedTaskView;
-import com.android.quickstep.views.TaskView;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.SplitInstructionsView;
import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
+import com.android.wm.shell.common.split.SplitScreenConstants.SnapPosition;
+import com.android.wm.shell.splitscreen.ISplitSelectListener;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.function.Consumer;
/**
@@ -92,36 +114,20 @@
public class SplitSelectStateController {
private static final String TAG = "SplitSelectStateCtor";
- private final Context mContext;
+ private StatefulActivity mContext;
private final Handler mHandler;
private final RecentsModel mRecentTasksModel;
+ @Nullable
+ private final Runnable mActivityBackCallback;
private final SplitAnimationController mSplitAnimationController;
private final AppPairsController mAppPairsController;
private final SplitSelectDataHolder mSplitSelectDataHolder;
- private StatsLogManager mStatsLogManager;
+ private final StatsLogManager mStatsLogManager;
private final SystemUiProxy mSystemUiProxy;
private final StateManager mStateManager;
+ private SplitFromDesktopController mSplitFromDesktopController;
@Nullable
private DepthController mDepthController;
- private @StagePosition int mInitialStagePosition;
- private ItemInfo mItemInfo;
- /** {@link #mInitialTaskIntent} and {@link #mInitialUser} (the user of the Intent) are set
- * together when split is initiated from an Intent. */
- private Intent mInitialTaskIntent;
- private UserHandle mInitialUser;
- private int mInitialTaskId = INVALID_TASK_ID;
- /** {@link #mSecondTaskIntent} and {@link #mSecondUser} (the user of the Intent) are set
- * together when split is confirmed with an Intent. Either this or {@link #mSecondPendingIntent}
- * will be set, but not both
- */
- private Intent mSecondTaskIntent;
- /**
- * Set when split is confirmed via a widget. Either this or {@link #mSecondTaskIntent} will be
- * set, but not both
- */
- private PendingIntent mSecondPendingIntent;
- private UserHandle mSecondUser;
- private int mSecondTaskId = INVALID_TASK_ID;
private boolean mRecentsAnimationRunning;
/** If {@code true}, animates the existing task view split placeholder view */
private boolean mAnimateCurrentTaskDismissal;
@@ -133,14 +139,34 @@
/** If not null, this is the TaskView we want to launch from */
@Nullable
private GroupedTaskView mLaunchingTaskView;
- /** Represents where split is intended to be invoked from. */
- private StatsLogManager.EventEnum mSplitEvent;
private FloatingTaskView mFirstFloatingTaskView;
+ private SplitInstructionsView mSplitInstructionsView;
- public SplitSelectStateController(Context context, Handler handler, StateManager stateManager,
- DepthController depthController, StatsLogManager statsLogManager,
- SystemUiProxy systemUiProxy, RecentsModel recentsModel) {
+ private final List<SplitSelectionListener> mSplitSelectionListeners = new ArrayList<>();
+
+ private final BackPressHandler mSplitBackHandler = new BackPressHandler() {
+ @Override
+ public boolean canHandleBack() {
+ return FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get() &&
+ isSplitSelectActive();
+ }
+
+ @Override
+ public void onBackInvoked() {
+ // When exiting from split selection, leave current context to go to
+ // homescreen as well
+ getSplitAnimationController().playPlaceholderDismissAnim(mContext);
+ if (mActivityBackCallback != null) {
+ mActivityBackCallback.run();
+ }
+ }
+ };
+
+ public SplitSelectStateController(StatefulActivity context, Handler handler,
+ StateManager stateManager, DepthController depthController,
+ StatsLogManager statsLogManager, SystemUiProxy systemUiProxy, RecentsModel recentsModel,
+ Runnable activityBackCallback) {
mContext = context;
mHandler = handler;
mStatsLogManager = statsLogManager;
@@ -148,11 +174,16 @@
mStateManager = stateManager;
mDepthController = depthController;
mRecentTasksModel = recentsModel;
+ mActivityBackCallback = activityBackCallback;
mSplitAnimationController = new SplitAnimationController(this);
- mAppPairsController = new AppPairsController(context, this);
+ mAppPairsController = new AppPairsController(context, this, statsLogManager);
mSplitSelectDataHolder = new SplitSelectDataHolder(mContext);
}
+ public void onDestroy() {
+ mContext = null;
+ }
+
/**
* @param alreadyRunningTask if set to {@link android.app.ActivityTaskManager#INVALID_TASK_ID}
* then @param intent will be used to launch the initial task
@@ -161,19 +192,8 @@
public void setInitialTaskSelect(@Nullable Intent intent, @StagePosition int stagePosition,
@NonNull ItemInfo itemInfo, StatsLogManager.EventEnum splitEvent,
int alreadyRunningTask) {
- if (alreadyRunningTask != INVALID_TASK_ID) {
- mInitialTaskId = alreadyRunningTask;
- } else {
- mInitialTaskIntent = intent;
- mInitialUser = itemInfo.user;
- }
-
- setInitialData(stagePosition, splitEvent, itemInfo);
-
- if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
- mSplitSelectDataHolder.setInitialTaskSelect(intent, stagePosition, itemInfo, splitEvent,
- alreadyRunningTask);
- }
+ mSplitSelectDataHolder.setInitialTaskSelect(intent, stagePosition, itemInfo, splitEvent,
+ alreadyRunningTask);
}
/**
@@ -183,53 +203,50 @@
public void setInitialTaskSelect(ActivityManager.RunningTaskInfo info,
@StagePosition int stagePosition, @NonNull ItemInfo itemInfo,
StatsLogManager.EventEnum splitEvent) {
- mInitialTaskId = info.taskId;
- setInitialData(stagePosition, splitEvent, itemInfo);
-
- if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
- mSplitSelectDataHolder.setInitialTaskSelect(info, stagePosition, itemInfo, splitEvent);
- }
- }
-
- private void setInitialData(@StagePosition int stagePosition,
- StatsLogManager.EventEnum splitEvent, ItemInfo itemInfo) {
- mItemInfo = itemInfo;
- mInitialStagePosition = stagePosition;
- mSplitEvent = splitEvent;
+ mSplitSelectDataHolder.setInitialTaskSelect(info, stagePosition, itemInfo, splitEvent);
}
/**
- * Pulls the list of active Tasks from RecentsModel, and finds the most recently active Task
- * matching a given ComponentName. Then uses that Task (which could be null) with the given
- * callback.
+ * Maps a List<ComponentKey> to List<@Nullable Task>, searching through active Tasks in
+ * RecentsModel. If found, the Task will be the most recently-interacted-with instance of that
+ * Task. Then runs the given callback on that List.
* <p>
* Used in various task-switching or splitscreen operations when we need to check if there is a
* currently running Task of a certain type and use the most recent one.
*/
- public void findLastActiveTaskAndRunCallback(
- @Nullable ComponentKey componentKey, Consumer<Task> callback) {
+ public void findLastActiveTasksAndRunCallback(
+ @Nullable List<ComponentKey> componentKeys, Consumer<List<Task>> callback) {
mRecentTasksModel.getTasks(taskGroups -> {
- if (componentKey == null) {
- callback.accept(null);
+ if (componentKeys == null || componentKeys.isEmpty()) {
+ callback.accept(Collections.emptyList());
return;
}
- Task lastActiveTask = null;
- // Loop through tasks in reverse, since they are ordered with most-recent tasks last.
- for (int i = taskGroups.size() - 1; i >= 0; i--) {
- GroupTask groupTask = taskGroups.get(i);
- Task task1 = groupTask.task1;
- if (isInstanceOfComponent(task1, componentKey)) {
- lastActiveTask = task1;
- break;
+
+ List<Task> lastActiveTasks = new ArrayList<>();
+ // For each key we are looking for, add to lastActiveTasks with the corresponding Task
+ // (or null if not found).
+ for (ComponentKey key : componentKeys) {
+ Task lastActiveTask = null;
+ // Loop through tasks in reverse, since they are ordered with most-recent tasks last
+ for (int i = taskGroups.size() - 1; i >= 0; i--) {
+ GroupTask groupTask = taskGroups.get(i);
+ Task task1 = groupTask.task1;
+ // Don't add duplicate Tasks
+ if (isInstanceOfComponent(task1, key) && !lastActiveTasks.contains(task1)) {
+ lastActiveTask = task1;
+ break;
+ }
+ Task task2 = groupTask.task2;
+ if (isInstanceOfComponent(task2, key) && !lastActiveTasks.contains(task2)) {
+ lastActiveTask = task2;
+ break;
+ }
}
- Task task2 = groupTask.task2;
- if (isInstanceOfComponent(task2, componentKey)) {
- lastActiveTask = task2;
- break;
- }
+
+ lastActiveTasks.add(lastActiveTask);
}
- callback.accept(lastActiveTask);
+ callback.accept(lastActiveTasks);
});
}
@@ -239,7 +256,7 @@
*/
public boolean isInstanceOfComponent(@Nullable Task task, @NonNull ComponentKey componentKey) {
// Exclude the task that is already staged
- if (task == null || task.key.id == mInitialTaskId) {
+ if (task == null || task.key.id == mSplitSelectDataHolder.getInitialTaskId()) {
return false;
}
@@ -248,20 +265,55 @@
}
/**
- * To be called when the actual tasks ({@link #mInitialTaskId}, {@link #mSecondTaskId}) are
- * to be launched. Call after launcher side animations are complete.
+ * Listener will only get callbacks going forward from the point of registration. No
+ * methods will be fired upon registering.
*/
- public void launchSplitTasks(Consumer<Boolean> callback) {
+ public void registerSplitListener(@NonNull SplitSelectionListener listener) {
+ if (mSplitSelectionListeners.contains(listener)) {
+ return;
+ }
+ mSplitSelectionListeners.add(listener);
+ }
+
+ public void unregisterSplitListener(@NonNull SplitSelectionListener listener) {
+ mSplitSelectionListeners.remove(listener);
+ }
+
+ private void dispatchOnSplitSelectionExit() {
+ for (SplitSelectionListener listener : mSplitSelectionListeners) {
+ listener.onSplitSelectionExit(false);
+ }
+ }
+
+ /**
+ * To be called when the both split tasks are ready to be launched. Call after launcher side
+ * animations are complete.
+ */
+ public void launchSplitTasks(@SnapPosition int snapPosition,
+ @Nullable Consumer<Boolean> callback) {
Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds =
LogUtils.getShellShareableInstanceId();
- launchTasks(mInitialTaskId, mInitialTaskIntent, mSecondTaskId, mSecondTaskIntent,
- mInitialStagePosition, callback, false /* freezeTaskList */, DEFAULT_SPLIT_RATIO,
- instanceIds.first);
+ launchTasks(callback, false /* freezeTaskList */, snapPosition, instanceIds.first);
mStatsLogManager.logger()
- .withItemInfo(mItemInfo)
+ .withItemInfo(mSplitSelectDataHolder.getItemInfo())
.withInstanceId(instanceIds.second)
- .log(mSplitEvent);
+ .log(mSplitSelectDataHolder.getSplitEvent());
+ }
+
+ /**
+ * A version of {@link #launchSplitTasks(int, Consumer)} that launches with default split ratio.
+ */
+ public void launchSplitTasks(@Nullable Consumer<Boolean> callback) {
+ launchSplitTasks(SNAP_TO_50_50, callback);
+ }
+
+ /**
+ * A version of {@link #launchSplitTasks(int, Consumer)} that launches with a default split
+ * ratio and no callback.
+ */
+ public void launchSplitTasks() {
+ launchSplitTasks(SNAP_TO_50_50, null);
}
/**
@@ -269,11 +321,7 @@
* @param task The second task that will be launched.
*/
public void setSecondTask(Task task) {
- mSecondTaskId = task.key.id;
-
- if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
- mSplitSelectDataHolder.setSecondTask(task.key.id);
- }
+ mSplitSelectDataHolder.setSecondTask(task.key.id);
}
/**
@@ -282,108 +330,29 @@
* @param user The user of that intent.
*/
public void setSecondTask(Intent intent, UserHandle user) {
- mSecondTaskIntent = intent;
- mSecondUser = user;
-
- if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
- mSplitSelectDataHolder.setSecondTask(intent, user);
- }
+ mSplitSelectDataHolder.setSecondTask(intent, user);
}
/**
* To be called as soon as user selects the second app (even if animations aren't complete)
- * Sets {@link #mSecondUser} from that of the pendingIntent
* @param pendingIntent The second PendingIntent that will be launched.
*/
public void setSecondTask(PendingIntent pendingIntent) {
- mSecondPendingIntent = pendingIntent;
- mSecondUser = pendingIntent.getCreatorUserHandle();
-
- if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
- mSplitSelectDataHolder.setSecondTask(pendingIntent);
- }
+ mSplitSelectDataHolder.setSecondTask(pendingIntent);
}
/**
* To be called when we want to launch split pairs from Overview. Split can be initiated from
* either Overview or home, or all apps. Either both taskIds are set, or a pending intent + a
* 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
* foreground (quickswitch, launching previous pairs from overview)
*/
- 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) {
+ public void launchTasks(@Nullable Consumer<Boolean> callback, boolean freezeTaskList,
+ @SnapPosition int snapPosition, @Nullable InstanceId shellInstanceId) {
TestLogging.recordEvent(
TestProtocol.SEQUENCE_MAIN, "launchSplitTasks");
- if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
- launchTasksRefactored(callback, freezeTaskList, splitRatio, shellInstanceId);
- return;
- }
-
- final ActivityOptions options1 = ActivityOptions.makeBasic();
- if (freezeTaskList) {
- options1.setFreezeRecentTasksReordering();
- }
- boolean hasSecondaryPendingIntent = mSecondPendingIntent != null;
- if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
- final RemoteTransition remoteTransition = getShellRemoteTransition(taskId1, taskId2,
- callback);
- if (intent1 == null && (intent2 == null && !hasSecondaryPendingIntent)) {
- mSystemUiProxy.startTasks(taskId1, options1.toBundle(), taskId2,
- null /* options2 */, stagePosition, splitRatio, remoteTransition,
- shellInstanceId);
- } else if (intent2 == null && !hasSecondaryPendingIntent) {
- launchIntentOrShortcut(intent1, mInitialUser, options1, taskId2, stagePosition,
- splitRatio, remoteTransition, shellInstanceId);
- } else if (intent1 == null) {
- launchIntentOrShortcut(intent2, mSecondUser, options1, taskId1,
- getOppositeStagePosition(stagePosition), splitRatio, remoteTransition,
- shellInstanceId);
- } else {
- mSystemUiProxy.startIntents(getPendingIntent(intent1, mInitialUser),
- mInitialUser.getIdentifier(), getShortcutInfo(intent1, mInitialUser),
- options1.toBundle(), hasSecondaryPendingIntent
- ? mSecondPendingIntent
- : getPendingIntent(intent2, mSecondUser),
- mSecondUser.getIdentifier(), getShortcutInfo(intent2, mSecondUser),
- null /* options2 */, stagePosition, splitRatio, remoteTransition,
- shellInstanceId);
- }
- } else {
- final RemoteAnimationAdapter adapter = getLegacyRemoteAdapter(taskId1, taskId2,
- callback);
-
- if (intent1 == null && (intent2 == null && !hasSecondaryPendingIntent)) {
- mSystemUiProxy.startTasksWithLegacyTransition(taskId1, options1.toBundle(),
- taskId2, null /* options2 */, stagePosition, splitRatio, adapter,
- shellInstanceId);
- } else if (intent2 == null && !hasSecondaryPendingIntent) {
- launchIntentOrShortcutLegacy(intent1, mInitialUser, options1, taskId2,
- stagePosition, splitRatio, adapter, shellInstanceId);
- } else if (intent1 == null) {
- launchIntentOrShortcutLegacy(intent2, mSecondUser, options1, taskId1,
- getOppositeStagePosition(stagePosition), splitRatio, adapter,
- shellInstanceId);
- } else {
- mSystemUiProxy.startIntentsWithLegacyTransition(
- getPendingIntent(intent1, mInitialUser), mInitialUser.getIdentifier(),
- getShortcutInfo(intent1, mInitialUser), options1.toBundle(),
- hasSecondaryPendingIntent
- ? mSecondPendingIntent
- : getPendingIntent(intent2, mSecondUser),
- mSecondUser.getIdentifier(), getShortcutInfo(intent2, mSecondUser),
- null /* options2 */, stagePosition, splitRatio, adapter, shellInstanceId);
- }
- }
- }
-
- private void launchTasksRefactored(Consumer<Boolean> callback, boolean freezeTaskList,
- float splitRatio, @Nullable InstanceId shellInstanceId) {
final ActivityOptions options1 = ActivityOptions.makeBasic();
if (freezeTaskList) {
options1.setFreezeRecentTasksReordering();
@@ -404,37 +373,37 @@
if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
final RemoteTransition remoteTransition = getShellRemoteTransition(firstTaskId,
- secondTaskId, callback);
+ secondTaskId, callback, "LaunchSplitPair");
switch (launchData.getSplitLaunchType()) {
case SPLIT_TASK_TASK ->
mSystemUiProxy.startTasks(firstTaskId, optionsBundle, secondTaskId,
- null /* options2 */, initialStagePosition, splitRatio,
+ null /* options2 */, initialStagePosition, snapPosition,
remoteTransition, shellInstanceId);
case SPLIT_TASK_PENDINGINTENT ->
mSystemUiProxy.startIntentAndTask(secondPI, secondUserId, optionsBundle,
- firstTaskId, null /*options2*/, initialStagePosition, splitRatio,
+ firstTaskId, null /*options2*/, initialStagePosition, snapPosition,
remoteTransition, shellInstanceId);
case SPLIT_TASK_SHORTCUT ->
mSystemUiProxy.startShortcutAndTask(secondShortcut, optionsBundle,
- firstTaskId, null /*options2*/, initialStagePosition, splitRatio,
+ firstTaskId, null /*options2*/, initialStagePosition, snapPosition,
remoteTransition, shellInstanceId);
case SPLIT_PENDINGINTENT_TASK ->
mSystemUiProxy.startIntentAndTask(firstPI, firstUserId, optionsBundle,
- secondTaskId, null /*options2*/, initialStagePosition, splitRatio,
+ secondTaskId, null /*options2*/, initialStagePosition, snapPosition,
remoteTransition, shellInstanceId);
case SPLIT_PENDINGINTENT_PENDINGINTENT ->
mSystemUiProxy.startIntents(firstPI, firstUserId, firstShortcut,
optionsBundle, secondPI, secondUserId, secondShortcut,
- null /*options2*/, initialStagePosition, splitRatio,
+ null /*options2*/, initialStagePosition, snapPosition,
remoteTransition, shellInstanceId);
case SPLIT_SHORTCUT_TASK ->
mSystemUiProxy.startShortcutAndTask(firstShortcut, optionsBundle,
- secondTaskId, null /*options2*/, initialStagePosition, splitRatio,
+ secondTaskId, null /*options2*/, initialStagePosition, snapPosition,
remoteTransition, shellInstanceId);
}
} else {
@@ -444,42 +413,41 @@
case SPLIT_TASK_TASK ->
mSystemUiProxy.startTasksWithLegacyTransition(firstTaskId, optionsBundle,
secondTaskId, null /* options2 */, initialStagePosition,
- splitRatio, adapter, shellInstanceId);
+ snapPosition, adapter, shellInstanceId);
case SPLIT_TASK_PENDINGINTENT ->
mSystemUiProxy.startIntentAndTaskWithLegacyTransition(secondPI,
secondUserId, optionsBundle, firstTaskId, null /*options2*/,
- initialStagePosition, splitRatio, adapter, shellInstanceId);
+ initialStagePosition, snapPosition, adapter, shellInstanceId);
case SPLIT_TASK_SHORTCUT ->
mSystemUiProxy.startShortcutAndTaskWithLegacyTransition(secondShortcut,
optionsBundle, firstTaskId, null /*options2*/, initialStagePosition,
- splitRatio, adapter, shellInstanceId);
+ snapPosition, adapter, shellInstanceId);
case SPLIT_PENDINGINTENT_TASK ->
mSystemUiProxy.startIntentAndTaskWithLegacyTransition(firstPI, firstUserId,
optionsBundle, secondTaskId, null /*options2*/,
- initialStagePosition, splitRatio, adapter, shellInstanceId);
+ initialStagePosition, snapPosition, adapter, shellInstanceId);
case SPLIT_PENDINGINTENT_PENDINGINTENT ->
mSystemUiProxy.startIntentsWithLegacyTransition(firstPI, firstUserId,
firstShortcut, optionsBundle, secondPI, secondUserId,
- secondShortcut, null /*options2*/, initialStagePosition, splitRatio,
- adapter, shellInstanceId);
+ secondShortcut, null /*options2*/, initialStagePosition,
+ snapPosition, adapter, shellInstanceId);
case SPLIT_SHORTCUT_TASK ->
mSystemUiProxy.startShortcutAndTaskWithLegacyTransition(firstShortcut,
optionsBundle, secondTaskId, null /*options2*/,
- initialStagePosition, splitRatio, adapter, shellInstanceId);
+ initialStagePosition, snapPosition, adapter, shellInstanceId);
}
}
}
/**
* Used to launch split screen from a split pair that already exists (usually accessible through
- * Overview). This is different than
- * {@link #launchTasks(int, Intent, int, Intent, int, Consumer, boolean, float, InstanceId)} in
- * that this only launches split screen that are existing tasks. This doesn't determine which
+ * Overview). This is different than {@link #launchTasks(Consumer, boolean, int, InstanceId)}
+ * in that this only launches split screen that are existing tasks. This doesn't determine which
* API should be used (i.e. launching split with existing tasks vs intents vs shortcuts, etc).
*
* <p/>
@@ -487,7 +455,7 @@
*/
public void launchExistingSplitPair(@Nullable GroupedTaskView groupedTaskView,
int firstTaskId, int secondTaskId, @StagePosition int stagePosition,
- Consumer<Boolean> callback, boolean freezeTaskList, float splitRatio) {
+ Consumer<Boolean> callback, boolean freezeTaskList, @SnapPosition int snapPosition) {
mLaunchingTaskView = groupedTaskView;
final ActivityOptions options1 = ActivityOptions.makeBasic();
if (freezeTaskList) {
@@ -497,30 +465,24 @@
if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
final RemoteTransition remoteTransition = getShellRemoteTransition(firstTaskId,
- secondTaskId, callback);
- mSystemUiProxy.startTasks(firstTaskId, optionsBundle, secondTaskId,
- null /* options2 */, stagePosition, splitRatio,
- remoteTransition, null /*shellInstanceId*/);
+ secondTaskId, callback, "LaunchExistingPair");
+ mSystemUiProxy.startTasks(firstTaskId, optionsBundle, secondTaskId, null /* options2 */,
+ stagePosition, snapPosition, remoteTransition, null /*shellInstanceId*/);
} else {
final RemoteAnimationAdapter adapter = getLegacyRemoteAdapter(firstTaskId,
secondTaskId, callback);
- mSystemUiProxy.startTasksWithLegacyTransition(firstTaskId, optionsBundle,
- secondTaskId, null /* options2 */, stagePosition,
- splitRatio, adapter, null /*shellInstanceId*/);
+ mSystemUiProxy.startTasksWithLegacyTransition(firstTaskId, optionsBundle, secondTaskId,
+ null /* options2 */, stagePosition, snapPosition, adapter,
+ null /*shellInstanceId*/);
}
}
/**
* Launches the initially selected task/intent in fullscreen (note the same SystemUi APIs are
- * used as {@link #launchSplitTasks(Consumer)} because they are overloaded to launch both
+ * used as {@link #launchSplitTasks(int, Consumer)} because they are overloaded to launch both
* split and fullscreen tasks)
*/
public void launchInitialAppFullscreen(Consumer<Boolean> callback) {
- if (!FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
- launchSplitTasks(callback);
- return;
- }
-
final ActivityOptions options1 = ActivityOptions.makeBasic();
SplitSelectDataHolder.SplitLaunchData launchData =
mSplitSelectDataHolder.getFullscreenLaunchData();
@@ -536,20 +498,19 @@
new RemoteSplitLaunchTransitionRunner(firstTaskId, secondTaskId, callback);
final RemoteTransition remoteTransition = new RemoteTransition(animationRunner,
ActivityThread.currentActivityThread().getApplicationThread(),
- "LaunchSplitPair");
+ "LaunchAppFullscreen");
InstanceId instanceId = LogUtils.getShellShareableInstanceId().first;
if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
switch (launchData.getSplitLaunchType()) {
case SPLIT_SINGLE_TASK_FULLSCREEN -> mSystemUiProxy.startTasks(firstTaskId,
optionsBundle, secondTaskId, null /* options2 */, initialStagePosition,
- DEFAULT_SPLIT_RATIO, remoteTransition, instanceId);
+ SNAP_TO_50_50, remoteTransition, instanceId);
case SPLIT_SINGLE_INTENT_FULLSCREEN -> mSystemUiProxy.startIntentAndTask(firstPI,
firstUserId, optionsBundle, secondTaskId, null /*options2*/,
- initialStagePosition, DEFAULT_SPLIT_RATIO, remoteTransition,
- instanceId);
+ initialStagePosition, SNAP_TO_50_50, remoteTransition, instanceId);
case SPLIT_SINGLE_SHORTCUT_FULLSCREEN -> mSystemUiProxy.startShortcutAndTask(
initialShortcut, optionsBundle, firstTaskId, null /* options2 */,
- initialStagePosition, DEFAULT_SPLIT_RATIO, remoteTransition, instanceId);
+ initialStagePosition, SNAP_TO_50_50, remoteTransition, instanceId);
}
} else {
final RemoteAnimationAdapter adapter = getLegacyRemoteAdapter(firstTaskId,
@@ -557,125 +518,51 @@
switch (launchData.getSplitLaunchType()) {
case SPLIT_SINGLE_TASK_FULLSCREEN -> mSystemUiProxy.startTasksWithLegacyTransition(
firstTaskId, optionsBundle, secondTaskId, null /* options2 */,
- initialStagePosition, DEFAULT_SPLIT_RATIO, adapter, instanceId);
+ initialStagePosition, SNAP_TO_50_50, adapter, instanceId);
case SPLIT_SINGLE_INTENT_FULLSCREEN ->
mSystemUiProxy.startIntentAndTaskWithLegacyTransition(firstPI, firstUserId,
optionsBundle, secondTaskId, null /*options2*/,
- initialStagePosition, DEFAULT_SPLIT_RATIO, adapter,
- instanceId);
+ initialStagePosition, SNAP_TO_50_50, adapter, instanceId);
case SPLIT_SINGLE_SHORTCUT_FULLSCREEN ->
mSystemUiProxy.startShortcutAndTaskWithLegacyTransition(
initialShortcut, optionsBundle, firstTaskId, null /* options2 */,
- initialStagePosition, DEFAULT_SPLIT_RATIO, adapter, instanceId);
+ initialStagePosition, SNAP_TO_50_50, adapter, instanceId);
}
}
}
+ public void initSplitFromDesktopController(Launcher launcher) {
+ mSplitFromDesktopController = new SplitFromDesktopController(launcher);
+ }
+
private RemoteTransition getShellRemoteTransition(int firstTaskId, int secondTaskId,
- Consumer<Boolean> callback) {
+ @Nullable Consumer<Boolean> callback, String transitionName) {
final RemoteSplitLaunchTransitionRunner animationRunner =
new RemoteSplitLaunchTransitionRunner(firstTaskId, secondTaskId, callback);
return new RemoteTransition(animationRunner,
- ActivityThread.currentActivityThread().getApplicationThread(), "LaunchSplitPair");
+ ActivityThread.currentActivityThread().getApplicationThread(), transitionName);
}
private RemoteAnimationAdapter getLegacyRemoteAdapter(int firstTaskId, int secondTaskId,
- Consumer<Boolean> callback) {
+ @Nullable Consumer<Boolean> callback) {
final RemoteSplitLaunchAnimationRunner animationRunner =
new RemoteSplitLaunchAnimationRunner(firstTaskId, secondTaskId, callback);
return new RemoteAnimationAdapter(animationRunner, 300, 150,
ActivityThread.currentActivityThread().getApplicationThread());
}
- private void launchIntentOrShortcut(Intent intent, UserHandle user, ActivityOptions options1,
- int taskId, @StagePosition int stagePosition, float splitRatio,
- RemoteTransition remoteTransition, @Nullable InstanceId shellInstanceId) {
- final ShortcutInfo shortcutInfo = getShortcutInfo(intent, user);
- if (shortcutInfo != null) {
- mSystemUiProxy.startShortcutAndTask(shortcutInfo,
- options1.toBundle(), taskId, null /* options2 */, stagePosition,
- splitRatio, remoteTransition, shellInstanceId);
- } else {
- mSystemUiProxy.startIntentAndTask(getPendingIntent(intent, user), user.getIdentifier(),
- options1.toBundle(), taskId, null /* options2 */, stagePosition, splitRatio,
- remoteTransition, shellInstanceId);
- }
- }
-
- private void launchIntentOrShortcutLegacy(Intent intent, UserHandle user,
- ActivityOptions options1, int taskId, @StagePosition int stagePosition,
- float splitRatio, RemoteAnimationAdapter adapter,
- @Nullable InstanceId shellInstanceId) {
- final ShortcutInfo shortcutInfo = getShortcutInfo(intent, user);
- if (shortcutInfo != null) {
- mSystemUiProxy.startShortcutAndTaskWithLegacyTransition(shortcutInfo,
- options1.toBundle(), taskId, null /* options2 */, stagePosition,
- splitRatio, adapter, shellInstanceId);
- } else {
- mSystemUiProxy.startIntentAndTaskWithLegacyTransition(
- getPendingIntent(intent, user), user.getIdentifier(), options1.toBundle(),
- taskId, null /* options2 */, stagePosition, splitRatio, adapter,
- shellInstanceId);
- }
- }
-
- /**
- * We treat launching by intents as grouped in two ways,
- * If {@param intent} represents the first app, we always convert the intent to pending intent
- * It it represents second app, either the second intent OR mSecondPendingIntent will be used
- * convert second intent to a pendingIntent OR return mSecondPendingIntent as is
- */
- private PendingIntent getPendingIntent(Intent intent, UserHandle user) {
- boolean isParamFirstIntent = intent != null && intent == mInitialTaskIntent;
- if (!isParamFirstIntent && mSecondPendingIntent != null) {
- // Because mSecondPendingIntent and mSecondTaskIntent can't both be set, we know we need
- // to be using mSecondPendingIntent
- return mSecondPendingIntent;
- }
-
- // intent param must either be mInitialTaskIntent or mSecondTaskIntent, convert either to
- // a new PendingIntent
- return intent == null ? null : (user != null
- ? PendingIntent.getActivityAsUser(mContext, 0, intent,
- FLAG_MUTABLE | FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT, null /* options */, user)
- : PendingIntent.getActivity(mContext, 0, intent,
- FLAG_MUTABLE | FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT));
- }
-
public @StagePosition int getActiveSplitStagePosition() {
- return mInitialStagePosition;
+ return mSplitSelectDataHolder.getInitialStagePosition();
}
public StatsLogManager.EventEnum getSplitEvent() {
- return mSplitEvent;
+ return mSplitSelectDataHolder.getSplitEvent();
}
public void setRecentsAnimationRunning(boolean running) {
mRecentsAnimationRunning = running;
}
- @Nullable
- private ShortcutInfo getShortcutInfo(Intent intent, UserHandle user) {
- if (intent == null || intent.getPackage() == null) {
- return null;
- }
-
- final String shortcutId = intent.getStringExtra(ShortcutKey.EXTRA_SHORTCUT_ID);
- if (shortcutId == null) {
- return null;
- }
-
- try {
- final Context context = mContext.createPackageContextAsUser(
- intent.getPackage(), 0 /* flags */, user);
- return new ShortcutInfo.Builder(context, shortcutId).build();
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Failed to create a ShortcutInfo for " + intent.getPackage());
- }
-
- return null;
- }
-
public boolean isAnimateCurrentTaskDismissal() {
return mAnimateCurrentTaskDismissal;
}
@@ -706,7 +593,7 @@
private final Consumer<Boolean> mSuccessCallback;
RemoteSplitLaunchTransitionRunner(int initialTaskId, int secondTaskId,
- Consumer<Boolean> callback) {
+ @Nullable Consumer<Boolean> callback) {
mInitialTaskId = initialTaskId;
mSecondTaskId = secondTaskId;
mSuccessCallback = callback;
@@ -731,9 +618,8 @@
if (mSuccessCallback != null) {
mSuccessCallback.accept(true);
}
+ resetState();
});
- // After successful launch, call resetState
- resetState();
});
}
@@ -754,7 +640,7 @@
private final Consumer<Boolean> mSuccessCallback;
RemoteSplitLaunchAnimationRunner(int initialTaskId, int secondTaskId,
- Consumer<Boolean> successCallback) {
+ @Nullable Consumer<Boolean> successCallback) {
mInitialTaskId = initialTaskId;
mSecondTaskId = secondTaskId;
mSuccessCallback = successCallback;
@@ -790,26 +676,20 @@
}
/**
- * To be called if split select was cancelled
+ * To be called whenever we exit split selection state. If
+ * {@link FeatureFlags#ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE} is set, this should be the
+ * central way split is getting reset, which should then go through the callbacks to reset
+ * other state.
*/
public void resetState() {
- if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
- mSplitSelectDataHolder.resetState();
- }
- mInitialTaskId = INVALID_TASK_ID;
- mInitialTaskIntent = null;
- mSecondTaskId = INVALID_TASK_ID;
- mSecondTaskIntent = null;
- mInitialUser = null;
- mSecondUser = null;
- mInitialStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
+ mSplitSelectDataHolder.resetState();
+ dispatchOnSplitSelectionExit();
mRecentsAnimationRunning = false;
mLaunchingTaskView = null;
- mItemInfo = null;
- mSplitEvent = null;
mAnimateCurrentTaskDismissal = false;
mDismissingFromSplitPair = false;
- mSecondPendingIntent = null;
+ mFirstFloatingTaskView = null;
+ mSplitInstructionsView = null;
}
/**
@@ -817,11 +697,7 @@
* chosen
*/
public boolean isSplitSelectActive() {
- if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
- return mSplitSelectDataHolder.isSplitSelectActive();
- } else {
- return isInitialTaskIntentSet() && !isSecondTaskIntentSet();
- }
+ return mSplitSelectDataHolder.isSplitSelectActive();
}
/**
@@ -829,53 +705,170 @@
* be launched
*/
public boolean isBothSplitAppsConfirmed() {
- if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
- return mSplitSelectDataHolder.isBothSplitAppsConfirmed();
- } else {
- return isInitialTaskIntentSet() && isSecondTaskIntentSet();
- }
- }
-
- private boolean isInitialTaskIntentSet() {
- return (mInitialTaskId != INVALID_TASK_ID || mInitialTaskIntent != null);
+ return mSplitSelectDataHolder.isBothSplitAppsConfirmed();
}
public int getInitialTaskId() {
- if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
- return mSplitSelectDataHolder.getInitialTaskId();
- } else {
- return mInitialTaskId;
- }
+ return mSplitSelectDataHolder.getInitialTaskId();
}
public int getSecondTaskId() {
- if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
- return mSplitSelectDataHolder.getSecondTaskId();
- } else {
- return mSecondTaskId;
- }
- }
-
- private boolean isSecondTaskIntentSet() {
- return (mSecondTaskId != INVALID_TASK_ID || mSecondTaskIntent != null
- || mSecondPendingIntent != null);
+ return mSplitSelectDataHolder.getSecondTaskId();
}
public void setFirstFloatingTaskView(FloatingTaskView floatingTaskView) {
mFirstFloatingTaskView = floatingTaskView;
}
+ public void setSplitInstructionsView(SplitInstructionsView splitInstructionsView) {
+ mSplitInstructionsView = splitInstructionsView;
+ }
+
+ @Nullable
public FloatingTaskView getFirstFloatingTaskView() {
return mFirstFloatingTaskView;
}
+ @Nullable
+ public SplitInstructionsView getSplitInstructionsView() {
+ return mSplitInstructionsView;
+ }
+
public AppPairsController getAppPairsController() {
return mAppPairsController;
}
+ public BackPressHandler getSplitBackHandler() {
+ return mSplitBackHandler;
+ }
+
public void dump(String prefix, PrintWriter writer) {
if (mSplitSelectDataHolder != null) {
mSplitSelectDataHolder.dump(prefix, writer);
}
}
+
+ public class SplitFromDesktopController {
+ private static final String TAG = "SplitFromDesktopController";
+
+ private final Launcher mLauncher;
+ private final OverviewComponentObserver mOverviewComponentObserver;
+ private final int mSplitPlaceholderSize;
+ private final int mSplitPlaceholderInset;
+ private ActivityManager.RunningTaskInfo mTaskInfo;
+ private ISplitSelectListener mSplitSelectListener;
+ private Drawable mAppIcon;
+
+ public SplitFromDesktopController(Launcher launcher) {
+ mLauncher = launcher;
+ RecentsAnimationDeviceState deviceState = new RecentsAnimationDeviceState(
+ launcher.getApplicationContext());
+ mOverviewComponentObserver =
+ new OverviewComponentObserver(launcher.getApplicationContext(), deviceState);
+ mSplitPlaceholderSize = mLauncher.getResources().getDimensionPixelSize(
+ R.dimen.split_placeholder_size);
+ mSplitPlaceholderInset = mLauncher.getResources().getDimensionPixelSize(
+ R.dimen.split_placeholder_inset);
+ mSplitSelectListener = new ISplitSelectListener.Stub() {
+ @Override
+ public boolean onRequestSplitSelect(ActivityManager.RunningTaskInfo taskInfo,
+ int splitPosition, Rect taskBounds) {
+ if (!ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE.get()) return false;
+ MAIN_EXECUTOR.execute(() -> enterSplitSelect(taskInfo, splitPosition,
+ taskBounds));
+ return true;
+ }
+ };
+ SystemUiProxy.INSTANCE.get(mLauncher).registerSplitSelectListener(mSplitSelectListener);
+ }
+
+ /**
+ * Enter split select from desktop mode.
+ * @param taskInfo the desktop task to move to split stage
+ * @param splitPosition the stage position used for this transition
+ * @param taskBounds the bounds of the task, used for {@link FloatingTaskView} animation
+ */
+ public void enterSplitSelect(ActivityManager.RunningTaskInfo taskInfo,
+ int splitPosition, Rect taskBounds) {
+ mTaskInfo = taskInfo;
+ String packageName = mTaskInfo.realActivity.getPackageName();
+ PackageManager pm = mLauncher.getApplicationContext().getPackageManager();
+ IconProvider provider = new IconProvider(mLauncher.getApplicationContext());
+ try {
+ mAppIcon = provider.getIcon(pm.getActivityInfo(mTaskInfo.baseActivity,
+ PackageManager.ComponentInfoFlags.of(0)));
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Package not found: " + packageName, e);
+ }
+ RecentsAnimationCallbacks callbacks = new RecentsAnimationCallbacks(
+ SystemUiProxy.INSTANCE.get(mLauncher.getApplicationContext()),
+ false /* allowMinimizeSplitScreen */);
+
+ DesktopSplitRecentsAnimationListener listener =
+ new DesktopSplitRecentsAnimationListener(splitPosition, taskBounds);
+
+ MAIN_EXECUTOR.execute(() -> {
+ callbacks.addListener(listener);
+ UI_HELPER_EXECUTOR.execute(
+ // Transition from app to enter stage split in launcher with
+ // recents animation.
+ () -> ActivityManagerWrapper.getInstance().startRecentsActivity(
+ mOverviewComponentObserver.getOverviewIntent(),
+ SystemClock.uptimeMillis(), callbacks, null, null));
+ });
+ }
+
+ private class DesktopSplitRecentsAnimationListener implements
+ RecentsAnimationCallbacks.RecentsAnimationListener {
+ private final Rect mTempRect = new Rect();
+ private final RectF mTaskBounds = new RectF();
+ private final int mSplitPosition;
+
+ DesktopSplitRecentsAnimationListener(int splitPosition, Rect taskBounds) {
+ mSplitPosition = splitPosition;
+ mTaskBounds.set(taskBounds);
+ }
+
+ @Override
+ public void onRecentsAnimationStart(RecentsAnimationController controller,
+ RecentsAnimationTargets targets) {
+ StatsLogManager.LauncherEvent launcherDesktopSplitEvent =
+ mSplitPosition == STAGE_POSITION_BOTTOM_OR_RIGHT ?
+ LAUNCHER_DESKTOP_MODE_SPLIT_RIGHT_BOTTOM :
+ LAUNCHER_DESKTOP_MODE_SPLIT_LEFT_TOP;
+ setInitialTaskSelect(mTaskInfo, mSplitPosition,
+ null, launcherDesktopSplitEvent);
+
+ RecentsView recentsView = mLauncher.getOverviewPanel();
+ recentsView.getPagedOrientationHandler().getInitialSplitPlaceholderBounds(
+ mSplitPlaceholderSize, mSplitPlaceholderInset,
+ mLauncher.getDeviceProfile(), getActiveSplitStagePosition(), mTempRect);
+
+ PendingAnimation anim = new PendingAnimation(
+ SplitAnimationTimings.TABLET_HOME_TO_SPLIT.getDuration());
+ final FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView(
+ mLauncher, mLauncher.getDragLayer(),
+ null /* thumbnail */,
+ mAppIcon, new RectF());
+ floatingTaskView.setAlpha(1);
+ floatingTaskView.addStagingAnimation(anim, mTaskBounds, mTempRect,
+ false /* fadeWithThumbnail */, true /* isStagedTask */);
+ setFirstFloatingTaskView(floatingTaskView);
+
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ controller.finish(true /* toRecents */, null /* onFinishComplete */,
+ false /* sendUserLeaveHint */);
+ }
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ SystemUiProxy.INSTANCE.get(mLauncher.getApplicationContext())
+ .onDesktopSplitSelectAnimComplete(mTaskInfo);
+ }
+ });
+ anim.buildAnim().start();
+ }
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java b/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
index f5b00cf..d1ec2b6 100644
--- a/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
+++ b/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
@@ -16,7 +16,7 @@
package com.android.quickstep.util;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
import android.view.animation.Interpolator;
diff --git a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
index 148a45a..056f9aa 100644
--- a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
@@ -16,6 +16,7 @@
package com.android.quickstep.util;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE;
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;
@@ -169,6 +170,7 @@
private void cleanUp() {
mLauncher.getDragLayer().removeView(firstFloatingTaskView);
mLauncher.getDragLayer().removeView(secondFloatingTaskView);
+ mController.getSplitAnimationController().removeSplitInstructionsView(mLauncher);
mController.resetState();
}
});
@@ -177,7 +179,8 @@
private boolean shouldIgnoreSecondSplitLaunch() {
return (!ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS.get()
- && !ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get())
+ && !ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()
+ && !ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE.get())
|| !mController.isSplitSelectActive();
}
}
diff --git a/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java b/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java
index 24d8326..f3fa86a 100644
--- a/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java
@@ -27,21 +27,15 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.ActivityManager;
-import android.content.Intent;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.SystemClock;
-import android.os.UserHandle;
-import android.view.View;
import androidx.annotation.BinderThread;
-import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.anim.PendingAnimation;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.uioverrides.QuickstepLauncher;
-import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.OverviewComponentObserver;
import com.android.quickstep.RecentsAnimationCallbacks;
import com.android.quickstep.RecentsAnimationController;
@@ -143,11 +137,7 @@
.updateIconInBackground(
Task.from(new Task.TaskKey(runningTaskInfo), runningTaskInfo,
false /* isLocked */),
- (task) -> {
- if (task.thumbnail != null) {
- floatingTaskView.setIcon(task.thumbnail.thumbnail);
- }
- });
+ (task) -> floatingTaskView.setIcon(task.icon));
floatingTaskView.setAlpha(1);
floatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect,
false /* fadeWithThumbnail */, true /* isStagedTask */);
diff --git a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index cd5edab..6b3199f 100644
--- a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -15,11 +15,11 @@
*/
package com.android.quickstep.util;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_DEPTH_CONTROLLER;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
@@ -177,8 +177,8 @@
addDepthAnimationForState(launcher, NORMAL, duration);
- mAnimators.play(launcher.getRootView().getSysUiScrim().createSysuiMultiplierAnim(0f, 1f)
- .setDuration(duration));
+ mAnimators.play(launcher.getRootView().getSysUiScrim().getSysUIMultiplier()
+ .animateToValue(0f, 1f).setDuration(duration));
}
private void addAnimationForPage(CellLayout page, int totalRows, long duration) {
diff --git a/quickstep/src/com/android/quickstep/util/SurfaceTransaction.java b/quickstep/src/com/android/quickstep/util/SurfaceTransaction.java
index 441f88d..5fd86c0 100644
--- a/quickstep/src/com/android/quickstep/util/SurfaceTransaction.java
+++ b/quickstep/src/com/android/quickstep/util/SurfaceTransaction.java
@@ -166,5 +166,10 @@
this.shadowRadius = radius;
return this;
}
+
+ @Override
+ public SurfaceProperties setShow() {
+ return this;
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
index 1112f4d..7cc2c46 100644
--- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
@@ -26,7 +26,6 @@
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
-import android.os.SystemProperties;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -153,14 +152,9 @@
// Create a new overlay layer. We do not call detach on this instance, it's propagated
// to other classes like PipTaskOrganizer / RecentsAnimationController to complete
// the cleanup.
- if (SystemProperties.getBoolean(
- "persist.wm.debug.enable_pip_app_icon_overlay", true)) {
- mPipContentOverlay = new PipContentOverlay.PipAppIconOverlay(view.getContext(),
- mAppBounds, new IconProvider(context).getIcon(mActivityInfo),
- appIconSizePx);
- } else {
- mPipContentOverlay = new PipContentOverlay.PipColorOverlay(view.getContext());
- }
+ mPipContentOverlay = new PipContentOverlay.PipAppIconOverlay(view.getContext(),
+ mAppBounds, new IconProvider(context).getIcon(mActivityInfo),
+ appIconSizePx);
final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
mPipContentOverlay.attach(tx, mLeash);
} else {
diff --git a/quickstep/src/com/android/quickstep/util/SystemActionConstants.java b/quickstep/src/com/android/quickstep/util/SystemActionConstants.java
new file mode 100644
index 0000000..522930f
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/SystemActionConstants.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.util;
+
+/**
+ * Constants for registering SystemActions.
+ *
+ * Prefer to use AccessibilityService.GLOBAL_ACTION_* if applicable.
+ */
+public final class SystemActionConstants {
+
+ public static final int SYSTEM_ACTION_ID_TASKBAR = 499;
+ public static final int SYSTEM_ACTION_ID_SEARCH_SCREEN = 500;
+
+ /**
+ * For Taskbar broadcast intent filter.
+ */
+ public static final String ACTION_SHOW_TASKBAR = "ACTION_SHOW_TASKBAR";
+
+ /**
+ * For Search Screen broadcast intent filter.
+ */
+ public static final String ACTION_SEARCH_SCREEN = "ACTION_SEARCH_SCREEN";
+
+ private SystemActionConstants() {}
+}
diff --git a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
index 9808b28..c82cdb7 100644
--- a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
+++ b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
@@ -24,11 +24,11 @@
import android.view.WindowMetrics;
import com.android.internal.policy.SystemBarUtils;
-import com.android.launcher3.logging.FileLog;
import com.android.launcher3.util.WindowBounds;
import com.android.launcher3.util.window.CachedDisplayInfo;
import com.android.launcher3.util.window.WindowManagerProxy;
+import java.util.List;
import java.util.Set;
/**
@@ -54,16 +54,15 @@
}
@Override
- public ArrayMap<CachedDisplayInfo, WindowBounds[]> estimateInternalDisplayBounds(
+ public ArrayMap<CachedDisplayInfo, List<WindowBounds>> estimateInternalDisplayBounds(
Context displayInfoContext) {
- ArrayMap<CachedDisplayInfo, WindowBounds[]> result = new ArrayMap<>();
+ ArrayMap<CachedDisplayInfo, List<WindowBounds>> result = new ArrayMap<>();
WindowManager windowManager = displayInfoContext.getSystemService(WindowManager.class);
Set<WindowMetrics> possibleMaximumWindowMetrics =
windowManager.getPossibleMaximumWindowMetrics(DEFAULT_DISPLAY);
- FileLog.d("b/283944974", "possibleMaximumWindowMetrics: " + possibleMaximumWindowMetrics);
for (WindowMetrics windowMetrics : possibleMaximumWindowMetrics) {
CachedDisplayInfo info = getDisplayInfo(windowMetrics, Surface.ROTATION_0);
- WindowBounds[] bounds = estimateWindowBounds(displayInfoContext, info);
+ List<WindowBounds> bounds = estimateWindowBounds(displayInfoContext, info);
result.put(info, bounds);
}
return result;
diff --git a/quickstep/src/com/android/quickstep/util/TISBindHelper.java b/quickstep/src/com/android/quickstep/util/TISBindHelper.java
index 7b122c6..ddc796f 100644
--- a/quickstep/src/com/android/quickstep/util/TISBindHelper.java
+++ b/quickstep/src/com/android/quickstep/util/TISBindHelper.java
@@ -23,6 +23,10 @@
import android.os.IBinder;
import android.util.Log;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.taskbar.TaskbarManager;
+import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.TouchInteractionService.TISBinder;
@@ -50,6 +54,7 @@
private short mConnectionAttempts;
private boolean mTisServiceBound;
private boolean mIsConnected;
+ @Nullable private TISBinder mBinder;
public TISBindHelper(Context context, Consumer<TISBinder> connectionCallback) {
mContext = context;
@@ -70,7 +75,8 @@
Log.d(TAG, "TIS service connected");
mIsConnected = true;
- mConnectionCallback.accept((TISBinder) iBinder);
+ mBinder = (TISBinder) iBinder;
+ mConnectionCallback.accept(mBinder);
// Flush the pending callbacks
for (Runnable r : mPendingConnectedCallbacks) {
r.run();
@@ -80,7 +86,11 @@
}
@Override
- public void onServiceDisconnected(ComponentName componentName) { }
+ public void onServiceDisconnected(ComponentName componentName) {
+ Log.d(TAG, "TIS service disconnected");
+ mBinder = null;
+ mIsConnected = false;
+ }
@Override
public void onBindingDied(ComponentName name) {
@@ -88,6 +98,21 @@
internalBindToTIS();
}
+ @Nullable
+ public TISBinder getBinder() {
+ return mBinder;
+ }
+
+ @Nullable
+ public TaskbarManager getTaskbarManager() {
+ return mBinder == null ? null : mBinder.getTaskbarManager();
+ }
+
+ @Nullable
+ public OverviewCommandHelper getOverviewCommandHelper() {
+ return mBinder == null ? null : mBinder.getOverviewCommandHelper();
+ }
+
/**
* Runs the given {@param r} runnable when the service is connected.
*/
@@ -139,6 +164,7 @@
public void onDestroy() {
internalUnbindToTIS();
resetServiceBindRetryState();
+ mBinder = null;
mIsConnected = false;
mPendingConnectedCallbacks.clear();
}
diff --git a/quickstep/src/com/android/quickstep/util/TabletHomeToSplitTimings.java b/quickstep/src/com/android/quickstep/util/TabletHomeToSplitTimings.java
index bf8612a..8804049 100644
--- a/quickstep/src/com/android/quickstep/util/TabletHomeToSplitTimings.java
+++ b/quickstep/src/com/android/quickstep/util/TabletHomeToSplitTimings.java
@@ -16,7 +16,7 @@
package com.android.quickstep.util;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.LINEAR;
import android.view.animation.Interpolator;
diff --git a/quickstep/src/com/android/quickstep/util/TabletOverviewToSplitTimings.java b/quickstep/src/com/android/quickstep/util/TabletOverviewToSplitTimings.java
index cbf46bf..5463d84 100644
--- a/quickstep/src/com/android/quickstep/util/TabletOverviewToSplitTimings.java
+++ b/quickstep/src/com/android/quickstep/util/TabletOverviewToSplitTimings.java
@@ -16,7 +16,7 @@
package com.android.quickstep.util;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.app.animation.Interpolators.DECELERATE_2;
import android.view.animation.Interpolator;
@@ -36,8 +36,8 @@
public int getGridSlideDuration() { return 500; }
public int getDuration() { return TABLET_ENTER_DURATION; }
- public Interpolator getStagedRectXInterpolator() { return DEACCEL_2; }
- public Interpolator getStagedRectYInterpolator() { return DEACCEL_2; }
- public Interpolator getStagedRectScaleXInterpolator() { return DEACCEL_2; }
- public Interpolator getStagedRectScaleYInterpolator() { return DEACCEL_2; }
+ public Interpolator getStagedRectXInterpolator() { return DECELERATE_2; }
+ public Interpolator getStagedRectYInterpolator() { return DECELERATE_2; }
+ public Interpolator getStagedRectScaleXInterpolator() { return DECELERATE_2; }
+ public Interpolator getStagedRectScaleYInterpolator() { return DECELERATE_2; }
}
diff --git a/quickstep/src/com/android/quickstep/util/TaskRemovedDuringLaunchListener.java b/quickstep/src/com/android/quickstep/util/TaskRemovedDuringLaunchListener.java
index c22e0bc..d7b3431 100644
--- a/quickstep/src/com/android/quickstep/util/TaskRemovedDuringLaunchListener.java
+++ b/quickstep/src/com/android/quickstep/util/TaskRemovedDuringLaunchListener.java
@@ -94,8 +94,10 @@
final Runnable taskLaunchFailedCallback = mTaskLaunchFailedCallback;
RecentsModel.INSTANCE.getNoCreate().isTaskRemoved(mLaunchedTaskId, (taskRemoved) -> {
if (taskRemoved) {
- ActiveGestureLog.INSTANCE.addLog("Launch failed, task (id=" + launchedTaskId
- + ") finished mid transition");
+ ActiveGestureLog.INSTANCE.addLog(
+ new ActiveGestureLog.CompoundString("Launch failed, task (id=")
+ .append(launchedTaskId)
+ .append(") finished mid transition"));
taskLaunchFailedCallback.run();
}
}, (task) -> true /* filter */);
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index 303a528..510044d 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -26,6 +26,7 @@
import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
import static com.android.quickstep.util.RecentsOrientedState.postDisplayRotation;
import static com.android.quickstep.util.RecentsOrientedState.preDisplayRotation;
+import static com.android.quickstep.util.SplitScreenUtils.convertLauncherSplitBoundsToShell;
import android.animation.TimeInterpolator;
import android.content.Context;
@@ -112,8 +113,7 @@
mContext = context;
mSizeStrategy = sizeStrategy;
- // TODO(b/187074722): Don't create this per-TaskViewSimulator
- mOrientationState = TraceHelper.allowIpcs("",
+ mOrientationState = TraceHelper.allowIpcs("TaskViewSimulator.init",
() -> new RecentsOrientedState(context, sizeStrategy, i -> { }));
mOrientationState.setGestureActive(true);
mCurrentFullscreenParams = new FullscreenDrawParams(context);
@@ -147,12 +147,6 @@
return 1;
}
- if (mIsDesktopTask) {
- mTaskRect.set(mThumbnailPosition);
- mPivot.set(mTaskRect.centerX(), mTaskRect.centerY());
- return 1;
- }
-
if (mIsGridTask) {
mSizeStrategy.calculateGridTaskSize(mContext, mDp, mTaskRect,
mOrientationState.getOrientationHandler());
@@ -170,6 +164,20 @@
mOrientationState.getOrientationHandler()
.setSplitTaskSwipeRect(mDp, mTaskRect, mSplitBounds, mStagePosition);
mTaskRect.offset(mTaskRectTranslationX, mTaskRectTranslationY);
+ } else if (mIsDesktopTask) {
+ // For desktop, tasks can take up only part of the screen size.
+ // Full task size represents the whole screen size, but scaled down to fit in recents.
+ // Task rect will represent the scaled down thumbnail position and is placed inside
+ // full task size as it is on the home screen.
+ fullTaskSize = new Rect(mTaskRect);
+ PointF fullscreenTaskDimension = new PointF();
+ BaseActivityInterface.getTaskDimension(mContext, mDp, fullscreenTaskDimension);
+ // Calculate the scale down factor used in recents
+ float scale = fullTaskSize.width() / fullscreenTaskDimension.x;
+ mTaskRect.set(mThumbnailPosition);
+ mTaskRect.scale(scale);
+ // Ensure the task rect is inside the full task rect
+ mTaskRect.offset(fullTaskSize.left, fullTaskSize.top);
} else {
fullTaskSize = mTaskRect;
}
@@ -203,7 +211,8 @@
mStagePosition = mThumbnailPosition.equals(splitInfo.leftTopBounds) ?
STAGE_POSITION_TOP_OR_LEFT :
STAGE_POSITION_BOTTOM_OR_RIGHT;
- mPositionHelper.setSplitBounds(convertSplitBounds(mSplitBounds), mStagePosition);
+ mPositionHelper.setSplitBounds(convertLauncherSplitBoundsToShell(mSplitBounds),
+ mStagePosition);
}
/**
@@ -336,8 +345,7 @@
boolean isRtlEnabled = !mIsRecentsRtl;
mPositionHelper.updateThumbnailMatrix(
mThumbnailPosition, mThumbnailData, mTaskRect.width(), mTaskRect.height(),
- mDp.widthPx, mDp.heightPx, mDp.taskbarHeight, mDp.isTablet,
- mOrientationState.getRecentsActivityRotation(), isRtlEnabled);
+ mDp.isTablet, mOrientationState.getRecentsActivityRotation(), isRtlEnabled);
mPositionHelper.getMatrix().invert(mInversePositionMatrix);
if (DEBUG) {
Log.d(TAG, " taskRect: " + mTaskRect);
@@ -346,7 +354,7 @@
float fullScreenProgress = Utilities.boundToRange(this.fullScreenProgress.value, 0, 1);
mCurrentFullscreenParams.setProgress(fullScreenProgress, recentsViewScale.value,
- /* taskViewScale= */1f, mTaskRect.width(), mDp, mPositionHelper);
+ /* taskViewScale= */1f);
// Apply thumbnail matrix
float taskWidth = mTaskRect.width();
@@ -429,16 +437,4 @@
// Ideally we should use square-root. This is an optimization as one of the dimension is 0.
return Math.max(Math.abs(mTempPoint[0]), Math.abs(mTempPoint[1]));
}
-
- /**
- * TODO(b/254378592): Remove this after consolidation of classes
- */
- public static com.android.wm.shell.util.SplitBounds convertSplitBounds(SplitBounds bounds) {
- return new com.android.wm.shell.util.SplitBounds(
- bounds.leftTopBounds,
- bounds.rightBottomBounds,
- bounds.leftTopTaskId,
- bounds.rightBottomTaskId
- );
- }
}
diff --git a/quickstep/src/com/android/quickstep/util/TransformParams.java b/quickstep/src/com/android/quickstep/util/TransformParams.java
index 0f20e43..1cbded6 100644
--- a/quickstep/src/com/android/quickstep/util/TransformParams.java
+++ b/quickstep/src/com/android/quickstep/util/TransformParams.java
@@ -21,8 +21,8 @@
import android.util.FloatProperty;
import android.view.RemoteAnimationTarget;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.Interpolators;
import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
@@ -153,7 +153,8 @@
// Fade out Assistant overlay.
if (activityType == ACTIVITY_TYPE_ASSISTANT && app.isNotInRecents) {
float progress = Utilities.boundToRange(getProgress(), 0, 1);
- builder.setAlpha(1 - Interpolators.DEACCEL_2_5.getInterpolation(progress));
+ builder.setAlpha(1 - Interpolators.DECELERATE_QUINT
+ .getInterpolation(progress));
} else {
builder.setAlpha(getTargetAlpha());
}
diff --git a/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java b/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
index 34fa7f1..0a97793 100644
--- a/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
+++ b/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
@@ -32,11 +32,11 @@
import android.util.FloatProperty;
import android.view.View;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.Hotseat;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Workspace;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.states.StateAnimationConfig;
@@ -92,7 +92,8 @@
}
// Add sysui scrim animation.
- mAnimators.play(launcher.getRootView().getSysUiScrim().createSysuiMultiplierAnim(0f, 1f));
+ mAnimators.play(launcher.getRootView().getSysUiScrim()
+ .getSysUIMultiplier().animateToValue(0f, 1f));
mAnimators.setDuration(DURATION_MS);
mAnimators.setInterpolator(Interpolators.DECELERATED_EASE);
diff --git a/quickstep/src/com/android/quickstep/views/AllAppsEduView.java b/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
index 716d389..fdc8f1f 100644
--- a/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
+++ b/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
@@ -15,12 +15,12 @@
*/
package com.android.quickstep.views;
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.OVERSHOOT_1_7;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALL_APPS_EDU_SHOWN;
import android.animation.Animator;
diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
index 6813857..cfb4d0d 100644
--- a/quickstep/src/com/android/quickstep/views/ClearAllButton.java
+++ b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
@@ -16,6 +16,8 @@
package com.android.quickstep.views;
+import static com.android.launcher3.config.FeatureFlags.enableGridOnlyOverview;
+
import android.content.Context;
import android.util.AttributeSet;
import android.util.FloatProperty;
@@ -248,8 +250,15 @@
*/
private float getOriginalTranslationY() {
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
- return deviceProfile.isTablet
- ? deviceProfile.overviewRowSpacing
- : deviceProfile.overviewTaskThumbnailTopMarginPx / 2.0f;
+ if (deviceProfile.isTablet) {
+ if (enableGridOnlyOverview()) {
+ return (getRecentsView().getLastComputedTaskSize().height()
+ + deviceProfile.overviewTaskThumbnailTopMarginPx) / 2.0f
+ + deviceProfile.overviewRowSpacing;
+ } else {
+ return deviceProfile.overviewRowSpacing;
+ }
+ }
+ return deviceProfile.overviewTaskThumbnailTopMarginPx / 2.0f;
}
}
diff --git a/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java b/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java
new file mode 100644
index 0000000..a5be142
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.views;
+
+import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
+import static com.android.app.animation.Interpolators.LINEAR;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+
+/**
+ * Floating view show on launcher home screen that notifies the user that an app will be launched to
+ * the desktop.
+ */
+public class DesktopAppSelectView extends LinearLayout {
+
+ private static final int SHOW_INITIAL_HEIGHT_DP = 7;
+ private static final int SHOW_CONTAINER_SCALE_DURATION = 333;
+ private static final int SHOW_CONTAINER_ALPHA_DURATION = 83;
+ private static final int SHOW_CONTENT_ALPHA_DELAY = 67;
+ private static final int SHOW_CONTENT_ALPHA_DURATION = 83;
+ private static final int HIDE_DURATION = 83;
+
+ private final Launcher mLauncher;
+
+ private View mText;
+ private View mCloseButton;
+ @Nullable
+ private Runnable mOnCloseCallback;
+ private AnimatorSet mShowAnimation;
+ private Animator mHideAnimation;
+
+ public DesktopAppSelectView(Context context) {
+ this(context, null);
+ }
+
+ public DesktopAppSelectView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public DesktopAppSelectView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public DesktopAppSelectView(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mLauncher = Launcher.getLauncher(context);
+ }
+
+ /**
+ * Show the popup on launcher home screen
+ *
+ * @param onCloseCallback optional callback that is called when user clicks the close button
+ * @return the created view
+ */
+ public static DesktopAppSelectView show(Launcher launcher, @Nullable Runnable onCloseCallback) {
+ DesktopAppSelectView view = (DesktopAppSelectView) launcher.getLayoutInflater().inflate(
+ R.layout.floating_desktop_app_select, launcher.getDragLayer(), false);
+ view.setOnCloseClickCallback(onCloseCallback);
+ view.show();
+ return view;
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mText = findViewById(R.id.desktop_app_select_text);
+ mCloseButton = findViewById(R.id.close_button);
+ mCloseButton.setOnClickListener(v -> {
+ if (mHideAnimation == null) {
+ hide();
+ if (mOnCloseCallback != null) {
+ mOnCloseCallback.run();
+ }
+ }
+ });
+ }
+
+ private void show() {
+ mLauncher.getDragLayer().addView(this);
+
+ // Set up initial values
+ getBackground().setAlpha(0);
+ mText.setAlpha(0);
+ mCloseButton.setAlpha(0);
+ int initialHeightPx = Utilities.dpToPx(SHOW_INITIAL_HEIGHT_DP);
+ int finalHeight = getResources().getDimensionPixelSize(
+ R.dimen.desktop_mode_floating_app_select_height);
+ float initialScale = initialHeightPx / (float) finalHeight;
+ setScaleY(initialScale);
+ setPivotY(0);
+
+ // Animate the container
+ ValueAnimator containerBackground = ValueAnimator.ofInt(0, 255);
+ containerBackground.addUpdateListener(
+ animation -> getBackground().setAlpha((Integer) animation.getAnimatedValue()));
+ containerBackground.setDuration(SHOW_CONTAINER_ALPHA_DURATION);
+ containerBackground.setInterpolator(LINEAR);
+
+ ObjectAnimator containerSize = ObjectAnimator.ofFloat(this, SCALE_Y, 1f);
+ containerSize.setDuration(SHOW_CONTAINER_SCALE_DURATION);
+ containerSize.setInterpolator(EMPHASIZED_DECELERATE);
+
+ // Animate the contents
+ ObjectAnimator textAlpha = ObjectAnimator.ofFloat(mText, ALPHA, 1);
+ ObjectAnimator buttonAlpha = ObjectAnimator.ofFloat(mCloseButton, ALPHA, 1);
+ AnimatorSet contentAlpha = new AnimatorSet();
+ contentAlpha.playTogether(textAlpha, buttonAlpha);
+ contentAlpha.setStartDelay(SHOW_CONTENT_ALPHA_DELAY);
+ contentAlpha.setDuration(SHOW_CONTENT_ALPHA_DURATION);
+ contentAlpha.setInterpolator(LINEAR);
+
+ // Start the animation
+ mShowAnimation = new AnimatorSet();
+ mShowAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ mShowAnimation = null;
+ }
+ });
+ mShowAnimation.playTogether(containerBackground, containerSize, contentAlpha);
+ mShowAnimation.start();
+ }
+
+ /**
+ * Hide the floating view
+ */
+ public void hide() {
+ if (mShowAnimation != null) {
+ mShowAnimation.cancel();
+ }
+ mHideAnimation = ObjectAnimator.ofFloat(this, ALPHA, 0);
+ mHideAnimation.setDuration(HIDE_DURATION).setInterpolator(LINEAR);
+ mHideAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ mLauncher.getDragLayer().removeView(DesktopAppSelectView.this);
+ mHideAnimation = null;
+ }
+ });
+ mHideAnimation.start();
+ }
+
+ /**
+ * Add a callback that is called when close button is clicked
+ */
+ public void setOnCloseClickCallback(@Nullable Runnable callback) {
+ mOnCloseCallback = callback;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
index 1cfaf14..5135345 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -43,6 +44,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.icons.IconProvider;
import com.android.launcher3.util.RunnableList;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.SystemUiProxy;
@@ -51,6 +53,7 @@
import com.android.quickstep.util.RecentsOrientedState;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.system.QuickStepContract;
import java.util.ArrayList;
import java.util.Arrays;
@@ -65,21 +68,13 @@
// TODO(b/249371338): TaskView needs to be refactored to have better support for N tasks.
public class DesktopTaskView extends TaskView {
- /** Flag to indicate whether desktop windowing proto 1 is enabled */
- private static final boolean DESKTOP_IS_PROTO1_ENABLED = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_mode", false);
-
/** Flag to indicate whether desktop windowing proto 2 is enabled */
- public static final boolean DESKTOP_IS_PROTO2_ENABLED = SystemProperties.getBoolean(
+ public static final boolean DESKTOP_MODE_SUPPORTED = SystemProperties.getBoolean(
"persist.wm.debug.desktop_mode_2", false);
- /** Flags to indicate whether desktop mode is available on the device */
- public static final boolean DESKTOP_MODE_SUPPORTED =
- DESKTOP_IS_PROTO1_ENABLED || DESKTOP_IS_PROTO2_ENABLED;
-
private static final String TAG = DesktopTaskView.class.getSimpleName();
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
@NonNull
private List<Task> mTasks = new ArrayList<>();
@@ -91,6 +86,8 @@
private final ArrayList<CancellableTask<?>> mPendingThumbnailRequests = new ArrayList<>();
+ private final TaskView.FullscreenDrawParams mSnapshotDrawParams;
+
private View mBackgroundView;
public DesktopTaskView(Context context) {
@@ -103,6 +100,18 @@
public DesktopTaskView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
+
+ mSnapshotDrawParams = new FullscreenDrawParams(context) {
+ @Override
+ public float computeTaskCornerRadius(Context context) {
+ return QuickStepContract.getWindowCornerRadius(context);
+ }
+
+ @Override
+ public float computeWindowCornerRadius(Context context) {
+ return QuickStepContract.getWindowCornerRadius(context);
+ }
+ };
}
@Override
@@ -213,7 +222,22 @@
private TaskIdAttributeContainer createAttributeContainer(Task task,
TaskThumbnailView thumbnailView) {
- return new TaskIdAttributeContainer(task, thumbnailView, null, STAGE_POSITION_UNDEFINED);
+ return new TaskIdAttributeContainer(task, thumbnailView, createIconView(task),
+ STAGE_POSITION_UNDEFINED);
+ }
+
+ private IconView createIconView(Task task) {
+ IconView iconView = new IconView(mContext);
+ PackageManager pm = mContext.getApplicationContext().getPackageManager();
+ try {
+ IconProvider provider = new IconProvider(mContext);
+ Drawable appIcon = provider.getIcon(pm.getActivityInfo(task.topActivity,
+ PackageManager.ComponentInfoFlags.of(0)));
+ iconView.setDrawable(appIcon);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Package not found: " + task.topActivity.getPackageName(), e);
+ }
+ return iconView;
}
@Nullable
@@ -465,14 +489,19 @@
for (int i = 0; i < mSnapshotViewMap.size(); i++) {
TaskThumbnailView thumbnailView = mSnapshotViewMap.valueAt(i);
thumbnailView.getTaskOverlay().setFullscreenProgress(progress);
- updateSnapshotRadius();
}
+ updateSnapshotRadius();
}
@Override
protected void updateSnapshotRadius() {
+ super.updateSnapshotRadius();
for (int i = 0; i < mSnapshotViewMap.size(); i++) {
- mSnapshotViewMap.valueAt(i).setFullscreenParams(mCurrentFullscreenParams);
+ if (i == 0) {
+ // All snapshots share the same params. Only update it with the first snapshot.
+ updateFullscreenParams(mSnapshotDrawParams);
+ }
+ mSnapshotViewMap.valueAt(i).setFullscreenParams(mSnapshotDrawParams);
}
}
diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
index 7bbe36a..e5a0e10 100644
--- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
+++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
@@ -145,23 +145,29 @@
mAppUsageLimitTimeMs = mAppRemainingTimeMs = -1;
mTask = task;
THREAD_POOL_EXECUTOR.execute(() -> {
- final AppUsageLimit usageLimit = mLauncherApps.getAppUsageLimit(
- mTask.getTopComponent().getPackageName(),
- UserHandle.of(mTask.key.userId));
+ AppUsageLimit usageLimit = null;
+ try {
+ usageLimit = mLauncherApps.getAppUsageLimit(
+ mTask.getTopComponent().getPackageName(),
+ UserHandle.of(mTask.key.userId));
+ } catch (Exception e) {
+ Log.e(TAG, "Error initializing digital well being toast", e);
+ }
+ final long appUsageLimitTimeMs =
+ usageLimit != null ? usageLimit.getTotalUsageLimit() : -1;
+ final long appRemainingTimeMs =
+ usageLimit != null ? usageLimit.getUsageRemaining() : -1;
- final long appUsageLimitTimeMs =
- usageLimit != null ? usageLimit.getTotalUsageLimit() : -1;
- final long appRemainingTimeMs =
- usageLimit != null ? usageLimit.getUsageRemaining() : -1;
+ mTaskView.post(() -> {
+ if (appUsageLimitTimeMs < 0 || appRemainingTimeMs < 0) {
+ setNoLimit();
+ } else {
+ setLimit(appUsageLimitTimeMs, appRemainingTimeMs);
+ }
+ });
- mTaskView.post(() -> {
- if (appUsageLimitTimeMs < 0 || appRemainingTimeMs < 0) {
- setNoLimit();
- } else {
- setLimit(appUsageLimitTimeMs, appRemainingTimeMs);
}
- });
- });
+ );
}
public void setSplitConfiguration(SplitBounds splitBounds) {
diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
index 75a8ea2..92ffcd0 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
@@ -1,8 +1,23 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.android.quickstep.views;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.clampToProgress;
import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.clampToProgress;
import android.animation.ValueAnimator;
import android.content.Context;
@@ -11,7 +26,6 @@
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.FloatProperty;
@@ -48,8 +62,6 @@
* {@link #addConfirmAnimation(PendingAnimation, RectF, Rect, boolean, boolean)}
* giving a starting and ending bounds. Currently this is set to use the split placeholder view,
* but it could be generified.
- *
- * TODO: Figure out how to copy thumbnail data from existing TaskView to this view.
*/
public class FloatingTaskView extends FrameLayout {
@@ -213,8 +225,8 @@
mSplitPlaceholderView.getIconView().setRotation(mOrientationHandler.getDegreesRotated());
}
- public void setIcon(Bitmap icon) {
- mSplitPlaceholderView.setIcon(new BitmapDrawable(icon), mSplitHolderSize);
+ public void setIcon(Drawable drawable) {
+ mSplitPlaceholderView.setIcon(drawable, mSplitHolderSize);
}
protected void initPosition(RectF pos, InsettableFrameLayout.LayoutParams lp) {
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index c91b183..7e58763 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -2,8 +2,8 @@
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static com.android.launcher3.util.SplitConfigurationOptions.DEFAULT_SPLIT_RATIO;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.quickstep.util.SplitScreenUtils.convertLauncherSplitBoundsToShell;
import android.content.Context;
import android.graphics.PointF;
@@ -28,11 +28,11 @@
import com.android.quickstep.util.CancellableTask;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.SplitSelectStateController;
-import com.android.quickstep.util.TaskViewSimulator;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.recents.utilities.PreviewPositionHelper;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
+import com.android.wm.shell.common.split.SplitScreenConstants.SnapPosition;
import java.util.HashMap;
import java.util.function.Consumer;
@@ -114,11 +114,11 @@
if (mSplitBoundsConfig == null) {
return;
}
- mSnapshotView.getPreviewPositionHelper().setSplitBounds(TaskViewSimulator
- .convertSplitBounds(splitBoundsConfig),
+ mSnapshotView.getPreviewPositionHelper().setSplitBounds(
+ convertLauncherSplitBoundsToShell(splitBoundsConfig),
PreviewPositionHelper.STAGE_POSITION_TOP_OR_LEFT);
- mSnapshotView2.getPreviewPositionHelper().setSplitBounds(TaskViewSimulator
- .convertSplitBounds(splitBoundsConfig),
+ mSnapshotView2.getPreviewPositionHelper().setSplitBounds(
+ convertLauncherSplitBoundsToShell(splitBoundsConfig),
PreviewPositionHelper.STAGE_POSITION_BOTTOM_OR_RIGHT);
}
@@ -180,12 +180,20 @@
invalidate();
}
- public float getSplitRatio() {
- if (mSplitBoundsConfig != null) {
- return mSplitBoundsConfig.appsStackedVertically
- ? mSplitBoundsConfig.topTaskPercent : mSplitBoundsConfig.leftTaskPercent;
+ @Nullable
+ public SplitBounds getSplitBoundsConfig() {
+ return mSplitBoundsConfig;
+ }
+
+ /**
+ * Returns the {@link SnapPosition} of this pair of tasks.
+ */
+ public int getSnapPosition() {
+ if (mSplitBoundsConfig == null) {
+ throw new IllegalStateException("mSplitBoundsConfig is null");
}
- return DEFAULT_SPLIT_RATIO;
+
+ return mSplitBoundsConfig.snapPosition;
}
@Override
@@ -223,11 +231,12 @@
// Callbacks run from remote animation when recents animation not currently running
InteractionJankMonitorWrapper.begin(this,
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "Enter form GroupedTaskView");
- launchTask(success -> {
+ launchTaskInternal(success -> {
endCallback.executeAllAndDestroy();
InteractionJankMonitorWrapper.end(
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
- }, false /* freezeTaskList */);
+ }, false /* freezeTaskList */, true /*launchingExistingTaskview*/);
+
// Callbacks get run from recentsView for case when recents animation already running
recentsView.addSideTaskLaunchCallback(endCallback);
@@ -236,9 +245,21 @@
@Override
public void launchTask(@NonNull Consumer<Boolean> callback, boolean isQuickswitch) {
- getRecentsView().getSplitSelectController().launchExistingSplitPair(this, mTask.key.id,
+ launchTaskInternal(callback, isQuickswitch, false /*launchingExistingTaskview*/);
+ }
+
+ /**
+ * @param launchingExistingTaskView {@link SplitSelectStateController#launchExistingSplitPair}
+ * uses existence of GroupedTaskView as control flow of how to animate in the incoming task. If
+ * we're launching from overview (from overview thumbnails) then pass in {@code true},
+ * otherwise pass in {@code false} for case like quickswitching from home to task
+ */
+ private void launchTaskInternal(@NonNull Consumer<Boolean> callback, boolean isQuickswitch,
+ boolean launchingExistingTaskView) {
+ getRecentsView().getSplitSelectController().launchExistingSplitPair(
+ launchingExistingTaskView ? this : null, mTask.key.id,
mSecondaryTask.key.id, SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT,
- callback, isQuickswitch, getSplitRatio());
+ callback, isQuickswitch, getSnapPosition());
}
@Override
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 4dbf4e3..892ebf9 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -31,12 +31,12 @@
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
-import android.view.Surface;
import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statehandlers.DesktopVisibilityController;
@@ -81,14 +81,23 @@
}
@Override
- public void startHome(boolean animated) {
+ protected void handleStartHome(boolean animated) {
StateManager stateManager = mActivity.getStateManager();
animated &= stateManager.shouldAnimateStateChange();
stateManager.goToState(NORMAL, animated);
+ if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ mSplitSelectStateController.getSplitAnimationController()
+ .playPlaceholderDismissAnim(mActivity);
+ }
AbstractFloatingView.closeAllOpenViews(mActivity, animated);
}
@Override
+ protected boolean canStartHomeSafely() {
+ return mActivity.canStartHomeSafely();
+ }
+
+ @Override
protected void onTaskLaunchAnimationEnd(boolean success) {
if (success) {
mActivity.getStateManager().moveToRestState();
@@ -118,12 +127,18 @@
@Override
public void reset() {
super.reset();
- setLayoutRotation(Surface.ROTATION_0, Surface.ROTATION_0);
+
+ int recentsActivityRotation = getPagedViewOrientedState().getRecentsActivityRotation();
+ setLayoutRotation(recentsActivityRotation, recentsActivityRotation);
}
@Override
public void onStateTransitionStart(LauncherState toState) {
setOverviewStateEnabled(toState.overviewUi);
+ if (toState.overviewUi) {
+ // If overview is enabled, we want to update at the start
+ updateOverviewStateForDesktop(true);
+ }
setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mActivity.getDeviceProfile()));
setOverviewFullscreenEnabled(toState.getOverviewFullscreenProgress() == 1);
if (toState == OVERVIEW_MODAL_TASK) {
@@ -150,6 +165,11 @@
runActionOnRemoteHandles(remoteTargetHandle ->
remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(true));
}
+
+ if (!finalState.overviewUi) {
+ // If overview is disabled, we want to update at the end
+ updateOverviewStateForDesktop(false);
+ }
}
@Override
@@ -218,7 +238,11 @@
@Override
protected boolean canLaunchFullscreenTask() {
- return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
+ if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ return !mSplitSelectStateController.isSplitSelectActive();
+ } else {
+ return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
+ }
}
@Override
@@ -228,7 +252,7 @@
DesktopVisibilityController desktopVisibilityController =
mActivity.getDesktopVisibilityController();
if (desktopVisibilityController != null) {
- desktopVisibilityController.setGestureInProgress(true);
+ desktopVisibilityController.setRecentsGestureStart();
}
}
@@ -236,9 +260,11 @@
public void onGestureAnimationEnd() {
DesktopVisibilityController desktopVisibilityController = null;
boolean showDesktopApps = false;
+ GestureState.GestureEndTarget endTarget = null;
if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
desktopVisibilityController = mActivity.getDesktopVisibilityController();
- if (mCurrentGestureEndTarget == GestureState.GestureEndTarget.LAST_TASK
+ endTarget = mCurrentGestureEndTarget;
+ if (endTarget == GestureState.GestureEndTarget.LAST_TASK
&& desktopVisibilityController.areFreeformTasksVisible()) {
// Recents gesture was cancelled and we are returning to the previous task.
// After super class has handled clean up, show desktop apps on top again
@@ -247,10 +273,17 @@
}
super.onGestureAnimationEnd();
if (desktopVisibilityController != null) {
- desktopVisibilityController.setGestureInProgress(false);
+ desktopVisibilityController.setRecentsGestureEnd(endTarget);
}
if (showDesktopApps) {
SystemUiProxy.INSTANCE.get(mActivity).showDesktopApps(mActivity.getDisplayId());
}
}
+
+ private void updateOverviewStateForDesktop(boolean enabled) {
+ DesktopVisibilityController controller = mActivity.getDesktopVisibilityController();
+ if (controller != null) {
+ controller.setOverviewStateEnabled(enabled);
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index e47c089..9141c99 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -258,6 +258,13 @@
}
/**
+ * Returns the visibility of the overview actions buttons.
+ */
+ public @Visibility int getActionsButtonVisibility() {
+ return findViewById(R.id.action_buttons).getVisibility();
+ }
+
+ /**
* Offsets OverviewActionsView horizontal position based on 3 button nav container in taskbar.
*/
private void updatePadding() {
@@ -282,7 +289,7 @@
return 0;
}
- if (mDp.isTablet && FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get()) {
+ if (mDp.isTablet && FeatureFlags.enableGridOnlyOverview()) {
return mDp.stashedTaskbarHeight;
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 55b9f95..9b41ccd 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -21,6 +21,16 @@
import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.makeMeasureSpec;
+import static com.android.app.animation.Interpolators.ACCELERATE;
+import static com.android.app.animation.Interpolators.ACCELERATE_0_75;
+import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
+import static com.android.app.animation.Interpolators.DECELERATE_2;
+import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.app.animation.Interpolators.FINAL_FRAME;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.OVERSHOOT_0_75;
+import static com.android.app.animation.Interpolators.clampToProgress;
import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
@@ -32,28 +42,19 @@
import static com.android.launcher3.Utilities.mapToRange;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.Utilities.squaredTouchSlop;
-import static com.android.launcher3.anim.Interpolators.ACCEL;
-import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
-import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
-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_GRID_ONLY_OVERVIEW;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_LAUNCH_FROM_STAGED_APP;
+import static com.android.launcher3.config.FeatureFlags.enableGridOnlyOverview;
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;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
+import static com.android.launcher3.testing.shared.TestProtocol.DISMISS_ANIMATION_ENDS_MESSAGE;
import static com.android.launcher3.touch.PagedOrientationHandler.CANVAS_TRANSLATE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
+import static com.android.quickstep.util.LogUtils.splitFailureMessage;
import static com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA;
import static com.android.quickstep.views.DesktopTaskView.DESKTOP_MODE_SUPPORTED;
import static com.android.quickstep.views.OverviewActionsView.FLAG_IS_NOT_TABLET;
@@ -165,6 +166,7 @@
import com.android.launcher3.util.ViewPool;
import com.android.quickstep.BaseActivityInterface;
import com.android.quickstep.GestureState;
+import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.RecentsAnimationController;
import com.android.quickstep.RecentsAnimationTargets;
import com.android.quickstep.RecentsFilterState;
@@ -173,6 +175,7 @@
import com.android.quickstep.RemoteTargetGluer;
import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
import com.android.quickstep.RotationTouchHelper;
+import com.android.quickstep.SplitSelectionListener;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskThumbnailCache;
@@ -211,6 +214,7 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@@ -661,7 +665,8 @@
/**
* Placeholder view indicating where the first split screen selected app will be placed
*/
- private SplitSelectStateController mSplitSelectStateController;
+ protected SplitSelectStateController mSplitSelectStateController;
+
/**
* The first task that split screen selection was initiated with. When split select state is
* initialized, we create a
@@ -679,11 +684,22 @@
private final Toast mSplitUnsupportedToast = Toast.makeText(getContext(),
R.string.toast_split_app_unsupported, Toast.LENGTH_SHORT);
- private SplitInstructionsView mSplitInstructionsView;
-
@Nullable
private SplitSelectSource mSplitSelectSource;
+ private final SplitSelectionListener mSplitSelectionListener = new SplitSelectionListener() {
+ @Override
+ public void onSplitSelectionConfirmed() { }
+
+ @Override
+ public void onSplitSelectionActive() { }
+
+ @Override
+ public void onSplitSelectionExit(boolean launchedSplit) {
+ resetFromSplitSelectionState();
+ }
+ };
+
/**
* Keeps track of the index of the TaskView that split screen was initialized with so we know
* where to insert it back into list of taskViews in case user backs out of entering split
@@ -694,8 +710,6 @@
*/
private int mSplitHiddenTaskViewIndex = -1;
@Nullable
- private FloatingTaskView mFirstFloatingTaskView;
- @Nullable
private FloatingTaskView mSecondFloatingTaskView;
/**
@@ -992,16 +1006,34 @@
}
/**
- * Update the thumbnail of the task.
+ * Update the thumbnail(s) of the relevant TaskView.
* @param refreshNow Refresh immediately if it's true.
*/
@Nullable
- public TaskView updateThumbnail(int taskId, ThumbnailData thumbnailData, boolean refreshNow) {
- TaskView taskView = getTaskViewByTaskId(taskId);
- if (taskView != null) {
- taskView.getThumbnail().setThumbnail(taskView.getTask(), thumbnailData, refreshNow);
+ public TaskView updateThumbnail(
+ HashMap<Integer, ThumbnailData> thumbnailData, boolean refreshNow) {
+ TaskView updatedTaskView = null;
+ for (Map.Entry<Integer, ThumbnailData> entry : thumbnailData.entrySet()) {
+ Integer id = entry.getKey();
+ ThumbnailData thumbnail = entry.getValue();
+ TaskView taskView = getTaskViewByTaskId(id);
+ if (taskView == null) {
+ continue;
+ }
+ // taskView could be a GroupedTaskView, so select the relevant task by ID
+ TaskIdAttributeContainer taskAttributes = taskView.getTaskAttributesById(id);
+ if (taskAttributes == null) {
+ continue;
+ }
+ Task task = taskAttributes.getTask();
+ TaskThumbnailView taskThumbnailView = taskAttributes.getThumbnailView();
+ taskThumbnailView.setThumbnail(task, thumbnail, refreshNow);
+ // thumbnailData can contain 1-2 ids, but they should correspond to the same
+ // TaskView, so overwriting is ok
+ updatedTaskView = taskView;
}
- return taskView;
+
+ return updatedTaskView;
}
@Override
@@ -1048,6 +1080,9 @@
mIPipAnimationListener);
mOrientationState.initListeners();
mTaskOverlayFactory.initListeners();
+ if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ mSplitSelectStateController.registerSplitListener(mSplitSelectionListener);
+ }
}
@Override
@@ -1066,6 +1101,9 @@
mIPipAnimationListener.setActivityAndRecentsView(null, null);
mOrientationState.destroyListeners();
mTaskOverlayFactory.removeListeners();
+ if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ mSplitSelectStateController.unregisterSplitListener(mSplitSelectionListener);
+ }
}
@Override
@@ -1180,7 +1218,7 @@
new SurfaceTransactionApplier(mActivity.getDragLayer());
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
appAnimator.setDuration(RECENTS_LAUNCH_DURATION);
- appAnimator.setInterpolator(ACCEL_DEACCEL);
+ appAnimator.setInterpolator(ACCELERATE_DECELERATE);
appAnimator.addUpdateListener(valueAnimator -> {
float percent = valueAnimator.getAnimatedFraction();
SurfaceTransaction transaction = new SurfaceTransaction();
@@ -1330,9 +1368,15 @@
return null;
}
+ // We're looking for a taskView that matches these ids, regardless of order
+ int[] taskIdsCopy = Arrays.copyOf(taskIds, taskIds.length);
+ Arrays.sort(taskIdsCopy);
+
for (int i = 0; i < getTaskViewCount(); i++) {
TaskView taskView = requireTaskViewAt(i);
- if (Arrays.equals(taskIds, taskView.getTaskIds())) {
+ int[] taskViewIdsCopy = taskView.getTaskIds();
+ Arrays.sort(taskViewIdsCopy);
+ if (Arrays.equals(taskIdsCopy, taskViewIdsCopy)) {
return taskView;
}
}
@@ -1353,6 +1397,7 @@
// its thumbnail
mTmpRunningTasks = null;
mSplitBoundsConfig = null;
+ mTaskOverlayFactory.clearAllActiveState();
}
updateLocusId();
}
@@ -1571,7 +1616,7 @@
mMovingTaskView = null;
runningTaskView.resetPersistentViewTransforms();
int frontTaskIndex = 0;
- if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED && mDesktopTaskView != null
+ if (DesktopTaskView.DESKTOP_MODE_SUPPORTED && mDesktopTaskView != null
&& !runningTaskView.isDesktopTask()) {
// If desktop mode is enabled, desktop task view is pinned at first position if present.
// Move running task to position 1.
@@ -1631,6 +1676,10 @@
int[] runningTaskId = getTaskIdsForTaskViewId(mRunningTaskViewId);
int[] focusedTaskId = getTaskIdsForTaskViewId(mFocusedTaskViewId);
+ // Reset the focused task to avoiding initializing TaskViews layout as focused task during
+ // binding. The focused task view will be updated after all the TaskViews are bound.
+ mFocusedTaskViewId = INVALID_TASK_ID;
+
// Removing views sets the currentPage to 0, so we save this and restore it after
// the new set of views are added
int previousCurrentPage = mCurrentPage;
@@ -1639,8 +1688,8 @@
// If we are entering Overview as a result of initiating a split from somewhere else
// (e.g. split from Home), we need to make sure the staged app is not drawn as a thumbnail.
int stagedTaskIdToBeRemovedFromGrid;
- if (mSplitSelectSource != null) {
- stagedTaskIdToBeRemovedFromGrid = mSplitSelectSource.alreadyRunningTaskId;
+ if (isSplitSelectionActive()) {
+ stagedTaskIdToBeRemovedFromGrid = mSplitSelectStateController.getInitialTaskId();
updateCurrentTaskActionsVisibility();
} else {
stagedTaskIdToBeRemovedFromGrid = INVALID_TASK_ID;
@@ -1707,7 +1756,7 @@
if (!taskGroups.isEmpty()) {
addView(mClearAllButton);
- if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+ if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
// Check if we have apps on the desktop
if (desktopTask != null && !desktopTask.tasks.isEmpty()) {
// If we are actively choosing apps for split, skip the desktop tile
@@ -1734,10 +1783,12 @@
newFocusedTaskView = getTaskViewAt(1);
}
}
- mFocusedTaskViewId = newFocusedTaskView != null && !ENABLE_GRID_ONLY_OVERVIEW.get()
+ mFocusedTaskViewId = newFocusedTaskView != null && !enableGridOnlyOverview()
? newFocusedTaskView.getTaskViewId() : INVALID_TASK_ID;
updateTaskSize();
- updateChildTaskOrientations();
+ if (newFocusedTaskView != null) {
+ newFocusedTaskView.setOrientationState(mOrientationState);
+ }
TaskView newRunningTaskView = null;
if (hasAnyValidTaskIds(runningTaskId)) {
@@ -1850,7 +1901,7 @@
* Returns the number of tasks in the bottom row of the overview grid.
*/
public int getBottomRowTaskCountForTablet() {
- return getTaskViewCount() - mTopRowIdSet.size() - (ENABLE_GRID_ONLY_OVERVIEW.get() ? 0 : 1);
+ return getTaskViewCount() - mTopRowIdSet.size() - (enableGridOnlyOverview() ? 0 : 1);
}
protected void onTaskStackUpdated() {
@@ -1928,7 +1979,7 @@
DeviceProfile dp = mActivity.getDeviceProfile();
setOverviewGridEnabled(
mActivity.getStateManager().getState().displayOverviewTasksAsGrid(dp));
- if (ENABLE_GRID_ONLY_OVERVIEW.get()) {
+ if (enableGridOnlyOverview()) {
mActionsView.updateHiddenFlags(HIDDEN_ACTIONS_IN_MENU, dp.isTablet);
}
setPageSpacing(dp.overviewPageSpacing);
@@ -2010,7 +2061,7 @@
mLastComputedGridSize);
mSizeStrategy.calculateGridTaskSize(mActivity, mActivity.getDeviceProfile(),
mLastComputedGridTaskSize, mOrientationHandler);
- if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+ if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
mSizeStrategy.calculateDesktopTaskSize(mActivity, mActivity.getDeviceProfile(),
mLastComputedDesktopTaskSize);
}
@@ -2090,7 +2141,7 @@
Rect outRect = new Rect(mLastComputedTaskSize);
outRect.offset(
-(primaryScroll - (selectedPageScroll + getOffsetFromScrollPosition(selectedPage))),
- (int) (showAsGrid() && ENABLE_GRID_ONLY_OVERVIEW.get() && !isTopRow
+ (int) (showAsGrid() && enableGridOnlyOverview() && !isTopRow
? mTopBottomRowHeightDiff : 0));
return outRect;
}
@@ -2322,7 +2373,15 @@
startHome(mActivity.isStarted());
}
- public abstract void startHome(boolean animated);
+ public void startHome(boolean animated) {
+ if (!canStartHomeSafely()) return;
+ handleStartHome(animated);
+ }
+
+ protected abstract void handleStartHome(boolean animated);
+
+ /** Returns whether user can start home based on state in {@link OverviewCommandHelper}. */
+ protected abstract boolean canStartHomeSafely();
public void reset() {
setCurrentTask(-1);
@@ -2344,7 +2403,9 @@
remoteTargetHandle.getTransformParams().setTargetSet(null);
remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(false);
});
- resetFromSplitSelectionState();
+ if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ resetFromSplitSelectionState();
+ }
// These are relatively expensive and don't need to be done this frame (RecentsView isn't
// visible anyway), so defer by a frame to get off the critical path, e.g. app to home.
@@ -2666,7 +2727,7 @@
boolean runningTaskTileHidden = mRunningTaskTileHidden;
setCurrentTask(runningTaskViewId);
- mFocusedTaskViewId = ENABLE_GRID_ONLY_OVERVIEW.get() ? INVALID_TASK_ID : runningTaskViewId;
+ mFocusedTaskViewId = enableGridOnlyOverview() ? INVALID_TASK_ID : runningTaskViewId;
runOnPageScrollsInitialized(() -> setCurrentPage(getRunningTaskIndex()));
setRunningTaskViewShowScreenshot(false);
setRunningTaskHidden(runningTaskTileHidden);
@@ -2679,7 +2740,7 @@
}
private boolean hasDesktopTask(Task[] runningTasks) {
- if (!DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+ if (!DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
return false;
}
for (Task task : runningTasks) {
@@ -2859,7 +2920,7 @@
// Desktop task view is hidden, skip it from grid calculations
continue;
}
- if (!ENABLE_GRID_ONLY_OVERVIEW.get()) {
+ if (!enableGridOnlyOverview()) {
// Only apply x-translation when using legacy overview grid
gridTranslations[i] += mIsRtl ? taskWidthAndSpacing : -taskWidthAndSpacing;
}
@@ -3126,7 +3187,7 @@
// Use setFloat instead of setViewAlpha as we want to keep the view visible even when it's
// alpha is set to 0 so that it can be recycled in the view pool properly
anim.setFloat(taskView, VIEW_ALPHA, 0,
- clampToProgress(isOnGridBottomRow(taskView) ? ACCEL : FINAL_FRAME, 0, 0.5f));
+ clampToProgress(isOnGridBottomRow(taskView) ? ACCELERATE : FINAL_FRAME, 0, 0.5f));
FloatProperty<TaskView> secondaryViewTranslate =
taskView.getSecondaryDismissTranslationProperty();
int secondaryTaskDimension = mOrientationHandler.getSecondaryDimension(taskView);
@@ -3165,7 +3226,7 @@
AnimUtils.getDeviceOverviewToSplitTimings(mActivity.getDeviceProfile().isTablet);
RectF startingTaskRect = new RectF();
- safeRemoveDragLayerView(mFirstFloatingTaskView);
+ safeRemoveDragLayerView(mSplitSelectStateController.getFirstFloatingTaskView());
SplitAnimInitProps splitAnimInitProps =
mSplitSelectStateController.getSplitAnimationController().getFirstAnimInitViews(
() -> mSplitHiddenTaskView, () -> mSplitSelectSource);
@@ -3178,33 +3239,34 @@
timings.getIconFadeEndOffset()));
}
- mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
+ FloatingTaskView firstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
splitAnimInitProps.getOriginalView(),
splitAnimInitProps.getOriginalBitmap(),
splitAnimInitProps.getIconDrawable(), startingTaskRect);
- mFirstFloatingTaskView.setAlpha(1);
- mFirstFloatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect,
+ firstFloatingTaskView.setAlpha(1);
+ firstFloatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect,
splitAnimInitProps.getFadeWithThumbnail(), splitAnimInitProps.isStagedTask());
+ mSplitSelectStateController.setFirstFloatingTaskView(firstFloatingTaskView);
// Allow user to click staged app to launch into fullscreen
- if (ENABLE_LAUNCH_FROM_STAGED_APP.get()) {
- mFirstFloatingTaskView.setOnClickListener(this::animateToFullscreen);
- }
+ firstFloatingTaskView.setOnClickListener(this::animateToFullscreen);
// SplitInstructionsView: animate in
- safeRemoveDragLayerView(mSplitInstructionsView);
- mSplitInstructionsView = SplitInstructionsView.getSplitInstructionsView(mActivity);
- mSplitInstructionsView.setAlpha(0);
- anim.setViewAlpha(mSplitInstructionsView, 1, clampToProgress(LINEAR,
+ safeRemoveDragLayerView(mSplitSelectStateController.getSplitInstructionsView());
+ SplitInstructionsView splitInstructionsView =
+ SplitInstructionsView.getSplitInstructionsView(mActivity);
+ splitInstructionsView.setAlpha(0);
+ anim.setViewAlpha(splitInstructionsView, 1, clampToProgress(LINEAR,
timings.getInstructionsContainerFadeInStartOffset(),
timings.getInstructionsContainerFadeInEndOffset()));
- anim.setViewAlpha(mSplitInstructionsView.getTextView(), 1, clampToProgress(LINEAR,
+ anim.setViewAlpha(splitInstructionsView.getTextView(), 1, clampToProgress(LINEAR,
timings.getInstructionsTextFadeInStartOffset(),
timings.getInstructionsTextFadeInEndOffset()));
- anim.addFloat(mSplitInstructionsView, mSplitInstructionsView.UNFOLD, 0.1f, 1,
+ anim.addFloat(splitInstructionsView, splitInstructionsView.UNFOLD, 0.1f, 1,
clampToProgress(EMPHASIZED_DECELERATE,
timings.getInstructionsUnfoldStartOffset(),
timings.getInstructionsUnfoldEndOffset()));
+ mSplitSelectStateController.setSplitInstructionsView(splitInstructionsView);
InteractionJankMonitorWrapper.begin(this,
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "First tile selected");
@@ -3227,7 +3289,11 @@
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
} else {
// If transition to split select was interrupted, clean up to prevent glitches
- resetFromSplitSelectionState();
+ if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ mSplitSelectStateController.resetState();
+ } else {
+ resetFromSplitSelectionState();
+ }
InteractionJankMonitorWrapper.cancel(
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
}
@@ -3260,8 +3326,13 @@
true /* isStagedTask */);
pendingAnimation.addEndListener(animationSuccess ->
- mSplitSelectStateController.launchInitialAppFullscreen(launchSuccess ->
- resetFromSplitSelectionState()));
+ mSplitSelectStateController.launchInitialAppFullscreen(launchSuccess -> {
+ if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ mSplitSelectStateController.resetState();
+ } else {
+ resetFromSplitSelectionState();
+ }
+ }));
pendingAnimation.buildAnim().start();
}
@@ -3362,7 +3433,7 @@
int topGridRowSize = mTopRowIdSet.size();
int bottomGridRowSize = taskCount - mTopRowIdSet.size()
- - (ENABLE_GRID_ONLY_OVERVIEW.get() ? 0 : 1);
+ - (enableGridOnlyOverview() ? 0 : 1);
boolean topRowLonger = topGridRowSize > bottomGridRowSize;
boolean bottomRowLonger = bottomGridRowSize > topGridRowSize;
boolean dismissedTaskFromTop = mTopRowIdSet.contains(dismissedTaskViewId);
@@ -3375,7 +3446,7 @@
}
int longRowWidth = Math.max(topGridRowSize, bottomGridRowSize)
* (mLastComputedGridTaskSize.width() + mPageSpacing);
- if (!ENABLE_GRID_ONLY_OVERVIEW.get() && !isStagingFocusedTask) {
+ if (!enableGridOnlyOverview() && !isStagingFocusedTask) {
longRowWidth += mLastComputedTaskSize.width() + mPageSpacing;
}
@@ -3742,33 +3813,19 @@
taskViewIdArray.removeValue(
finalNextFocusedTaskView.getTaskViewId());
}
- try {
- if (snappedIndex < taskViewIdArray.size()) {
- taskViewIdToSnapTo = taskViewIdArray.get(snappedIndex);
- } else if (snappedIndex == taskViewIdArray.size()) {
- // If the snapped task is the last item from the
- // dismissed row,
- // snap to the same column in the other grid row
- IntArray inverseRowTaskViewIdArray =
- isSnappedTaskInTopRow ? getBottomRowIdArray()
- : getTopRowIdArray();
- if (snappedIndex < inverseRowTaskViewIdArray.size()) {
- taskViewIdToSnapTo = inverseRowTaskViewIdArray.get(
- snappedIndex);
- }
+ if (snappedIndex < taskViewIdArray.size()) {
+ taskViewIdToSnapTo = taskViewIdArray.get(snappedIndex);
+ } else if (snappedIndex == taskViewIdArray.size()) {
+ // If the snapped task is the last item from the
+ // dismissed row,
+ // snap to the same column in the other grid row
+ IntArray inverseRowTaskViewIdArray =
+ isSnappedTaskInTopRow ? getBottomRowIdArray()
+ : getTopRowIdArray();
+ if (snappedIndex < inverseRowTaskViewIdArray.size()) {
+ taskViewIdToSnapTo = inverseRowTaskViewIdArray.get(
+ snappedIndex);
}
- } catch (ArrayIndexOutOfBoundsException e) {
- throw new IllegalStateException(
- "b/269956477 invalid snappedIndex"
- + "\nsnappedTaskViewId: "
- + snappedTaskViewId
- + "\nfocusedTaskViewId: "
- + mFocusedTaskViewId
- + "\ntopRowIdArray: "
- + getTopRowIdArray().toConcatString()
- + "\nbottomRowIdArray: "
- + getBottomRowIdArray().toConcatString(),
- e);
}
}
}
@@ -3797,7 +3854,7 @@
} else {
// Update focus task and its size.
if (finalIsFocusedTaskDismissed && finalNextFocusedTaskView != null) {
- mFocusedTaskViewId = ENABLE_GRID_ONLY_OVERVIEW.get()
+ mFocusedTaskViewId = enableGridOnlyOverview()
? INVALID_TASK_ID
: finalNextFocusedTaskView.getTaskViewId();
mTopRowIdSet.remove(mFocusedTaskViewId);
@@ -3968,19 +4025,19 @@
private void removeTaskInternal(int dismissedTaskViewId) {
int[] taskIds = getTaskIdsForTaskViewId(dismissedTaskViewId);
- int primaryTaskId = taskIds[0];
- int secondaryTaskId = taskIds[1];
UI_HELPER_EXECUTOR.getHandler().post(
() -> {
- ActivityManagerWrapper.getInstance().removeTask(primaryTaskId);
- if (secondaryTaskId != -1) {
- ActivityManagerWrapper.getInstance().removeTask(secondaryTaskId);
+ for (int taskId : taskIds) {
+ if (taskId != -1) {
+ ActivityManagerWrapper.getInstance().removeTask(taskId);
+ }
}
});
}
protected void onDismissAnimationEnds() {
- AccessibilityManagerCompat.sendDismissAnimationEndsEventToTest(getContext());
+ AccessibilityManagerCompat.sendTestProtocolEventToTest(getContext(),
+ DISMISS_ANIMATION_ENDS_MESSAGE);
}
public PendingAnimation createAllTasksDismissAnimation(long duration) {
@@ -4294,7 +4351,7 @@
private void updatePageOffsets() {
float offset = mAdjacentPageHorizontalOffset;
- float modalOffset = ACCEL_0_75.getInterpolation(mTaskModalness);
+ float modalOffset = ACCELERATE_0_75.getInterpolation(mTaskModalness);
int count = getChildCount();
boolean showAsGrid = showAsGrid();
@@ -4303,7 +4360,7 @@
int midpoint = runningTask == null ? -1 : indexOfChild(runningTask);
int modalMidpoint = getCurrentPage();
boolean isModalGridWithoutFocusedTask =
- showAsGrid && ENABLE_GRID_ONLY_OVERVIEW.get() && mTaskModalness > 0;
+ showAsGrid && enableGridOnlyOverview() && mTaskModalness > 0;
if (isModalGridWithoutFocusedTask) {
modalMidpoint = indexOfChild(mSelectedTask);
}
@@ -4365,7 +4422,7 @@
redrawLiveTile();
}
- if (showAsGrid && ENABLE_GRID_ONLY_OVERVIEW.get() && child instanceof TaskView) {
+ if (showAsGrid && enableGridOnlyOverview() && child instanceof TaskView) {
float totalTranslationY = getVerticalOffsetSize(i, modalOffset);
FloatProperty translationPropertyY =
((TaskView) child).getSecondaryTaskOffsetTranslationProperty();
@@ -4474,7 +4531,7 @@
* @param offsetProgress From 0 to 1 where 0 means no offset and 1 means offset offscreen.
*/
private float getVerticalOffsetSize(int childIndex, float offsetProgress) {
- if (offsetProgress == 0 || !(showAsGrid() && ENABLE_GRID_ONLY_OVERVIEW.get())
+ if (offsetProgress == 0 || !(showAsGrid() && enableGridOnlyOverview())
|| mSelectedTask == null) {
// Don't bother calculating everything below if we won't offset vertically.
return 0;
@@ -4564,7 +4621,7 @@
mSplitSelectStateController.setAnimateCurrentTaskDismissal(
true /*animateCurrentTaskDismissal*/);
mSplitHiddenTaskViewIndex = indexOfChild(taskView);
- if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+ if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
updateDesktopTaskVisibility(false /* visible */);
}
}
@@ -4588,7 +4645,7 @@
mSplitSelectStateController.setInitialTaskSelect(splitSelectSource.intent,
splitSelectSource.position.stagePosition, splitSelectSource.itemInfo,
splitSelectSource.splitEvent, splitSelectSource.alreadyRunningTaskId);
- if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+ if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
updateDesktopTaskVisibility(false /* visible */);
}
}
@@ -4662,6 +4719,8 @@
return false;
}
if (mSplitSelectStateController.isBothSplitAppsConfirmed()) {
+ Log.w(TAG, splitFailureMessage(
+ "confirmSplitSelect", "both apps have already been set"));
return true;
}
// Second task is selected either as an already-running Task or an Intent
@@ -4669,6 +4728,9 @@
if (!task.isDockable) {
// Task does not support split screen
mSplitUnsupportedToast.show();
+ Log.w(TAG, splitFailureMessage("confirmSplitSelect",
+ "selected Task (" + task.key.getPackageName()
+ + ") is not dockable / does not support splitscreen"));
return true;
}
mSplitSelectStateController.setSecondTask(task);
@@ -4693,8 +4755,10 @@
mSplitSelectStateController.getActiveSplitStagePosition(), firstTaskEndingBounds,
secondTaskEndingBounds);
- mFirstFloatingTaskView.getBoundsOnScreen(firstTaskStartingBounds);
- mFirstFloatingTaskView.addConfirmAnimation(pendingAnimation,
+ FloatingTaskView firstFloatingTaskView =
+ mSplitSelectStateController.getFirstFloatingTaskView();
+ firstFloatingTaskView.getBoundsOnScreen(firstTaskStartingBounds);
+ firstFloatingTaskView.addConfirmAnimation(pendingAnimation,
new RectF(firstTaskStartingBounds), firstTaskEndingBounds,
false /* fadeWithThumbnail */, true /* isStagedTask */);
@@ -4706,14 +4770,21 @@
mSecondFloatingTaskView.addConfirmAnimation(pendingAnimation, secondTaskStartingBounds,
secondTaskEndingBounds, true /* fadeWithThumbnail */, false /* isStagedTask */);
- pendingAnimation.setViewAlpha(mSplitInstructionsView, 0, clampToProgress(LINEAR,
- timings.getInstructionsFadeStartOffset(),
- timings.getInstructionsFadeEndOffset()));
+ pendingAnimation.setViewAlpha(mSplitSelectStateController.getSplitInstructionsView(), 0,
+ clampToProgress(LINEAR, timings.getInstructionsFadeStartOffset(),
+ timings.getInstructionsFadeEndOffset()));
pendingAnimation.addEndListener(aBoolean -> {
mSplitSelectStateController.launchSplitTasks(
- aBoolean1 -> RecentsView.this.resetFromSplitSelectionState());
- InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
+ aBoolean1 -> {
+ if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ mSplitSelectStateController.resetState();
+ } else {
+ resetFromSplitSelectionState();
+ }
+ InteractionJankMonitorWrapper.end(
+ InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
+ });
});
mSecondSplitHiddenView = containerTaskView;
@@ -4727,21 +4798,22 @@
// Fade out all other views underneath placeholders
ObjectAnimator tvFade = ObjectAnimator.ofFloat(this, RecentsView.CONTENT_ALPHA,1, 0);
- pendingAnimation.add(tvFade, DEACCEL_2, SpringProperty.DEFAULT);
+ pendingAnimation.add(tvFade, DECELERATE_2, SpringProperty.DEFAULT);
pendingAnimation.buildAnim().start();
return true;
}
@SuppressLint("WrongCall")
protected void resetFromSplitSelectionState() {
- if (mSplitSelectSource != null || mSplitHiddenTaskViewIndex != -1) {
- safeRemoveDragLayerView(mFirstFloatingTaskView);
+ if (mSplitSelectSource != null || mSplitHiddenTaskViewIndex != -1 ||
+ FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ safeRemoveDragLayerView(mSplitSelectStateController.getFirstFloatingTaskView());
safeRemoveDragLayerView(mSecondFloatingTaskView);
- safeRemoveDragLayerView(mSplitInstructionsView);
- mFirstFloatingTaskView = null;
+ safeRemoveDragLayerView(mSplitSelectStateController.getSplitInstructionsView());
mSecondFloatingTaskView = null;
- mSplitInstructionsView = null;
mSplitSelectSource = null;
+ mSplitSelectStateController.getSplitAnimationController()
+ .removeSplitInstructionsView(mActivity);
}
if (mSecondSplitHiddenView != null) {
@@ -4754,7 +4826,11 @@
setTaskViewsPrimarySplitTranslation(0);
setTaskViewsSecondarySplitTranslation(0);
- mSplitSelectStateController.resetState();
+ if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ // When flag is on, this method gets called from resetState() call below, let's avoid
+ // infinite recursion today
+ mSplitSelectStateController.resetState();
+ }
if (mSplitHiddenTaskViewIndex == -1) {
return;
}
@@ -4775,7 +4851,7 @@
mSplitHiddenTaskView.setThumbnailVisibility(VISIBLE, INVALID_TASK_ID);
mSplitHiddenTaskView = null;
}
- if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+ if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
updateDesktopTaskVisibility(true /* visible */);
}
}
@@ -4821,8 +4897,10 @@
mSplitPlaceholderInset, mActivity.getDeviceProfile(),
mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);
mTempRectF.set(mTempRect);
- mFirstFloatingTaskView.updateOrientationHandler(mOrientationHandler);
- mFirstFloatingTaskView.update(mTempRectF, /*progress=*/1f);
+ FloatingTaskView firstFloatingTaskView =
+ mSplitSelectStateController.getFirstFloatingTaskView();
+ firstFloatingTaskView.updateOrientationHandler(mOrientationHandler);
+ firstFloatingTaskView.update(mTempRectF, /*progress=*/1f);
PagedOrientationHandler orientationHandler = getPagedOrientationHandler();
Pair<FloatProperty, FloatProperty> taskViewsFloat =
@@ -4832,8 +4910,8 @@
taskViewsFloat.first.set(this, getSplitSelectTranslation());
taskViewsFloat.second.set(this, 0f);
- if (mSplitInstructionsView != null) {
- mSplitInstructionsView.ensureProperRotation();
+ if (mSplitSelectStateController.getSplitInstructionsView() != null) {
+ mSplitSelectStateController.getSplitInstructionsView().ensureProperRotation();
}
}
@@ -5152,7 +5230,8 @@
true /* forDesktop */);
mRemoteTargetHandles = gluer.assignTargetsForDesktop(recentsAnimationTargets);
} else {
- gluer = new RemoteTargetGluer(getContext(), getSizeStrategy());
+ gluer = new RemoteTargetGluer(getContext(), getSizeStrategy(), recentsAnimationTargets,
+ false);
mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(recentsAnimationTargets);
}
mSplitBoundsConfig = gluer.getSplitBounds();
@@ -5207,6 +5286,8 @@
cleanupRemoteTargets();
if (mRecentsAnimationController == null) {
+ Log.d(TestProtocol.INCORRECT_HOME_STATE, "finish recents animation but recents "
+ + "animation controller was null. returning.");
if (onFinishComplete != null) {
onFinishComplete.run();
}
@@ -5319,7 +5400,7 @@
}
private int getFirstViewIndex() {
- if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED && mDesktopTaskView != null) {
+ if (DesktopTaskView.DESKTOP_MODE_SUPPORTED && mDesktopTaskView != null) {
// Desktop task is at position 0, that is the first view
return 0;
}
@@ -5943,13 +6024,8 @@
}
@Nullable
- public FloatingTaskView getFirstFloatingTaskView() {
- return mFirstFloatingTaskView;
- }
-
- @Nullable
public SplitInstructionsView getSplitInstructionsView() {
- return mSplitInstructionsView;
+ return mSplitSelectStateController.getSplitInstructionsView();
}
/** Update the current activity locus id to show the enabled state of Overview */
diff --git a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
index 0d9e412..4ca02e0 100644
--- a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
+++ b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
@@ -17,15 +17,21 @@
package com.android.quickstep.views;
import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.util.AttributeSet;
import android.util.FloatProperty;
+import android.view.MotionEvent;
import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
+import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.StatefulActivity;
/**
@@ -65,7 +71,7 @@
mLauncher = (StatefulActivity) context;
}
- static SplitInstructionsView getSplitInstructionsView(StatefulActivity launcher) {
+ public static SplitInstructionsView getSplitInstructionsView(StatefulActivity launcher) {
ViewGroup dragLayer = launcher.getDragLayer();
final SplitInstructionsView splitInstructionsView =
(SplitInstructionsView) launcher.getLayoutInflater().inflate(
@@ -73,9 +79,7 @@
dragLayer,
false
);
-
- splitInstructionsView.mTextView = splitInstructionsView.findViewById(
- R.id.split_instructions_text);
+ splitInstructionsView.init();
// Since textview overlays base view, and we sometimes manipulate the alpha of each
// simultaneously, force overlapping rendering to false prevents redrawing of pixels,
@@ -92,6 +96,71 @@
ensureProperRotation();
}
+ private void init() {
+ mTextView = findViewById(R.id.split_instructions_text);
+
+ if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ mTextView.setCompoundDrawables(null, null, null, null);
+ return;
+ }
+
+ mTextView.setOnTouchListener((v, event) -> {
+ if (isTouchInsideRightCompoundDrawable(event)) {
+ if (event.getAction() == MotionEvent.ACTION_UP) {
+ exitSplitSelection();
+ }
+ return true;
+ }
+ return false;
+ });
+ }
+
+ private void exitSplitSelection() {
+ ((RecentsView) mLauncher.getOverviewPanel()).getSplitSelectController()
+ .getSplitAnimationController().playPlaceholderDismissAnim(mLauncher);
+ mLauncher.getStateManager().goToState(LauncherState.NORMAL);
+ }
+
+ private boolean isTouchInsideRightCompoundDrawable(MotionEvent event) {
+ // Get the right compound drawable of the TextView.
+ Drawable rightDrawable = mTextView.getCompoundDrawablesRelative()[2];
+
+ // Check if the touch event intersects with the drawable's bounds.
+ if (rightDrawable != null) {
+ // We can get away w/o caring about the Y bounds since it's such a small view, if it's
+ // above/below the drawable just assume they meant to touch it. ¯\_(ツ)_/¯
+ return event.getX() >= (mTextView.getWidth() - rightDrawable.getBounds().width());
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ return;
+ }
+
+ info.addAction(new AccessibilityNodeInfo.AccessibilityAction(
+ R.string.toast_split_select_cont_desc,
+ getResources().getString(R.string.toast_split_select_cont_desc)
+ ));
+ }
+
+ @Override
+ public boolean performAccessibilityAction(int action, Bundle arguments) {
+ if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ return super.performAccessibilityAction(action, arguments);
+ }
+
+ if (action == R.string.toast_split_select_cont_desc) {
+ exitSplitSelection();
+ return true;
+ }
+ return super.performAccessibilityAction(action, arguments);
+ }
+
void ensureProperRotation() {
((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler()
.setSplitInstructionsParams(
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index 2c9afb4..b4d24e5 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -36,12 +36,12 @@
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimationSuccessListener;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.touch.PagedOrientationHandler;
@@ -256,7 +256,7 @@
final Animator revealAnimator = createOpenCloseOutlineProvider()
.createRevealAnimator(this, closing);
- revealAnimator.setInterpolator(Interpolators.DEACCEL);
+ revealAnimator.setInterpolator(Interpolators.DECELERATE);
mOpenCloseAnimator.playTogether(revealAnimator,
ObjectAnimator.ofFloat(
mTaskContainer.getThumbnailView(), DIM_ALPHA,
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
index 8ee0fbb..b373911 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
@@ -121,7 +121,7 @@
override fun onFinishInflate() {
super.onFinishInflate()
- optionLayout = findViewById(R.id.menu_option_layout)
+ optionLayout = requireViewById(R.id.menu_option_layout)
}
private fun populateAndShowForTask(
@@ -193,8 +193,8 @@
mActivityContext.layoutInflater.inflate(R.layout.task_view_menu_option, this, false)
as LinearLayout
menuOption.setIconAndLabelFor(
- menuOptionView.findViewById(R.id.icon),
- menuOptionView.findViewById(R.id.text)
+ menuOptionView.requireViewById(R.id.icon),
+ menuOptionView.requireViewById(R.id.text)
)
val lp = menuOptionView.layoutParams as LayoutParams
lp.width = menuWidth
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index f746203..dff0580 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -558,13 +558,12 @@
.getRecentsActivityRotation();
boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
mPreviewPositionHelper.updateThumbnailMatrix(mPreviewRect, mThumbnailData,
- getMeasuredWidth(), getMeasuredHeight(), dp.widthPx, dp.heightPx,
- dp.taskbarHeight, dp.isTablet, currentRotation, isRtl);
+ getMeasuredWidth(), getMeasuredHeight(), dp.isTablet, currentRotation, isRtl);
mBitmapShader.setLocalMatrix(mPreviewPositionHelper.getMatrix());
mPaint.setShader(mBitmapShader);
}
- getTaskView().updateCurrentFullscreenParams(mPreviewPositionHelper);
+ getTaskView().updateCurrentFullscreenParams();
invalidate();
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 83a5c72..f84b549 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -20,11 +20,11 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.widget.Toast.LENGTH_SHORT;
+import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
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;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -32,6 +32,7 @@
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
+import static com.android.quickstep.TaskOverlayFactory.getEnabledShortcuts;
import static com.android.quickstep.util.BorderAnimator.DEFAULT_BORDER_COLOR;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -70,12 +71,13 @@
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.SystemShortcut;
@@ -88,6 +90,7 @@
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
+import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.TransformingTouchDelegate;
import com.android.launcher3.util.ViewPool.Reusable;
import com.android.quickstep.RecentsModel;
@@ -95,7 +98,6 @@
import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
import com.android.quickstep.TaskAnimationManager;
import com.android.quickstep.TaskIconCache;
-import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.TaskViewUtils;
@@ -108,7 +110,6 @@
import com.android.quickstep.util.TransformParams;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
-import com.android.systemui.shared.recents.utilities.PreviewPositionHelper;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
@@ -132,15 +133,17 @@
public static final int FLAG_UPDATE_ICON = 1;
public static final int FLAG_UPDATE_THUMBNAIL = FLAG_UPDATE_ICON << 1;
+ public static final int FLAG_UPDATE_CORNER_RADIUS = FLAG_UPDATE_THUMBNAIL << 1;
- public static final int FLAG_UPDATE_ALL = FLAG_UPDATE_ICON | FLAG_UPDATE_THUMBNAIL;
+ public static final int FLAG_UPDATE_ALL = FLAG_UPDATE_ICON | FLAG_UPDATE_THUMBNAIL
+ | FLAG_UPDATE_CORNER_RADIUS;
/**
* Used in conjunction with {@link #onTaskListVisibilityChanged(boolean, int)}, providing more
* granularity on which components of this task require an update
*/
@Retention(SOURCE)
- @IntDef({FLAG_UPDATE_ALL, FLAG_UPDATE_ICON, FLAG_UPDATE_THUMBNAIL})
+ @IntDef({FLAG_UPDATE_ALL, FLAG_UPDATE_ICON, FLAG_UPDATE_THUMBNAIL, FLAG_UPDATE_CORNER_RADIUS})
public @interface TaskDataChanges {}
/**
@@ -163,7 +166,7 @@
public static final long SCALE_ICON_DURATION = 120;
private static final long DIM_ANIM_DURATION = 700;
- private static final Interpolator GRID_INTERPOLATOR = ACCEL_DEACCEL;
+ private static final Interpolator GRID_INTERPOLATOR = ACCELERATE_DECELERATE;
/**
* This technically can be a vanilla {@link TouchDelegate} class, however that class requires
@@ -411,7 +414,9 @@
private boolean mIsClickableAsLiveTile = true;
- @Nullable private final BorderAnimator mBorderAnimator;
+ @Nullable private final BorderAnimator mFocusBorderAnimator;
+
+ @Nullable private final BorderAnimator mHoverBorderAnimator;
public TaskView(Context context) {
this(context, null);
@@ -437,23 +442,40 @@
boolean keyboardFocusHighlightEnabled = FeatureFlags.ENABLE_KEYBOARD_QUICK_SWITCH.get()
|| DesktopTaskView.DESKTOP_MODE_SUPPORTED;
- setWillNotDraw(!keyboardFocusHighlightEnabled);
+ boolean willDrawBorder =
+ keyboardFocusHighlightEnabled || FeatureFlags.enableCursorHoverStates();
+ setWillNotDraw(!willDrawBorder);
- TypedArray ta = context.obtainStyledAttributes(
- attrs, R.styleable.TaskView, defStyleAttr, defStyleRes);
+ if (willDrawBorder) {
+ TypedArray styledAttrs = context.obtainStyledAttributes(
+ attrs, R.styleable.TaskView, defStyleAttr, defStyleRes);
- mBorderAnimator = !keyboardFocusHighlightEnabled
- ? null
- : new BorderAnimator(
- /* borderRadiusPx= */ (int) mCurrentFullscreenParams.mCornerRadius,
- /* borderColor= */ ta.getColor(
- R.styleable.TaskView_borderColor, DEFAULT_BORDER_COLOR),
- /* borderAnimationParams= */ new BorderAnimator.SimpleParams(
- /* borderWidthPx= */ context.getResources().getDimensionPixelSize(
- R.dimen.keyboard_quick_switch_border_width),
- /* boundsBuilder= */ this::updateBorderBounds,
- /* targetView= */ this));
- ta.recycle();
+ mFocusBorderAnimator = keyboardFocusHighlightEnabled ? new BorderAnimator(
+ /* borderRadiusPx= */ (int) mCurrentFullscreenParams.mCornerRadius,
+ /* borderColor= */ styledAttrs.getColor(
+ R.styleable.TaskView_focusBorderColor, DEFAULT_BORDER_COLOR),
+ /* borderAnimationParams= */ new BorderAnimator.SimpleParams(
+ /* borderWidthPx= */ context.getResources().getDimensionPixelSize(
+ R.dimen.keyboard_quick_switch_border_width),
+ /* boundsBuilder= */ this::updateBorderBounds,
+ /* targetView= */ this)) : null;
+
+ mHoverBorderAnimator =
+ FeatureFlags.enableCursorHoverStates() ? new BorderAnimator(
+ /* borderRadiusPx= */ (int) mCurrentFullscreenParams.mCornerRadius,
+ /* borderColor= */ styledAttrs.getColor(
+ R.styleable.TaskView_hoverBorderColor, DEFAULT_BORDER_COLOR),
+ /* borderAnimationParams= */ new BorderAnimator.SimpleParams(
+ /* borderWidthPx= */ context.getResources()
+ .getDimensionPixelSize(R.dimen.task_hover_border_width),
+ /* boundsBuilder= */ this::updateBorderBounds,
+ /* targetView= */ this)) : null;
+
+ styledAttrs.recycle();
+ } else {
+ mFocusBorderAnimator = null;
+ mHoverBorderAnimator = null;
+ }
}
protected void updateBorderBounds(Rect bounds) {
@@ -507,16 +529,48 @@
@Override
protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
- if (mBorderAnimator != null) {
- mBorderAnimator.buildAnimator(gainFocus).start();
+ if (mFocusBorderAnimator != null) {
+ mFocusBorderAnimator.buildAnimator(gainFocus).start();
+ }
+ }
+
+ @Override
+ public boolean onHoverEvent(MotionEvent event) {
+ if (FeatureFlags.enableCursorHoverStates()) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_HOVER_ENTER:
+ mHoverBorderAnimator.buildAnimator(/* isAppearing= */ true).start();
+ break;
+ case MotionEvent.ACTION_HOVER_EXIT:
+ mHoverBorderAnimator.buildAnimator(/* isAppearing= */ false).start();
+ break;
+ default:
+ break;
+ }
+ }
+ return super.onHoverEvent(event);
+ }
+
+ @Override
+ public boolean onInterceptHoverEvent(MotionEvent event) {
+ if (FeatureFlags.enableCursorHoverStates()) {
+ // avoid triggering hover event on child elements which would cause HOVER_EXIT for this
+ // task view
+ return true;
+ } else {
+ return super.onInterceptHoverEvent(event);
}
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
- if (mBorderAnimator != null) {
- mBorderAnimator.drawBorder(canvas);
+ if (mFocusBorderAnimator != null) {
+ mFocusBorderAnimator.drawBorder(canvas);
+ }
+
+ if (mHoverBorderAnimator != null) {
+ mHoverBorderAnimator.drawBorder(canvas);
}
}
@@ -580,7 +634,6 @@
mIconView, STAGE_POSITION_UNDEFINED);
mSnapshotView.bind(task);
setOrientationState(orientedState);
- mDigitalWellBeingToast.initialize(mTask);
}
/**
@@ -1028,6 +1081,9 @@
mDigitalWellBeingToast.initialize(task);
});
}
+ if (needsUpdate(changes, FLAG_UPDATE_CORNER_RADIUS)) {
+ mCurrentFullscreenParams.updateCornerRadius(getContext());
+ }
} else {
if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
mSnapshotView.setThumbnail(null, null);
@@ -1080,7 +1136,7 @@
if (dp.isTablet) {
int alignedOptionIndex = 0;
if (getRecentsView().isOnGridBottomRow(menuContainer.getTaskView()) && dp.isLandscape) {
- if (FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get()) {
+ if (FeatureFlags.enableGridOnlyOverview()) {
// With no focused task, there is less available space below the tasks, so align
// the arrow to the third option in the menu.
alignedOptionIndex = 2;
@@ -1563,8 +1619,8 @@
if (taskContainer == null) {
continue;
}
- for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this,
- taskContainer)) {
+ for (SystemShortcut s : TraceHelper.allowIpcs(
+ "TV.a11yInfo", () -> getEnabledShortcuts(this, taskContainer))) {
info.addAction(s.createAccessibilityAction(context));
}
}
@@ -1601,7 +1657,7 @@
if (taskContainer == null) {
continue;
}
- for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this,
+ for (SystemShortcut s : getEnabledShortcuts(this,
taskContainer)) {
if (s.hasHandlerForAction(action)) {
s.onClick(this);
@@ -1651,16 +1707,20 @@
}
protected void updateSnapshotRadius() {
- updateCurrentFullscreenParams(mSnapshotView.getPreviewPositionHelper());
+ updateCurrentFullscreenParams();
mSnapshotView.setFullscreenParams(mCurrentFullscreenParams);
}
- void updateCurrentFullscreenParams(PreviewPositionHelper previewPositionHelper) {
+ void updateCurrentFullscreenParams() {
+ updateFullscreenParams(mCurrentFullscreenParams);
+ }
+
+ protected void updateFullscreenParams(TaskView.FullscreenDrawParams fullscreenParams) {
if (getRecentsView() == null) {
return;
}
- mCurrentFullscreenParams.setProgress(mFullscreenProgress, getRecentsView().getScaleX(),
- getScaleX(), getWidth(), mActivity.getDeviceProfile(), previewPositionHelper);
+ fullscreenParams.setProgress(mFullscreenProgress, getRecentsView().getScaleX(),
+ getScaleX());
}
/**
@@ -1803,23 +1863,35 @@
*/
public static class FullscreenDrawParams {
- private final float mCornerRadius;
- private final float mWindowCornerRadius;
+ private float mCornerRadius;
+ private float mWindowCornerRadius;
public float mCurrentDrawnCornerRadius;
public FullscreenDrawParams(Context context) {
- mCornerRadius = TaskCornerRadius.get(context);
- mWindowCornerRadius = QuickStepContract.getWindowCornerRadius(context);
+ updateCornerRadius(context);
+ }
- mCurrentDrawnCornerRadius = mCornerRadius;
+ /** Recomputes the start and end corner radius for the given Context. */
+ public void updateCornerRadius(Context context) {
+ mCornerRadius = computeTaskCornerRadius(context);
+ mWindowCornerRadius = computeWindowCornerRadius(context);
+ }
+
+ @VisibleForTesting
+ public float computeTaskCornerRadius(Context context) {
+ return TaskCornerRadius.get(context);
+ }
+
+ @VisibleForTesting
+ public float computeWindowCornerRadius(Context context) {
+ return QuickStepContract.getWindowCornerRadius(context);
}
/**
* Sets the progress in range [0, 1]
*/
- public void setProgress(float fullscreenProgress, float parentScale, float taskViewScale,
- int previewWidth, DeviceProfile dp, PreviewPositionHelper pph) {
+ public void setProgress(float fullscreenProgress, float parentScale, float taskViewScale) {
mCurrentDrawnCornerRadius =
Utilities.mapRange(fullscreenProgress, mCornerRadius, mWindowCornerRadius)
/ parentScale / taskViewScale;
diff --git a/quickstep/tests/src/com/android/launcher3/model/QuickstepModelDelegateTest.kt b/quickstep/tests/src/com/android/launcher3/model/QuickstepModelDelegateTest.kt
new file mode 100644
index 0000000..a532762
--- /dev/null
+++ b/quickstep/tests/src/com/android/launcher3/model/QuickstepModelDelegateTest.kt
@@ -0,0 +1,127 @@
+package com.android.launcher3.model
+
+import android.app.prediction.AppPredictor
+import android.app.prediction.AppTarget
+import android.app.prediction.AppTargetEvent
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.launcher3.LauncherAppState
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WALLPAPERS
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION
+import com.android.launcher3.util.LauncherModelHelper
+import org.junit.After
+import org.junit.Assert.assertNotSame
+import org.junit.Assert.assertSame
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.MockitoAnnotations
+
+/** Unit tests for [QuickstepModelDelegate]. */
+@RunWith(AndroidJUnit4::class)
+class QuickstepModelDelegateTest {
+
+ private lateinit var underTest: QuickstepModelDelegate
+ private lateinit var modelHelper: LauncherModelHelper
+
+ @Mock private lateinit var target: AppTarget
+ @Mock private lateinit var mockedAppTargetEvent: AppTargetEvent
+ @Mock private lateinit var allAppsPredictor: AppPredictor
+ @Mock private lateinit var hotseatPredictor: AppPredictor
+ @Mock private lateinit var widgetRecommendationPredictor: AppPredictor
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ modelHelper = LauncherModelHelper()
+ underTest = QuickstepModelDelegate(modelHelper.sandboxContext)
+ underTest.mAllAppsState.predictor = allAppsPredictor
+ underTest.mHotseatState.predictor = hotseatPredictor
+ underTest.mWidgetsRecommendationState.predictor = widgetRecommendationPredictor
+ underTest.mApp = LauncherAppState.getInstance(modelHelper.sandboxContext)
+ underTest.mDataModel = BgDataModel()
+ }
+
+ @After
+ fun tearDown() {
+ modelHelper.destroy()
+ }
+
+ @Test
+ fun onAppTargetEvent_notifyTarget() {
+ underTest.onAppTargetEvent(mockedAppTargetEvent, CONTAINER_PREDICTION)
+
+ verify(allAppsPredictor).notifyAppTargetEvent(mockedAppTargetEvent)
+ verifyZeroInteractions(hotseatPredictor)
+ verifyZeroInteractions(widgetRecommendationPredictor)
+ }
+
+ @Test
+ fun onWidgetPrediction_notifyWidgetRecommendationPredictor() {
+ underTest.onAppTargetEvent(mockedAppTargetEvent, CONTAINER_WIDGETS_PREDICTION)
+
+ verifyZeroInteractions(allAppsPredictor)
+ verify(widgetRecommendationPredictor).notifyAppTargetEvent(mockedAppTargetEvent)
+ verifyZeroInteractions(hotseatPredictor)
+ }
+
+ @Test
+ fun onHotseatPrediction_notifyHotseatPredictor() {
+ underTest.onAppTargetEvent(mockedAppTargetEvent, CONTAINER_HOTSEAT_PREDICTION)
+
+ verifyZeroInteractions(allAppsPredictor)
+ verifyZeroInteractions(widgetRecommendationPredictor)
+ verify(hotseatPredictor).notifyAppTargetEvent(mockedAppTargetEvent)
+ }
+
+ @Test
+ fun onOtherClient_notifyHotseatPredictor() {
+ underTest.onAppTargetEvent(mockedAppTargetEvent, CONTAINER_WALLPAPERS)
+
+ verifyZeroInteractions(allAppsPredictor)
+ verifyZeroInteractions(widgetRecommendationPredictor)
+ verify(hotseatPredictor).notifyAppTargetEvent(mockedAppTargetEvent)
+ }
+
+ @Test
+ fun hotseatActionPin_recreateHotSeat() {
+ assertSame(underTest.mHotseatState.predictor, hotseatPredictor)
+ val appTargetEvent = AppTargetEvent.Builder(target, AppTargetEvent.ACTION_PIN).build()
+ underTest.markActive()
+
+ underTest.onAppTargetEvent(appTargetEvent, CONTAINER_HOTSEAT_PREDICTION)
+
+ verify(hotseatPredictor).destroy()
+ assertNotSame(underTest.mHotseatState.predictor, hotseatPredictor)
+ }
+
+ @Test
+ fun hotseatActionUnpin_recreateHotSeat() {
+ assertSame(underTest.mHotseatState.predictor, hotseatPredictor)
+ underTest.markActive()
+ val appTargetEvent = AppTargetEvent.Builder(target, AppTargetEvent.ACTION_UNPIN).build()
+
+ underTest.onAppTargetEvent(appTargetEvent, CONTAINER_HOTSEAT_PREDICTION)
+
+ verify(hotseatPredictor).destroy()
+ assertNotSame(underTest.mHotseatState.predictor, hotseatPredictor)
+ }
+
+ @Test
+ fun container_actionPin_notRecreateHotSeat() {
+ assertSame(underTest.mHotseatState.predictor, hotseatPredictor)
+ val appTargetEvent = AppTargetEvent.Builder(target, AppTargetEvent.ACTION_UNPIN).build()
+ underTest.markActive()
+
+ underTest.onAppTargetEvent(appTargetEvent, CONTAINER_PREDICTION)
+
+ verify(allAppsPredictor, never()).destroy()
+ verify(hotseatPredictor, never()).destroy()
+ assertSame(underTest.mHotseatState.predictor, hotseatPredictor)
+ }
+}
diff --git a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
index 83341cb..b12d98b 100644
--- a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
+++ b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
@@ -20,6 +20,7 @@
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.TestUtil.runOnExecutorSync;
import static com.android.launcher3.util.WidgetUtils.createAppWidgetProviderInfo;
import static com.google.common.truth.Truth.assertThat;
@@ -40,11 +41,9 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.icons.ComponentWithLabel;
-import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.QuickstepModelDelegate.PredictorState;
+import com.android.launcher3.util.LauncherLayoutBuilder;
import com.android.launcher3.util.LauncherModelHelper;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
@@ -53,8 +52,6 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import java.util.List;
@@ -76,17 +73,9 @@
private LauncherModelHelper mModelHelper;
private UserHandle mUserHandle;
- @Mock
- private IconCache mIconCache;
-
@Before
public void setup() throws Exception {
mModelHelper = new LauncherModelHelper();
- MockitoAnnotations.initMocks(this);
- doAnswer(invocation -> {
- ComponentWithLabel componentWithLabel = invocation.getArgument(0);
- return componentWithLabel.getComponent().getShortClassName();
- }).when(mIconCache).getTitleNoCache(any());
mUserHandle = myUserHandle();
mApp1Provider1 = createAppWidgetProviderInfo(
@@ -114,16 +103,12 @@
.collect(Collectors.toList());
}).when(manager).getInstalledProvidersForPackage(any(), eq(myUserHandle()));
- // 2 widgets, app4/provider1 & app5/provider1, have already been added to the workspace.
- mModelHelper.initializeData("widgets_predication_update_task_data");
-
+ LauncherLayoutBuilder builder = new LauncherLayoutBuilder()
+ .atWorkspace(0, 1, 2).putWidget("app4", "provider1", 1, 1)
+ .atWorkspace(0, 1, 3).putWidget("app5", "provider1", 1, 1);
+ mModelHelper.setupDefaultLayoutProvider(builder);
MAIN_EXECUTOR.submit(() -> mModelHelper.getModel().addCallbacks(mCallback)).get();
- MODEL_EXECUTOR.post(() -> mModelHelper.getBgDataModel().widgetsModel.update(
- LauncherAppState.getInstance(mModelHelper.sandboxContext),
- /* packageUser= */ null));
-
- MODEL_EXECUTOR.submit(() -> { }).get();
- MAIN_EXECUTOR.submit(() -> { }).get();
+ mModelHelper.loadModelSync();
}
@After
@@ -132,65 +117,72 @@
}
@Test
- public void widgetsRecommendationRan_shouldOnlyReturnNotAddedWidgetsInAppPredictionOrder()
- throws Exception {
- // WHEN newPredicationTask is executed with app predication of 5 apps.
- AppTarget app1 = new AppTarget(new AppTargetId("app1"), "app1", "provider1",
- mUserHandle);
- AppTarget app2 = new AppTarget(new AppTargetId("app2"), "app2", "provider1",
- mUserHandle);
- AppTarget app3 = new AppTarget(new AppTargetId("app3"), "app3", "className",
- mUserHandle);
- AppTarget app4 = new AppTarget(new AppTargetId("app4"), "app4", "provider1",
- mUserHandle);
- AppTarget app5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1",
- mUserHandle);
- mModelHelper.executeTaskForTest(
- newWidgetsPredicationTask(List.of(app5, app3, app2, app4, app1)))
- .forEach(Runnable::run);
+ public void widgetsRecommendationRan_shouldOnlyReturnNotAddedWidgetsInAppPredictionOrder() {
+ // Run on model executor so that no other task runs in the middle.
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
+ // WHEN newPredicationTask is executed with app predication of 5 apps.
+ AppTarget app1 = new AppTarget(new AppTargetId("app1"), "app1", "provider1",
+ mUserHandle);
+ AppTarget app2 = new AppTarget(new AppTargetId("app2"), "app2", "provider1",
+ mUserHandle);
+ AppTarget app3 = new AppTarget(new AppTargetId("app3"), "app3", "className",
+ mUserHandle);
+ AppTarget app4 = new AppTarget(new AppTargetId("app4"), "app4", "provider1",
+ mUserHandle);
+ AppTarget app5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1",
+ mUserHandle);
+ mCallback.mRecommendedWidgets = null;
+ mModelHelper.getModel().enqueueModelUpdateTask(
+ newWidgetsPredicationTask(List.of(app5, app3, app2, app4, app1)));
+ runOnExecutorSync(MAIN_EXECUTOR, () -> { });
- // THEN only 2 widgets are returned because
- // 1. app5/provider1 & app4/provider1 have already been added to workspace. They are
- // excluded from the result.
- // 2. app3 doesn't have a widget.
- // 3. only 1 widget is picked from app1 because we only want to promote one widget per app.
- List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items
- .stream()
- .map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
- .collect(Collectors.toList());
- assertThat(recommendedWidgets).hasSize(2);
- assertWidgetInfo(recommendedWidgets.get(0).info, mApp2Provider1);
- assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1);
+ // THEN only 2 widgets are returned because
+ // 1. app5/provider1 & app4/provider1 have already been added to workspace. They are
+ // excluded from the result.
+ // 2. app3 doesn't have a widget.
+ // 3. only 1 widget is picked from app1 because we only want to promote one widget per app.
+ List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items
+ .stream()
+ .map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
+ .collect(Collectors.toList());
+ assertThat(recommendedWidgets).hasSize(2);
+ assertWidgetInfo(recommendedWidgets.get(0).info, mApp2Provider1);
+ assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1);
+ });
}
@Test
- public void widgetsRecommendationRan_shouldReturnPackageWidgetsWhenEmpty()
- throws Exception {
+ public void widgetsRecommendationRan_shouldReturnPackageWidgetsWhenEmpty() {
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
- // Not installed widget
- AppTarget widget1 = new AppTarget(new AppTargetId("app1"), "app1", "provider3",
- mUserHandle);
- // Not installed app
- AppTarget widget3 = new AppTarget(new AppTargetId("app2"), "app3", "provider1",
- mUserHandle);
- // Workspace added widgets
- AppTarget widget4 = new AppTarget(new AppTargetId("app4"), "app4", "provider1",
- mUserHandle);
- AppTarget widget5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1",
- mUserHandle);
- mModelHelper.executeTaskForTest(
- newWidgetsPredicationTask(List.of(widget5, widget3, widget4, widget1)))
- .forEach(Runnable::run);
+ // Not installed widget
+ AppTarget widget1 = new AppTarget(new AppTargetId("app1"), "app1", "provider3",
+ mUserHandle);
+ // Not installed app
+ AppTarget widget3 = new AppTarget(new AppTargetId("app2"), "app3", "provider1",
+ mUserHandle);
+ // Workspace added widgets
+ AppTarget widget4 = new AppTarget(new AppTargetId("app4"), "app4", "provider1",
+ mUserHandle);
+ AppTarget widget5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1",
+ mUserHandle);
- // THEN only 2 widgets are returned because the launcher only filters out non-exist widgets.
- List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items
- .stream()
- .map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
- .collect(Collectors.toList());
- assertThat(recommendedWidgets).hasSize(2);
- // Another widget from the same package
- assertWidgetInfo(recommendedWidgets.get(0).info, mApp4Provider2);
- assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1);
+ mCallback.mRecommendedWidgets = null;
+ mModelHelper.getModel().enqueueModelUpdateTask(
+ newWidgetsPredicationTask(List.of(widget5, widget3, widget4, widget1)));
+ runOnExecutorSync(MAIN_EXECUTOR, () -> { });
+
+ // THEN only 2 widgets are returned because the launcher only filters out
+ // non-exist widgets.
+ List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items
+ .stream()
+ .map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
+ .collect(Collectors.toList());
+ assertThat(recommendedWidgets).hasSize(2);
+ // Another widget from the same package
+ assertWidgetInfo(recommendedWidgets.get(0).info, mApp4Provider2);
+ assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1);
+ });
}
private void assertWidgetInfo(
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java
new file mode 100644
index 0000000..1b208a7
--- /dev/null
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarHoverToolTipControllerTest.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.Display;
+import android.view.MotionEvent;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.folder.Folder;
+import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.model.data.FolderInfo;
+import com.android.launcher3.util.ActivityContextWrapper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Tests for TaskbarHoverToolTipController.
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class TaskbarHoverToolTipControllerTest extends TaskbarBaseTestCase {
+
+ private TaskbarHoverToolTipController mTaskbarHoverToolTipController;
+ private TestableLooper mTestableLooper;
+
+ @Mock private TaskbarView mTaskbarView;
+ @Mock private MotionEvent mMotionEvent;
+ @Mock private BubbleTextView mHoverBubbleTextView;
+ @Mock private FolderIcon mHoverFolderIcon;
+ @Mock private Display mDisplay;
+ @Mock private TaskbarDragLayer mTaskbarDragLayer;
+ private Folder mSpyFolderView;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+
+ Context context = getApplicationContext();
+
+ doAnswer((Answer<Object>) invocation -> context.getSystemService(
+ (String) invocation.getArgument(0)))
+ .when(taskbarActivityContext).getSystemService(anyString());
+ when(taskbarActivityContext.getResources()).thenReturn(context.getResources());
+ when(taskbarActivityContext.getApplicationInfo()).thenReturn(
+ context.getApplicationInfo());
+ when(taskbarActivityContext.getDragLayer()).thenReturn(mTaskbarDragLayer);
+ when(taskbarActivityContext.getMainLooper()).thenReturn(context.getMainLooper());
+ when(taskbarActivityContext.getDisplay()).thenReturn(mDisplay);
+
+ when(mTaskbarDragLayer.getChildCount()).thenReturn(1);
+ mSpyFolderView = spy(new Folder(new ActivityContextWrapper(context), null));
+ when(mTaskbarDragLayer.getChildAt(anyInt())).thenReturn(mSpyFolderView);
+ doReturn(false).when(mSpyFolderView).isOpen();
+
+ when(mHoverBubbleTextView.getText()).thenReturn("tooltip");
+ doAnswer((Answer<Void>) invocation -> {
+ Object[] args = invocation.getArguments();
+ ((int[]) args[0])[0] = 0;
+ ((int[]) args[0])[1] = 0;
+ return null;
+ }).when(mHoverBubbleTextView).getLocationOnScreen(any(int[].class));
+ when(mHoverBubbleTextView.getWidth()).thenReturn(100);
+ when(mHoverBubbleTextView.getHeight()).thenReturn(100);
+
+ mHoverFolderIcon.mInfo = new FolderInfo();
+ mHoverFolderIcon.mInfo.title = "tooltip";
+ doAnswer((Answer<Void>) invocation -> {
+ Object[] args = invocation.getArguments();
+ ((int[]) args[0])[0] = 0;
+ ((int[]) args[0])[1] = 0;
+ return null;
+ }).when(mHoverFolderIcon).getLocationOnScreen(any(int[].class));
+ when(mHoverFolderIcon.getWidth()).thenReturn(100);
+ when(mHoverFolderIcon.getHeight()).thenReturn(100);
+
+ when(mTaskbarView.getTop()).thenReturn(200);
+
+ mTaskbarHoverToolTipController = new TaskbarHoverToolTipController(
+ taskbarActivityContext, mTaskbarView, mHoverBubbleTextView);
+ mTestableLooper = TestableLooper.get(this);
+ }
+
+ @Test
+ public void onHover_hoverEnterIcon_revealToolTip() {
+ when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
+ when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
+ when(taskbarActivityContext.isTaskbarWindowFullscreen()).thenReturn(true);
+
+ boolean hoverHandled =
+ mTaskbarHoverToolTipController.onHover(mHoverBubbleTextView, mMotionEvent);
+ waitForIdleSync();
+
+ assertThat(hoverHandled).isTrue();
+ verify(taskbarActivityContext).setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS,
+ true);
+ verify(taskbarActivityContext, never()).setTaskbarWindowFullscreen(anyBoolean());
+ }
+
+ @Test
+ public void onHover_hoverEnterIcon_setFullScreenFirstHover() {
+ when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
+ when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
+ when(taskbarActivityContext.isTaskbarWindowFullscreen()).thenReturn(false);
+
+ boolean hoverHandled =
+ mTaskbarHoverToolTipController.onHover(mHoverBubbleTextView, mMotionEvent);
+ waitForIdleSync();
+
+ assertThat(hoverHandled).isFalse();
+ verify(taskbarActivityContext, never()).setAutohideSuspendFlag(
+ FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS, true);
+ verify(taskbarActivityContext).setTaskbarWindowFullscreen(true);
+ }
+
+ @Test
+ public void onHover_hoverExitIcon_closeToolTip() {
+ when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_EXIT);
+ when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_EXIT);
+
+ boolean hoverHandled =
+ mTaskbarHoverToolTipController.onHover(mHoverBubbleTextView, mMotionEvent);
+ waitForIdleSync();
+
+ assertThat(hoverHandled).isTrue();
+ verify(taskbarActivityContext).setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS,
+ false);
+ }
+
+ @Test
+ public void onHover_hoverEnterFolderIcon_revealToolTip() {
+ when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
+ when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
+ when(taskbarActivityContext.isTaskbarWindowFullscreen()).thenReturn(true);
+
+ boolean hoverHandled =
+ mTaskbarHoverToolTipController.onHover(mHoverFolderIcon, mMotionEvent);
+ waitForIdleSync();
+
+ assertThat(hoverHandled).isTrue();
+ verify(taskbarActivityContext).setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS,
+ true);
+ verify(taskbarActivityContext, never()).setTaskbarWindowFullscreen(anyBoolean());
+ }
+
+ @Test
+ public void onHover_hoverExitFolderIcon_closeToolTip() {
+ when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_EXIT);
+ when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_EXIT);
+
+ boolean hoverHandled =
+ mTaskbarHoverToolTipController.onHover(mHoverFolderIcon, mMotionEvent);
+ waitForIdleSync();
+
+ assertThat(hoverHandled).isTrue();
+ verify(taskbarActivityContext).setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS,
+ false);
+ }
+
+ @Test
+ public void onHover_hoverExitFolderOpen_closeToolTip() {
+ when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_EXIT);
+ when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_EXIT);
+ doReturn(true).when(mSpyFolderView).isOpen();
+
+ boolean hoverHandled =
+ mTaskbarHoverToolTipController.onHover(mHoverFolderIcon, mMotionEvent);
+ waitForIdleSync();
+
+ assertThat(hoverHandled).isTrue();
+ verify(taskbarActivityContext).setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS,
+ false);
+ }
+
+ @Test
+ public void onHover_hoverEnterFolderOpen_noToolTip() {
+ when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
+ when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
+ doReturn(true).when(mSpyFolderView).isOpen();
+
+ boolean hoverHandled =
+ mTaskbarHoverToolTipController.onHover(mHoverFolderIcon, mMotionEvent);
+
+ assertThat(hoverHandled).isFalse();
+ }
+
+ @Test
+ public void onHover_hoverMove_noUpdate() {
+ when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_MOVE);
+ when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_MOVE);
+
+ boolean hoverHandled =
+ mTaskbarHoverToolTipController.onHover(mHoverFolderIcon, mMotionEvent);
+
+ assertThat(hoverHandled).isFalse();
+ }
+
+ private void waitForIdleSync() {
+ mTestableLooper.processAllMessages();
+ }
+}
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
index 9622619..58be345 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
@@ -17,6 +17,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -26,12 +27,14 @@
import android.os.Handler;
import android.view.View;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.logging.StatsLogManager;
import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TouchInteractionService;
+import com.android.quickstep.util.AssistUtils;
import org.junit.Before;
import org.junit.Test;
@@ -53,6 +56,8 @@
@Mock
Handler mockHandler;
@Mock
+ AssistUtils mockAssistUtils;
+ @Mock
StatsLogManager mockStatsLogManager;
@Mock
StatsLogManager.StatsLogger mockStatsLogger;
@@ -70,12 +75,15 @@
MockitoAnnotations.initMocks(this);
when(mockService.getDisplayId()).thenReturn(DISPLAY_ID);
when(mockService.getOverviewCommandHelper()).thenReturn(mockCommandHelper);
+ when(mockService.getApplicationContext())
+ .thenReturn(InstrumentationRegistry.getInstrumentation().getTargetContext()
+ .getApplicationContext());
when(mockStatsLogManager.logger()).thenReturn(mockStatsLogger);
when(mockTaskbarControllers.getTaskbarActivityContext())
.thenReturn(mockTaskbarActivityContext);
doReturn(mockStatsLogManager).when(mockTaskbarActivityContext).getStatsLogManager();
mNavButtonController = new TaskbarNavButtonController(mockService,
- mockSystemUiProxy, mockHandler);
+ mockSystemUiProxy, mockHandler, mockAssistUtils);
}
@Test
@@ -104,16 +112,42 @@
}
@Test
- public void testLongPressHome_enabled() {
+ public void testLongPressHome_enabled_withoutOverride() {
mNavButtonController.setAssistantLongPressEnabled(true /*assistantLongPressEnabled*/);
+ when(mockAssistUtils.tryStartAssistOverride(anyInt())).thenReturn(false);
+
mNavButtonController.onButtonLongClick(BUTTON_HOME, mockView);
+ verify(mockAssistUtils, times(1)).tryStartAssistOverride(anyInt());
verify(mockSystemUiProxy, times(1)).startAssistant(any());
}
@Test
- public void testLongPressHome_disabled() {
- mNavButtonController.setAssistantLongPressEnabled(false /*assistantLongPressEnabled*/);
+ public void testLongPressHome_enabled_withOverride() {
+ mNavButtonController.setAssistantLongPressEnabled(true /*assistantLongPressEnabled*/);
+ when(mockAssistUtils.tryStartAssistOverride(anyInt())).thenReturn(true);
+
mNavButtonController.onButtonLongClick(BUTTON_HOME, mockView);
+ verify(mockAssistUtils, times(1)).tryStartAssistOverride(anyInt());
+ verify(mockSystemUiProxy, never()).startAssistant(any());
+ }
+
+ @Test
+ public void testLongPressHome_disabled_withoutOverride() {
+ mNavButtonController.setAssistantLongPressEnabled(false /*assistantLongPressEnabled*/);
+ when(mockAssistUtils.tryStartAssistOverride(anyInt())).thenReturn(false);
+
+ mNavButtonController.onButtonLongClick(BUTTON_HOME, mockView);
+ verify(mockAssistUtils, never()).tryStartAssistOverride(anyInt());
+ verify(mockSystemUiProxy, never()).startAssistant(any());
+ }
+
+ @Test
+ public void testLongPressHome_disabled_withOverride() {
+ mNavButtonController.setAssistantLongPressEnabled(false /*assistantLongPressEnabled*/);
+ when(mockAssistUtils.tryStartAssistOverride(anyInt())).thenReturn(true);
+
+ mNavButtonController.onButtonLongClick(BUTTON_HOME, mockView);
+ verify(mockAssistUtils, never()).tryStartAssistOverride(anyInt());
verify(mockSystemUiProxy, never()).startAssistant(any());
}
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
index 236b5db..3920b08 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
@@ -1,6 +1,9 @@
package com.android.launcher3.taskbar.navbutton
import android.content.res.Resources
+import android.view.Surface
+import android.view.Surface.ROTATION_270
+import android.view.Surface.Rotation
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
@@ -32,6 +35,8 @@
@Mock lateinit var mockRecentsButton: ImageView
@Mock lateinit var mockHomeButton: ImageView
+ private var surfaceRotation = Surface.ROTATION_0
+
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
@@ -60,7 +65,8 @@
isKidsMode = true,
isInSetup = false,
isThreeButtonNav = false,
- phoneMode = false
+ phoneMode = false,
+ surfaceRotation = surfaceRotation
)
assert(layoutter is KidsNavLayoutter)
}
@@ -74,7 +80,8 @@
isKidsMode = false,
isInSetup = true,
isThreeButtonNav = false,
- phoneMode = false
+ phoneMode = false,
+ surfaceRotation = surfaceRotation
)
assert(layoutter is SetupNavLayoutter)
}
@@ -88,7 +95,8 @@
isKidsMode = false,
isInSetup = false,
isThreeButtonNav = false,
- phoneMode = false
+ phoneMode = false,
+ surfaceRotation = surfaceRotation
)
assert(layoutter is TaskbarNavLayoutter)
}
@@ -101,7 +109,8 @@
isKidsMode = false,
isInSetup = false,
isThreeButtonNav = false,
- phoneMode = false
+ phoneMode = false,
+ surfaceRotation = surfaceRotation
)
}
@@ -114,7 +123,8 @@
isKidsMode = false,
isInSetup = false,
isThreeButtonNav = true,
- phoneMode = true
+ phoneMode = true,
+ surfaceRotation = surfaceRotation
)
assert(layoutter is PhonePortraitNavLayoutter)
}
@@ -129,11 +139,28 @@
isKidsMode = false,
isInSetup = false,
isThreeButtonNav = true,
- phoneMode = true
+ phoneMode = true,
+ surfaceRotation = surfaceRotation
)
assert(layoutter is PhoneLandscapeNavLayoutter)
}
+ @Test
+ fun getTaskbarSeascapeLayoutter() {
+ assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
+ mockDeviceProfile.isTaskbarPresent = false
+ setDeviceProfileLandscape()
+ val layoutter: NavButtonLayoutFactory.NavButtonLayoutter =
+ getLayoutter(
+ isKidsMode = false,
+ isInSetup = false,
+ isThreeButtonNav = true,
+ phoneMode = true,
+ surfaceRotation = ROTATION_270
+ )
+ assert(layoutter is PhoneSeascapeNavLayoutter)
+ }
+
@Test(expected = IllegalStateException::class)
fun noValidLayoutForPhoneGestureNav() {
assumeTrue(TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW)
@@ -142,7 +169,8 @@
isKidsMode = false,
isInSetup = false,
isThreeButtonNav = false,
- phoneMode = true
+ phoneMode = true,
+ surfaceRotation = surfaceRotation
)
}
@@ -157,7 +185,8 @@
isKidsMode: Boolean,
isInSetup: Boolean,
isThreeButtonNav: Boolean,
- phoneMode: Boolean
+ phoneMode: Boolean,
+ @Rotation surfaceRotation: Int
): NavButtonLayoutFactory.NavButtonLayoutter {
return NavButtonLayoutFactory.getUiLayoutter(
deviceProfile = mockDeviceProfile,
@@ -166,7 +195,8 @@
isKidsMode = isKidsMode,
isInSetup = isInSetup,
isThreeButtonNav = isThreeButtonNav,
- phoneMode = phoneMode
+ phoneMode = phoneMode,
+ surfaceRotation = surfaceRotation
)
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
index 59f9d5f..3a5fb04 100644
--- a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
+++ b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
@@ -16,11 +16,17 @@
package com.android.quickstep;
+import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
+
import static org.junit.Assert.assertTrue;
import android.os.SystemProperties;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.Until;
+
import com.android.launcher3.Launcher;
+import com.android.launcher3.tapl.LaunchedAppState;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.LauncherInstrumentation.ContainerType;
import com.android.launcher3.ui.AbstractLauncherUiTest;
@@ -76,6 +82,21 @@
}
}
+ protected void assertTestActivityIsRunning(int activityNumber, String message) {
+ assertTrue(message, mDevice.wait(
+ Until.hasObject(By.pkg(getAppPackageName()).text("TestActivity" + activityNumber)),
+ DEFAULT_UI_TIMEOUT));
+ }
+
+ protected LaunchedAppState getAndAssertLaunchedApp() {
+ final LaunchedAppState launchedAppState = mLauncher.getLaunchedAppState();
+ executeOnLauncher(launcher -> assertTrue(
+ "Launcher activity is the top activity; expecting another activity to be the top "
+ + "one",
+ isInLaunchedApp(launcher)));
+ return launchedAppState;
+ }
+
private boolean isInLiveTileMode(Launcher launcher,
LauncherInstrumentation.ContainerType expectedContainerType) {
if (expectedContainerType != LauncherInstrumentation.ContainerType.OVERVIEW) {
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index 97e34c5..a10b24d 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -61,6 +61,7 @@
import com.android.launcher3.util.rule.FailureWatcher;
import com.android.launcher3.util.rule.SamplerRule;
import com.android.launcher3.util.rule.ScreenRecordRule;
+import com.android.launcher3.util.rule.TestIsolationRule;
import com.android.launcher3.util.rule.TestStabilityRule;
import com.android.launcher3.util.rule.ViewCaptureRule;
import com.android.quickstep.views.RecentsView;
@@ -94,9 +95,6 @@
public final TestRule mDisableHeadsUpNotification = disableHeadsUpNotification();
@Rule
- public final TestRule mSetLauncherCommand;
-
- @Rule
public final TestRule mOrderSensitiveRules;
@Rule
@@ -116,18 +114,7 @@
Utilities.enableRunningInTestHarnessForTests();
}
- final ViewCaptureRule viewCaptureRule = new ViewCaptureRule();
- mOrderSensitiveRules = RuleChain
- .outerRule(new SamplerRule())
- .around(new NavigationModeSwitchRule(mLauncher))
- .around(viewCaptureRule)
- .around(new FailureWatcher(mDevice, mLauncher, viewCaptureRule.getViewCapture()));
-
- mOtherLauncherActivity = context.getPackageManager().queryIntentActivities(
- getHomeIntentInPackage(context),
- MATCH_DISABLED_COMPONENTS).get(0).activityInfo;
-
- mSetLauncherCommand = (base, desc) -> new Statement() {
+ final TestRule setLauncherCommand = (base, desc) -> new Statement() {
@Override
public void evaluate() throws Throwable {
TestCommandReceiver.callCommand(TestCommandReceiver.ENABLE_TEST_LAUNCHER);
@@ -150,6 +137,22 @@
}
}
};
+
+ final ViewCaptureRule viewCaptureRule = new ViewCaptureRule(
+ RecentsActivity.ACTIVITY_TRACKER::getCreatedActivity);
+ mOrderSensitiveRules = RuleChain
+ .outerRule(new SamplerRule())
+ .around(new TestStabilityRule())
+ .around(new NavigationModeSwitchRule(mLauncher))
+ .around(new FailureWatcher(mLauncher, viewCaptureRule::getViewCaptureData))
+ .around(viewCaptureRule)
+ .around(new TestIsolationRule(mLauncher))
+ .around(setLauncherCommand);
+
+ mOtherLauncherActivity = context.getPackageManager().queryIntentActivities(
+ getHomeIntentInPackage(context),
+ MATCH_DISABLED_COMPONENTS).get(0).activityInfo;
+
if (TestHelpers.isInLauncherProcess()) {
mLauncher.setSystemHealthSupplier(startTime -> TestCommandReceiver.callCommand(
TestCommandReceiver.GET_SYSTEM_HEALTH_MESSAGE, startTime.toString()).
@@ -174,7 +177,6 @@
// b/143488140
//@NavigationModeSwitch
- @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/266606727
@Test
public void goToOverviewFromHome() {
mDevice.pressHome();
@@ -222,7 +224,6 @@
// b/143488140
//@NavigationModeSwitch
- @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/266606727
@Test
public void testOverview() {
startAppFast(getAppPackageName());
diff --git a/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt b/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
index a9dc043..db06b6b 100644
--- a/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
@@ -15,31 +15,26 @@
*/
package com.android.quickstep
-import android.graphics.Rect
+import android.content.Context
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.launcher3.FakeInvariantDeviceProfileTest
import com.android.quickstep.util.TaskCornerRadius
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.systemui.shared.system.QuickStepContract
import com.google.common.truth.Truth.assertThat
-import kotlin.math.roundToInt
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock
+import org.mockito.Mockito.spy
/** Test for FullscreenDrawParams class. */
@SmallTest
@RunWith(AndroidJUnit4::class)
class FullscreenDrawParamsTest : FakeInvariantDeviceProfileTest() {
- private val TASK_SCALE = 0.7f
- private var mThumbnailData: ThumbnailData = mock(ThumbnailData::class.java)
-
- private val mPreviewPositionHelper = PreviewPositionHelper()
private lateinit var params: FullscreenDrawParams
@Before
@@ -50,32 +45,11 @@
@Test
fun setStartProgress_correctCornerRadiusForTablet() {
initializeVarsForTablet()
- val dp = newDP()
- val previewRect = Rect(0, 0, 100, 100)
- 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.heightPx,
- dp.taskbarHeight,
- dp.isTablet,
- currentRotation,
- isRtl
- )
params.setProgress(
/* fullscreenProgress= */ 0f,
/* parentScale= */ 1.0f,
- /* taskViewScale= */ 1.0f,
- /* previewWidth= */ 0,
- dp,
- mPreviewPositionHelper
+ /* taskViewScale= */ 1.0f
)
val expectedRadius = TaskCornerRadius.get(context)
@@ -85,32 +59,11 @@
@Test
fun setFullProgress_correctCornerRadiusForTablet() {
initializeVarsForTablet()
- val dp = newDP()
- val previewRect = Rect(0, 0, 100, 100)
- 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.heightPx,
- dp.taskbarHeight,
- dp.isTablet,
- currentRotation,
- isRtl
- )
params.setProgress(
/* fullscreenProgress= */ 1.0f,
/* parentScale= */ 1.0f,
- /* taskViewScale= */ 1.0f,
- /* previewWidth= */ 0,
- dp,
- mPreviewPositionHelper
+ /* taskViewScale= */ 1.0f
)
val expectedRadius = QuickStepContract.getWindowCornerRadius(context)
@@ -120,32 +73,11 @@
@Test
fun setStartProgress_correctCornerRadiusForPhone() {
initializeVarsForPhone()
- val dp = newDP()
- val previewRect = Rect(0, 0, 100, 100)
- 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.heightPx,
- dp.taskbarHeight,
- dp.isTablet,
- currentRotation,
- isRtl
- )
params.setProgress(
/* fullscreenProgress= */ 0f,
/* parentScale= */ 1.0f,
- /* taskViewScale= */ 1.0f,
- /* previewWidth= */ 0,
- dp,
- mPreviewPositionHelper
+ /* taskViewScale= */ 1.0f
)
val expectedRadius = TaskCornerRadius.get(context)
@@ -155,35 +87,74 @@
@Test
fun setFullProgress_correctCornerRadiusForPhone() {
initializeVarsForPhone()
- val dp = newDP()
- val previewRect = Rect(0, 0, 100, 100)
- 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.heightPx,
- dp.taskbarHeight,
- dp.isTablet,
- currentRotation,
- isRtl
- )
params.setProgress(
/* fullscreenProgress= */ 1.0f,
/* parentScale= */ 1.0f,
- /* taskViewScale= */ 1.0f,
- /* previewWidth= */ 0,
- dp,
- mPreviewPositionHelper
+ /* taskViewScale= */ 1.0f
)
val expectedRadius = QuickStepContract.getWindowCornerRadius(context)
assertThat(params.mCurrentDrawnCornerRadius).isEqualTo(expectedRadius)
}
+
+ @Test
+ fun setStartProgress_correctCornerRadiusForMultiDisplay() {
+ val display1Context = context
+ val display2Context = mock(Context::class.java)
+ val spyParams = spy(params)
+
+ val display1TaskRadius = TaskCornerRadius.get(display1Context)
+ val display1WindowRadius = QuickStepContract.getWindowCornerRadius(display1Context)
+ val display2TaskRadius = display1TaskRadius * 2 + 1 // Arbitrarily different.
+ val display2WindowRadius = display1WindowRadius * 2 + 1 // Arbitrarily different.
+ doReturn(display2TaskRadius).`when`(spyParams).computeTaskCornerRadius(display2Context)
+ doReturn(display2WindowRadius).`when`(spyParams).computeWindowCornerRadius(display2Context)
+
+ spyParams.updateCornerRadius(display1Context)
+ spyParams.setProgress(
+ /* fullscreenProgress= */ 0f,
+ /* parentScale= */ 1.0f,
+ /* taskViewScale= */ 1.0f
+ )
+ assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display1TaskRadius)
+
+ spyParams.updateCornerRadius(display2Context)
+ spyParams.setProgress(
+ /* fullscreenProgress= */ 0f,
+ /* parentScale= */ 1.0f,
+ /* taskViewScale= */ 1.0f
+ )
+ assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display2TaskRadius)
+ }
+
+ @Test
+ fun setFullProgress_correctCornerRadiusForMultiDisplay() {
+ val display1Context = context
+ val display2Context = mock(Context::class.java)
+ val spyParams = spy(params)
+
+ val display1TaskRadius = TaskCornerRadius.get(display1Context)
+ val display1WindowRadius = QuickStepContract.getWindowCornerRadius(display1Context)
+ val display2TaskRadius = display1TaskRadius * 2 + 1 // Arbitrarily different.
+ val display2WindowRadius = display1WindowRadius * 2 + 1 // Arbitrarily different.
+ doReturn(display2TaskRadius).`when`(spyParams).computeTaskCornerRadius(display2Context)
+ doReturn(display2WindowRadius).`when`(spyParams).computeWindowCornerRadius(display2Context)
+
+ spyParams.updateCornerRadius(display1Context)
+ spyParams.setProgress(
+ /* fullscreenProgress= */ 1.0f,
+ /* parentScale= */ 1.0f,
+ /* taskViewScale= */ 1.0f
+ )
+ assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display1WindowRadius)
+
+ spyParams.updateCornerRadius(display2Context)
+ spyParams.setProgress(
+ /* fullscreenProgress= */ 1.0f,
+ /* parentScale= */ 1.0f,
+ /* taskViewScale= */ 1.0f,
+ )
+ assertThat(spyParams.mCurrentDrawnCornerRadius).isEqualTo(display2WindowRadius)
+ }
}
diff --git a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
index 9c240f0..298dd6c 100644
--- a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
+++ b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
@@ -53,6 +53,8 @@
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
+import java.util.List;
+
@SmallTest
@RunWith(AndroidJUnit4.class)
public class OrientationTouchTransformerTest {
@@ -296,7 +298,7 @@
WindowManagerProxy wmProxy = mock(WindowManagerProxy.class);
doReturn(cachedDisplayInfo).when(wmProxy).getDisplayInfo(any());
doReturn(windowBounds).when(wmProxy).getRealBounds(any(), any());
- ArrayMap<CachedDisplayInfo, WindowBounds[]> internalDisplayBounds = new ArrayMap<>();
+ ArrayMap<CachedDisplayInfo, List<WindowBounds>> internalDisplayBounds = new ArrayMap<>();
doReturn(internalDisplayBounds).when(wmProxy).estimateInternalDisplayBounds(any());
return new DisplayController.Info(
getApplicationContext(), wmProxy, new ArrayMap<>());
diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
index df5303f..a89eab5 100644
--- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
+++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
@@ -16,15 +16,17 @@
package com.android.quickstep;
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
+
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.ui.TaplTestsLauncher3;
-import com.android.launcher3.util.RaceConditionReproducer;
+import com.android.launcher3.util.rule.TestStabilityRule.Stability;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -45,19 +47,6 @@
startTestActivity(2);
}
- private void runTest(String... eventSequence) {
- final RaceConditionReproducer eventProcessor = new RaceConditionReproducer(eventSequence);
-
- // Destroy Launcher activity.
- closeLauncherActivity();
-
- // The test action.
- eventProcessor.startIteration();
- mLauncher.goHome();
- eventProcessor.finishIteration();
- }
-
- @Ignore
@Test
@NavigationModeSwitch
public void testStressPressHome() {
@@ -70,9 +59,9 @@
}
}
- @Ignore
@Test
@NavigationModeSwitch
+ @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/187761685
public void testStressSwipeToOverview() {
for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
// Destroy Launcher activity.
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java
index 1b5313b..9a2826d 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java
@@ -22,6 +22,7 @@
import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -38,6 +39,7 @@
@Test
@TaskbarModeSwitch(mode = PERSISTENT)
+ @Ignore // b/301575789
public void testHideTaskbarPersistsOnRecreate() {
getTaskbar().hide();
mLauncher.recreateTaskbar();
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 32eadce..5531c6e 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -16,8 +16,13 @@
package com.android.quickstep;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_CURSOR_HOVER_STATES;
+import static com.android.launcher3.testing.shared.TestProtocol.FLAKY_QUICK_SWITCH_TO_PREVIOUS_APP;
import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
import static com.android.quickstep.TaskbarModeSwitchRule.Mode.PERSISTENT;
+import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -27,6 +32,7 @@
import android.content.Intent;
import android.platform.test.annotations.PlatinumTest;
+import android.util.Log;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -42,9 +48,14 @@
import com.android.launcher3.tapl.Overview;
import com.android.launcher3.tapl.OverviewActions;
import com.android.launcher3.tapl.OverviewTask;
+import com.android.launcher3.tapl.OverviewTaskMenu;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.ui.TaplTestsLauncher3;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.TestUtil;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
+import com.android.launcher3.util.rule.TestStabilityRule;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
import com.android.quickstep.views.RecentsView;
@@ -143,7 +154,7 @@
assertNotNull("overview.getCurrentTask() returned null (1)", task);
assertNotNull("OverviewTask.open returned null", task.open());
assertTrue("Test activity didn't open from Overview", mDevice.wait(Until.hasObject(
- By.pkg(getAppPackageName()).text("TestActivity2")),
+ By.pkg(getAppPackageName()).text("TestActivity2")),
DEFAULT_UI_TIMEOUT));
executeOnLauncher(launcher -> assertTrue(
"Launcher activity is the top activity; expecting another activity to be the top "
@@ -177,7 +188,6 @@
@Test
@NavigationModeSwitch
@PortraitLandscape
- @ScreenRecord // b/195673272
@PlatinumTest(focusArea = "launcher")
public void testOverviewActions() throws Exception {
// Experimenting for b/165029151:
@@ -192,6 +202,19 @@
actionsView.clickAndDismissScreenshot();
}
+
+ @Test
+ public void testOverviewActionsMenu() throws Exception {
+ startTestAppsWithCheck();
+
+ OverviewTaskMenu menu = mLauncher.goHome().switchToOverview().getCurrentTask().tapMenu();
+
+ assertNotNull("Tapping App info menu item returned null", menu.tapAppInfoMenuItem());
+ executeOnLauncher(launcher -> assertTrue(
+ "Launcher activity is the top activity; expecting another activity to be the top",
+ isInLaunchedApp(launcher)));
+ }
+
private int getCurrentOverviewPage(Launcher launcher) {
return launcher.<RecentsView>getOverviewPanel().getCurrentPage();
}
@@ -222,6 +245,19 @@
isInState(() -> LauncherState.OVERVIEW));
}
+ @Test
+ @TaskbarModeSwitch(mode = TRANSIENT)
+ public void testSwitchToOverviewWithStashedTaskbar() throws Exception {
+ try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
+ startTestAppsWithCheck();
+ // Set ignoreTaskbarVisibility, as transient taskbar will be stashed after app launch.
+ mLauncher.setIgnoreTaskbarVisibility(true);
+ mLauncher.getLaunchedAppState().switchToOverview();
+ } finally {
+ mLauncher.setIgnoreTaskbarVisibility(false);
+ }
+ }
+
@Ignore
@Test
@NavigationModeSwitch
@@ -237,16 +273,6 @@
isInState(() -> LauncherState.OVERVIEW));
}
- private LaunchedAppState getAndAssertLaunchedApp() {
- final LaunchedAppState launchedAppState = mLauncher.getLaunchedAppState();
- assertNotNull("Launcher.getLaunchedApp() returned null", launchedAppState);
- executeOnLauncher(launcher -> assertTrue(
- "Launcher activity is the top activity; expecting another activity to be the top "
- + "one",
- isInLaunchedApp(launcher)));
- return launchedAppState;
- }
-
private void quickSwitchToPreviousAppAndAssert(boolean toRight) {
final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
if (toRight) {
@@ -261,24 +287,6 @@
}
@Test
- @PortraitLandscape
- public void testAllAppsFromHome() throws Exception {
- // Test opening all apps
- assertNotNull("switchToAllApps() returned null",
- mLauncher.getWorkspace().switchToAllApps());
-
- TaplTestsLauncher3.runAllAppsTest(this, mLauncher.getAllApps());
-
- // Testing pressHome.
- assertTrue("Launcher internal state is not All Apps",
- isInState(() -> LauncherState.ALL_APPS));
- assertNotNull("pressHome returned null", mLauncher.goHome());
- assertTrue("Launcher internal state is not Home",
- isInState(() -> LauncherState.NORMAL));
- assertNotNull("getHome returned null", mLauncher.getWorkspace());
- }
-
- @Test
@NavigationModeSwitch
@PortraitLandscape
@PlatinumTest(focusArea = "launcher")
@@ -288,22 +296,22 @@
startTestActivity(4);
quickSwitchToPreviousAppAndAssert(true /* toRight */);
- assertTrue("The first app we should have quick switched to is not running",
- isTestActivityRunning(3));
+ assertTestActivityIsRunning(3,
+ "The first app we should have quick switched to is not running");
quickSwitchToPreviousAppAndAssert(true /* toRight */);
if (mLauncher.getNavigationModel() == NavigationModel.THREE_BUTTON) {
// 3-button mode toggles between 2 apps, rather than going back further.
- assertTrue("Second quick switch should have returned to the first app.",
- isTestActivityRunning(4));
+ assertTestActivityIsRunning(4,
+ "Second quick switch should have returned to the first app.");
} else {
- assertTrue("The second app we should have quick switched to is not running",
- isTestActivityRunning(2));
+ assertTestActivityIsRunning(2,
+ "The second app we should have quick switched to is not running");
}
quickSwitchToPreviousAppAndAssert(false /* toRight */);
- assertTrue("The 2nd app we should have quick switched to is not running",
- isTestActivityRunning(3));
+ assertTestActivityIsRunning(3,
+ "The 2nd app we should have quick switched to is not running");
final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
launchedAppState.switchToOverview();
@@ -312,7 +320,7 @@
@Test
@ScreenRecord // b/242163205
@PlatinumTest(focusArea = "launcher")
- @TaskbarModeSwitch(mode = PERSISTENT)
+ @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/286084688
public void testQuickSwitchToPreviousAppForTablet() throws Exception {
assumeTrue(mLauncher.isTablet());
startTestActivity(2);
@@ -328,17 +336,20 @@
// Quick-switch to the test app with swiping to right.
quickSwitchToPreviousAppAndAssert(true /* toRight */);
- assertTrue("The first app we should have quick switched to is not running",
- isTestActivityRunning(2));
+ assertTestActivityIsRunning(2,
+ "The first app we should have quick switched to is not running");
// Expect task bar visible when the launched app was the test activity.
launchedAppState = getAndAssertLaunchedApp();
- launchedAppState.assertTaskbarVisible();
- }
- private boolean isTestActivityRunning(int activityNumber) {
- return mDevice.wait(Until.hasObject(By.pkg(getAppPackageName())
- .text("TestActivity" + activityNumber)),
- DEFAULT_UI_TIMEOUT);
+ Log.e(FLAKY_QUICK_SWITCH_TO_PREVIOUS_APP,
+ "is Taskbar Transient : " + DisplayController.isTransientTaskbar(mTargetContext));
+ // TODO(b/286084688): Remove this branching check after test corruption is resolved.
+ // Branching this check because of test corruption.
+ if (DisplayController.isTransientTaskbar(mTargetContext)) {
+ launchedAppState.assertTaskbarHidden();
+ } else {
+ launchedAppState.assertTaskbarVisible();
+ }
}
@Test
@@ -348,8 +359,8 @@
public void testQuickSwitchFromHome() throws Exception {
startTestActivity(2);
mLauncher.goHome().quickSwitchToPreviousApp();
- assertTrue("The most recent task is not running after quick switching from home",
- isTestActivityRunning(2));
+ assertTestActivityIsRunning(2,
+ "The most recent task is not running after quick switching from home");
getAndAssertLaunchedApp();
}
@@ -489,7 +500,6 @@
}
@Test
- @ScreenRecord // b/242163205
public void testDisableRotationCheckForPhone() throws Exception {
assumeFalse(mLauncher.isTablet());
try {
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
index e8cadab..cc56faf 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
@@ -15,25 +15,42 @@
*/
package com.android.quickstep;
+
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import android.content.Intent;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.LargeTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.ui.TaplTestsLauncher3;
+import com.android.launcher3.util.rule.TestStabilityRule;
import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
+import org.junit.runner.RunWith;
+@LargeTest
+@RunWith(AndroidJUnit4.class)
public class TaplTestsSplitscreen extends AbstractQuickStepTest {
private static final String CALCULATOR_APP_NAME = "Calculator";
private static final String CALCULATOR_APP_PACKAGE =
resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
+ private static final String READ_DEVICE_CONFIG_PERMISSION =
+ "android.permission.READ_DEVICE_CONFIG";
+
@Override
@Before
public void setUp() throws Exception {
@@ -44,6 +61,8 @@
mLauncher.enableBlockTimeout(true);
mLauncher.showTaskbarIfHidden();
}
+ InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
+ READ_DEVICE_CONFIG_PERMISSION);
}
@After
@@ -62,6 +81,7 @@
@Test
@PortraitLandscape
@TaskbarModeSwitch
+ @TestStabilityRule.Stability(flavors = PLATFORM_POSTSUBMIT | LOCAL) // b/295225524
public void testSplitAppFromHomeWithItself() throws Exception {
// Currently only tablets have Taskbar in Overview, so test is only active on tablets
assumeTrue(mLauncher.isTablet());
@@ -88,8 +108,10 @@
}
@Test
+ @Ignore("Enable once App Pairs flagged on. These cause memory leaks b/297135374")
public void testSaveAppPairMenuItemExistsOnSplitPair() throws Exception {
- assumeTrue(FeatureFlags.ENABLE_APP_PAIRS.get());
+ assumeTrue("App pairs feature is currently not enabled, no test needed",
+ FeatureFlags.ENABLE_APP_PAIRS.get());
createAndLaunchASplitPair();
@@ -102,8 +124,10 @@
}
@Test
+ @Ignore("Enable once App Pairs flagged on. These cause memory leaks b/297135374")
public void testSaveAppPairMenuItemDoesNotExistOnSingleTask() throws Exception {
- assumeTrue(FeatureFlags.ENABLE_APP_PAIRS.get());
+ assumeTrue("App pairs feature is currently not enabled, no test needed",
+ FeatureFlags.ENABLE_APP_PAIRS.get());
startAppFast(CALCULATOR_APP_PACKAGE);
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
index 40be480..093c45d 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
@@ -20,6 +20,7 @@
import androidx.test.filters.LargeTest;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import org.junit.Test;
@@ -150,6 +151,13 @@
.dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
}
+ @Test
+ @PortraitLandscape
+ public void testDismissAllAppsByTappingOutsideSheet() {
+ getTaskbar().openAllApps().dismissByTappingOutsideForTablet(/* tapRight= */ true);
+ getTaskbar().openAllApps().dismissByTappingOutsideForTablet(/* tapRight= */ false);
+ }
+
private boolean isTaskbarTestModeTransient() {
return TRANSIENT == mTaskbarMode;
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
new file mode 100644
index 0000000..907dbcc
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep;
+
+import static com.android.quickstep.NavigationModeSwitchRule.Mode.ZERO_BUTTON;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Instrumentation;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.tapl.LauncherInstrumentation.TrackpadGestureType;
+import com.android.launcher3.tapl.Workspace;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
+import com.android.launcher3.ui.TaplTestsLauncher3;
+import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class TaplTestsTrackpad extends AbstractQuickStepTest {
+
+ private static final String READ_DEVICE_CONFIG_PERMISSION =
+ "android.permission.READ_DEVICE_CONFIG";
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ TaplTestsLauncher3.initialize(this);
+ }
+
+ @After
+ public void tearDown() {
+ mLauncher.setTrackpadGestureType(TrackpadGestureType.NONE);
+ }
+
+ @Test
+ @PortraitLandscape
+ @NavigationModeSwitch
+ public void goHome() throws Exception {
+ assumeTrue(mLauncher.isTablet());
+
+ mLauncher.setTrackpadGestureType(TrackpadGestureType.THREE_FINGER);
+ startTestActivity(2);
+ mLauncher.goHome();
+ }
+
+ @Test
+ @PortraitLandscape
+ // TODO(b/291944684): Support back in 3-button mode. It requires triggering the logic to enable
+ // trackpad gesture back in SysUI. Normally it's triggered by the attachment of a trackpad. We
+ // need to figure out a way to emulate that in the test, or bypass the logic altogether.
+ @NavigationModeSwitch(mode = ZERO_BUTTON)
+ public void pressBack() throws Exception {
+ assumeTrue(mLauncher.isTablet());
+ assumeFalse(FeatureFlags.ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION.get());
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+
+ try {
+ instrumentation.getUiAutomation().adoptShellPermissionIdentity(
+ READ_DEVICE_CONFIG_PERMISSION);
+ mLauncher.setTrackpadGestureType(TrackpadGestureType.THREE_FINGER);
+
+ startTestActivity(2);
+ mLauncher.pressBack();
+ } finally {
+ instrumentation.getUiAutomation().dropShellPermissionIdentity();
+ }
+ }
+
+ @Test
+ @PortraitLandscape
+ @NavigationModeSwitch
+ public void switchToOverview() throws Exception {
+ assumeTrue(mLauncher.isTablet());
+
+ mLauncher.setTrackpadGestureType(TrackpadGestureType.THREE_FINGER);
+ startTestActivity(2);
+ mLauncher.goHome().switchToOverview();
+ }
+
+ @Test
+ @PortraitLandscape
+ @NavigationModeSwitch
+ public void testAllAppsFromHome() throws Exception {
+ assumeTrue(mLauncher.isTablet());
+
+ mLauncher.setTrackpadGestureType(TrackpadGestureType.TWO_FINGER);
+ assertNotNull("switchToAllApps() returned null",
+ mLauncher.getWorkspace().switchToAllApps());
+ }
+
+ @Test
+ @NavigationModeSwitch
+ @PortraitLandscape
+ public void testQuickSwitchFromHome() throws Exception {
+ assumeTrue(mLauncher.isTablet());
+
+ startTestActivity(2);
+ Workspace workspace = mLauncher.goHome();
+ mLauncher.setTrackpadGestureType(TrackpadGestureType.FOUR_FINGER);
+ workspace.quickSwitchToPreviousApp();
+ assertTestActivityIsRunning(2,
+ "The most recent task is not running after quick switching from home");
+ getAndAssertLaunchedApp();
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
index b58fe29..b3cec4e 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.config.FeatureFlags.ENABLE_CURSOR_HOVER_STATES;
import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
-
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
@@ -64,4 +63,13 @@
throw new RuntimeException(e);
}
}
+
+ @Test
+ @TaskbarModeSwitch(mode = TRANSIENT)
+ public void testClickHoveredTaskbarToGoHome() throws Exception {
+ try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
+ getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ mLauncher.getLaunchedAppState().clickStashedTaskbarToGoHome();
+ }
+ }
}
diff --git a/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java b/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java
index 7e408a8..8cc8487 100644
--- a/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java
+++ b/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java
@@ -17,8 +17,8 @@
import static androidx.test.InstrumentationRegistry.getContext;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
-import static androidx.test.InstrumentationRegistry.getTargetContext;
+import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
import static com.android.launcher3.testcomponent.TestCommandReceiver.EXTRA_VALUE;
import static com.android.launcher3.testcomponent.TestCommandReceiver.SET_LIST_VIEW_SERVICE_BINDER;
import static com.android.launcher3.util.WidgetUtils.createWidgetInfo;
@@ -32,7 +32,6 @@
import static org.mockito.Mockito.spy;
import android.appwidget.AppWidgetManager;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -42,14 +41,16 @@
import android.view.ViewConfiguration;
import android.widget.RemoteViews;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.filters.Suppress;
-import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
-import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel;
+import com.android.launcher3.celllayout.FavoriteItemsTransaction;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.tapl.LaunchedAppState;
import com.android.launcher3.testcomponent.ListViewService;
@@ -57,6 +58,7 @@
import com.android.launcher3.testcomponent.TestCommandReceiver;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.ui.TestViewHelpers;
+import com.android.launcher3.util.Executors;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
@@ -67,6 +69,7 @@
import org.mockito.stubbing.Answer;
import java.lang.reflect.Field;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.IntConsumer;
/**
@@ -84,9 +87,9 @@
@RunWith(AndroidJUnit4.class)
public class ViewInflationDuringSwipeUp extends AbstractQuickStepTest {
- private ContentResolver mResolver;
private SparseArray<ViewConfiguration> mConfigMap;
private InitTracker mInitTracker;
+ private LauncherModel mModel;
@Before
public void setUp() throws Exception {
@@ -101,8 +104,8 @@
TaplTestsLauncher3.initialize(this);
- mResolver = mTargetContext.getContentResolver();
- LauncherSettings.Settings.call(mResolver, LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
+ mModel = LauncherAppState.getInstance(mTargetContext).getModel();
+ Executors.MODEL_EXECUTOR.submit(mModel.getModelDbController()::createEmptyDB).get();
// Get static configuration map
Field field = ViewConfiguration.class.getDeclaredField("sConfigurations");
@@ -182,26 +185,30 @@
private void executeSwipeUpTestWithWidget(IntConsumer widgetIdCreationCallback,
IntConsumer updateBeforeSwipeUp, String finalWidgetText) {
try {
- // Clear all existing data
- LauncherSettings.Settings.call(mResolver,
- LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
- LauncherSettings.Settings.call(mResolver,
- LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG);
- LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, false);
+ LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(false);
+
// Make sure the widget is big enough to show a list of items
info.minSpanX = 2;
info.minSpanY = 2;
info.spanX = 2;
info.spanY = 2;
- LauncherAppWidgetInfo item = createWidgetInfo(info, getTargetContext(), true);
+ AtomicInteger widgetId = new AtomicInteger();
+ new FavoriteItemsTransaction(mTargetContext)
+ .addItem(() -> {
+ LauncherAppWidgetInfo item = createWidgetInfo(info, mTargetContext, true);
+ item.screenId = FIRST_SCREEN_ID;
+ widgetId.set(item.appWidgetId);
+ return item;
+ })
+ .commitAndLoadHome(mLauncher);
- addItemToScreen(item);
+
+
assertTrue("Widget is not present",
mLauncher.goHome().tryGetWidget(info.label, DEFAULT_UI_TIMEOUT) != null);
- int widgetId = item.appWidgetId;
// Verify widget id
- widgetIdCreationCallback.accept(widgetId);
+ widgetIdCreationCallback.accept(widgetId.get());
// Go to overview once so that all views are initialized and cached
startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
@@ -214,7 +221,7 @@
LaunchedAppState launchedAppState = mLauncher.getLaunchedAppState();
// Update widget
- updateBeforeSwipeUp.accept(widgetId);
+ updateBeforeSwipeUp.accept(widgetId.get());
launchedAppState.switchToOverview();
assertEquals("Views inflated during swipe up", 0, mInitTracker.viewInitCount);
diff --git a/quickstep/tests/src/com/android/quickstep/util/SplitSelectDataHolderTest.kt b/quickstep/tests/src/com/android/quickstep/util/SplitSelectDataHolderTest.kt
new file mode 100644
index 0000000..c6c5be4
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/util/SplitSelectDataHolderTest.kt
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.quickstep.util
+
+import android.app.ActivityManager.RunningTaskInfo
+import android.app.ActivityTaskManager.INVALID_TASK_ID
+import android.content.Context
+import android.content.ContextWrapper
+import android.content.Intent
+import android.os.UserHandle
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.shortcuts.ShortcutKey
+import com.android.launcher3.ui.AbstractLauncherUiTest
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT
+import com.android.quickstep.util.SplitSelectDataHolder.Companion.SPLIT_PENDINGINTENT_PENDINGINTENT
+import com.android.quickstep.util.SplitSelectDataHolder.Companion.SPLIT_PENDINGINTENT_TASK
+import com.android.quickstep.util.SplitSelectDataHolder.Companion.SPLIT_SHORTCUT_TASK
+import com.android.quickstep.util.SplitSelectDataHolder.Companion.SPLIT_SINGLE_INTENT_FULLSCREEN
+import com.android.quickstep.util.SplitSelectDataHolder.Companion.SPLIT_SINGLE_SHORTCUT_FULLSCREEN
+import com.android.quickstep.util.SplitSelectDataHolder.Companion.SPLIT_SINGLE_TASK_FULLSCREEN
+import com.android.quickstep.util.SplitSelectDataHolder.Companion.SPLIT_TASK_PENDINGINTENT
+import com.android.quickstep.util.SplitSelectDataHolder.Companion.SPLIT_TASK_SHORTCUT
+import com.android.quickstep.util.SplitSelectDataHolder.Companion.SPLIT_TASK_TASK
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+
+class SplitSelectDataHolderTest {
+ private lateinit var splitSelectDataHolder: SplitSelectDataHolder
+
+ private val context: Context =
+ ContextWrapper(InstrumentationRegistry.getInstrumentation().targetContext)
+ private val sampleTaskInfo = RunningTaskInfo()
+ private val sampleTaskId = 10
+ private val sampleTaskId2 = 11
+ private val sampleUser = UserHandle(0)
+ private val sampleIntent = Intent()
+ private val sampleIntent2 = Intent()
+ private val sampleShortcut = Intent()
+ private val sampleShortcut2 = Intent()
+ private val sampleItemInfo = ItemInfo()
+ private val samplePackage =
+ AbstractLauncherUiTest.resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR)
+
+ @Before
+ fun setup() {
+ splitSelectDataHolder = SplitSelectDataHolder(context)
+
+ sampleTaskInfo.taskId = sampleTaskId
+ sampleItemInfo.user = sampleUser
+ sampleIntent.setPackage(samplePackage)
+ sampleIntent2.setPackage(samplePackage)
+ sampleShortcut.setPackage(samplePackage)
+ sampleShortcut2.setPackage(samplePackage)
+ sampleShortcut.putExtra(ShortcutKey.EXTRA_SHORTCUT_ID, "sampleShortcut")
+ sampleShortcut2.putExtra(ShortcutKey.EXTRA_SHORTCUT_ID, "sampleShortcut2")
+ }
+
+ @Test
+ fun setInitialAsTask() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleTaskInfo,
+ STAGE_POSITION_TOP_OR_LEFT,
+ null,
+ null
+ )
+ assertTrue(splitSelectDataHolder.isSplitSelectActive())
+ }
+
+ @Test
+ fun setInitialAsIntent() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleIntent,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null,
+ INVALID_TASK_ID
+ )
+ assertTrue(splitSelectDataHolder.isSplitSelectActive())
+ }
+
+ @Test
+ fun setInitialAsIntentWithAlreadyRunningTask() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleIntent,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null,
+ sampleTaskId
+ )
+ assertTrue(splitSelectDataHolder.isSplitSelectActive())
+ }
+
+ @Test
+ fun setInitialAsShortcut() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleShortcut,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null,
+ INVALID_TASK_ID
+ )
+ assertTrue(splitSelectDataHolder.isSplitSelectActive())
+ }
+
+ @Test
+ fun setSecondAsTask() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleShortcut,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null,
+ INVALID_TASK_ID
+ )
+ splitSelectDataHolder.setSecondTask(sampleTaskId)
+ assertTrue(splitSelectDataHolder.isBothSplitAppsConfirmed())
+ }
+
+ @Test
+ fun setSecondAsIntent() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleTaskInfo,
+ STAGE_POSITION_TOP_OR_LEFT,
+ null,
+ null
+ )
+ splitSelectDataHolder.setSecondTask(sampleIntent, sampleUser)
+ assertTrue(splitSelectDataHolder.isBothSplitAppsConfirmed())
+ }
+
+ @Test
+ fun setSecondAsShortcut() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleIntent,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null,
+ INVALID_TASK_ID
+ )
+ splitSelectDataHolder.setSecondTask(sampleShortcut, sampleUser)
+ assertTrue(splitSelectDataHolder.isBothSplitAppsConfirmed())
+ }
+
+ @Test
+ fun generateLaunchData_Task_Task() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleTaskInfo,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null
+ )
+ splitSelectDataHolder.setSecondTask(sampleTaskId2)
+ val launchData = splitSelectDataHolder.getSplitLaunchData()
+
+ assertEquals(launchData.splitLaunchType, SPLIT_TASK_TASK)
+
+ // should contain a valid task ID for first app, and no intent or shortcut
+ assertNotEquals(launchData.initialTaskId, INVALID_TASK_ID)
+ assertNull(launchData.initialPendingIntent)
+ assertNull(launchData.initialShortcut)
+
+ // should contain a valid task ID for second app, and no intent or shortcut
+ assertNotEquals(launchData.secondTaskId, INVALID_TASK_ID)
+ assertNull(launchData.secondPendingIntent)
+ assertNull(launchData.secondShortcut)
+ }
+
+ @Test
+ fun generateLaunchData_Task_Intent() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleTaskInfo,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null
+ )
+ splitSelectDataHolder.setSecondTask(sampleIntent, sampleUser)
+ val launchData = splitSelectDataHolder.getSplitLaunchData()
+
+ assertEquals(launchData.splitLaunchType, SPLIT_TASK_PENDINGINTENT)
+
+ // should contain a valid task ID for first app, and no intent or shortcut
+ assertNotEquals(launchData.initialTaskId, INVALID_TASK_ID)
+ assertNull(launchData.initialPendingIntent)
+ assertNull(launchData.initialShortcut)
+
+ // should contain a valid intent for second app, and no task ID or shortcut
+ assertNotNull(launchData.secondPendingIntent)
+ assertEquals(launchData.secondTaskId, INVALID_TASK_ID)
+ assertNull(launchData.secondShortcut)
+ }
+
+ @Test
+ fun generateLaunchData_Task_Shortcut() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleTaskInfo,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null
+ )
+ splitSelectDataHolder.setSecondTask(sampleShortcut, sampleUser)
+ val launchData = splitSelectDataHolder.getSplitLaunchData()
+
+ assertEquals(launchData.splitLaunchType, SPLIT_TASK_SHORTCUT)
+
+ // should contain a valid task ID for first app, and no intent or shortcut
+ assertNotEquals(launchData.initialTaskId, INVALID_TASK_ID)
+ assertNull(launchData.initialPendingIntent)
+ assertNull(launchData.initialShortcut)
+
+ // should contain a valid shortcut and intent for second app, and no task ID
+ assertNotNull(launchData.secondShortcut)
+ assertNotNull(launchData.secondPendingIntent)
+ assertEquals(launchData.secondTaskId, INVALID_TASK_ID)
+ }
+
+ @Test
+ fun generateLaunchData_Intent_Task() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleIntent,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null,
+ INVALID_TASK_ID
+ )
+ splitSelectDataHolder.setSecondTask(sampleTaskId)
+ val launchData = splitSelectDataHolder.getSplitLaunchData()
+
+ assertEquals(launchData.splitLaunchType, SPLIT_PENDINGINTENT_TASK)
+
+ // should contain a valid intent for first app, and no task ID or shortcut
+ assertNotNull(launchData.initialPendingIntent)
+ assertEquals(launchData.initialTaskId, INVALID_TASK_ID)
+ assertNull(launchData.initialShortcut)
+
+ // should contain a valid task ID for second app, and no intent or shortcut
+ assertNotEquals(launchData.secondTaskId, INVALID_TASK_ID)
+ assertNull(launchData.secondPendingIntent)
+ assertNull(launchData.secondShortcut)
+ }
+
+ @Test
+ fun generateLaunchData_Shortcut_Task() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleShortcut,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null,
+ INVALID_TASK_ID
+ )
+ splitSelectDataHolder.setSecondTask(sampleTaskId)
+ val launchData = splitSelectDataHolder.getSplitLaunchData()
+
+ assertEquals(launchData.splitLaunchType, SPLIT_SHORTCUT_TASK)
+
+ // should contain a valid shortcut and intent for first app, and no task ID
+ assertNotNull(launchData.initialShortcut)
+ assertNotNull(launchData.initialPendingIntent)
+ assertEquals(launchData.initialTaskId, INVALID_TASK_ID)
+
+ // should contain a valid task ID for second app, and no intent or shortcut
+ assertNotEquals(launchData.secondTaskId, INVALID_TASK_ID)
+ assertNull(launchData.secondPendingIntent)
+ assertNull(launchData.secondShortcut)
+ }
+
+ @Test
+ fun generateLaunchData_Intent_Intent() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleIntent,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null,
+ INVALID_TASK_ID
+ )
+ splitSelectDataHolder.setSecondTask(sampleIntent2, sampleUser)
+ val launchData = splitSelectDataHolder.getSplitLaunchData()
+
+ assertEquals(launchData.splitLaunchType, SPLIT_PENDINGINTENT_PENDINGINTENT)
+
+ // should contain a valid intent for first app, and no task ID or shortcut
+ assertNotNull(launchData.initialPendingIntent)
+ assertEquals(launchData.initialTaskId, INVALID_TASK_ID)
+ assertNull(launchData.initialShortcut)
+
+ // should contain a valid intent for second app, and no task ID or shortcut
+ assertNotNull(launchData.secondPendingIntent)
+ assertEquals(launchData.secondTaskId, INVALID_TASK_ID)
+ assertNull(launchData.secondShortcut)
+ }
+
+ @Test
+ fun generateLaunchData_Single_Task() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleTaskInfo,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null
+ )
+ val launchData = splitSelectDataHolder.getFullscreenLaunchData()
+
+ assertEquals(launchData.splitLaunchType, SPLIT_SINGLE_TASK_FULLSCREEN)
+
+ // should contain a valid task ID for first app, and no intent or shortcut
+ assertNotEquals(launchData.initialTaskId, INVALID_TASK_ID)
+ assertNull(launchData.initialPendingIntent)
+ assertNull(launchData.initialShortcut)
+
+ // should contain no task ID, intent, or shortcut for second app
+ assertEquals(launchData.secondTaskId, INVALID_TASK_ID)
+ assertNull(launchData.secondPendingIntent)
+ assertNull(launchData.secondShortcut)
+ }
+
+ @Test
+ fun generateLaunchData_Single_Intent() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleIntent,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null,
+ INVALID_TASK_ID
+ )
+ val launchData = splitSelectDataHolder.getFullscreenLaunchData()
+
+ assertEquals(launchData.splitLaunchType, SPLIT_SINGLE_INTENT_FULLSCREEN)
+
+ // should contain a valid intent for first app, and no task ID or shortcut
+ assertNotNull(launchData.initialPendingIntent)
+ assertEquals(launchData.initialTaskId, INVALID_TASK_ID)
+ assertNull(launchData.initialShortcut)
+
+ // should contain no task ID, intent, or shortcut for second app
+ assertEquals(launchData.secondTaskId, INVALID_TASK_ID)
+ assertNull(launchData.secondPendingIntent)
+ assertNull(launchData.secondShortcut)
+ }
+
+ @Test
+ fun generateLaunchData_Single_Shortcut() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleShortcut,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null,
+ INVALID_TASK_ID
+ )
+ val launchData = splitSelectDataHolder.getFullscreenLaunchData()
+
+ assertEquals(launchData.splitLaunchType, SPLIT_SINGLE_SHORTCUT_FULLSCREEN)
+
+ // should contain a valid shortcut and intent for first app, and no task ID
+ assertNotNull(launchData.initialShortcut)
+ assertNotNull(launchData.initialPendingIntent)
+ assertEquals(launchData.initialTaskId, INVALID_TASK_ID)
+
+ // should contain no task ID, intent, or shortcut for second app
+ assertEquals(launchData.secondTaskId, INVALID_TASK_ID)
+ assertNull(launchData.secondPendingIntent)
+ assertNull(launchData.secondShortcut)
+ }
+
+ @Test
+ fun clearState_task() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleTaskInfo,
+ STAGE_POSITION_TOP_OR_LEFT,
+ null,
+ null
+ )
+ splitSelectDataHolder.setSecondTask(sampleIntent, sampleUser)
+ splitSelectDataHolder.resetState()
+ assertFalse(splitSelectDataHolder.isSplitSelectActive())
+ }
+
+ @Test
+ fun clearState_intent() {
+ splitSelectDataHolder.setInitialTaskSelect(
+ sampleIntent,
+ STAGE_POSITION_TOP_OR_LEFT,
+ sampleItemInfo,
+ null,
+ INVALID_TASK_ID
+ )
+ splitSelectDataHolder.setSecondTask(sampleIntent, sampleUser)
+ splitSelectDataHolder.resetState()
+ assertFalse(splitSelectDataHolder.isSplitSelectActive())
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt b/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
index 65542cf..f198741 100644
--- a/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
@@ -20,7 +20,6 @@
import android.app.ActivityManager
import android.app.PendingIntent
import android.content.ComponentName
-import android.content.Context
import android.content.Intent
import android.graphics.Rect
import android.os.Handler
@@ -31,12 +30,14 @@
import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.statehandlers.DepthController
import com.android.launcher3.statemanager.StateManager
+import com.android.launcher3.statemanager.StatefulActivity
import com.android.launcher3.util.ComponentKey
import com.android.launcher3.util.SplitConfigurationOptions
import com.android.launcher3.util.withArgCaptor
import com.android.quickstep.RecentsModel
import com.android.quickstep.SystemUiProxy
import com.android.systemui.shared.recents.model.Task
+import com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
@@ -58,7 +59,7 @@
@Mock lateinit var statsLogManager: StatsLogManager
@Mock lateinit var stateManager: StateManager<LauncherState>
@Mock lateinit var handler: Handler
- @Mock lateinit var context: Context
+ @Mock lateinit var context: StatefulActivity<*>
@Mock lateinit var recentsModel: RecentsModel
@Mock lateinit var pendingIntent: PendingIntent
@@ -67,6 +68,9 @@
private val primaryUserHandle = UserHandle(ActivityManager.RunningTaskInfo().userId)
private val nonPrimaryUserHandle = UserHandle(ActivityManager.RunningTaskInfo().userId + 10)
+ private var taskIdCounter = 0
+ private fun getUniqueId(): Int { return ++taskIdCounter }
+
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
@@ -78,7 +82,8 @@
depthController,
statsLogManager,
systemUiProxy,
- recentsModel
+ recentsModel,
+ null /*activityBackCallback*/
)
}
@@ -100,15 +105,15 @@
tasks.add(groupTask2)
// Assertions happen in the callback we get from what we pass into
- // #findLastActiveTaskAndRunCallback
+ // #findLastActiveTasksAndRunCallback
val taskConsumer =
- Consumer<Task> { assertNull("No tasks should have matched", it /*task*/) }
+ Consumer<List<Task>> { assertNull("No tasks should have matched", it[0] /*task*/) }
// Capture callback from recentsModel#getTasks()
val consumer =
withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTaskAndRunCallback(
- nonMatchingComponent,
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(nonMatchingComponent),
taskConsumer
)
verify(recentsModel).getTasks(capture())
@@ -139,27 +144,27 @@
tasks.add(groupTask2)
// Assertions happen in the callback we get from what we pass into
- // #findLastActiveTaskAndRunCallback
+ // #findLastActiveTasksAndRunCallback
val taskConsumer =
- Consumer<Task> {
+ Consumer<List<Task>> {
assertEquals(
"ComponentName package mismatched",
- it.key.baseIntent.component.packageName,
+ it[0].key.baseIntent.component?.packageName,
matchingPackage
)
assertEquals(
"ComponentName class mismatched",
- it.key.baseIntent.component.className,
+ it[0].key.baseIntent.component?.className,
matchingClass
)
- assertEquals(it, groupTask1.task1)
+ assertEquals(it[0], groupTask1.task1)
}
// Capture callback from recentsModel#getTasks()
val consumer =
withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTaskAndRunCallback(
- matchingComponent,
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(matchingComponent),
taskConsumer
)
verify(recentsModel).getTasks(capture())
@@ -190,15 +195,15 @@
tasks.add(groupTask2)
// Assertions happen in the callback we get from what we pass into
- // #findLastActiveTaskAndRunCallback
+ // #findLastActiveTasksAndRunCallback
val taskConsumer =
- Consumer<Task> { assertNull("No tasks should have matched", it /*task*/) }
+ Consumer<List<Task>> { assertNull("No tasks should have matched", it[0] /*task*/) }
// Capture callback from recentsModel#getTasks()
val consumer =
withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTaskAndRunCallback(
- nonPrimaryUserComponent,
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(nonPrimaryUserComponent),
taskConsumer
)
verify(recentsModel).getTasks(capture())
@@ -231,28 +236,28 @@
tasks.add(groupTask2)
// Assertions happen in the callback we get from what we pass into
- // #findLastActiveTaskAndRunCallback
+ // #findLastActiveTasksAndRunCallback
val taskConsumer =
- Consumer<Task> {
+ Consumer<List<Task>> {
assertEquals(
"ComponentName package mismatched",
- it.key.baseIntent.component.packageName,
+ it[0].key.baseIntent.component?.packageName,
matchingPackage
)
assertEquals(
"ComponentName class mismatched",
- it.key.baseIntent.component.className,
+ it[0].key.baseIntent.component?.className,
matchingClass
)
- assertEquals("userId mismatched", it.key.userId, nonPrimaryUserHandle.identifier)
- assertEquals(it, groupTask1.task1)
+ assertEquals("userId mismatched", it[0].key.userId, nonPrimaryUserHandle.identifier)
+ assertEquals(it[0], groupTask1.task1)
}
// Capture callback from recentsModel#getTasks()
val consumer =
withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTaskAndRunCallback(
- nonPrimaryUserComponent,
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(nonPrimaryUserComponent),
taskConsumer
)
verify(recentsModel).getTasks(capture())
@@ -283,27 +288,200 @@
tasks.add(groupTask1)
// Assertions happen in the callback we get from what we pass into
- // #findLastActiveTaskAndRunCallback
+ // #findLastActiveTasksAndRunCallback
val taskConsumer =
- Consumer<Task> {
+ Consumer<List<Task>> {
assertEquals(
"ComponentName package mismatched",
- it.key.baseIntent.component.packageName,
+ it[0].key.baseIntent.component?.packageName,
matchingPackage
)
assertEquals(
"ComponentName class mismatched",
- it.key.baseIntent.component.className,
+ it[0].key.baseIntent.component?.className,
matchingClass
)
- assertEquals(it, groupTask2.task2)
+ assertEquals(it[0], groupTask1.task1)
}
// Capture callback from recentsModel#getTasks()
val consumer =
withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTaskAndRunCallback(
- matchingComponent,
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(matchingComponent),
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+
+ // Send our mocked tasks
+ consumer.accept(tasks)
+ }
+
+ @Test
+ fun activeTasks_multipleSearchShouldFindTask() {
+ val nonMatchingComponent = ComponentKey(ComponentName("no", "match"), primaryUserHandle)
+ val matchingPackage = "hotdog"
+ val matchingClass = "juice"
+ val matchingComponent =
+ ComponentKey(ComponentName(matchingPackage, matchingClass), primaryUserHandle)
+
+ val groupTask1 =
+ generateGroupTask(
+ ComponentName("hotdog", "pie"),
+ ComponentName("pumpkin", "pie")
+ )
+ val groupTask2 =
+ generateGroupTask(
+ ComponentName("pomegranate", "juice"),
+ ComponentName(matchingPackage, matchingClass)
+ )
+ val tasks: ArrayList<GroupTask> = ArrayList()
+ tasks.add(groupTask2)
+ tasks.add(groupTask1)
+
+ // Assertions happen in the callback we get from what we pass into
+ // #findLastActiveTasksAndRunCallback
+ val taskConsumer =
+ Consumer<List<Task>> {
+ assertEquals("Expected array length 2", 2, it.size)
+ assertNull("No tasks should have matched", it[0] /*task*/)
+ assertEquals(
+ "ComponentName package mismatched",
+ it[1].key.baseIntent.component?.packageName,
+ matchingPackage
+ )
+ assertEquals(
+ "ComponentName class mismatched",
+ it[1].key.baseIntent.component?.className,
+ matchingClass
+ )
+ assertEquals(it[1], groupTask2.task2)
+ }
+
+ // Capture callback from recentsModel#getTasks()
+ val consumer =
+ withArgCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(nonMatchingComponent, matchingComponent),
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+
+ // Send our mocked tasks
+ consumer.accept(tasks)
+ }
+
+ @Test
+ fun activeTasks_multipleSearchShouldNotFindSameTaskTwice() {
+ val matchingPackage = "hotdog"
+ val matchingClass = "juice"
+ val matchingComponent =
+ ComponentKey(ComponentName(matchingPackage, matchingClass), primaryUserHandle)
+
+ val groupTask1 =
+ generateGroupTask(
+ ComponentName("hotdog", "pie"),
+ ComponentName("pumpkin", "pie")
+ )
+ val groupTask2 =
+ generateGroupTask(
+ ComponentName("pomegranate", "juice"),
+ ComponentName(matchingPackage, matchingClass)
+ )
+ val tasks: ArrayList<GroupTask> = ArrayList()
+ tasks.add(groupTask2)
+ tasks.add(groupTask1)
+
+ // Assertions happen in the callback we get from what we pass into
+ // #findLastActiveTasksAndRunCallback
+ val taskConsumer =
+ Consumer<List<Task>> {
+ assertEquals("Expected array length 2", 2, it.size)
+ assertEquals(
+ "ComponentName package mismatched",
+ it[0].key.baseIntent.component?.packageName,
+ matchingPackage
+ )
+ assertEquals(
+ "ComponentName class mismatched",
+ it[0].key.baseIntent.component?.className,
+ matchingClass
+ )
+ assertEquals(it[0], groupTask2.task2)
+ assertNull("No tasks should have matched", it[1] /*task*/)
+ }
+
+ // Capture callback from recentsModel#getTasks()
+ val consumer =
+ withArgCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(matchingComponent, matchingComponent),
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+
+ // Send our mocked tasks
+ consumer.accept(tasks)
+ }
+
+ @Test
+ fun activeTasks_multipleSearchShouldFindDifferentInstancesOfSameTask() {
+ val matchingPackage = "hotdog"
+ val matchingClass = "juice"
+ val matchingComponent =
+ ComponentKey(ComponentName(matchingPackage, matchingClass), primaryUserHandle)
+
+ val groupTask1 =
+ generateGroupTask(
+ ComponentName(matchingPackage, matchingClass),
+ ComponentName("pumpkin", "pie")
+ )
+ val groupTask2 =
+ generateGroupTask(
+ ComponentName("pomegranate", "juice"),
+ ComponentName(matchingPackage, matchingClass)
+ )
+ val tasks: ArrayList<GroupTask> = ArrayList()
+ tasks.add(groupTask2)
+ tasks.add(groupTask1)
+
+ // Assertions happen in the callback we get from what we pass into
+ // #findLastActiveTasksAndRunCallback
+ val taskConsumer =
+ Consumer<List<Task>> {
+ assertEquals("Expected array length 2", 2, it.size)
+ assertEquals(
+ "ComponentName package mismatched",
+ it[0].key.baseIntent.component?.packageName,
+ matchingPackage
+ )
+ assertEquals(
+ "ComponentName class mismatched",
+ it[0].key.baseIntent.component?.className,
+ matchingClass
+ )
+ assertEquals(it[0], groupTask1.task1)
+ assertEquals(
+ "ComponentName package mismatched",
+ it[1].key.baseIntent.component?.packageName,
+ matchingPackage
+ )
+ assertEquals(
+ "ComponentName class mismatched",
+ it[1].key.baseIntent.component?.className,
+ matchingClass
+ )
+ assertEquals(it[1], groupTask2.task2)
+ }
+
+ // Capture callback from recentsModel#getTasks()
+ val consumer =
+ withArgCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTasksAndRunCallback(
+ listOf(matchingComponent, matchingComponent),
taskConsumer
)
verify(recentsModel).getTasks(capture())
@@ -366,6 +544,7 @@
): GroupTask {
val task1 = Task()
var taskInfo = ActivityManager.RunningTaskInfo()
+ taskInfo.taskId = getUniqueId()
var intent = Intent()
intent.component = task1ComponentName
taskInfo.baseIntent = intent
@@ -373,6 +552,7 @@
val task2 = Task()
taskInfo = ActivityManager.RunningTaskInfo()
+ taskInfo.taskId = getUniqueId()
intent = Intent()
intent.component = task2ComponentName
taskInfo.baseIntent = intent
@@ -380,7 +560,7 @@
return GroupTask(
task1,
task2,
- SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1)
+ SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1, SNAP_TO_50_50)
)
}
@@ -393,6 +573,7 @@
): GroupTask {
val task1 = Task()
var taskInfo = ActivityManager.RunningTaskInfo()
+ taskInfo.taskId = getUniqueId()
// Apply custom userHandle1
taskInfo.userId = userHandle1.identifier
var intent = Intent()
@@ -401,6 +582,7 @@
task1.key = Task.TaskKey(taskInfo)
val task2 = Task()
taskInfo = ActivityManager.RunningTaskInfo()
+ taskInfo.taskId = getUniqueId()
// Apply custom userHandle2
taskInfo.userId = userHandle2.identifier
intent = Intent()
@@ -410,7 +592,7 @@
return GroupTask(
task1,
task2,
- SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1)
+ SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1, SNAP_TO_50_50)
)
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java b/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
index 83602be..a54dc2d 100644
--- a/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
+++ b/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
@@ -50,6 +50,9 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
+import java.util.List;
+
@SmallTest
@RunWith(AndroidJUnit4.class)
public class TaskViewSimulatorTest {
@@ -150,7 +153,7 @@
WindowBounds wm = new WindowBounds(
new Rect(0, 0, mDisplaySize.x, mDisplaySize.y),
mDisplayInsets);
- WindowBounds[] allBounds = new WindowBounds[4];
+ List<WindowBounds> allBounds = new ArrayList<>(4);
for (int i = 0; i < 4; i++) {
Rect boundsR = new Rect(wm.bounds);
Rect insetsR = new Rect(wm.insets);
@@ -158,7 +161,7 @@
RotationUtils.rotateRect(insetsR, RotationUtils.deltaRotation(rotation, i));
RotationUtils.rotateRect(boundsR, RotationUtils.deltaRotation(rotation, i));
boundsR.set(0, 0, Math.abs(boundsR.width()), Math.abs(boundsR.height()));
- allBounds[i] = new WindowBounds(boundsR, insetsR);
+ allBounds.add(new WindowBounds(boundsR, insetsR));
}
WindowManagerProxy wmProxy = mock(WindowManagerProxy.class);
@@ -166,7 +169,7 @@
doReturn(wm).when(wmProxy).getRealBounds(any(), any());
doReturn(NavigationMode.NO_BUTTON).when(wmProxy).getNavigationMode(any());
- ArrayMap<CachedDisplayInfo, WindowBounds[]> perDisplayBoundsCache =
+ ArrayMap<CachedDisplayInfo, List<WindowBounds>> perDisplayBoundsCache =
new ArrayMap<>();
perDisplayBoundsCache.put(cdi.normalize(), allBounds);
diff --git a/res/anim-v33/shared_x_axis_activity_close_enter.xml b/res/anim-v33/shared_x_axis_activity_close_enter.xml
index 94ef06c..3d7ad2b 100644
--- a/res/anim-v33/shared_x_axis_activity_close_enter.xml
+++ b/res/anim-v33/shared_x_axis_activity_close_enter.xml
@@ -25,7 +25,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/standard_decelerate"
+ android:interpolator="@interpolator/standard_decelerate_interpolator"
android:startOffset="100"
android:duration="350" />
@@ -35,7 +35,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:interpolator="@interpolator/emphasized_interpolator"
android:startOffset="0"
android:duration="450" />
diff --git a/res/anim-v33/shared_x_axis_activity_close_exit.xml b/res/anim-v33/shared_x_axis_activity_close_exit.xml
index 19eb09e..fb63602 100644
--- a/res/anim-v33/shared_x_axis_activity_close_exit.xml
+++ b/res/anim-v33/shared_x_axis_activity_close_exit.xml
@@ -24,7 +24,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/standard_accelerate"
+ android:interpolator="@interpolator/standard_accelerate_interpolator"
android:startOffset="0"
android:duration="100" />
@@ -34,7 +34,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:interpolator="@interpolator/emphasized_interpolator"
android:startOffset="0"
android:duration="450" />
diff --git a/res/anim-v33/shared_x_axis_activity_open_enter.xml b/res/anim-v33/shared_x_axis_activity_open_enter.xml
index f699cec..cba74ba 100644
--- a/res/anim-v33/shared_x_axis_activity_open_enter.xml
+++ b/res/anim-v33/shared_x_axis_activity_open_enter.xml
@@ -25,7 +25,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/standard_decelerate"
+ android:interpolator="@interpolator/standard_decelerate_interpolator"
android:startOffset="100"
android:duration="350" />
@@ -35,7 +35,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:interpolator="@interpolator/emphasized_interpolator"
android:startOffset="0"
android:duration="450" />
diff --git a/res/anim-v33/shared_x_axis_activity_open_exit.xml b/res/anim-v33/shared_x_axis_activity_open_exit.xml
index 85988ec..22e878d 100644
--- a/res/anim-v33/shared_x_axis_activity_open_exit.xml
+++ b/res/anim-v33/shared_x_axis_activity_open_exit.xml
@@ -24,7 +24,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/standard_accelerate"
+ android:interpolator="@interpolator/standard_accelerate_interpolator"
android:startOffset="0"
android:duration="100" />
@@ -34,7 +34,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:interpolator="@interpolator/emphasized_interpolator"
android:startOffset="0"
android:duration="450" />
diff --git a/res/drawable-hdpi/workspace_bg.9.png b/res/drawable-hdpi/workspace_bg.9.png
deleted file mode 100755
index 1d82fd4..0000000
--- a/res/drawable-hdpi/workspace_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/workspace_bg.9.png b/res/drawable-mdpi/workspace_bg.9.png
deleted file mode 100755
index 116ce44..0000000
--- a/res/drawable-mdpi/workspace_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-sw720dp/ic_transient_taskbar_all_apps_search_button.xml b/res/drawable-sw720dp/ic_transient_taskbar_all_apps_search_button.xml
new file mode 100644
index 0000000..654f0b3
--- /dev/null
+++ b/res/drawable-sw720dp/ic_transient_taskbar_all_apps_search_button.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="52dp"
+ android:height="52dp"
+ android:viewportWidth="52"
+ android:viewportHeight="52">
+ <path
+ android:pathData="M39.4,17.5c0,3.1 -2.5,5.5 -5.5,5.5c-3.1,0 -5.5,-2.5 -5.5,-5.5s2.5,-5.5 5.5,-5.5C36.9,12 39.4,14.5 39.4,17.5z"
+ android:fillColor="#FF000000"/>
+ <path
+ android:pathData="M23.1,17.5c0,3.1 -2.5,5.5 -5.5,5.5S12,20.6 12,17.5s2.5,-5.5 5.5,-5.5S23.1,14.5 23.1,17.5z"
+ android:fillColor="#FF000000"/>
+ <path
+ android:pathData="M17.5,33.9m-5.5,0a5.5,5.5 0,1 1,11 0a5.5,5.5 0,1 1,-11 0"
+ android:fillColor="#FF000000"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M33.9,30c2.1,0 3.9,1.7 3.9,3.9s-1.7,3.9 -3.9,3.9S30,36.1 30,33.9S31.8,30 33.9,30M33.9,28.3c-3.1,0 -5.6,2.5 -5.6,5.6c0,3.1 2.5,5.6 5.6,5.6c3.1,0 5.6,-2.5 5.6,-5.6C39.5,30.8 37,28.3 33.9,28.3L33.9,28.3z"/>
+ <path
+ android:pathData="M36.9,37L43.2,43.3"
+ android:strokeWidth="1.7"
+ android:fillColor="#00000000"
+ android:strokeColor="#000000"/>
+</vector>
diff --git a/res/drawable-xhdpi/workspace_bg.9.png b/res/drawable-xhdpi/workspace_bg.9.png
deleted file mode 100755
index b1b3b85..0000000
--- a/res/drawable-xhdpi/workspace_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/workspace_bg.9.png b/res/drawable-xxhdpi/workspace_bg.9.png
deleted file mode 100755
index d47f6b2..0000000
--- a/res/drawable-xxhdpi/workspace_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/workspace_bg.9.png b/res/drawable-xxxhdpi/workspace_bg.9.png
deleted file mode 100755
index 3281548..0000000
--- a/res/drawable-xxxhdpi/workspace_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/all_apps_tabs_background.xml b/res/drawable/all_apps_tabs_background.xml
index 8471cd4..1e7cff2 100644
--- a/res/drawable/all_apps_tabs_background.xml
+++ b/res/drawable/all_apps_tabs_background.xml
@@ -30,7 +30,7 @@
android:state_selected="false">
<shape android:shape="rectangle">
<corners android:radius="@dimen/all_apps_header_pill_corner_radius" />
- <solid android:color="@color/all_apps_tabs_background" />
+ <solid android:color="@color/material_color_surface_bright" />
</shape>
</item>
@@ -39,7 +39,7 @@
android:state_selected="true">
<shape android:shape="rectangle">
<corners android:radius="@dimen/all_apps_header_pill_corner_radius" />
- <solid android:color="@color/all_apps_tab_background_selected" />
+ <solid android:color="@color/material_color_primary" />
</shape>
</item>
</selector>
diff --git a/res/drawable/arrow_toast_rounded_background.xml b/res/drawable/arrow_toast_rounded_background.xml
index 1206ddd..d7d6255 100644
--- a/res/drawable/arrow_toast_rounded_background.xml
+++ b/res/drawable/arrow_toast_rounded_background.xml
@@ -14,6 +14,6 @@
limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
- <solid android:color="@color/arrow_tip_view_bg" />
+ <solid android:color="?attr/arrowTipBackground" />
<corners android:radius="@dimen/dialogCornerRadius" />
</shape>
diff --git a/res/drawable/bottom_rounded_popup_ripple.xml b/res/drawable/bottom_rounded_popup_ripple.xml
deleted file mode 100644
index 739833a..0000000
--- a/res/drawable/bottom_rounded_popup_ripple.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="?android:attr/colorControlHighlight">
- <item android:id="@android:id/mask">
- <shape android:shape="rectangle">
- <solid android:color="#FFFFFFFF"/>
- <corners android:bottomLeftRadius="@dimen/dialogCornerRadius"
- android:bottomRightRadius="@dimen/dialogCornerRadius"
- android:topLeftRadius="0dp"
- android:topRightRadius="0dp"/>
- </shape>
- </item>
-</ripple>
\ No newline at end of file
diff --git a/res/drawable/bubble_ic_overflow_button.xml b/res/drawable/bubble_ic_overflow_button.xml
new file mode 100644
index 0000000..475639e
--- /dev/null
+++ b/res/drawable/bubble_ic_overflow_button.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2023 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:width="24dp"
+ android:height="24dp">
+ <path
+ android:fillColor="#1A73E8"
+ android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
+</vector>
diff --git a/res/layout/popup_container_material_u.xml b/res/drawable/ic_split_exit.xml
similarity index 61%
rename from res/layout/popup_container_material_u.xml
rename to res/drawable/ic_split_exit.xml
index d34c500..d7e8b03 100644
--- a/res/layout/popup_container_material_u.xml
+++ b/res/drawable/ic_split_exit.xml
@@ -13,11 +13,13 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<com.android.launcher3.popup.PopupContainerWithArrow
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/popup_container"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:orientation="vertical"/>
\ No newline at end of file
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="20dp"
+ android:tint="#000000"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="20dp">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_taskbar_all_apps_search_button.xml b/res/drawable/ic_taskbar_all_apps_search_button.xml
new file mode 100644
index 0000000..8fbe539
--- /dev/null
+++ b/res/drawable/ic_taskbar_all_apps_search_button.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="44dp"
+ android:height="44dp"
+ android:viewportWidth="44"
+ android:viewportHeight="44">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M34.1,14.9c0,2.7 -2.2,4.9 -4.9,4.9s-4.9,-2.2 -4.9,-4.9s2.2,-4.9 4.9,-4.9S34.1,12.2 34.1,14.9z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M19.7,14.9c0,2.7 -2.2,4.9 -4.9,4.9S10,17.6 10,14.9s2.2,-4.9 4.9,-4.9S19.7,12.2 19.7,14.9z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M14.9,29.2m-4.9,0a4.9,4.9 0,1 1,9.8 0a4.9,4.9 0,1 1,-9.8 0"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M29.3,25.9c1.9,0 3.4,1.5 3.4,3.4c0,1.9 -1.5,3.4 -3.4,3.4s-3.4,-1.5 -3.4,-3.4C25.9,27.4 27.4,25.9 29.3,25.9M29.3,24.4c-2.7,0 -4.9,2.2 -4.9,4.9s2.2,4.9 4.9,4.9c2.7,0 4.9,-2.2 4.9,-4.9S32,24.4 29.3,24.4L29.3,24.4z"/>
+ <path
+ android:pathData="M31.9,32L37.4,37.5"
+ android:strokeWidth="1.5"
+ android:fillColor="#00000000"
+ android:strokeColor="#000000"/>
+</vector>
diff --git a/res/drawable/ic_transient_taskbar_all_apps_search_button.xml b/res/drawable/ic_transient_taskbar_all_apps_search_button.xml
new file mode 100644
index 0000000..59a666b
--- /dev/null
+++ b/res/drawable/ic_transient_taskbar_all_apps_search_button.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M37.4,15.5c0,3.1 -2.5,5.5 -5.5,5.5c-3.1,0 -5.5,-2.5 -5.5,-5.5s2.5,-5.5 5.5,-5.5C34.9,10 37.4,12.5 37.4,15.5z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M21.1,15.5c0,3.1 -2.5,5.5 -5.5,5.5S10,18.6 10,15.5s2.5,-5.5 5.5,-5.5S21.1,12.5 21.1,15.5z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M15.5,31.9m-5.5,0a5.5,5.5 0,1 1,11 0a5.5,5.5 0,1 1,-11 0"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M31.9,28c2.1,0 3.9,1.7 3.9,3.9s-1.7,3.9 -3.9,3.9c-2.1,0 -3.9,-1.7 -3.9,-3.9S29.8,28 31.9,28M31.9,26.3c-3.1,0 -5.6,2.5 -5.6,5.6c0,3.1 2.5,5.6 5.6,5.6c3.1,0 5.6,-2.5 5.6,-5.6C37.5,28.8 35,26.3 31.9,26.3L31.9,26.3z"/>
+ <path
+ android:pathData="M34.9,35L41.2,41.3"
+ android:strokeWidth="1.7"
+ android:fillColor="#00000000"
+ android:strokeColor="#000000"/>
+</vector>
diff --git a/res/drawable/ic_wallpaper.xml b/res/drawable/ic_wallpaper.xml
deleted file mode 100644
index 9543f88..0000000
--- a/res/drawable/ic_wallpaper.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/options_menu_icon_size"
- android:height="@dimen/options_menu_icon_size"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/textColorPrimary">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M9,12.71l2.14,2.58l3-3.87L18,16.57H6L9,12.71z M5,5h6V3H5C3.9,3,3,3.9,3,5v6h2V5z M19,19h-6v2h6c1.1,0,2-0.9,2-2v-6h-2V19z
- M5,19v-6H3v6c0,1.1,0.9,2,2,2h6v-2H5z M19,5v6h2V5c0-1.1-0.9-2-2-2h-6v2H19z M16,9c0.55,0,1-0.45,1-1s-0.45-1-1-1
- c-0.55,0-1,0.45-1,1S15.45,9,16,9z"/>
-</vector>
diff --git a/res/drawable/popup_background_material_u.xml b/res/drawable/popup_background.xml
similarity index 100%
rename from res/drawable/popup_background_material_u.xml
rename to res/drawable/popup_background.xml
diff --git a/res/drawable/top_rounded_popup_ripple.xml b/res/drawable/rounded_popup_ripple.xml
similarity index 80%
rename from res/drawable/top_rounded_popup_ripple.xml
rename to res/drawable/rounded_popup_ripple.xml
index 7468480..b0dcc80 100644
--- a/res/drawable/top_rounded_popup_ripple.xml
+++ b/res/drawable/rounded_popup_ripple.xml
@@ -18,10 +18,7 @@
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#FFFFFFFF"/>
- <corners android:bottomLeftRadius="0dp"
- android:bottomRightRadius="0dp"
- android:topLeftRadius="@dimen/dialogCornerRadius"
- android:topRightRadius="@dimen/dialogCornerRadius"/>
+ <corners android:radius="@dimen/dialogCornerRadius" />
</shape>
</item>
</ripple>
\ No newline at end of file
diff --git a/res/interpolator/back_cancel.xml b/res/interpolator/back_cancel.xml
deleted file mode 100644
index 2165457..0000000
--- a/res/interpolator/back_cancel.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:controlX1="0.2"
- android:controlY1="0"
- android:controlX2="0"
- android:controlY2="1"/>
\ No newline at end of file
diff --git a/res/interpolator/fast_out_extra_slow_in.xml b/res/interpolator/fast_out_extra_slow_in.xml
deleted file mode 100644
index f296a82..0000000
--- a/res/interpolator/fast_out_extra_slow_in.xml
+++ /dev/null
@@ -1,19 +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
- -->
-
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0,0 C 0.05, 0, 0.133333, 0.06, 0.166666, 0.4 C 0.208333, 0.82, 0.25, 1, 1, 1"/>
\ No newline at end of file
diff --git a/res/interpolator/folder_interpolator.xml b/res/interpolator/folder_interpolator.xml
deleted file mode 100644
index b95d454..0000000
--- a/res/interpolator/folder_interpolator.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2017, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:controlX1="0.2"
- android:controlY1="0"
- android:controlX2="0"
- android:controlY2="1"/>
diff --git a/res/interpolator/large_folder_preview_item_close_interpolator.xml b/res/interpolator/large_folder_preview_item_close_interpolator.xml
deleted file mode 100644
index d28af63..0000000
--- a/res/interpolator/large_folder_preview_item_close_interpolator.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2017, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:controlX1="0.3"
- android:controlY1="0"
- android:controlX2="1"
- android:controlY2="1"/>
diff --git a/res/interpolator/standard_accelerate.xml b/res/interpolator/standard_accelerate.xml
deleted file mode 100644
index 394393d..0000000
--- a/res/interpolator/standard_accelerate.xml
+++ /dev/null
@@ -1,22 +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.
- -->
-
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:controlX1="0.3"
- android:controlY1="0"
- android:controlX2="1"
- android:controlY2="1"/>
\ No newline at end of file
diff --git a/res/layout/all_apps_prediction_row_icon.xml b/res/layout/all_apps_prediction_row_icon.xml
new file mode 100644
index 0000000..c9b3275
--- /dev/null
+++ b/res/layout/all_apps_prediction_row_icon.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.launcher3.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ style="@style/BaseIcon.AllApps"
+ android:id="@+id/icon"
+ launcher:iconDisplay="prediction_row"
+ launcher:centerVertically="true" />
diff --git a/res/layout/system_shortcut_icons_container_material_u.xml b/res/layout/app_pair_icon.xml
similarity index 60%
copy from res/layout/system_shortcut_icons_container_material_u.xml
copy to res/layout/app_pair_icon.xml
index fbf18af..2b9a98b 100644
--- a/res/layout/system_shortcut_icons_container_material_u.xml
+++ b/res/layout/app_pair_icon.xml
@@ -14,13 +14,17 @@
limitations under the License.
-->
-<LinearLayout
+<com.android.launcher3.apppairs.AppPairIcon
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/system_shortcuts_container"
- android:tag="@string/popup_container_iterate_children"
android:layout_width="match_parent"
- android:layout_height="@dimen/system_shortcut_header_height"
- android:orientation="horizontal"
- android:gravity="end|center_vertical"
- android:background="@drawable/popup_background_material_u"
- android:elevation="@dimen/deep_shortcuts_elevation"/>
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:focusable="true" >
+ <com.android.launcher3.views.DoubleShadowBubbleTextView
+ style="@style/BaseIcon.Workspace"
+ android:id="@+id/app_pair_icon_name"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:focusable="false"
+ android:layout_gravity="top" />
+</com.android.launcher3.apppairs.AppPairIcon>
diff --git a/res/layout/arrow_toast.xml b/res/layout/arrow_toast.xml
index 88a92eb..004e778 100644
--- a/res/layout/arrow_toast.xml
+++ b/res/layout/arrow_toast.xml
@@ -28,7 +28,7 @@
android:padding="16dp"
android:background="@drawable/arrow_toast_rounded_background"
android:elevation="@dimen/arrow_toast_elevation"
- android:textColor="@color/arrow_tip_view_content"
+ android:textColor="?attr/arrowTipTextColor"
android:textSize="14sp"/>
<View
diff --git a/res/layout/deep_shortcut.xml b/res/layout/deep_shortcut.xml
index b175d17..6c1a2f7 100644
--- a/res/layout/deep_shortcut.xml
+++ b/res/layout/deep_shortcut.xml
@@ -13,10 +13,10 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
<com.android.launcher3.shortcuts.DeepShortcutView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/deep_shortcut_material"
android:layout_width="@dimen/bg_popup_item_width"
android:layout_height="@dimen/bg_popup_item_height"
android:elevation="@dimen/deep_shortcuts_elevation"
@@ -31,12 +31,11 @@
android:textAlignment="viewStart"
android:paddingStart="@dimen/deep_shortcuts_text_padding_start"
android:paddingEnd="@dimen/popup_padding_end"
- android:drawableEnd="@drawable/ic_drag_handle"
android:drawablePadding="@dimen/deep_shortcut_drawable_padding"
android:singleLine="true"
android:ellipsize="end"
android:textSize="14sp"
- android:textColor="?android:attr/textColorPrimary"
+ android:textColor="?attr/popupTextColor"
launcher:layoutHorizontal="true"
launcher:iconDisplay="shortcut_popup"
launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size" />
@@ -48,5 +47,4 @@
android:layout_marginStart="@dimen/popup_padding_start"
android:layout_gravity="start|center_vertical"
android:background="@drawable/ic_deepshortcut_placeholder"/>
-
-</com.android.launcher3.shortcuts.DeepShortcutView>
+</com.android.launcher3.shortcuts.DeepShortcutView>
\ No newline at end of file
diff --git a/res/layout/deep_shortcut_container.xml b/res/layout/deep_shortcut_container.xml
index b6c3f56..bf9124a 100644
--- a/res/layout/deep_shortcut_container.xml
+++ b/res/layout/deep_shortcut_container.xml
@@ -16,7 +16,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/deep_shortcuts_container"
- android:background="@drawable/popup_background_material_u"
+ android:background="@drawable/popup_background"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tag="@string/popup_container_iterate_children"
diff --git a/res/layout/deep_shortcut_material_u.xml b/res/layout/deep_shortcut_material_u.xml
deleted file mode 100644
index 2e21ddb..0000000
--- a/res/layout/deep_shortcut_material_u.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.launcher3.shortcuts.DeepShortcutView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res-auto"
- android:id="@+id/deep_shortcut_material"
- android:layout_width="@dimen/bg_popup_item_width"
- android:layout_height="@dimen/bg_popup_item_height"
- android:elevation="@dimen/deep_shortcuts_elevation"
- android:background="@drawable/middle_item_primary"
- android:theme="@style/PopupItem" >
-
- <com.android.launcher3.shortcuts.DeepShortcutTextView
- style="@style/BaseIcon"
- android:id="@+id/bubble_text"
- android:background="?android:attr/selectableItemBackground"
- android:gravity="start|center_vertical"
- android:textAlignment="viewStart"
- android:paddingStart="@dimen/deep_shortcuts_text_padding_start"
- android:paddingEnd="@dimen/popup_padding_end"
- android:drawablePadding="@dimen/deep_shortcut_drawable_padding"
- android:singleLine="true"
- android:ellipsize="end"
- android:textSize="14sp"
- android:textColor="?attr/popupTextColor"
- launcher:layoutHorizontal="true"
- launcher:iconDisplay="shortcut_popup"
- launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size" />
-
- <View
- android:id="@+id/icon"
- android:layout_width="@dimen/deep_shortcut_icon_size"
- android:layout_height="@dimen/deep_shortcut_icon_size"
- android:layout_marginStart="@dimen/popup_padding_start"
- android:layout_gravity="start|center_vertical"
- android:background="@drawable/ic_deepshortcut_placeholder"/>
-</com.android.launcher3.shortcuts.DeepShortcutView>
\ No newline at end of file
diff --git a/res/layout/popup_container.xml b/res/layout/popup_container.xml
index 9327287..bf7b126 100644
--- a/res/layout/popup_container.xml
+++ b/res/layout/popup_container.xml
@@ -13,27 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
<com.android.launcher3.popup.PopupContainerWithArrow
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/popup_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:clipToPadding="false"
android:clipChildren="false"
- android:orientation="vertical">
-
- <LinearLayout
- android:id="@+id/deep_shortcuts_container"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:tag="@string/popup_container_iterate_children"
- android:elevation="@dimen/deep_shortcuts_elevation"
- android:orientation="vertical"/>
-
- <com.android.launcher3.notification.NotificationContainer
- android:id="@+id/notification_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone"/>
-</com.android.launcher3.popup.PopupContainerWithArrow>
\ No newline at end of file
+ android:clipToPadding="false"
+ android:orientation="vertical"/>
\ No newline at end of file
diff --git a/res/layout/system_shortcut_icons_container.xml b/res/layout/system_shortcut_icons_container.xml
index fa92ba3..a5c0be3 100644
--- a/res/layout/system_shortcut_icons_container.xml
+++ b/res/layout/system_shortcut_icons_container.xml
@@ -17,9 +17,10 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/system_shortcuts_container"
+ android:tag="@string/popup_container_iterate_children"
android:layout_width="match_parent"
android:layout_height="@dimen/system_shortcut_header_height"
android:orientation="horizontal"
android:gravity="end|center_vertical"
- android:background="@drawable/single_item_primary"
+ android:background="@drawable/popup_background"
android:elevation="@dimen/deep_shortcuts_elevation"/>
diff --git a/res/layout/system_shortcut_rows_container.xml b/res/layout/system_shortcut_rows_container.xml
index f992ef5..1940139 100644
--- a/res/layout/system_shortcut_rows_container.xml
+++ b/res/layout/system_shortcut_rows_container.xml
@@ -17,6 +17,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/system_shortcuts_container"
+ android:background="@drawable/popup_background"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tag="@string/popup_container_iterate_children"
diff --git a/res/layout/system_shortcut_rows_container_material_u.xml b/res/layout/system_shortcut_rows_container_material_u.xml
deleted file mode 100644
index 006e280..0000000
--- a/res/layout/system_shortcut_rows_container_material_u.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/system_shortcuts_container"
- android:background="@drawable/popup_background_material_u"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:tag="@string/popup_container_iterate_children"
- android:elevation="@dimen/deep_shortcuts_elevation"
- android:orientation="vertical"/>
diff --git a/res/layout/widget_shortcut_container_material_u.xml b/res/layout/widget_shortcut_container_material_u.xml
index aab34e3..3a49c70 100644
--- a/res/layout/widget_shortcut_container_material_u.xml
+++ b/res/layout/widget_shortcut_container_material_u.xml
@@ -17,7 +17,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/widget_shortcut_container"
- android:background="@drawable/popup_background_material_u"
+ android:background="@drawable/popup_background"
android:layout_width="match_parent"
android:layout_height="@dimen/system_shortcut_header_height"
android:orientation="horizontal"
diff --git a/res/layout/widgets_table_container.xml b/res/layout/widgets_table_container.xml
index 4a32672..c41d0bb 100644
--- a/res/layout/widgets_table_container.xml
+++ b/res/layout/widgets_table_container.xml
@@ -16,6 +16,7 @@
<com.android.launcher3.widget.picker.WidgetsListTableView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/widgets_table"
+ android:paddingHorizontal="@dimen/widget_list_horizontal_margin"
android:background="@drawable/bg_widgets_content"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
diff --git a/res/layout/work_apps_paused.xml b/res/layout/work_apps_paused.xml
index 52c5a49..695270e 100644
--- a/res/layout/work_apps_paused.xml
+++ b/res/layout/work_apps_paused.xml
@@ -15,7 +15,7 @@
<com.android.launcher3.allapps.WorkPausedCard xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:padding="@dimen/work_edu_card_margin"
+ android:padding="@dimen/all_apps_tabs_margin_top"
android:orientation="vertical"
android:gravity="center_horizontal">
@@ -25,7 +25,6 @@
android:id="@+id/work_apps_paused_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="40dp"
android:text="@string/work_apps_paused_title"
android:textAlignment="center"
android:textSize="18sp" />
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 7b97abc..b5e4012 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Tuis"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Verdeelde skerm"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Programinligting vir %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Stoor apppaar"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Raak en hou om \'n legstuk te skuif."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dubbeltik en hou om \'n legstuk te skuif of gebruik gepasmaakte handelinge."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Raak en hou die legstuk om dit op die tuisskerm rond te beweeg"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Voeg by tuisskerm"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-legstuk by tuisskerm gevoeg"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Voorstelle"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# legstuk}other{# legstukke}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# kortpad}other{# kortpaaie}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Persoonlik"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Werk"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Gesprekke"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Neem notas"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Nuttige inligting binne jou bereik"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Jy kan legstukke by jou tuisskerm voeg om inligting te kry sonder om programme oop te maak"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tik om legstukinstellings te verander"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Laat die program toe om die instellings en kortpaaie op tuisskerm te lees."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"skryf tuis-instellings en -kortpaaie"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Laat die program toe om die instellings en kortpaaie op tuisskerm te verander."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> word nie toegelaat om foonoproepe te maak nie"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Kan nie legstuk laai nie"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Legstukinstellings"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Tik om opstelling te voltooi"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Vouer hernoem na <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Vouer: <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">"Vouer: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> of meer items"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Muurpapiere"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Muurpapier en styl"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Wysig tuisskerm"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Tuis-instellings"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Gedeaktiveer deur jou administrateur"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Laat toe dat tuisskerm gedraai word"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Werkprogramme het \'n kenteken en is sigbaar vir jou IT-administrateur"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Het dit"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Werkprogramme is onderbreek"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Jy sal nie kennisgewings van jou werkapps af ontvang nie"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Jou werkprogramme kan nie vir jou kennisgewings stuur, jou battery gebruik of toegang tot jou ligging kry nie"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Werkprogramme is af. Jou werkprogramme kan nie vir jou kennisgewings stuur, jou battery gebruik of toegang tot jou ligging kry nie"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Jy sal nie foonoproepe, SMS’e of kennisgewings van jou werkapps af ontvang nie"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Werkprogramme het \'n kenteken en is sigbaar vir jou IT-administrateur"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Het dit"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Onderbreek werkprogramme"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Skakel werkprogramme aan"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Hervat"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Deursoek jou foon"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Deursoek jou tablet"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 6208fb1..bcc626e 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -20,25 +20,25 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="work_folder_name" msgid="3753320833950115786">"ስራ"</string>
+ <string name="work_folder_name" msgid="3753320833950115786">"ሥራ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"መተግበሪያ አልተጫነም።"</string>
<string name="activity_not_available" msgid="7456344436509528827">"መተግበሪያ አይገኝም"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"የወረደው መተግበሪያ ደህንነቱ በተጠበቀ ሁኔታ ውስጥ ተሰናክሏል"</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"ምግብሮች በደህንነቱ የተጠበቀ ሁኔታ ተሰናክለዋል"</string>
<string name="shortcut_not_available" msgid="2536503539825726397">"አቋራጭ አይገኝም"</string>
<string name="home_screen" msgid="5629429142036709174">"መነሻ"</string>
- <string name="recent_task_option_split_screen" msgid="6690461455618725183">"የተከፈለ ማያ ገጽ"</string>
+ <string name="recent_task_option_split_screen" msgid="6690461455618725183">"የተከፈለ ማያ ገፅ"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"የመተግበሪያ መረጃ ለ%1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"የመተግበሪያ ጥምረትን ያስቀምጡ"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"ምግብርን ለማንቀሳቀስ ይንኩ እና ይያዙ።"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"ምግብርን ለማንቀሳቀስ ወይም ብጁ እርምጃዎችን ለመጠቀም ሁለቴ መታ ያድርጉ እና ይያዙ።"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ስፋት በ%2$d ከፍታ"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"የ<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ምግብር"</string>
- <string name="add_item_request_drag_hint" msgid="8730547755622776606">"በመነሻ ማያ ገጽ አካባቢ ላይ ለማንቀሳቀስ ነክተው ይያዙት"</string>
- <string name="add_to_home_screen" msgid="9168649446635919791">"ወደ መነሻ ማያ ገጽ አክል"</string>
- <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ምግብር ወደ መነሻ ማያ ገጽ ታክሏል"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="add_item_request_drag_hint" msgid="8730547755622776606">"በመነሻ ማያ ገፅ አካባቢ ላይ ለማንቀሳቀስ ነክተው ይያዙት"</string>
+ <string name="add_to_home_screen" msgid="9168649446635919791">"ወደ መነሻ ማያ ገፅ አክል"</string>
+ <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ምግብር ወደ መነሻ ማያ ገፅ ታክሏል"</string>
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"የአስተያየት ጥቆማዎች"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ምግብር}one{# ምግብሮች}other{# ምግብሮች}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# አቋራጭ}one{# አቋራጭ}other{# አቋራጮች}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>፣ <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -48,8 +48,9 @@
<string name="no_widgets_available" msgid="4337693382501046170">"መግብሮች እና አቋራጮች አይገኙም"</string>
<string name="no_search_results" msgid="3787956167293097509">"ምንም መግብሮች ወይም አቋራጮች አልተገኙም"</string>
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"የግል"</string>
- <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ስራ"</string>
+ <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ሥራ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"ውይይቶች"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"የማስታወሻ አያያዝ"</string>
<string name="widget_education_header" msgid="4874760613775913787">"በጣቶችዎ ጫፎች ላይ ጠቃሚ መረጃ"</string>
<string name="widget_education_content" msgid="1731667670753497052">"መተግበሪያዎችን ሳይከፍቱ መረጃ ለማግኘት በመነሻ ማያ ገጽዎ ላይ ምግብሮችን ማከል ይችላሉ"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"የምግብር ቅንብሮችን ለመለወጥ መታ ያድርጉ"</string>
@@ -63,7 +64,7 @@
<string name="notifications_header" msgid="1404149926117359025">"ማሳወቂያዎች"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"አቋራጭን ለማንቀሳቀስ ይንኩ እና ይያዙ"</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"አቋራጭን ለማንቀሳቀስ ወይም ብጁ እርምጃዎችን ለመጠቀም ሁለቴ መታ ያድርጉ እና ይያዙ።"</string>
- <string name="out_of_space" msgid="6455557115204099579">"በዚህ የመነሻ ማያ ገጽ ላይ ምንም ክፍል የለም"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"በዚህ የመነሻ ማያ ገፅ ላይ ምንም ክፍል የለም"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"በተወዳጆች መሣቢያ ውስጥ ተጨማሪ ቦታ የለም"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"የመተግበሪያዎች ዝርዝር"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"የፍለጋ ውጤቶች"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"ቅንብሮችን እና አቋራጮችን በመነሻ ለማንበብ ለትግበራ ይፈቅዳል።"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"መነሻ ቅንብሮች እና አቋራጮች ጻፍ"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"ቅንብሮችን እና አቋራጮችን በመነሻ ለመለወጥ ለመተግበሪያ ይፈቅዳል።"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> የስልክ ጥሪዎችን ለማድረግ አልተፈቀደለትም"</string>
<string name="gadget_error_text" msgid="740356548025791839">"ምግብርን መጫን አልተቻለም"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"የምግብር ቅንብሮች"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"ማዋቀርን ለመጨረስ መታ ያድርጉ"</string>
@@ -89,9 +89,9 @@
<string name="folder_hint_text" msgid="5174843001373488816">"ስም ያርትዑ"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> ተሰናክሏል"</string>
<string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name}፣ # ማሳወቂያ አለው}one{{app_name}፣ # ማሳወቂያዎች አሉት}other{{app_name}፣ # ማሳወቂያዎች አሉት}}"</string>
- <string name="default_scroll_format" msgid="7475544710230993317">"ገጽ %1$d ከ%2$d"</string>
- <string name="workspace_scroll_format" msgid="8458889198184077399">"መነሻ ማያ ገጽ %1$d ከ%2$d"</string>
- <string name="workspace_new_page" msgid="257366611030256142">"አዲስ የመነሻ ማያ ገጽ"</string>
+ <string name="default_scroll_format" msgid="7475544710230993317">"ገፅ %1$d ከ%2$d"</string>
+ <string name="workspace_scroll_format" msgid="8458889198184077399">"መነሻ ማያ ገፅ %1$d ከ%2$d"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"አዲስ የመነሻ ማያ ገፅ"</string>
<string name="folder_opened" msgid="94695026776264709">"አቃፊ ተከፍቷል፣ <xliff:g id="WIDTH">%1$d</xliff:g> በ<xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="4625795376335528256">"አቃፊን ለመዝጋት መታ ያድርጉ"</string>
<string name="folder_tap_to_rename" msgid="4017685068016979677">"ዳግም የተሰጠውን ስም ለማስቀመጥ መታ ያድርጉ"</string>
@@ -99,11 +99,11 @@
<string name="folder_renamed" msgid="1794088362165669656">"አቃፊ <xliff:g id="NAME">%1$s</xliff:g> ተብሎ ዳግም ተሰይሟል"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"አቃፊ፦ <xliff:g id="NAME">%1$s</xliff:g>፣ <xliff:g id="SIZE">%2$d</xliff:g> ንጥሎች"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"አቃፊ፦ <xliff:g id="NAME">%1$s</xliff:g>፣ <xliff:g id="SIZE">%2$d</xliff:g> ወይም ተጨማሪ ንጥሎች"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"የግድግዳ ወረቀቶች"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ልጣፍ እና ቅጥ"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"መነሻ ማያ ገጽን አርትዕ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"የመነሻ ቅንብሮች"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"በእርስዎ አስተዳዳሪ የተሰናከለ"</string>
- <string name="allow_rotation_title" msgid="7222049633713050106">"የመነሻ ማያ ገጽ ማሽከርከርን ይፍቀዱ"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"የመነሻ ማያ ገፅ ማሽከርከርን ይፍቀዱ"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ስልኩ ሲዞር"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"የማሳወቂያ ነጥቦች"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"አብራ"</string>
@@ -129,9 +129,9 @@
<string name="dialog_remove" msgid="6510806469849709407">"አስወግድ"</string>
<string name="widgets_list" msgid="796804551140113767">"የመግብሮች ዝርዝር"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"የመግብሮች ዝርዝር ተዘግቷል"</string>
- <string name="action_add_to_workspace" msgid="215894119683164916">"ወደ መነሻ ማያ ገጽ አክል"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"ወደ መነሻ ማያ ገፅ አክል"</string>
<string name="action_move_here" msgid="2170188780612570250">"ንጥልን ወደዚህ ውሰድ"</string>
- <string name="item_added_to_workspace" msgid="4211073925752213539">"ወደ መነሻ ማያ ገጽ ንጥል ታክሏል"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"ወደ መነሻ ማያ ገፅ ንጥል ታክሏል"</string>
<string name="item_removed" msgid="851119963877842327">"ንጥል ነገር ተንቀሳቅሷል"</string>
<string name="undo" msgid="4151576204245173321">"ቀልብስ"</string>
<string name="action_move" msgid="4339390619886385032">"ንጥልን አንቀሳቅስ"</string>
@@ -144,7 +144,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"ንጥል ወደ አቃፊ ታክሏል"</string>
<string name="create_folder_with" msgid="4050141361160214248">"አቃፊ ፍጠር ከዚህ ጋር፦ <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"አቃፊ ተፈጥሮዋል"</string>
- <string name="action_move_to_workspace" msgid="39528912300293768">"ወደ መነሻ ማያ ገጽ አንቀሳቅስ"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"ወደ መነሻ ማያ ገፅ አንቀሳቅስ"</string>
<string name="action_resize" msgid="1802976324781771067">"መጠን ቀይር"</string>
<string name="action_increase_width" msgid="8773715375078513326">"ስፋት ጨምር"</string>
<string name="action_increase_height" msgid="459390020612501122">"ቁመት ጨምር"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"የሥራ መተግበሪያዎች ባጅ የተደረገባቸው እና ለእርስዎ የአይቲ አስተዳዳሪ የሚታዩ ናቸው"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"ገባኝ"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"የስራ መተግበሪያዎች ባሉበት ቆመዋል"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"ከሥራ መተግበሪያዎችዎ ማሳወቂያዎች አይደርሱዎትም"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"የስራ መተግበሪያዎችዎ ማሳወቂያዎችን ሊልክልዎ፣ ባትሪዎን መጠቀም ወይም አካባቢዎን መድረስ አይችሉም"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"የሥራ መተግበሪያዎች ጠፍተዋል። የስራ መተግበሪያዎችዎ ማሳወቂያዎችን ሊልክልዎ፣ ባትሪዎን መጠቀም ወይም አካባቢዎን መድረስ አይችሉም"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"ከሥራ መተግበሪያዎችዎ የስልክ ጥሪዎች፣ ኤስኤምኤሶች ወይም ማሳወቂያዎች አይደርሱዎትም"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"የሥራ መተግበሪያዎች ባጅ የተደረገባቸው ሲሆን ለእርስዎ IT ቡድን ታይ ናቸው"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"ገባኝ"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"የሥራ መተግበሪያዎችን ባሉበት አቁም"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"የሥራ መተግበሪያዎችን ያብሩ"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"ካቆመበት ቀጥል"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"አጣራ"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"ስልክዎን ይፈልጉ"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"ጡባዊዎን ይፈልጉ"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index a38fe0b..69e96cb 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"الشاشة الرئيسية"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"تقسيم الشاشة"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"معلومات تطبيق %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"حفظ إعدادات ميزة \"استخدام تطبيقين في الوقت نفسه\""</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"انقر مع الاستمرار لنقل أداة."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"انقر مرتين مع تثبيت إصبعك لنقل أداة أو استخدام الإجراءات المخصّصة."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"انقر مع الاستمرار على التطبيق المصغّر لنقله إلى الشاشة الرئيسية."</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"إضافة إلى الشاشة الرئيسية"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"تمت إضافة الأداة <xliff:g id="WIDGET_NAME">%1$s</xliff:g> إلى الشاشة الرئيسية."</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"اقتراحات"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{تطبيق مصغّر واحد}zero{# تطبيق مصغّر}two{تطبيقان مصغّران}few{# تطبيقات مصغّرة}many{# تطبيقًا مصغّرًا}other{# تطبيق مصغّر}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{اختصار واحد}zero{# اختصار}two{اختصاران}few{# اختصارات}many{# اختصارًا}other{# اختصار}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>، <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -47,9 +47,10 @@
<string name="widgets_full_sheet_cancel_button_description" msgid="5766167035728653605">"محو النص من مربّع البحث"</string>
<string name="no_widgets_available" msgid="4337693382501046170">"الأدوات والاختصارات غير متاحة."</string>
<string name="no_search_results" msgid="3787956167293097509">"لم يتم العثور على تطبيقات مصغّرة أو اختصارات."</string>
- <string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"الأدوات الشخصية"</string>
- <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"أدوات العمل"</string>
+ <string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"التطبيقات الشخصية"</string>
+ <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"تطبيقات العمل"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"المحادثات"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"تدوين الملاحظات"</string>
<string name="widget_education_header" msgid="4874760613775913787">"معلومات مفيدة في متناول يديك"</string>
<string name="widget_education_content" msgid="1731667670753497052">"للحصول على معلومات بدون فتح التطبيقات، يمكنك إضافة التطبيقات المصغّرة إلى الشاشة الرئيسية."</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"انقر لتغيير إعدادات الأداة"</string>
@@ -81,9 +82,8 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"يسمح هذا الإذن للتطبيق بالاطلاع على الإعدادات والاختصارات على الشاشة الرئيسية."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"تعديل الإعدادات والاختصارات على الشاشة الرئيسية"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"يسمح هذا الإذن للتطبيق بتغيير الإعدادات والاختصارات على الشاشة الرئيسية."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> غير مسموح به لإجراء مكالمات هاتفية"</string>
<string name="gadget_error_text" msgid="740356548025791839">"يتعذّر تحميل الأداة."</string>
- <string name="gadget_setup_text" msgid="8348374825537681407">"إعدادات الأداة"</string>
+ <string name="gadget_setup_text" msgid="8348374825537681407">"إعدادات التطبيق المصغّر"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"انقر لإكمال الإعداد."</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"هذا تطبيق نظام وتتعذر إزالته."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"تعديل الاسم"</string>
@@ -99,14 +99,14 @@
<string name="folder_renamed" msgid="1794088362165669656">"تمت إعادة تسمية المجلد إلى <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"المجلد: <xliff:g id="NAME">%1$s</xliff:g>، <xliff:g id="SIZE">%2$d</xliff:g> عنصر"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"المجلد: <xliff:g id="NAME">%1$s</xliff:g>، <xliff:g id="SIZE">%2$d</xliff:g> عنصر أو أكثر"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"الخلفيات"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"الخلفية والأسلوب"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"تعديل الشاشة الرئيسية"</string>
<string name="settings_button_text" msgid="8873672322605444408">"إعدادات الشاشة الرئيسية"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"أوقف المشرف هذه الميزة"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"السماح بتدوير الشاشة الرئيسية"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"عند تدوير الهاتف"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"نقاط الإشعارات"</string>
- <string name="notification_dots_desc_on" msgid="1679848116452218908">"مفعّلة"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"الإعداد مفعّل"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"غير مفعّل"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"يلزم تمكين الوصول إلى الإشعارات"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"لعرض نقاط الإشعارات، يجب تفعيل إشعارات التطبيق في <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -159,15 +159,16 @@
<string name="all_apps_personal_tab" msgid="4190252696685155002">"شخصية"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"للعمل"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"الملف الشخصي للعمل"</string>
- <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"تحمل تطبيقات العمل شارة وتكون مرئية لمشرف تكنولوجيا المعلومات."</string>
+ <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"تحمل تطبيقات العمل مميّزة بشارة ومرئية لمشرف تكنولوجيا المعلومات."</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"حسنًا"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"تطبيقات العمل متوقفة مؤقتًا"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"لن تتلقّى إشعارات من تطبيقات العمل."</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"لا يمكن لتطبيقات العمل إرسال إشعارات إليك أو استخدام بطاريتك أو الوصول إلى موقعك الجغرافي."</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"تطبيقات العمل غير مفعّلة، وبالتالي لا يمكنها إرسال إشعارات إليك أو استخدام بطاريتك أو الوصول إلى موقعك الجغرافي."</string>
- <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"تحمل تطبيقات العمل شارة وتكون مرئية لمشرف تكنولوجيا المعلومات."</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"لن تتلقّى مكالمات هاتفية أو رسائل نصية أو إشعارات من تطبيقات العمل."</string>
+ <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"تكون تطبيقات العمل مميّزة بشارة ومرئية لمشرف تكنولوجيا المعلومات."</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"حسنًا"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"إيقاف تطبيقات العمل مؤقتًا"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"تفعيل تطبيقات العمل"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"إلغاء الإيقاف المؤقت"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"فلتر"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"البحث في هاتفك"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"البحث في جهازك اللوحي"</string>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 3a67edb..8c18e8d 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"গৃহ স্ক্ৰীন"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"বিভাজিত স্ক্ৰীন"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$sৰ বাবে এপৰ তথ্য"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"এপৰ পেয়াৰ ছেভ কৰক"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"ৱিজেট স্থানান্তৰ কৰিবলৈ টিপি ধৰি ৰাখক।"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"কোনো ৱিজেট স্থানান্তৰ কৰিবলৈ দুবাৰ টিপি ধৰি ৰাখক অথবা কাষ্টম কাৰ্য ব্যৱহাৰ কৰক।"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"ৱিজেটটো গৃহ স্ক্ৰীনৰ আশে-পাশে নিবলৈ সেইটোত স্পৰ্শ কৰি ধৰি ৰাখক"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"গৃহ স্ক্ৰীনত যোগ কৰক"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ৱিজেটটো গৃহ স্ক্ৰীনত যোগ দিয়া হৈছে"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"পৰামৰ্শ"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# টা ৱিজেট}one{# টা ৱিজেট}other{# টা ৱিজেট}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# টা শ্বৰ্টকাট}one{# টা শ্বৰ্টকাট}other{# টা শ্বৰ্টকাট}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,13 +50,14 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"ব্যক্তিগত"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"কৰ্মস্থান"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"বাৰ্তালাপ"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"টোকা গ্ৰহণ কৰা"</string>
<string name="widget_education_header" msgid="4874760613775913787">"আপোনাৰ আঙুলিৰে টিপতে উপযোগী তথ্য পাওক"</string>
<string name="widget_education_content" msgid="1731667670753497052">"এপ্ নোখোলাকৈ তথ্য পাবলৈ আপুনি নিজৰ গৃহ স্ক্ৰীনত ৱিজেট যোগ দিব পাৰে"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ৱিজেটৰ ছেটিং সলনি কৰিবলৈ টিপক"</string>
<string name="widget_education_close_button" msgid="8676165703104836580">"বুজি পালোঁ"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"ৱিজেটৰ ছেটিং সলনি কৰক"</string>
- <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"এপসমূহ সন্ধান কৰক"</string>
- <string name="all_apps_loading_message" msgid="5813968043155271636">"এপসমূহ ল’ড কৰি থকা হৈছে…"</string>
+ <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"এপ্সমূহ সন্ধান কৰক"</string>
+ <string name="all_apps_loading_message" msgid="5813968043155271636">"এপ্সমূহ ল’ড কৰি থকা হৈছে…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\"ৰ সৈতে মিলা কোনো এপ্ বিচাৰি পোৱা নগ\'ল"</string>
<string name="label_application" msgid="8531721983832654978">"এপ্"</string>
<string name="all_apps_label" msgid="5015784846527570951">"আটাইবোৰ এপ্"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"এপ্টোক গৃহ স্ক্ৰীনত ছেটিং আৰু শ্বৰ্টকাটসমূহ পঢ়াৰ অনুমতি দিয়ে।"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"গৃহ স্ক্ৰীনত ছেটিং আৰু শ্বৰ্টকাটসমূহ লিখা"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"এপ্টোক গৃহ স্ক্ৰীনত ছেটিং আৰু শ্বৰ্টকাটসমূহ সলনি কৰাৰ অনুমতি দিয়ে।"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g>ক ফ\'ন কলবোৰ কৰাৰ অনুমতি দিয়া হোৱা নাই"</string>
<string name="gadget_error_text" msgid="740356548025791839">"ৱিজেট ল’ড কৰিব নোৱাৰি"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"ৱিজেটৰ ছেটিং"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"ছেটআপ সমাপ্ত কৰিবলৈ টিপক"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"ফ\'ল্ডাৰৰ নাম সলনি কৰি <xliff:g id="NAME">%1$s</xliff:g> কৰা হৈছে"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"ফ’ল্ডাৰ: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> টা বস্তু"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ফ’ল্ডাৰ: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> টা অথবা তাতকৈ অধিক বস্তু"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"ৱালপেপাৰসমূহ"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ৱালপেপাৰ আৰু শৈলী"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"গৃহ স্ক্ৰীন সম্পাদনা কৰক"</string>
<string name="settings_button_text" msgid="8873672322605444408">"গৃহ ছেটিং"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"আপোনাৰ প্ৰশাসকে অক্ষম কৰি ৰাখিছে"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"গৃহ স্ক্ৰীন ঘূৰোৱাৰ অনুমতি দিয়ক"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"কৰ্মস্থানৰ এপ্সমূহ প্ৰতীকেৰে চিহ্নিত কৰা হয় আৰু সেইবোৰ আপোনাৰ আইটি প্ৰশাসকৰ বাবে দৃশ্যমান হয়"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"বুজি পালোঁ"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"কৰ্মস্থানৰ এপ্সমূহ পজ হৈ আছে"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"আপুনি আপোনাৰ কৰ্মস্থানৰ এপ্সমূহৰ পৰা জাননী নাপাব"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"আপোনাৰ কৰ্মস্থানৰ এপ্সমূহে আপোনালৈ জাননী পঠিয়াব, আপোনাৰ বেটাৰী ব্যৱহাৰ কৰিব অথবা আপোনাৰ অৱস্থান এক্সেছ কৰিব নোৱাৰে"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"কৰ্মস্থানৰ এপ্সমূহ অফ হৈ আছে। আপোনাৰ কৰ্মস্থানৰ এপ্সমূহে আপোনালৈ জাননী পঠিয়াব, আপোনাৰ বেটাৰী ব্যৱহাৰ কৰিব অথবা আপোনাৰ অৱস্থান এক্সেছ কৰিব নোৱাৰে"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"আপুনি আপোনাৰ কৰ্মস্থানৰ এপ্সমূহৰ পৰা ফ’ন কল, পাঠ বাৰ্তা অথবা জাননী নাপাব"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"কর্মস্থানৰ এপ্সমূহ প্ৰতীকেৰে চিহ্নিত কৰা হয় আৰু সেইবোৰ আপোনাৰ আইটি প্ৰশাসকৰ বাবে দৃশ্যমান হয়"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"বুজি পালোঁ"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"কৰ্মস্থানৰ এপ্ পজ কৰক"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"কৰ্মস্থানৰ এপ্সমূহ অন কৰক"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"আনপজ কৰক"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"ফিল্টাৰ"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"আপোনাৰ ফ’নৰ বস্তু সন্ধান কৰক"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"আপোনাৰ টেবলেটৰ বস্তু সন্ধান কৰক"</string>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 326ac68..bf12761 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Əsas səhifə"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ekran bölünməsi"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ilə bağlı tətbiq məlumatı"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Tətbiq cütünü saxlayın"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Vidceti daşımaq üçün toxunub saxlayın."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Vidceti daşımaq üçün iki dəfə toxunub saxlayın və ya fərdi əməliyyatlardan istifadə edin."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Əsas ekranda hərəkət etdirmək üçün vidcetə toxunub saxlayın"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Əsas ekrana əlavə edin"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidceti əsas ekrana əlavə edildi"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Təkliflər"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# vidcet}other{# vidcet}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# qısayol}other{# qısayol}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Şəxsi"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"İş"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Söhbətlər"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Qeydgötürmə"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Faydalı məlumatlar barmaqlarınızın ucunda"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Tətbiqləri açmadan məlumat almaq üçün Əsas ekrana vidcet əlavə edə bilərsiniz"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Vidcet ayarlarını dəyişmək üçün toxunun"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Tətbiqə Əsas səhifədə ayarları və qısayolları oxumağa icazə verir."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"Əsas səhifə ayarlarını və qısayollarını yazmaq"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Tətbiqə Əsas səhifədə ayarları və qısayolları dəyişməyə icazə verir."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqinə telefon zəngləri etmək üçün icazə verilmir"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Vidceti yükləmək olmur"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Vidcet ayarları"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Ayarlamanı tamamlamaq üçün toxunun"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Qovluq adı <xliff:g id="NAME">%1$s</xliff:g> ilə dəyişdirildi"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Qovluq: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> element"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Qovluq: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> və ya daha çox element"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Divar kağızları"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Divar kağızı və üslub"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Əsas ekranı redaktə edin"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Home ayarları"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Admininiz tərəfindən deaktiv edilib"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Əsas ekran çevrilsin"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"İş tətbiqləri nişanlanıb və İT administratorunuza görünür"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Anladım"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"İş tətbiqlərinə pauza verilib"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"İş tətbiqlərindən bildiriş almayacaqsınız"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"İş tətbiqləriniz sizə bildirişlər göndərə, batareyanızdan istifadə edə və ya məkanınıza daxil ola bilməz"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"İş tətbiqləri deaktivdir. İş tətbiqləriniz sizə bildirişlər göndərə, batareyanızdan istifadə edə və ya məkanınıza daxil ola bilməz"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"İş tətbiqlərindən telefon zəngi, mətn mesajı və ya bildiriş almayacaqsınız"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"İş tətbiqləri nişanlanıb və İT administratorunuza görünür"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Anladım"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"İş tətbiqlərini durdurun"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"İş tətbiqlərini aktiv edin"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Davam etdirin"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtr"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Telefonunuzu axtarın"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Planşetinizi axtarın"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index fc656bd..cfb6fbd 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Početni ekran"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Podeljeni ekran"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacije o aplikaciji za: %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Sačuvaj par aplikacija"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Dodirnite i zadržite radi pomeranja vidžeta."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvaput dodirnite i zadržite da biste pomerali vidžet ili koristite prilagođene radnje."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Dodirnite i zadržite vidžet da biste ga pomerali po početnom ekranu"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Dodaj na početni ekran"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Dodali ste vidžet <xliff:g id="WIDGET_NAME">%1$s</xliff:g> na početni ekran"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Predlozi"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# vidžet}one{# vidžet}few{# vidžeta}other{# vidžeta}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# prečica}one{# prečica}few{# prečice}other{# prečica}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Lično"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Posao"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Konverzacije"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Pravljenje beležaka"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Korisne informacije nadohvat ruke"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Da biste pronašli informacije bez otvaranja aplikacija, možete da dodate vidžete na početni ekran"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Dodirnite da biste promenili podešavanja vidžeta"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Dozvoljava aplikaciji da čita podešavanja i prečice na početnom ekranu."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"upisivanje podešavanja i prečica na početnom ekranu"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Dozvoljava aplikaciji da menja podešavanja i prečice na početnom ekranu."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> nema dozvolu za upućivanje telefonskih poziva"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Učitavanje vidžeta nije uspelo"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Podešavanja vidžeta"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Dodirnite da biste dovršili podešavanje"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Folder je preimenovan u <xliff:g id="NAME">%1$s</xliff:g>"</string>
<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> stavke"</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> ili više stavki"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Pozadine"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Pozadina i stil"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Izmeni početni ekran"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Podešavanja početnog ekrana"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administrator je onemogućio"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Dozvoli rotaciju početnog ekrana"</string>
@@ -156,18 +156,19 @@
<string name="action_dismiss_notification" msgid="5909461085055959187">"Odbaci"</string>
<string name="accessibility_close" msgid="2277148124685870734">"Zatvori"</string>
<string name="notification_dismissed" msgid="6002233469409822874">"Obaveštenje je odbačeno"</string>
- <string name="all_apps_personal_tab" msgid="4190252696685155002">"Lične"</string>
- <string name="all_apps_work_tab" msgid="4884822796154055118">"Poslovne"</string>
+ <string name="all_apps_personal_tab" msgid="4190252696685155002">"Lično"</string>
+ <string name="all_apps_work_tab" msgid="4884822796154055118">"Posao"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Poslovni profil"</string>
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Poslovne aplikacije su označene značkom i IT administrator može da ih vidi"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Važi"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Poslovne aplikacije su pauzirane"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Nećete dobijati obaveštenja iz poslovnih aplikacija"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Poslovne aplikacije ne mogu da vam šalju obaveštenja, koriste bateriju niti pristupaju lokaciji"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Poslovne aplikacije su isključene. Poslovne aplikacije ne mogu da vam šalju obaveštenja, koriste bateriju niti pristupaju lokaciji"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Nećete primati telefonske pozive, tekstualne poruke niti obaveštenja iz poslovnih aplikacija"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Poslovne aplikacije su označene značkom i IT administrator može da ih vidi"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Važi"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pauziraj poslovne aplikacije"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Uključi poslovne aplikacije"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Ponovo aktiviraj"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Pretražite telefon"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Pretražite tablet"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index d5097c3..5950ec5 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Галоўны экран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Падзелены экран"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Інфармацыя пра праграму для: %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Захаваць спалучэнне праграм"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Націсніце і ўтрымлівайце віджэт для перамяшчэння."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Дакраніцеся двойчы і ўтрымлівайце, каб перамясціць віджэт або выкарыстоўваць спецыяльныя дзеянні."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Утрымліваючы віджэт націснутым, перамяшчайце яго па галоўным экране"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Дадаць на галоўны экран"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Віджэт \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\" дададзены на галоўны экран"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Прапановы"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# віджэт}one{# віджэт}few{# віджэты}many{# віджэтаў}other{# віджэта}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ярлык}one{# ярлык}few{# ярлыкі}many{# ярлыкоў}other{# ярлыка}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Асабістыя"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Працоўныя"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Размовы"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Стварэнне нататак"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Карысная інфармацыя ў вас пад рукой"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Каб не адкрываць праграмы для прагляду патрэбнай інфармацыі, дадайце віджэты на галоўны экран"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Націсніце, каб змяніць налады віджэта"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Дазваляе праграме счытваць налады і ярлыкі на галоўным экране."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"запісваць налады і ярлыкі на галоўны экран"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Дазваляе праграме змяняць налады і ярлыкі на галоўным экране."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> не мае дазволу на здзяйсненне тэлефонных званкоў"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Не ўдаецца загрузіць віджэт"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Налады віджэта"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Націсніце, каб завяршыць наладжванне"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Папка перайменавана ў <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Папка: <xliff:g id="NAME">%1$s</xliff:g>, элементы: <xliff:g id="SIZE">%2$d</xliff:g>"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Папка: <xliff:g id="NAME">%1$s</xliff:g>, элементы: <xliff:g id="SIZE">%2$d</xliff:g> ці больш"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Шпалеры"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Шпалеры і стыль"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Змяніць Галоўны экран"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Налады галоўнага экрана"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Адключаная адміністратарам"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Дазволіць паварот галоўнага экрана"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Працоўныя праграмы пазначаны спецыяльнымі значкамі, а таксама бачныя IT-адміністратару"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Зразумела"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Працоўныя праграмы прыпынены"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Вы не будзеце атрымліваць апавяшчэнні ад працоўных праграм"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Працоўныя праграмы не могуць адпраўляць вам апавяшчэнні, выкарыстоўваць акумулятар або атрымліваць доступ да даных пра ваша месцазнаходжанне"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Працоўныя праграмы выключаны. Яны не могуць адпраўляць вам апавяшчэнні, выкарыстоўваць акумулятар або атрымліваць доступ да вашага месцазнаходжання"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Вы не будзеце атрымліваць выклікі, тэкставыя паведамленні або апавяшчэнні ад працоўных праграм"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Працоўныя праграмы пазначаны спецыяльнымі значкамі, а таксама бачныя IT-адміністратару"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Зразумела"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Прыпыніць працоўныя праграмы"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Уключыць працоўныя праграмы"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Актываваць"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Фільтр"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Пошук на тэлефоне"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Пошук на планшэце"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index ff40365..b0f1c4c 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Начален екран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Разделен екран"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Информация за приложението за %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Запазване на двойката приложения"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Докоснете и задръжте за преместване на приспособление"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Докоснете двукратно и задръжте за преместване на приспособление или използвайте персонал. действия."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Докоснете приспособлението и го задръжте, за да го местите на началния екран"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Добавяне към началния екран"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Приспособлението <xliff:g id="WIDGET_NAME">%1$s</xliff:g> е добавено към началния екран"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Предложения"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# приспособление}other{# приспособления}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# пряк път}other{# преки пътя}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Лични"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Служебни"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Разговори"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Водене на бележки"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Лесен достъп до полезна информация"</string>
<string name="widget_education_content" msgid="1731667670753497052">"За да получавате информация, без да отваряте приложенията, можете да добавите приспособления към началния екран"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Докоснете, за да промените настройките на приспособлението"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Разрешава на приложението да чете настройките и преките пътища на началния екран."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"запис на настройките и преките пътища на началния екран"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Разрешава на приложението да променя настройките и преките пътища на началния екран."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> няма разрешение да извършва телефонни обаждания"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Приспособлението не може да се зареди"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Настройки за приспособленията"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Докоснете, за да завършите настройването"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Папката е преименувана на „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Папка: „<xliff:g id="NAME">%1$s</xliff:g>“ – <xliff:g id="SIZE">%2$d</xliff:g> елемента"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Папка: „<xliff:g id="NAME">%1$s</xliff:g>“ – <xliff:g id="SIZE">%2$d</xliff:g> или повече елементи"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Тапети"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Тапет и стил"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Редактиране на началния екран"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Настройки за началния екран"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Деактивирано от администратора ви"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Разрешаване на завъртането на началния екран"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Служебните приложения са означени със значка и са видими за системния администратор"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Разбрах"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Служебните приложения са поставени на пауза"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Няма да получавате известия от служебните си приложения"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Служебните ви приложения не могат да ви изпращат известия, да използват батерията или да осъществяват достъп до местоположението ви"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Служебните ви приложения са изключени. Те не могат да ви изпращат известия, да използват батерията или да осъществяват достъп до местоположението ви"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Няма да получавате телефонни обаждания, текстови съобщения и известия от служебните си приложения"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Служебните приложения са означени със значка и са видими за системния администратор"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Разбрах"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Поставяне на пауза на служебните приложения"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Включване на служебните приложения"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Отмяна на паузата"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Филтър"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Търсене в телефона ви"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Търсене в таблета ви"</string>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 509c68a..e28638b 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"হোম"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"স্প্লিট স্ক্রিন"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s-এর জন্য অ্যাপ সম্পর্কিত তথ্য"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"অ্যাপ পেয়ার সেভ করুন"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"কোনও উইজেট সরাতে সেটি টাচ করে ধরে রাখুন।"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"একটি উইজেট সরাতে বা কাস্টম অ্যাকশন ব্যবহার করতে ডবল ট্যাপ করে ধরে রাখুন।"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"হোম স্ক্রিনের যেকোনও জায়গায় নিয়ে যেতে, উইজেট টাচ করে ধরে থাকুন"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"হোম স্ক্রিনে যোগ করুন"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> উইজেট হোম স্ক্রিনে যোগ করা হয়েছে"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"সাজেশন"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{#টি উইজেট}one{#টি উইজেট}other{#টি উইজেট}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{#টি শর্টকাট}one{#টি শর্টকাট}other{#টি শর্টকাট}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"ব্যক্তিগত"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"অফিস"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"কথোপকথন"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"নোট নেওয়া"</string>
<string name="widget_education_header" msgid="4874760613775913787">"সহজেই দরকারি তথ্য পান"</string>
<string name="widget_education_content" msgid="1731667670753497052">"অ্যাপ না খুলেই তথ্য পাওয়ার জন্য, হোম স্ক্রিনে উইজেট যোগ করতে পারবেন"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"উইজেট সেটিংস পরিবর্তন করতে ট্যাপ করুন"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"অ্যাপকে হোম স্ক্রিনে সেটিংস ও শর্টকাট পড়ার অনুমতি দেয়।"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"হোম স্ক্রিনে সেটিংস ও শর্টকাট লিখুন"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"অ্যাপকে হোম স্ক্রিনে সেটিংস ও শর্টকাট পরিবর্তন করার অনুমতি দেয়।"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"ফোন কলগুলি করার জন্য <xliff:g id="APP_NAME">%1$s</xliff:g> এর অনুমতি নেই"</string>
<string name="gadget_error_text" msgid="740356548025791839">"উইজেট লোড করা যাচ্ছে না"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"উইজেট সেটিংস"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"সেটআপ সম্পূর্ণ করতে ট্যাপ করুন"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"ফোল্ডারের নাম পাল্টে <xliff:g id="NAME">%1$s</xliff:g> করা হয়েছে"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"ফোল্ডার: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g>টি আইটেম"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ফোল্ডার: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g>টি বা তার বেশি আইটেম"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"ওয়ালপেপারগুলি"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ওয়ালপেপার এবং স্টাইল"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"হোম স্ক্রিন এডিট করুন"</string>
<string name="settings_button_text" msgid="8873672322605444408">"হোম সেটিংস"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"আপনার প্রশাসক দ্বারা অক্ষম করা হয়েছে"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"হোম স্ক্রিন রোটেট করার অনুমতি দিন"</string>
@@ -159,15 +159,16 @@
<string name="all_apps_personal_tab" msgid="4190252696685155002">"ব্যক্তিগত"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"অফিস"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"অফিসের প্রোফাইল"</string>
- <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"অফিসের অ্যাপে ব্যাজ যোগ করা হয়েছে এবং আপনার আইটি অ্যাডমিন সেটি দেখতে পাবেন"</string>
+ <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"অফিস অ্যাপে ব্যাজ যোগ করা হয়েছে এবং আপনার আইটি অ্যাডমিন সেগুলি দেখতে পাবেন"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"বুঝেছি"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"অফিস অ্যাপ বন্ধ করা আছে"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"আপনার অফিসের অ্যাপ থেকে আপনি কোনও বিজ্ঞপ্তি পাবেন না"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"অফিসের অ্যাপ আপনাকে নোটিফিকেশন পাঠাতে পারবে না। এছাড়া, ব্যাটারি ব্যবহার করতে বা লোকেশন অ্যাক্সেস করতে পারবে না"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"অফিসের অ্যাপ বন্ধ আছে। আপনার অফিসের অ্যাপ আপনাকে বিজ্ঞপ্তি পাঠাতে, ব্যাটারি ব্যবহার করতে বা লোকেশন অ্যাক্সেস করতে পারবে না"</string>
- <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"অফিসের অ্যাপে ব্যাজ যোগ করা হয়েছে এবং আপনার আইটি অ্যাডমিন সেটি দেখতে পাবেন"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"আপনি কোনও ফোন কল, টেক্সট মেসেজ বা অফিসের অ্যাপ থেকে বিজ্ঞপ্তি পাবেন না"</string>
+ <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"অফিসের অ্যাপে ব্যাজ যোগ করা হয়েছে এবং আপনার আইটি অ্যাডমিন সেগুলি দেখতে পাবেন"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"বুঝেছি"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"অফিসের অ্যাপ পজ করুন"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"অফিস অ্যাপ চালু করুন"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"আনপজ করুন"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"ফিল্টার"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"ফোনে সার্চ করে দেখুন"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"আপনার ট্যাবলেটে সার্চ করুন"</string>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 46bac11..8387f14 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Početni ekran"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Podijeljeni ekran"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacije o aplikaciji %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Sačuvaj par aplikacija"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Dodirnite i zadržite da pomjerite vidžet."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvaput dodirnite i zadržite da pomjerite vidžet ili da koristite prilagođene radnje."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -49,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Lično"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Posao"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Razgovori"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Pisanje bilješki"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Korisne informacije nadohvat ruke"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Da dobijete informacije bez otvaranja aplikacija, možete dodati vidžete na početni ekran"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Dodirnite da promijenite postavke vidžeta"</string>
@@ -80,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Dopušta aplikaciji čitanje postavki i prečica na početnom ekranu."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"zapisuje postavke na početnom ekranu i prečice"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Dopušta aplikaciji promjenu postavki i prečica na početnom ekranu."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> nema odobrenje da uspostavlja telefonske pozive"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Nije moguće učitati vidžet"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Postavke vidžeta"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Dodirnite da završite postavljanje"</string>
@@ -98,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Ime foldera je promijenjeno u <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Folder: <xliff:g id="NAME">%1$s</xliff:g>, br. stavki: <xliff:g id="SIZE">%2$d</xliff:g>"</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> ili više stavki"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Pozadinske slike"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Pozadinska slika i stil"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Uredi Početni ekran"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Postavke početnog ekrana"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogućio vaš administrator"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Dozvoli rotiranje početnog ekrana"</string>
@@ -155,18 +156,19 @@
<string name="action_dismiss_notification" msgid="5909461085055959187">"Odbaci"</string>
<string name="accessibility_close" msgid="2277148124685870734">"Zatvaranje"</string>
<string name="notification_dismissed" msgid="6002233469409822874">"Obavještenje je odbačeno"</string>
- <string name="all_apps_personal_tab" msgid="4190252696685155002">"Lične"</string>
- <string name="all_apps_work_tab" msgid="4884822796154055118">"Poslovne"</string>
+ <string name="all_apps_personal_tab" msgid="4190252696685155002">"Lično"</string>
+ <string name="all_apps_work_tab" msgid="4884822796154055118">"Poslovno"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Radni profil"</string>
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Poslovne aplikacije su označene i vaš IT administrator ih može vidjeti"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Razumijem"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Poslovne aplikacije su pauzirane"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Nećete primati obavještenja iz poslovnih aplikacija"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Poslovne aplikacije vam ne mogu slati obavještenja, koristiti bateriju niti pristupiti vašoj lokaciji"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Poslovne aplikacije su isključene. Poslovne aplikacije vam ne mogu slati obavještenja, koristiti bateriju ili pristupiti vašoj lokaciji"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Nećete primati telefonske pozive, poruke ili obavještenja iz poslovnih aplikacija"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Poslovne aplikacije su označene i vaš IT administrator ih može vidjeti"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Razumijem"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pauziraj poslovne aplikacije"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Uključi poslovne aplikacije"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Ponovo pokreni"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrirajte"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Pretražite telefon"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Pretražite tablet"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 739bd98..dd2d03f 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Inici"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantalla dividida"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informació de l\'aplicació %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Desa la parella d\'aplicacions"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Fes doble toc i mantén premut per moure un widget."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Fes doble toc i mantén premut per moure un widget o per utilitzar accions personalitzades."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Mantén premut el widget per moure\'l per la pantalla d\'inici"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Afegeix a la pantalla d\'inici"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"El widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> s\'ha afegit a la pantalla d\'inici"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggeriments"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# drecera}other{# dreceres}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personal"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Treball"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Converses"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Presa de notes"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Informació útil a l\'abast de la mà"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Per obtenir informació sense obrir les aplicacions, pots afegir widgets a la pantalla d\'inici"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Toca per canviar la configuració del widget"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Permet que l\'aplicació llegeixi la configuració i les dreceres de la pantalla d\'inici."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"escriure la configuració i les dreceres de la pantalla d\'inici"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Permet que l\'aplicació canviï la configuració i les dreceres de la pantalla d\'inici."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> no té permís per fer trucades telefòniques"</string>
<string name="gadget_error_text" msgid="740356548025791839">"No es pot carregar el widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Configuració del widget"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Toca per finalitzar la configuració"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"S\'ha canviat el nom de la carpeta a <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> elements"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> o més elements"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Fons de pantalla"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Estil i fons de pantalla"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Edita la pantalla d\'inici"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Config. pantalla d\'inici"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Desactivada per l\'administrador"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Permet la rotació de la pantalla d\'inici"</string>
@@ -159,15 +159,16 @@
<string name="all_apps_personal_tab" msgid="4190252696685155002">"Personal"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"Treball"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Perfil de treball"</string>
- <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Les aplicacions de treball tenen una insígnia i són visibles per al teu administrador de TI"</string>
+ <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Les aplicacions de treball tenen una insígnia i el teu administrador de TI les pot veure"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Entesos"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Les aplicacions de treball estan en pausa"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"No rebràs cap notificació de les aplicacions de treball"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Les aplicacions de treball no poden enviar-te notificacions, consumir bateria ni accedir a la teva ubicació"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Les aplicacions de treball estan desactivades: no poden enviar-te notificacions, consumir bateria ni accedir a la teva ubicació"</string>
- <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Les aplicacions de treball tenen una insígnia i són visibles per al teu administrador de TI"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"No rebràs trucades, missatges de text ni notificacions de les aplicacions de treball"</string>
+ <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Les aplicacions de treball tenen una insígnia i el teu administrador de TI les pot veure"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Entesos"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Posa en pausa les aplicacions de treball"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Activa les aplicacions de treball"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Reactiva"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtra"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Cerca al telèfon"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Cerca a la tauleta"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index fac5e9f..f9c7c77 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -27,8 +27,9 @@
<string name="safemode_widget_error" msgid="4863470563535682004">"V nouzovém režimu jsou widgety zakázány."</string>
<string name="shortcut_not_available" msgid="2536503539825726397">"Zkratka není k dispozici"</string>
<string name="home_screen" msgid="5629429142036709174">"Domů"</string>
- <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Rozdělená obrazovka"</string>
+ <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Rozdělit obrazovku"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informace o aplikaci %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Uložit pár aplikací"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Widget přesunete klepnutím a podržením."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvojitým klepnutím a podržením přesunete widget, případně použijte vlastní akce."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Pokud chcete widgetem pohybovat po ploše, podržte ho"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Přidat na plochu"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> byl přidán na plochu"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Návrhy"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ # widget}few{# widgety}many{# widgetu}other{# widgetů}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# zkratka}few{# zkratky}many{# zkratky}other{# zkratek}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Osobní"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Práce"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Konverzace"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Psaní poznámek"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Užitečné informace na dosah"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Pokud chcete mít informace k dispozici bez otevírání aplikací, můžete si na plochu přidat widgety"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Klepnutím změníte nastavení widgetu"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Umožňuje aplikaci číst nastavení a zkratky na ploše."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"zápis nastavení a zkratek plochy"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Umožňuje aplikaci změnit nastavení a zkratky na ploše."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> nemá oprávnění telefonovat"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Widget se nepodařilo načíst"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Nastavení widgetů"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Klepnutím dokončíte konfiguraci"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Složka přejmenována na <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Složka: <xliff:g id="NAME">%1$s</xliff:g>, počet položek: <xliff:g id="SIZE">%2$d</xliff:g>"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Složka: <xliff:g id="NAME">%1$s</xliff:g>, počet položek: <xliff:g id="SIZE">%2$d</xliff:g> nebo více"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Tapety"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Tapeta a styl"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Upravit plochu"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Nastavení plochy"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Zakázáno administrátorem"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Povolit otáčení plochy"</string>
@@ -162,14 +162,15 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Pracovní aplikace jsou označené a váš administrátor IT je vidí"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Rozumím"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Pracovní aplikace jsou pozastaveny"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Z pracovních aplikací nebudete dostávat oznámení."</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Pracovní aplikace vám nemohou zasílat oznámení, používat vaši baterii ani získat přístup k vaší poloze"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Pracovní aplikace jsou vypnuté. Nemohou vám zasílat oznámení, používat vaši baterii ani získat přístup k vaší poloze"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Z pracovních aplikací nebudete dostávat telefonní hovory, SMS ani oznámení"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Pracovní aplikace jsou označené a viditelné vašemu administrátorovi IT"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pozastavit pracovní aplikace"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Zapnout pracovní aplikace"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Zrušit pozastavení"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtr"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Prohledávání telefonu"</string>
- <string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Vyhledávat na tabletu"</string>
+ <string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Vyhledávání na tabletu"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"Selhalo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 2125ed7..134cbb0 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Startskærm"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Opdel skærm"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Appinfo for %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Gem appsammenknytning"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Hold en widget nede for at flytte den."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Tryk to gange, og hold en widget nede for at flytte den eller bruge tilpassede handlinger."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Hold widgetten nede for at flytte den rundt på startskærmen"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Føj til startskærm"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widgetten <xliff:g id="WIDGET_NAME">%1$s</xliff:g> blev føjet til startskærmen"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Forslag"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# genvej}one{# genvej}other{# genveje}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -47,9 +47,10 @@
<string name="widgets_full_sheet_cancel_button_description" msgid="5766167035728653605">"Ryd teksten i søgefeltet"</string>
<string name="no_widgets_available" msgid="4337693382501046170">"Der er ingen tilgængelige widgets eller genveje"</string>
<string name="no_search_results" msgid="3787956167293097509">"Der blev ikke fundet nogen widgets eller genveje"</string>
- <string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personlige"</string>
+ <string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personlig"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Arbejde"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Samtaler"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Notetagning"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Nyttige oplysninger lige ved hånden"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Hvis du vil have oplysninger uden at åbne apps, kan du føje widgets til din startskærm"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tryk for at ændre widgetindstillinger"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Tillader, at appen læser indstillingerne og genvejene på startskærmen."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"skriv indstillinger og genveje for startskærm"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Tillader, at appen ændrer indstillingerne og genvejene på startskærmen."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> har ikke tilladelse til at foretage telefonopkald"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Widgetten kan ikke indlæses"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Widget-indstillinger"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Tryk for at fuldføre konfigurationen"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Mappen er omdøbt til <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Mappe: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> elementer"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Mappe: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> eller flere elementer"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Baggrunde"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Baggrund og stil"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Rediger startskærm"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Indst. for startskærm"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Deaktiveret af din administrator"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Tillad rotation af startskærmen"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Arbejdsapps har badges og kan ses af din it-administrator"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Dine arbejdsapps er sat på pause"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Du vil ikke modtage notifikationer fra dine arbejdsapps"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Arbejdsapps kan ikke sende dig notifikationer, bruge dit batteri eller få adgang til din lokation"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Arbejdsapps er deaktiveret. Dine arbejdsapps kan ikke sende dig notifikationer, bruge dit batteri eller få adgang til din lokation"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Du vil ikke modtage telefonopkald, beskeder eller notifikationer fra dine arbejdsapps"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Arbejdsapps har badges og kan ses af din it-administrator"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Sæt arbejdsapps på pause"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Aktivér arbejdsapps"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Genoptag"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Søg på din telefon"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Søg på din tablet"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 29a2c5b..2fa7f91 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -27,8 +27,9 @@
<string name="safemode_widget_error" msgid="4863470563535682004">"Widgets im abgesicherten Modus deaktiviert"</string>
<string name="shortcut_not_available" msgid="2536503539825726397">"Verknüpfung nicht verfügbar"</string>
<string name="home_screen" msgid="5629429142036709174">"Startbildschirm"</string>
- <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Geteilter Bildschirm"</string>
+ <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Splitscreen"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"App-Info für %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"App-Paar speichern"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Zum Verschieben des Widgets berühren und halten"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Doppeltippen und halten, um ein Widget zu bewegen oder benutzerdefinierte Aktionen zu nutzen."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Wenn du das Widget auf dem Startbildschirm verschieben möchtest, halte es gedrückt"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Zum Startbildschirm hinzufügen"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-Widget zum Startbildschirm hinzugefügt"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Vorschläge"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# Widget}other{# Widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# Verknüpfung}other{# Verknüpfungen}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Privat"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Geschäftlich"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Unterhaltungen"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Notizen"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Praktische Informationen – immer zur Hand"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Wenn du Informationen erhalten möchtest, ohne Apps zu öffnen, kannst du deinem Startbildschirm Widgets hinzufügen"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tippen, um die Widget-Einstellungen zu ändern"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Ermöglicht der App, die Einstellungen und Verknüpfungen auf dem Startbildschirm zu lesen."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"Einstellungen und Verknüpfungen für den Startbildschirm schreiben"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Ermöglicht der App, die Einstellungen und Verknüpfungen auf dem Startbildschirm zu ändern."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> darf keine Telefonanrufe tätigen."</string>
<string name="gadget_error_text" msgid="740356548025791839">"Widget kann nicht geladen werden"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Widget-Einstellungen"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Tippen, um Einrichtung abzuschließen"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Ordner umbenannt in <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Ordner: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> Elemente"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Ordner: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> oder mehr Elemente"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Hintergründe"</string>
- <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Hintergrund & Stil"</string>
+ <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Hintergrund und Stil"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Startbildschirm bearbeiten"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Einstellungen"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Von deinem Administrator deaktiviert"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Drehen des Startbildschirms zulassen"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Geschäftliche Apps sind gekennzeichnet und für deinen IT-Administrator sichtbar"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Geschäftliche Apps sind pausiert"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Du erhältst von geschäftlichen Apps keine Benachrichtigungen mehr"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Deine geschäftlichen Apps können dir keine Benachrichtigungen senden, deinen Akku nicht nutzen und nicht auf deinen Standort zugreifen"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Geschäftliche Apps sind deaktiviert. Sie können dir keine Benachrichtigungen senden, deinen Akku nicht nutzen und nicht auf deinen Standort zugreifen."</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Du erhältst von geschäftlichen Apps keine Benachrichtigungen mehr und auch keine Anrufe oder SMS"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Geschäftliche Apps sind gekennzeichnet und für deinen IT-Administrator sichtbar"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Geschäftliche Apps pausieren"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Geschäftliche Apps aktivieren"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Nicht mehr pausieren"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Auf dem Smartphone suchen"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Auf dem Tablet suchen"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 0c64060..35cac5b 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Αρχική οθόνη"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Διαχωρισμός οθόνης"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Πληροφορίες εφαρμογής για %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Αποθήκευση ζεύγους εφαρμογών"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Πατήστε παρατετ. για μετακίνηση γραφ. στοιχείου."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Πατήστε δύο φορές παρατεταμένα για μετακίνηση γραφικού στοιχείου ή χρήση προσαρμοσμένων ενεργειών."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Αγγίξτε παρατεταμένα το γραφικό στοιχείο για να το μετακινήσετε στην αρχική οθόνη"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Προσθήκη στην αρχική οθόνη"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Το γραφικό στοιχείο <xliff:g id="WIDGET_NAME">%1$s</xliff:g> προστέθηκε στην αρχική οθόνη."</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Προτάσεις"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# γραφικό στοιχείο}other{# γραφικά στοιχεία}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# συντόμευση}other{# συντομεύσεις}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Προσωπικά"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Εργασίας"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Συζητήσεις"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Δημιουργία σημειώσεων"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Χρήσιμες πληροφορίες στη διάθεσή σας"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Για να λάβετε πληροφορίες χωρίς να ανοίξετε εφαρμογές, μπορείτε να προσθέσετε γραφικά στοιχεία στην αρχική οθόνη."</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Πατήστε για αλλαγή των ρυθμίσεων του γραφικού στοιχείου"</string>
@@ -63,7 +64,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Ειδοποιήσεις"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Πατήστε παρατεταμένα για μετακίνηση συντόμευσης."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Πατήστε δύο φορές παρατεταμένα για μετακίνηση συντόμευσης ή χρήση προσαρμοσμένων ενεργειών."</string>
- <string name="out_of_space" msgid="6455557115204099579">"Δεν υπάρχει χώρος σε αυτήν την αρχική οθόνη"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Δεν υπάρχει χώρος σε αυτή την αρχική οθόνη"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Δεν υπάρχει επιπλέον χώρος στην περιοχή Αγαπημένα"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Λίστα εφαρμογών"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Αποτελέσματα αναζήτησης"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Επιτρέπει στην εφαρμογή την ανάγνωση των ρυθμίσεων και των συντομεύσεων στην αρχική οθόνη."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"εγγραφή ρυθμίσεων και συντομεύσεων αρχικής οθόνης"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Επιτρέπει στην εφαρμογή την αλλαγή των ρυθμίσεων και των συντομεύσεων στην αρχική οθόνη."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> δεν επιτρέπεται να πραγματοποιεί τηλεφωνικές κλήσεις"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Δεν είναι δυνατή η φόρτωση του γραφικού στοιχείου"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Ρυθμίσεις γραφικών στοιχείων"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Πατήστε για να ολοκληρώσετε τη ρύθμιση"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Ο φάκελος μετονομάστηκε σε <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Φάκελος: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> στοιχεία"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Φάκελος: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ή περισσότερα στοιχεία"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Ταπετσαρίες"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Ταπετσαρία και στιλ"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Επεξεργασία αρχικής οθόνης"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Ρυθμίσεις Αρχ. Οθ."</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Απενεργοποιήθηκε από τον διαχειριστή σας"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Να επιτρέπεται η περιστροφή της αρχικής οθόνης"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Οι εφαρμογές εργασιών φέρουν σήμα και είναι ορατές στον διαχειριστή IT σας"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Το κατάλαβα"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Οι εφαρμογές εργασίας τέθηκαν σε παύση."</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Δεν θα λαμβάνετε ειδοποιήσεις από τις εφαρμογές εργασιών σας"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Οι εφαρμογές εργασίας δεν έχουν τη δυνατότητα αποστολής ειδοποιήσεων, χρήσης της μπαταρίας ή πρόσβασης στην τοποθεσία σας"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Οι εφαρμογές εργασίας είναι απενεργοποιημένες. Οι εφαρμογές εργασίας δεν έχουν τη δυνατότητα αποστολής ειδοποιήσεων, χρήσης της μπαταρίας ή πρόσβασης στην τοποθεσία σας"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Δεν θα λαμβάνετε τηλεφωνικές κλήσεις, μηνύματα κειμένου ή ειδοποιήσεις από τις εφαρμογές εργασιών σας"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Οι εφαρμογές εργασιών φέρουν σήμα και είναι ορατές στον διαχειριστή IT σας"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Το κατάλαβα"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Παύση εφαρμογών εργασιών"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Ενεργοποίηση εφαρμογών εργασίας"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Αναίρεση παύσης"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Φίλτρο"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Αναζήτηση στο τηλέφωνό σας"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Αναζήτηση στο tablet σας"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index ef9dfb3..47a67a8 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Home"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"App info for %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Save app pair"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Touch and 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>
@@ -49,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personal"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Work"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Note-taking"</string>
<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>
@@ -80,7 +82,6 @@
<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>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Tap to finish setup"</string>
@@ -98,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Folder renamed to <xliff:g id="NAME">%1$s</xliff:g>"</string>
<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="edit_home_screen" msgid="8947858375782098427">"Edit home screen"</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>
@@ -161,12 +162,13 @@
<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_apps_paused_title" msgid="3040901117349444598">"Work apps are paused"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"You won’t receive notifications from your work apps"</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_telephony_unavailable_body" msgid="8358872357502756790">"You won’t receive phone calls, text messages or notifications from your work apps"</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_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="work_apps_enable_btn_text" msgid="1736198302467317371">"Unpause"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Search your phone"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Search your tablet"</string>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index a623919..cc86e87 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -29,12 +29,13 @@
<string name="home_screen" msgid="5629429142036709174">"Home"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</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 & 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="save_app_pair" msgid="5647523853662686243">"Save app pair"</string>
+ <string name="long_press_widget_to_add" msgid="3587712543577675817">"Touch and hold to move a widget."</string>
+ <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Double-tap and 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 & hold the widget to move it around the home screen"</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_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="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
@@ -49,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personal"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Work"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Note-taking"</string>
<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>
@@ -60,8 +62,8 @@
<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="long_press_shortcut_to_add" msgid="5405328730817637737">"Touch and hold to move a shortcut."</string>
+ <string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Double-tap and 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 Favorites tray"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Apps list"</string>
@@ -80,7 +82,6 @@
<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>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Tap to finish setup"</string>
@@ -98,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Folder renamed to <xliff:g id="NAME">%1$s</xliff:g>"</string>
<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 & style"</string>
+ <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Wallpaper and style"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Edit Home Screen"</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>
@@ -161,12 +162,13 @@
<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">"Got it"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Work apps are paused"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"You won’t receive notifications from your work apps"</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_telephony_unavailable_body" msgid="8358872357502756790">"You won’t receive phone calls, text messages, or notifications from your work apps"</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">"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="work_apps_enable_btn_text" msgid="1736198302467317371">"Unpause"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Search your phone"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Search your tablet"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index ef9dfb3..47a67a8 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Home"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"App info for %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Save app pair"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Touch and 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>
@@ -49,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personal"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Work"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Note-taking"</string>
<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>
@@ -80,7 +82,6 @@
<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>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Tap to finish setup"</string>
@@ -98,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Folder renamed to <xliff:g id="NAME">%1$s</xliff:g>"</string>
<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="edit_home_screen" msgid="8947858375782098427">"Edit home screen"</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>
@@ -161,12 +162,13 @@
<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_apps_paused_title" msgid="3040901117349444598">"Work apps are paused"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"You won’t receive notifications from your work apps"</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_telephony_unavailable_body" msgid="8358872357502756790">"You won’t receive phone calls, text messages or notifications from your work apps"</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_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="work_apps_enable_btn_text" msgid="1736198302467317371">"Unpause"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Search your phone"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Search your tablet"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index ef9dfb3..47a67a8 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Home"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"App info for %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Save app pair"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Touch and 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>
@@ -49,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personal"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Work"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Note-taking"</string>
<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>
@@ -80,7 +82,6 @@
<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>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Tap to finish setup"</string>
@@ -98,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Folder renamed to <xliff:g id="NAME">%1$s</xliff:g>"</string>
<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="edit_home_screen" msgid="8947858375782098427">"Edit home screen"</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>
@@ -161,12 +162,13 @@
<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_apps_paused_title" msgid="3040901117349444598">"Work apps are paused"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"You won’t receive notifications from your work apps"</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_telephony_unavailable_body" msgid="8358872357502756790">"You won’t receive phone calls, text messages or notifications from your work apps"</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_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="work_apps_enable_btn_text" msgid="1736198302467317371">"Unpause"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Search your phone"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Search your tablet"</string>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index da3fea1..cca6551 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Home"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"App info for %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Save app pair"</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>
@@ -49,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personal"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Work"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Note-taking"</string>
<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>
@@ -80,7 +82,6 @@
<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>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Tap to finish setup"</string>
@@ -98,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Folder renamed to <xliff:g id="NAME">%1$s</xliff:g>"</string>
<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 & style"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Edit Home Screen"</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>
@@ -161,12 +162,13 @@
<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">"Got it"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Work apps are paused"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"You won’t receive notifications from your work apps"</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_telephony_unavailable_body" msgid="8358872357502756790">"You won’t receive phone calls, text messages, or notifications from your work apps"</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">"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="work_apps_enable_btn_text" msgid="1736198302467317371">"Unpause"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Search your phone"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Search your tablet"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index b01679f..c49fa0e 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Pantalla principal"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantalla dividida"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Información de la app de %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Guardar vinculación de apps"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Mantén presionado para mover un widget."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Presiona dos veces y mantén presionado para mover un widget o usar acciones personalizadas."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Mantén presionado el widget para moverlo por la pantalla principal"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Agregar a pantalla principal"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Se agregó el widget de <xliff:g id="WIDGET_NAME">%1$s</xliff:g> a la pantalla principal"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugerencias"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# acceso directo}other{# accesos directos}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personales"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabajo"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversaciones"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Tomar notas"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Información útil a tu alcance"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Para recibir información de apps sin abrirlas, puedes agregar widgets a la pantalla principal"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Presiona para cambiar la configuración del widget"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Permite que la app lea los parámetros de configuración y los accesos directos de la página principal."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"escribir parámetros de configuración y accesos directos de la página principal"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Permite que la app cambie los parámetros de configuración y los accesos directos de la página principal."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> no puede realizar llamadas telefónicas"</string>
<string name="gadget_error_text" msgid="740356548025791839">"No se puede cargar el widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Configuración del widget"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Presiona para finalizar la configuración"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"El nombre de la carpeta se cambió a <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> elementos"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> o más elementos"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Fondo de pantalla y estilo"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Editar pantalla principal"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Configuración de pantalla principal"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"El administrador inhabilitó esta función"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Permitir la rotación de la pantalla principal"</string>
@@ -162,14 +162,15 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Las apps de trabajo tienen una insignia y el administrador de TI las puede ver"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Entendido"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Las apps de trabajo están detenidas"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"No recibirás notificaciones de las apps de trabajo"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Las apps de trabajo no pueden enviarte notificaciones, usar la batería ni acceder a tu ubicación"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Las apps de trabajo están desactivadas y, por ende, no pueden enviarte notificaciones, usar la batería ni acceder a tu ubicación"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"No recibirás llamadas telefónicas, mensajes de texto ni notificaciones de tus apps de trabajo."</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Las apps de trabajo tienen una insignia y el administrador de TI las puede ver"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Entendido"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Detener apps de trabajo"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Activar las apps de trabajo"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Reanudar"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtro"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Busca tu teléfono"</string>
- <string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Busca tu tablet"</string>
+ <string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Busca en tu tablet"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"Error: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 73dcad5..b89a717 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Inicio"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantalla dividida"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Información de la aplicación %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Guardar aplicaciones emparejadas"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Mantén pulsado un widget para moverlo"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toca dos veces y mantén pulsado un widget para moverlo o usar acciones personalizadas."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Mantén pulsado el widget para moverlo por la pantalla de inicio"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Añadir a pantalla de inicio"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> añadido a la pantalla de inicio"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugerencias"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# acceso directo}other{# accesos directos}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personales"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabajo"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversaciones"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Toma de notas"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Información útil al alcance de la mano"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Para ver información sin abrir una aplicación, puedes añadir widgets a la pantalla de inicio"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Toca para cambiar los ajustes del widget"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Permite que la aplicación lea los ajustes y los accesos directos de la pantalla de inicio."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"escribir ajustes y accesos directos de la pantalla de inicio"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Permite que la aplicación cambie los ajustes y los accesos directos de la pantalla de inicio."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> no puede hacer llamadas"</string>
<string name="gadget_error_text" msgid="740356548025791839">"No se puede cargar el widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Ajustes de widget"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Toca para finalizar la configuración"</string>
@@ -99,13 +99,13 @@
<string name="folder_renamed" msgid="1794088362165669656">"Se ha cambiado el nombre de la carpeta a <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SIZE">%2$d</xliff:g> elementos)"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Carpeta: <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SIZE">%2$d</xliff:g> o más elementos)"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Fondo de pantalla y estilo"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Editar pantalla de inicio"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Ajustes de la pantalla de inicio"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Inhabilitado por el administrador"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Permitir rotación de la pantalla de inicio"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Al girar el teléfono"</string>
- <string name="notification_dots_title" msgid="9062440428204120317">"Puntos de notificación"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"Burbujas de notificación"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Activado"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"Desactivadas"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Se necesita acceso a las notificaciones"</string>
@@ -162,14 +162,15 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Las aplicaciones de trabajo tienen una insignia, y tu administrador de TI las puede ver"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Entendido"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Las aplicaciones de trabajo están en pausa"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"No recibirás notificaciones de tus aplicaciones de trabajo"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Tus aplicaciones de trabajo no pueden enviarte notificaciones, usar batería ni acceder a tu ubicación"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Las aplicaciones de trabajo están desactivadas, por lo que no pueden enviarte notificaciones, consumir batería ni acceder a tu ubicación"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"No recibirás llamadas, mensajes de texto ni notificaciones de tus aplicaciones de trabajo"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Las aplicaciones de trabajo tienen una insignia y tu administrador de TI las puede ver"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Entendido"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pausar aplicaciones de trabajo"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Activar aplicaciones de trabajo"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Reanudar"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtro"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Busca en tu teléfono"</string>
- <string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Busca en tu tablet"</string>
+ <string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Buscar en tu tablet"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"Se ha producido un error: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index efeb853..333fded 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -29,16 +29,16 @@
<string name="home_screen" msgid="5629429142036709174">"Avakuva"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Jagatud ekraanikuva"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Rakenduse teave: %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Salvesta rakendusepaar"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Vidina teisaldamiseks puudutage ja hoidke all."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Vidina teisaldamiseks või kohandatud toimingute kasutamiseks topeltpuudutage ja hoidke all."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d lai ja %2$d kõrge"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Vidin <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Vidina teisaldamiseks avakuval puudutage vidinat ja hoidke seda all"</string>
+ <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Vidina teisaldamiseks avakuval puudutage vidinat pikalt"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Lisa avakuvale"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Vidin <xliff:g id="WIDGET_NAME">%1$s</xliff:g> lisati avakuvale"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Soovitused"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# vidin}other{# vidinat}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# otsetee}other{# otseteed}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Isiklikud"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Töö"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Vestlused"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Märkmete tegemine"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Kasulik teave on teie käeulatuses"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Teabe saamiseks rakendusi avamata võite oma avakuvale lisada vidinaid"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Puudutage vidina seadete muutmiseks"</string>
@@ -71,7 +72,7 @@
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Töörakenduste loend"</string>
<string name="remove_drop_target_label" msgid="7812859488053230776">"Eemalda"</string>
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalli"</string>
- <string name="app_info_drop_target_label" msgid="692894985365717661">"Rakenduste teave"</string>
+ <string name="app_info_drop_target_label" msgid="692894985365717661">"Rakenduse teave"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Installimine"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Ära soovita rakendust"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Kinnita ennustus"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Võimaldab rakendusel lugeda avakuva seadeid ja otseteid."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"avakuva seadete ja otseteede kirjutamine"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Võimaldab rakendusel muuta avakuval seadeid ja otseteid."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"Rakendusel <xliff:g id="APP_NAME">%1$s</xliff:g> pole lubatud helistada"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Vidinat ei saa laadida"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Vidina seaded"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Puudutage seadistuse lõpuleviimiseks"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Kausta uus nimi: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Kaust: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> üksust"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Kaust: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> või rohkem üksust"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Taustapildid"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Taustapilt ja stiil"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Muuda avaekraani"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Avakuva seaded"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Keelas administraator"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Luba avakuva pööramine"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Töörakendustel on märk ja need on teie IT-administraatorile nähtavad"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Selge"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Töörakendused on peatatud"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Te ei saa oma töörakendustelt märguandeid"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Töörakendused ei saa teile märguandeid saata, akut kasutada ega teie asukohale juurde pääseda"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Töörakendused on välja lülitatud. Töörakendused ei saa teile märguandeid saata, akut kasutada ega teie asukohale juurde pääseda."</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Te ei saa oma töörakendustelt telefonikõnesid, tekstsõnumeid ega märguandeid"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Töörakendustel on märk ja need on teie IT-administraatorile nähtavad"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Selge"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Peata töörakendused"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Lülita töörakendused sisse"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Lõpeta peatamine"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Otsimine telefonist"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Otsimine tahvelarvutist"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index d0b6f54..cbf7e1c 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Hasierako pantaila"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Zatitu pantaila"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s aplikazioari buruzko informazioa"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Gorde aplikazio parea"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Eduki sakatuta widget bat mugitzeko."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Sakatu birritan eta eduki sakatuta widget bat mugitzeko edo ekintza pertsonalizatuak erabiltzeko."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Widgeta hasierako pantailan zehar mugitzeko, eduki ezazu sakatuta"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Gehitu hasierako pantailan"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widgeta hasierako pantailan gehitu da"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Iradokizunak"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# lasterbide}other{# lasterbide}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Pertsonalak"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Lanekoak"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Elkarrizketak"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Oharrak idazteko"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Informazio erabilgarria beti eskura"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Aplikaziorik ireki beharrik gabe informazioa zuzenean jasotzeko, gehitu widgetak hasierako pantailan"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Sakatu hau widgeten ezarpenak aldatzeko"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Hasierako pantailako ezarpenak eta lasterbideak irakurtzeko baimena ematen die aplikazioei."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"idatzi hasierako pantailako ezarpenak eta lasterbideak"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Hasierako pantailako ezarpenak eta lasterbideak aldatzeko baimena ematen die aplikazioei."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak ez du telefono-deiak egiteko baimenik"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Ezin da kargatu widgeta"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Widgetaren ezarpenak"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Sakatu konfiguratzen amaitzeko"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Karpetari <xliff:g id="NAME">%1$s</xliff:g> izena eman zaio"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"<xliff:g id="NAME">%1$s</xliff:g> karpeta (<xliff:g id="SIZE">%2$d</xliff:g> elementu)"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"<xliff:g id="NAME">%1$s</xliff:g> karpeta (<xliff:g id="SIZE">%2$d</xliff:g> elementu edo gehiago)"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Horma-paperak"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Horma-papera eta estiloa"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Editatu hasierako pantaila"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Hasierako pantailaren ezarpenak"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administratzaileak desgaitu du"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Eman hasierako pantaila biratzeko baimena"</string>
@@ -161,13 +161,14 @@
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Laneko profila"</string>
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Laneko aplikazioek bereizgarriak dituzte, eta IKT saileko administratzaileak ikus ditzake"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Ados"</string>
- <string name="work_apps_paused_title" msgid="3040901117349444598">"Pausatu egin dira laneko aplikazioak"</string>
+ <string name="work_apps_paused_title" msgid="3040901117349444598">"Pausatuta daude laneko aplikazioak"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Ez duzu jasoko laneko aplikazioen jakinarazpenik"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Laneko aplikazioek ezin dute jakinarazpenik bidali, bateria erabili edo kokapena atzitu"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Laneko aplikazioak desaktibatuta daude. Hori dela eta, ezin dute jakinarazpenik bidali, bateria erabili edo kokapena atzitu."</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Ez duzu jasoko laneko aplikazioen telefono-deirik, testu-mezurik edo jakinarazpenik"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Laneko aplikazioek bereizgarriak dituzte, eta IKT saileko administratzaileak ikus ditzake"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Ados"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pausatu laneko aplikazioak"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Aktibatu laneko aplikazioak"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Aktibatu berriro"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Iragazi"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Bilatu telefonoan"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Bilatu tabletan"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 5ec5b54..4ec760e 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"صفحه اصلی"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"صفحهٔ دونیمه"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"اطلاعات برنامه %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"ذخیره جفت برنامه"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"برای جابهجا کردن ابزارک، لمس کنید و نگه دارید."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"برای جابهجا کردن ابزارک یا استفاده از کنشهای سفارشی، دوضربه بزنید و نگه دارید."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"ابزارک را لمس کنید و نگه دارید تا بتوانید آن را در صفحه اصلی حرکت دهید"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"افزودن به صفحه اصلی"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"ابزارک <xliff:g id="WIDGET_NAME">%1$s</xliff:g> به صفحه اصلی اضافه شد"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"پیشنهادها"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ابزارک}one{# ابزارک}other{# ابزارک}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# میانبر}one{# میانبر}other{# میانبر}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>،<xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"ابزارکهای شخصی"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"کار"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"مکالمهها"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"یادداشتبرداری"</string>
<string name="widget_education_header" msgid="4874760613775913787">"دسترسی آسان به اطلاعات سودمند"</string>
<string name="widget_education_content" msgid="1731667670753497052">"با افزودن ابزارکها به صفحه اصلی میتوانید اطلاعات را بدون باز کردن برنامهها دریافت کنید"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"برای تغییر تنظیمات ابزارک، ضربه بزنید"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"به برنامه اجازه میدهد تنظیمات و میانبرهای صفحه اصلی را بخواند."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"نوشتن تنظیمات و میانبرهای صفحه اصلی"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"به برنامه اجازه میدهد تنظیمات و میانبرهای صفحه اصلی را تغییر دهد."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> مجاز نیست تماس تلفنی برقرار کند"</string>
<string name="gadget_error_text" msgid="740356548025791839">"ابزارک را نمیتوان بار کرد"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"تنظیمات ابزارک"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"برای تکمیل راهاندازی ضربه بزنید"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"نام پوشه به <xliff:g id="NAME">%1$s</xliff:g> تغییر کرد"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"پوشه: <xliff:g id="NAME">%1$s</xliff:g>، <xliff:g id="SIZE">%2$d</xliff:g> مورد"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"پوشه: <xliff:g id="NAME">%1$s</xliff:g>، <xliff:g id="SIZE">%2$d</xliff:g> مورد یا بیشتر"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"کاغذدیواریها"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"کاغذدیواری و سبک"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"ویرایش «صفحه اصلی»"</string>
<string name="settings_button_text" msgid="8873672322605444408">"تنظیمات صفحه اصلی"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"توسط سرپرست سیستم غیرفعال شده است"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"مجاز کردن چرخش صفحه اصلی"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"برنامههای کاری نشاندار هستند و سرپرست فناوری اطلاعات میتواند آنها را ببیند"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"متوجهام"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"برنامههای کاری موقتاً متوقف شدهاند."</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"از برنامههای کاریتان اعلان دریافت نخواهید کرد"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"برنامههای کاری نمیتوانند برای شما اعلان ارسال کنند، از باتری استفاده کنند، یا به مکانتان دسترسی داشته باشند"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"برنامههای کاری خاموش است. برنامههای کاری نمیتوانند برای شما اعلان ارسال کنند، از باتری استفاده کنند، یا به مکانتان دسترسی داشته باشند"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"از برنامههای کاریتان تماس تلفنی، پیام نوشتاری، یا اعلان دریافت نخواهید کرد"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"برنامههای کاری نشاندار هستند و سرپرست فناوری اطلاعات میتواند آنها را ببیند."</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"متوجهام"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"توقف موقت برنامههای کاری"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"روشن کردن برنامههای کاری"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"ازسرگیری"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"فیلتر"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"جستجوی تلفن"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"جستجوی رایانه لوحی"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 1b02c14..16dabb7 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Etusivu"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Jaettu näyttö"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Sovellustiedot: %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Tallenna sovelluspari"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Kosketa pitkään, niin voit siirtää widgetiä."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Kaksoisnapauta ja paina pitkään, niin voit siirtää widgetiä tai käyttää muokattuja toimintoja."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Voit siirtää widgetiä aloitusnäytöllä koskettamalla sitä pitkään"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Lisää aloitusnäytölle"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget lisätty aloitusnäytölle: <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Ehdotukset"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgetiä}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# pikakuvake}other{# pikakuvaketta}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Henkilökohtaiset"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Työ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Keskustelut"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Muistiinpanojen tekeminen"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Hyödyllisiä tietoja käden ulottuvilla"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Jos haluat nähdä tietoja avaamatta sovelluksia, voit lisätä aloitusnäytölle widgetejä"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Napauta, niin voit muuttaa widgetin asetuksia"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Antaa sovelluksen lukea aloitusnäytön asetuksia ja pikakuvakkeita"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"muokata aloitusnäytön asetuksia ja pikakuvakkeita"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Antaa sovelluksen muuttaa aloitusnäytön asetuksia ja pikakuvakkeita"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei saa soittaa puheluita."</string>
<string name="gadget_error_text" msgid="740356548025791839">"Widgetiä ei voi ladata"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Widgetin asetukset"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Viimeistele asennus napauttamalla"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Kansion nimeksi vaihdettiin <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Kansio: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> kohdetta"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Kansio: <xliff:g id="NAME">%1$s</xliff:g>, ainakin <xliff:g id="SIZE">%2$d</xliff:g> kohdetta"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Taustakuvat"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Taustakuva ja tyyli"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Muokkaa aloitusnäyttöä"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Aloitusnäyttö"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Järjestelmänvalvoja on poistanut toiminnon käytöstä."</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Salli aloitusnäytön kiertäminen"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Työsovellukset on merkitty sellaisiksi ja näkyvät IT-järjestelmänvalvojille"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Selvä"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Työsovellukset on keskeytetty"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Et saa ilmoituksia työsovelluksilta."</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Työsovellukset eivät voi lähettää sinulle ilmoituksia eivätkä käyttää akkuasi tai paikantaa sijaintiasi"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Työsovellukset ovat pois päältä. Ne eivät voi lähettää sinulle ilmoituksia eivätkä käyttää akkuasi tai sijaintiasi"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Et saa puheluja, tekstiviestejä tai ilmoituksia työsovelluksilta."</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Työsovellukset on merkitty sellaisiksi ja näkyvät IT-järjestelmänvalvojille"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Keskeytä työsovellusten käyttö"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Laita työsovellukset päälle"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Jatka"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Suodatin"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Hae puhelimesta"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Hae tabletilta"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 604cb31..1267205 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Accueil"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Écran partagé"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Renseignements sur l\'appli pour %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Enregistrer la paire d\'applications"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Maintenez le doigt sur un widget pour le déplacer."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Touchez 2x un widget et maintenez le doigt dessus pour le déplacer ou utiliser des actions personnalisées."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Maintenez le doigt sur le widget pour le déplacer sur l\'écran d\'accueil"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Ajouter à l\'écran d\'accueil"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Le widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> a été ajouté à l\'écran d\'accueil"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# raccourci}one{# raccourci}other{# raccourcis}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personnels"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Professionnels"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Prise de note"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Renseignements utiles à portée de main"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Pour obtenir des informations sans ouvrir d\'applications, vous pouvez ajouter des widgets à votre écran d\'accueil"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Touchez pour modifier les paramètres du widget"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Permet à l\'application de lire les paramètres et les raccourcis de l\'écran d\'accueil."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"modifier les paramètres et les raccourcis de la page d\'accueil"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Permet à l\'application de modifier les paramètres et les raccourcis de l\'écran d\'accueil."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"L\'application <xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas autorisée à faire des appels téléphoniques"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Impossible de charger le widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Paramètres du widget"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Touchez pour terminer la configuration"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Nouveau nom du dossier : <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Dossier : <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> élément(s)"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Dossier : <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> éléments ou plus"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Fonds d\'écran"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Fond d\'écran et style"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Modifier l\'écran d\'accueil"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Paramètres d\'accueil"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Cette fonction est désactivée par votre administrateur"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Autoriser la rotation de l\'écran d\'accueil"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Les applications professionnelles sont indiquées par un badge et elles sont visibles pour votre administrateur informatique"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Les applications professionnelles sont interrompues"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Vous ne recevrez pas de notifications de vos applications professionnelles"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Les applications professionnelles ne peuvent ni vous envoyer de notifications, ni utiliser la pile, ni accéder à votre position"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Les applications professionnelles sont désactivées. Vos applications professionnelles ne peuvent ni vous envoyer de notifications, ni utiliser la pile, ni accéder à votre position"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Vous ne recevrez pas d\'appels téléphoniques, de messages texte ni de notifications de vos applications professionnelles"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Les applications professionnelles sont indiquées par un badge et sont visibles pour votre administrateur informatique"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Mettre en pause les applications professionnelles"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Activer les applications professionnelles"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Réactiver"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrer"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Rechercher sur votre téléphone"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Rechercher sur votre tablette"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 1d22a5f..1addca7 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Accueil"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Écran partagé"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Infos sur l\'appli pour %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Enregistrer la paire d\'applis"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Appuyez de manière prolongée sur un widget pour le déplacer."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Appuyez deux fois et maintenez la pression pour déplacer widget ou utiliser actions personnalisées."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Appuyez de manière prolongée sur le widget pour le déplacer sur l\'écran d\'accueil"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Ajouter à l\'écran d\'accueil"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ajouté à l\'écran d\'accueil"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# raccourci}one{# raccourci}other{# raccourcis}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personnels"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Professionnels"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Prise de notes"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Infos utiles à portée de main"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Pour obtenir des infos sans ouvrir d\'applis, vous pouvez ajouter des widgets à votre écran d\'accueil"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Appuyez pour modifier les paramètres du widget"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Permet à l\'application de lire les paramètres et les raccourcis de l\'écran d\'accueil."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"Modifier les paramètres de la page d\'accueil et les raccourcis"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Permet à l\'application de modifier les paramètres et les raccourcis de l\'écran d\'accueil."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"L\'application <xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas autorisée à passer des appels téléphoniques."</string>
<string name="gadget_error_text" msgid="740356548025791839">"Impossible de charger le widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Paramètres du widget"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Appuyez pour terminer la configuration"</string>
@@ -99,15 +99,15 @@
<string name="folder_renamed" msgid="1794088362165669656">"Nouveau nom du dossier : <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Dossier : <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> éléments"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Dossier : <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> éléments ou plus"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Fonds d\'écran"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Fond d\'écran et style"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Modifier l\'écran d\'accueil"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Paramètres de l\'accueil"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Désactivé par votre administrateur"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Autoriser la rotation de l\'écran d\'accueil"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Lorsque vous faites pivoter le téléphone"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Pastilles de notification"</string>
- <string name="notification_dots_desc_on" msgid="1679848116452218908">"Activées"</string>
- <string name="notification_dots_desc_off" msgid="1760796511504341095">"Désactivées"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Activé"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Désactivé"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Accès aux notifications requis"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Pour afficher les pastilles de notification, activez les notifications de l\'application <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Modifier les paramètres"</string>
@@ -161,13 +161,14 @@
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Profil professionnel"</string>
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Les applis professionnelles sont identifiées par un badge et votre administrateur informatique peut les voir"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
- <string name="work_apps_paused_title" msgid="3040901117349444598">"Applications professionnelles en veille"</string>
+ <string name="work_apps_paused_title" msgid="3040901117349444598">"Applis professionnelles en pause"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Vous ne recevrez pas de notifications de vos applications professionnelles"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Vos applis professionnelles ne peuvent pas vous envoyer de notifications, utiliser votre batterie ni accéder à votre position"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Vos applis professionnelles sont désactivées. Elles ne peuvent pas vous envoyer de notifications, utiliser votre batterie ni accéder à votre position."</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Vous ne recevrez pas d\'appels téléphoniques, de messages ni de notifications de vos applications professionnelles"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Les applis professionnelles sont identifiées par un badge et votre administrateur informatique peut les voir"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Mettre en pause les applis professionnelles"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Activer les applications professionnelles"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Réactiver"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtre"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Rechercher sur votre téléphone"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Rechercher sur votre tablette"</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 8e90cbc..cf6ac1c 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Inicio"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantalla dividida"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Información da aplicación para %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Gardar emparellamento de aplicacións"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Mantén premido un widget para movelo."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toca dúas veces un widget e manteno premido para movelo ou utiliza accións personalizadas."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Mantén premido o widget para movelo pola pantalla de inicio"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Engadir á pantalla de inicio"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Engadiuse o widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> á pantalla de inicio"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suxestións"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# atallo}other{# atallos}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Widgets persoais"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Widgets do traballo"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversas"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Toma de notas"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Información útil ao teu alcance"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Se queres obter información sen abrir as aplicacións, podes engadir widgets á pantalla de inicio"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Toca para cambiar a configuración do widget"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Permite que a aplicación lea a configuración e os atallos da pantalla de inicio."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"editar a configuración e os atallos da pantalla de inicio"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Permite que a aplicación cambie a configuración e os atallos da pantalla de inicio."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> non ten permiso para facer chamadas telefónicas"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Non se puido cargar o widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Configuración do widget"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Toca para rematar a configuración"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"O cartafol cambiou o nome a <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Cartafol: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> elementos"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Cartafol: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> elementos ou máis"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Estilo e fondo de pantalla"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Editar pantalla de inicio"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Axustes de Inicio"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Función desactivada polo administrador"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Permitir xirar a pantalla de inicio"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"O administrador de TI pode ver as aplicacións do traballo e engadirlles indicadores"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Entendido"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Puxéronse en pausa as aplicacións do traballo"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Non recibirás notificacións das aplicacións do traballo"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"As aplicacións do traballo non poden enviarche notificacións, utilizar a batería nin acceder á túa localización"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"As aplicacións do traballo están desactivadas e non poden enviarche notificacións, utilizar a batería nin acceder á túa localización"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Non recibirás chamadas telefónicas, mensaxes de texto nin notificacións das aplicacións do traballo"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"O administrador de TI pode ver as aplicacións do traballo e engadirlles indicadores"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Entendido"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pór en pausa aplicacións do traballo"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Activar aplicacións do traballo"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Volver activar"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtra"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Buscar no teléfono"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Facer buscas na tableta"</string>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index 487fb9e..7f5c39f 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"હોમ સ્ક્રીન"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"સ્ક્રીનને વિભાજિત કરો"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s માટે ઍપ માહિતી"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"ઍપની જોડી સાચવો"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"વિજેટ ખસેડવા ટચ કરીને થોડી વાર દબાવી રાખો."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"વિજેટ ખસેડવા બે વાર ટૅપ કરીને દબાવી રાખો અથવા કસ્ટમ ક્રિયાઓનો ઉપયોગ કરો."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"વિજેટને હોમ સ્ક્રીનની આજુબાજુ ખસેડવા માટે, તેને ટચ કરીને થોડીવાર દબાવી રાખો"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"હોમ સ્ક્રીનમાં ઉમેરો"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"હોમ સ્ક્રીન પર <xliff:g id="WIDGET_NAME">%1$s</xliff:g> વિજેટ ઉમેર્યુ"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"સૂચનો"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# વિજેટ}one{# વિજેટ}other{# વિજેટ}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# શૉર્ટકટ}one{# શૉર્ટકટ}other{# શૉર્ટકટ}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,12 +50,13 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"વ્યક્તિગત"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ઑફિસ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"વાતચીતો"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"નોંધ લેવી"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ઉપયોગી માહિતી તમારી આંગળીના ટેરવે"</string>
<string name="widget_education_content" msgid="1731667670753497052">"ઍપને ખોલ્યા વિના માહિતી મેળવવા માટે, તમે તમારી હોમ સ્ક્રીનમાં વિજેટ ઉમેરી શકો છો"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"વિજેટના સેટિંગ બદલવા માટે ટૅપ કરો"</string>
<string name="widget_education_close_button" msgid="8676165703104836580">"સમજાઈ ગયું"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"વિજેટના સેટિંગ બદલો"</string>
- <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"શોધ ઍપ્લિકેશનો"</string>
+ <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"ઍપ શોધો"</string>
<string name="all_apps_loading_message" msgid="5813968043155271636">"ઍપ્લિકેશનો લોડ કરી રહ્યું છે…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\"થી મેળ ખાતી કોઈ ઍપ્લિકેશનો મળી નથી"</string>
<string name="label_application" msgid="8531721983832654978">"ઍપ"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"ઍપને હોમમાંના સેટિંગ અને શૉર્ટકટ વાંચવાની મંજૂરી આપે છે."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"હોમ સેટિંગ અને શૉર્ટકટ લખો"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"ઍપને હોમમાંના સેટિંગ અને શૉર્ટકટમાં ફેરફાર કરવાની મંજૂરી આપે છે."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ને ફોન કૉલ્સ કરવાની મંજૂરી નથી"</string>
<string name="gadget_error_text" msgid="740356548025791839">"વિજેટ લોડ કરી શકાતું નથી"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"વિજેટ સેટિંગ"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"સેટઅપ પૂર્ણ કરવા માટે ટૅપ કરો"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"ફોલ્ડરનું નામ બદલીને <xliff:g id="NAME">%1$s</xliff:g> કર્યું"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"ફોલ્ડર: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> આઇટમ"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ફોલ્ડર: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> કે વધુ આઇટમ"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"વૉલપેપર"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"વૉલપેપર અને સ્ટાઇલ"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"હોમ સ્ક્રીનમાં ફેરફાર કરો"</string>
<string name="settings_button_text" msgid="8873672322605444408">"હોમ સેટિંગ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"તમારા વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"હોમ સ્ક્રીનને ફેરવવાની મંજૂરી આપો"</string>
@@ -156,18 +156,19 @@
<string name="action_dismiss_notification" msgid="5909461085055959187">"છોડી દો"</string>
<string name="accessibility_close" msgid="2277148124685870734">"બંધ કરો"</string>
<string name="notification_dismissed" msgid="6002233469409822874">"સૂચના છોડી દીધી"</string>
- <string name="all_apps_personal_tab" msgid="4190252696685155002">"મનગમતી ઍપ"</string>
+ <string name="all_apps_personal_tab" msgid="4190252696685155002">"વ્યક્તિગત ઍપ"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"ઑફિસની ઍપ"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"ઑફિસની પ્રોફાઇલ"</string>
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"ઑફિસની ઍપને બૅજ આપેલા હોય છે અને તમારા IT ઍડમિન તેમને જોઈ શકે છે"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"સમજાઈ ગયું"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"ઑફિસ માટેની ઍપ થોભાવવામાં આવી છે"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"તમને તમારી ઑફિસ માટેની ઍપ તરફથી નોટિફિકેશન મળશે નહીં"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"ઑફિસ માટેની તમારી ઍપ તમને નોટિફિકેશન મોકલી શકતી નથી, તમારી બૅટરી વાપરી શકતી નથી કે તમારું સ્થાન ઍક્સેસ કરી શકતી નથી"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"ઑફિસ માટેની ઍપ બંધ છે. ઑફિસ માટેની તમારી ઍપ તમને નોટિફિકેશન મોકલી શકતી નથી, તમારી બૅટરી વાપરી શકતી નથી કે તમારું સ્થાન ઍક્સેસ કરી શકતી નથી"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"તમને તમારી ઑફિસ માટેની ઍપ તરફથી ફોન કૉલ, ટેક્સ્ટ મેસેજ કે નોટિફિકેશન મળશે નહીં"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"ઑફિસની ઍપને બૅજ આપેલા હોય છે અને તમારા IT ઍડમિન તેમને જોઈ શકે છે"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"સમજાઈ ગયું"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ઑફિસની ઍપ થોભાવો"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ઑફિસ માટેની ઍપ ચાલુ કરો"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"ફરી ચાલુ કરો"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"ફિલ્ટર કરો"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"તમારો ફોન શોધો"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"તમારું ટૅબ્લેટ શોધો"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index d937288..8301194 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -29,16 +29,16 @@
<string name="home_screen" msgid="5629429142036709174">"होम स्क्रीन"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"स्प्लिट स्क्रीन"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s के लिए ऐप्लिकेशन की जानकारी"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"साथ में इस्तेमाल किए जा सकने वाले ऐप्लिकेशन की जानकारी सेव करें"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"किसी विजेट को एक से दूसरी जगह ले जाने के लिए, उसे दबाकर रखें."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"किसी विजेट को एक से दूसरी जगह ले जाने के लिए, उस पर दो बार टैप करके दबाकर रखें या पसंद के मुताबिक कार्रवाइयां इस्तेमाल करें."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d चौड़ाई गुणा %2$d ऊंचाई"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट"</string>
- <string name="add_item_request_drag_hint" msgid="8730547755622776606">"होम स्क्रीन पर इधर-उधर ले जाने के लिए, विजेट को दबाकर रखें"</string>
+ <string name="add_item_request_drag_hint" msgid="8730547755622776606">"विजेट को होम स्क्रीन पर इधर-उधर ले जाने के लिए, उसे दबाकर रखें"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"होम स्क्रीन पर जोड़ें"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट को होम स्क्रीन पर जोड़ा गया"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"सुझाव"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# विजेट}one{# विजेट}other{# विजेट}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# शॉर्टकट}one{# शॉर्टकट}other{# शॉर्टकट}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -48,14 +48,15 @@
<string name="no_widgets_available" msgid="4337693382501046170">"विजेट और शॉर्टकट उपलब्ध नहीं हैं"</string>
<string name="no_search_results" msgid="3787956167293097509">"कोई विजेट या शॉर्टकट नहीं मिला"</string>
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"निजी विजेट"</string>
- <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ऑफ़िस"</string>
+ <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"वर्क विजेट"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"बातचीत"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"नोट बनाने से जुड़े विजेट"</string>
<string name="widget_education_header" msgid="4874760613775913787">"काम की जानकारी आसानी से पाएं"</string>
<string name="widget_education_content" msgid="1731667670753497052">"ऐप्लिकेशन को खोले बिना उनकी जानकारी पाने के लिए, होम स्क्रीन पर विजेट जोड़े जा सकते हैं"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"विजेट की सेटिंग में बदलाव करने के लिए टैप करें"</string>
<string name="widget_education_close_button" msgid="8676165703104836580">"ठीक है"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"विजेट की सेटिंग में बदलाव करें"</string>
- <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"ऐप सर्च करें"</string>
+ <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"ऐप्लिकेशन खोजें"</string>
<string name="all_apps_loading_message" msgid="5813968043155271636">"ऐप्लिकेशन लोड हो रहे हैं…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" से मिलता-जुलता कोई ऐप्लिकेशन नहीं मिला"</string>
<string name="label_application" msgid="8531721983832654978">"ऐप्लिकेशन"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"इससे ऐप्लिकेशन, होम स्क्रीन की सेटिंग और शॉर्टकट पढ़ पाएगा."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"होम स्क्रीन की सेटिंग और शॉर्टकट में बदलाव करने की अनुमति"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"इससे ऐप्लिकेशन, होम स्क्रीन की सेटिंग और शॉर्टकट बदल पाएगा."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> को फ़ोन कॉल करने की अनुमति नहीं है"</string>
<string name="gadget_error_text" msgid="740356548025791839">"विजेट को लोड नहीं किया जा सका"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"विजेट की सेटिंग"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"सेट अप पूरा करने के लिए टैप करें"</string>
@@ -99,9 +99,9 @@
<string name="folder_renamed" msgid="1794088362165669656">"फ़ोल्डर का नाम बदलकर <xliff:g id="NAME">%1$s</xliff:g> किया गया"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"फ़ोल्डर: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> आइटम"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"फ़ोल्डर: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> या इससे ज़्यादा आइटम"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"वॉलपेपर"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"वॉलपेपर और स्टाइल"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"होम पेज की सेटिंग"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"होम स्क्रीन में बदलाव करें"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"होम स्क्रीन की सेटिंग"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"आपके एडमिन ने बंद किया हुआ है"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"होम स्क्रीन घुमाने की अनुमति दें"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"फ़ोन घुुमाए जाने पर"</string>
@@ -156,18 +156,19 @@
<string name="action_dismiss_notification" msgid="5909461085055959187">"खारिज करें"</string>
<string name="accessibility_close" msgid="2277148124685870734">"बंद करें"</string>
<string name="notification_dismissed" msgid="6002233469409822874">"सूचना को खारिज किया गया"</string>
- <string name="all_apps_personal_tab" msgid="4190252696685155002">"निजी ऐप"</string>
+ <string name="all_apps_personal_tab" msgid="4190252696685155002">"निजी ऐप्लिकेशन"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"वर्क ऐप्लिकेशन"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"वर्क प्रोफ़ाइल"</string>
- <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"वर्क ऐप्लिकेशन बैज किए गए हैं और आईटी एडमिन को दिख रहे हैं"</string>
+ <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"वर्क ऐप्लिकेशन बैज किए गए हैं. आईटी एडमिन इन्हें देख सकता है"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"ठीक है"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"वर्क ऐप्लिकेशन रोके गए"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"आपको वर्क ऐप्लिकेशन से सूचनाएं नहीं मिलेंगी"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"आपके वर्क ऐप्लिकेशन, आपको सूचनाएं नहीं भेज सकते. साथ ही, आपकी बैटरी का इस्तेमाल या आपकी जगह की जानकारी को ऐक्सेस भी नहीं कर सकते"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"ऑफ़िस के काम से जुड़े ऐप्लिकेशन बंद हैं. ये ऐप्लिकेशन, आपको सूचनाएं नहीं भेज सकते. साथ ही, आपकी बैटरी का इस्तेमाल या आपकी जगह की जानकारी को ऐक्सेस भी नहीं कर सकते"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"आपको वर्क ऐप्लिकेशन से फ़ोन कॉल, टेक्स्ट मैसेज या सूचनाएं नहीं मिलेंगी"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"ऑफ़िस के काम से जुड़े ऐप्लिकेशन बैज किए गए हैं और आईटी एडमिन को दिख रहे हैं"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"ठीक है"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"वर्क ऐप्लिकेशन रोकें"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ऑफ़िस के काम से जुड़े ऐप्लिकेशन चालू करें"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"चालू करें"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"फ़िल्टर"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"अपने फ़ोन में खोजें"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"अपने टैबलेट में खोजें"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 66b5ef9..59630f4 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Početni zaslon"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Podijeljeni zaslon"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacije o aplikaciji %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Spremi par aplikacija"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Dodirnite i zadržite da biste premjestili widget."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvaput dodirnite i zadržite pritisak da biste premjestili widget ili upotrijebite prilagođene radnje"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -49,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Osobni"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Posao"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Razgovori"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Pisanje bilježaka"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Korisne informacije nadohvat ruke"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Da biste dobili informacije bez otvaranja aplikacija, možete dodati widgete na početni zaslon"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Dodirnite da biste promijenili postavke widgeta"</string>
@@ -80,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Aplikaciji omogućuje čitanje postavki i prečaca na početnom zaslonu."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"pisati postavke i prečace početnog zaslona"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Aplikaciji omogućuje promjenu postavki i prečaca na početnom zaslonu."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> nema dopuštenje za telefonske pozive"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Widget se ne može učitati"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Postavke widgeta"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Dodirnite da biste dovršili postavljanje"</string>
@@ -98,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Mapa je preimenovana u <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Mapa: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> stavke"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Mapa: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ili više stavki"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Pozadine"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Pozadina i stil"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Uredi početni zaslon"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Postavke početnog zaslona"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogućio administrator"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Dopusti zakretanje početnog zaslona"</string>
@@ -161,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Poslovne su aplikacije označene i vidljive vašem IT administratoru"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Shvaćam"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Poslovne aplikacije su pauzirane"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Nećete primati obavijesti poslovnih aplikacija"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Poslovne aplikacije ne mogu vam slati obavijesti, trošiti bateriju ili pristupati vašoj lokaciji"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Poslovne aplikacije su isključene. Ne mogu vam slati obavijesti, trošiti bateriju ili pristupati vašoj lokaciji"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Nećete primati telefonske pozive, tekstne poruke niti obavijesti poslovnih aplikacija"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Poslovne su aplikacije označene i vidljive vašem IT administratoru"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Shvaćam"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pauziraj poslovne aplikacije"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Uključite poslovne aplikacije"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Ponovno pokreni"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrirajte"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Pretraživanje telefona"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Pretraživanje tableta"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index e25fc8d..3bcf350 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Kezdőképernyő"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Osztott képernyő"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Alkalmazásinformáció a következőhöz: %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Alkalmazáspár mentése"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Tartsa lenyomva a modult az áthelyezéshez."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Modul áthelyezéséhez koppintson duplán, tartsa nyomva az ujját, vagy használjon egyéni műveleteket."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Tartsa lenyomva a modult a kezdőképernyőn való mozgatáshoz"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Hozzáadás a kezdőképernyőhöz"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> modul hozzáadva a kezdőképernyőhöz"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Javaslatok"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# modul}other{# modul}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# gyorsparancs}other{# gyorsparancs}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Személyes"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Munka"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Beszélgetések"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Jegyzetelés"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Hasznos információk egy koppintásnyira"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Ha az alkalmazások megnyitása nélkül szeretne információhoz jutni, felvehet modulokat a kezdőképernyőre"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Ide koppintva módosíthatja a modulbeállításokat"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Lehetővé teszi az alkalmazás számára a kezdőképernyő beállításainak és parancsikonjainak olvasását."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"kezdőképernyő beállításainak és parancsikonjainak írása"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Lehetővé teszi az alkalmazás számára a kezdőképernyő beállításainak és parancsikonjainak módosítását."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> nem kezdeményezhet telefonhívásokat"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Nem tölthető le a modul"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Modulbeállítások"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Koppintson a beállítás befejezéséhez"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"A mappa új neve: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Mappa: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> elem"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Mappa: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> vagy több elem"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Háttérképek"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Háttérkép és stílus"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Kezdőképernyő szerkesztése"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Kezdőképernyő beállításai"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"A rendszergazda letiltotta"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"A kezdőképernyő elforgatásának engedélyezése"</string>
@@ -159,15 +159,16 @@
<string name="all_apps_personal_tab" msgid="4190252696685155002">"Személyes"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"Munkahelyi"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Munkaprofil"</string>
- <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"A munkahelyi alkalmazások jelvénnyel vannak megjelölve, és láthatók a rendszergazda számára"</string>
+ <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"A munkahelyi alkalmazások jelvénnyel vannak megjelölve, és ezeket láthatja a rendszergazda"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Értem"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"A munkahelyi alkalmazások szüneteltetve vannak"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"A munkahelyi alkalmazásoktól nem kap értesítést."</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"A munkahelyi alkalmazások nem küldhetnek Önnek értesítéseket, nem használhatják az akkumulátorát, és nem férhetnek hozzá a tartózkodási helyéhez."</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"A munkahelyi alkalmazások nem küldhetnek Önnek értesítéseket, nem használhatják az akkumulátorát, és nem férhetnek hozzá a tartózkodási helyéhez"</string>
- <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"A munkahelyi alkalmazások jelvénnyel vannak megjelölve, és láthatók a rendszergazda számára"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"A munkahelyi alkalmazásoktól nem kap telefonhívásokat, szöveges üzeneteket vagy értesítéseket."</string>
+ <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"A munkahelyi alkalmazások jelvénnyel vannak megjelölve, és ezeket láthatja a rendszergazda"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Értem"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Munkahelyi alkalmazások szüneteltetése"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Munkahelyi alkalmazások bekapcsolása"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Folytatás"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Szűrő"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Keresés a telefonon"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Keresés a táblagépen"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index bdb2259..ccc028f 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Հիմնական էկրան"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Տրոհել էկրանը"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Տեղեկություններ %1$s հավելվածի մասին"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Պահել հավելվածների զույգը"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Հպեք և պահեք՝ վիջեթ տեղափոխելու համար։"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Կրկնակի հպեք և պահեք՝ վիջեթ տեղափոխելու համար, կամ օգտվեք հատուկ գործողություններից։"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Հպեք վիջեթին և պահեք՝ հիմնական էկրան տեղափոխելու համար"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Ավելացնել հիմնական էկրանին"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> վիջեթն ավելացվել է հիմնական էկրանին"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Առաջարկներ"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# վիջեթ}one{# վիջեթ}other{# վիջեթ}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# դյուրանցում}one{# դյուրանցում}other{# դյուրանցում}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Անձնական"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Աշխատանքային"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Զրույցներ"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Նշումների ստեղծում"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Բոլոր կարևոր տեղեկությունները՝ ձեռքի տակ"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Ավելացրեք վիջեթներ ձեր հիմնական էկրանին, որպեսզի տեղեկություններ ստանաք՝ առանց հավելվածները բացելու։"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Հպեք՝ վիջեթի կարգավորումները փոփոխելու համար"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Հավելվածին թույլ է տալիս կարդալ հիմնական էկրանի կարգավորումներն ու դյուրանցումները։"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"փոփոխել հիմնական էկրանի կարգավորումներն ու դյուրանցումները"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Հավելվածին թույլ է տալիս փոփոխել հիմնական էկրանի կարգավորումներն ու դյուրանցումները։"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածին չի թույլատրվում հեռախոսազանգեր կատարել"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Չհաջողվեց բեռնել վիջեթը"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Վիջեթի կարգավորումներ"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Հպեք՝ կարգավորումն ավարտելու համար"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Պանակը վերանվանվեց <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Պանակ՝ <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> տարր"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Պանակ՝ <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> կամ ավելի տարրեր"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Պաստառներ"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Պաստառ և ոճ"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Փոփոխել հիմնական էկրանը"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Գլխավոր էկրանի կարգավորումներ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Անջատվել է ձեր ադմինիստրատորի կողմից"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Թույլ տալ հիմնական էկրանի պտտումը"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Աշխատանքային հավելվածները հատուկ նշանակ ունեն և տեսանելի են ՏՏ ադմինիստրատորին"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Եղավ"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Աշխատանքային հավելվածները դադարեցված են"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Դուք ծանուցումներ չեք ստանա ձեր աշխատանքային հավելվածներից"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Աշխատանքային հավելվածները չեն կարող ծանուցումներ ուղարկել ձեզ, օգտագործել մարտկոցը և ձեր տեղադրության մասին տվյալներ ստանալ։"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Աշխատանքային հավելվածներն անջատված են։ Դրանք չեն կարող ծանուցումներ ուղարկել ձեզ, օգտագործել մարտկոցը և ձեր տեղադրության մասին տվյալներ ստանալ։"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Դուք ձեր աշխատանքային հավելվածներից հեռախոսազանգեր, տեքստային հաղորդագրություններ կամ ծանուցումներ չեք ստանա"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Աշխատանքային հավելվածները հատուկ նշանակ ունեն և տեսանելի են ՏՏ ադմինիստրատորին"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Եղավ"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Դադարեցնել աշխատանքային հավելվածները"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Միացնել աշխատանքային հավելվածները"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Վերսկսել"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Զտեք"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Որոնում հեռախոսում"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Որոնում պլանշետում"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index ec3531b..c1d62d4 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -29,16 +29,16 @@
<string name="home_screen" msgid="5629429142036709174">"Layar utama"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Layar terpisah"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Info aplikasi untuk %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Simpan pasangan aplikasi"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Sentuh lama untuk memindahkan widget."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ketuk dua kali & tahan untuk memindahkan widget atau gunakan tindakan khusus."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"lebar %1$d x tinggi %2$d"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Sentuh lama widget untuk memindahkannya di sekitar layar utama"</string>
+ <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Sentuh lama widget untuk memindah-mindahkannya di layar utama"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Tambahkan ke layar utama"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ditambahkan ke layar utama"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Saran"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# pintasan}other{# pintasan}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Pribadi"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Kerja"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Percakapan"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Pembuatan catatan"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Info bermanfaat mudah dilihat"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Untuk mendapatkan info tanpa membuka aplikasi, Anda dapat menambahkan widget ke layar utama"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Ketuk untuk mengubah setelan widget"</string>
@@ -81,11 +82,10 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Mengizinkan aplikasi membaca setelan dan pintasan di layar utama."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"menulis setelan dan pintasan layar utama"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Mengizinkan aplikasi mengubah setelan dan pintasan di layar utama."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak diizinkan untuk melakukan panggilan telepon"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Tidak dapat memuat widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Setelan widget"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Ketuk untuk menyelesaikan penyiapan"</string>
- <string name="uninstall_system_app_text" msgid="4172046090762920660">"Ini adalah aplikasi sistem dan tidak dapat dicopot pemasangannya."</string>
+ <string name="uninstall_system_app_text" msgid="4172046090762920660">"Ini adalah aplikasi sistem dan tidak dapat di-uninstal."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Sunting Nama"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> dinonaktifkan"</string>
<string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} memiliki # notifikasi}other{{app_name} memiliki # notifikasi}}"</string>
@@ -99,9 +99,9 @@
<string name="folder_renamed" msgid="1794088362165669656">"Folder diganti namanya menjadi <xliff:g id="NAME">%1$s</xliff:g>"</string>
<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> item"</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> item atau lebih"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpaper"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Wallpaper & gaya"</string>
- <string name="settings_button_text" msgid="8873672322605444408">"Setelan Layar utama"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Edit Layar Utama"</string>
+ <string name="settings_button_text" msgid="8873672322605444408">"Setelan layar utama"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Dinonaktifkan oleh admin"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Izinkan layar utama diputar"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Saat ponsel diputar"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Aplikasi kerja diberi badge dan terlihat oleh admin IT"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Oke"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Aplikasi kerja dijeda"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Anda tidak akan menerima notifikasi dari aplikasi kerja"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Aplikasi kerja tidak dapat mengirimkan notifikasi, menggunakan baterai, atau mengakses lokasi Anda"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Aplikasi kerja dinonaktifkan. Aplikasi kerja tidak dapat mengirimkan notifikasi, menggunakan baterai, atau mengakses lokasi Anda"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Anda tidak akan menerima panggilan telepon, pesan teks, atau notifikasi dari aplikasi kerja"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Aplikasi kerja diberi badge dan terlihat oleh admin IT"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Oke"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Jeda aplikasi kerja"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Aktifkan aplikasi kerja"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Aktifkan lagi"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Telusuri di ponsel"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Telusuri di tablet"</string>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index ee57fbc..e336a4b 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Heim"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Skipta skjá"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Upplýsingar um forrit fyrir %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Vista forritapar"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Haltu fingri á græju til að færa hana."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ýttu tvisvar og haltu fingri á græju til að færa hana eða notaðu sérsniðnar aðgerðir."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Haltu fingri á græjunni til að hreyfa hana um heimaskjáinn"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Bæta á heimaskjá"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> græju bætt við heimaskjá"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Tillögur"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# græja}one{# græja}other{# græjur}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# flýtileið}one{# flýtileið}other{# flýtileiðir}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Persónulegt"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Vinna"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Samtöl"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Glósugerð"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Gagnlegar upplýsingar innan seilingar"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Þú getur bætt við græjum á heimaskjáinn til að fá upplýsingar án þess að opna forrit"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Ýttu til að breyta græjustillingum"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Leyfir forriti að lesa stillingar og flýtileiðir heimaskjás."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"skrifa stillingar og flýtileiðir heimaskjás"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Leyfir forriti að breyta stillingum og flýtileiðum heimaskjás."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> hefur ekki leyfi til að hringja símtöl"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Ekki hægt að hlaða græju"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Græjustillingar"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Ýttu til að ljúka við uppsetningu"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Heiti möppu breytt í <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Mappa: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> atriði"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Mappa: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> eða fleiri atriði"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Veggfóður"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Veggfóður og stíll"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Breyta heimaskjá"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Heimastillingar"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Gert óvirkt af kerfisstjóra"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Leyfa snúning á heimaskjá"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Vinnuforrit eru merkt og kerfisstjórinn getur séð þau"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Ég skil"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Hlé gert á vinnuforritum"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Þú færð ekki tilkynningar frá vinnuforritum"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Vinnuforrit geta ekki sent þér tilkynningar, notað rafhlöðuorku eða fengið aðgang að staðsetningu þinni"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Slökkt er á vinnuforritum. Vinnuforrit geta ekki sent þér tilkynningar, notað rafhlöðuorku eða fengið aðgang að staðsetningu þinni"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Þú munt ekki taka á móti símtölum, textaskilaboðum eða tilkynningum frá vinnuforritum"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Vinnuforrit eru merkt og kerfisstjórinn getur séð þau"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Ég skil"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Setja vinnuforrit í bið"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Kveikja á vinnuforritum"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Ljúka hléi"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Sía"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Leita í símanum"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Leita í spjaldtölvunni"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 6a20454..4342ce6 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Home"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Schermo diviso"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informazioni sull\'app %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Salva coppia di app"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Tocca e tieni premuto per spostare un widget."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Tocca due volte e tieni premuto per spostare un widget o per usare le azioni personalizzate."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Tocca e tieni premuto il widget per spostarlo nella schermata Home"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Aggiungi alla schermata Home"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> aggiunto alla schermata Home"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggerimenti"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# scorciatoia}other{# scorciatoie}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personali"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Lavoro"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversazioni"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Aggiunta di note"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Informazioni utili a portata di mano"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Per ricevere informazioni senza aprire le app, puoi aggiungere dei widget alla schermata Home"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tocca per modificare le impostazioni del widget"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Consente all\'app di leggere le impostazioni e le scorciatoie nella schermata Home."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"creare impostazioni e scorciatoie nella schermata Home"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Consente all\'app di modificare le impostazioni e le scorciatoie nella schermata Home."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> non è autorizzata a effettuare telefonate"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Impossibile caricare il widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Impostazioni widget"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Tocca per completare la configurazione"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Nome della cartella sostituito con <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Cartella: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> elementi"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Cartella: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> o più elementi"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Sfondi"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Sfondo e stile"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Modifica la schermata Home"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Impostazioni schermata Home"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disattivata dall\'amministratore"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Consenti rotazione della schermata Home"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Le app di lavoro sono contrassegnate con un badge e visibili all\'amministratore IT"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Le app di lavoro sono in pausa"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Non riceverai notifiche dalle app di lavoro"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Le app di lavoro non possono inviarti notifiche, usare la batteria o accedere alla tua posizione"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Le app di lavoro non sono attive e non possono inviarti notifiche, usare la batteria o accedere alla tua posizione"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Non riceverai telefonate, messaggi o notifiche dalle app di lavoro"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Le app di lavoro sono contrassegnate con un badge e sono visibili dal tuo amministratore IT"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Metti in pausa le app di lavoro"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Attiva app di lavoro"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Riattiva"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtra"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Ricerche sul telefono"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Ricerche sul tablet"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 191efb8..808d324 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"בית"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"מסך מפוצל"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"פרטים על האפליקציה %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"שמירה של צמד אפליקציות"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"להעברת ווידג\'ט למקום אחר לוחצים עליו לחיצה ארוכה."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"כדי להעביר ווידג\'ט למקום אחר או להשתמש בפעולות מותאמות אישית, יש ללחוץ פעמיים ולא להרפות."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"לוחצים לחיצה ארוכה על הווידג\'ט כדי להזיז אותו במסך הבית"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"הוספה למסך הבית"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"הווידג\'ט <xliff:g id="WIDGET_NAME">%1$s</xliff:g> נוסף למסך הבית"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"הצעות"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ווידג\'ט אחד}one{# ווידג\'טים}two{# ווידג\'טים}other{# ווידג\'טים}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{קיצור דרך אחד}one{# קיצורי דרך}two{# קיצורי דרך}other{# קיצורי דרך}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"ווידג\'טים אישיים"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"עבודה"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"שיחות"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"כתיבת הערות"</string>
<string name="widget_education_header" msgid="4874760613775913787">"קבלת מידע שימושי בהקשה"</string>
<string name="widget_education_content" msgid="1731667670753497052">"רוצה לקבל מידע בלי לפתוח אפליקציות? אפשר להוסיף ווידג\'טים למסך הבית"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"אפשר לשנות את הגדרות הווידג\'ט בהקשה"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"מאפשרת לאפליקציה לקרוא את ההגדרות וקיצורי הדרך בדף הבית."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"כתיבת ההגדרות וקיצורי הדרך בדף הבית"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"מאפשרת לאפליקציה לשנות את ההגדרות וקיצורי הדרך בדף הבית."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> אינו רשאי להתקשר"</string>
<string name="gadget_error_text" msgid="740356548025791839">"לא ניתן לטעון את הווידג\'ט"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"הגדרות הווידג\'ט"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"צריך להקיש כדי לסיים את תהליך ההגדרה"</string>
@@ -99,12 +99,12 @@
<string name="folder_renamed" msgid="1794088362165669656">"שם התיקייה שונה ל-<xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"תיקייה: <xliff:g id="NAME">%1$s</xliff:g>, מספר הפריטים: <xliff:g id="SIZE">%2$d</xliff:g>"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"תיקייה: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> פריטים או יותר"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"טפטים"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"טפט וסגנון"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"עריכה של מסך הבית"</string>
<string name="settings_button_text" msgid="8873672322605444408">"הגדרות של מסך הבית"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"הושבת על ידי מנהל המערכת שלך"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"אישור לסיבוב מסך הבית"</string>
- <string name="allow_rotation_desc" msgid="8662546029078692509">"כאשר הטלפון מסובב"</string>
+ <string name="allow_rotation_desc" msgid="8662546029078692509">"כאשר מסובבים את הטלפון"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"סימני ההתראות"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"מופעל"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"כבוי"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"האפליקציות לעבודה מתויגות ומוצגות למנהל ה-IT"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"הבנתי"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"האפליקציות לעבודה מושהות"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"לא יתקבלו התראות מהאפליקציות לעבודה"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"האפליקציות לעבודה לא יכולות לשלוח לך התראות, להשתמש בסוללה או לגשת למיקום שלך"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"האפליקציות לעבודה מושבתות. האפליקציות לא יכולות לשלוח לך התראות, להשתמש בסוללה או לגשת למיקום שלך"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"לא יתקבלו שיחות טלפון, הודעות טקסט או התראות מהאפליקציות לעבודה"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"האפליקציות לעבודה מתויגות ומוצגות למנהל ה-IT"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"הבנתי"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"השהיית האפליקציות לעבודה"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"הפעלה של אפליקציות לעבודה"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"ביטול ההשהיה"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"סינון"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"חיפוש בטלפון"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"חיפוש בטאבלט"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 117ba4d..a6b1a21 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"ホーム"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"分割画面"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s のアプリ情報"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"アプリのペア設定を保存"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"長押ししてウィジェットを移動させます。"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"ウィジェットをダブルタップして長押ししながら移動するか、カスタム操作を使用してください。"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$dx%2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"ウィジェットを押し続けると、ホーム画面上に移動できます"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"ホーム画面に追加"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"「<xliff:g id="WIDGET_NAME">%1$s</xliff:g>」ウィジェットをホーム画面に追加しました"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"候補"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 件のウィジェット}other{# 件のウィジェット}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# 件のショートカット}other{# 件のショートカット}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>、<xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"個人用"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"仕事用"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"会話"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"メモ"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ウィジェットで情報を得る"</string>
<string name="widget_education_content" msgid="1731667670753497052">"ホーム画面にウィジェットを追加すると、アプリを開かずに情報を入手できます"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"タップしてウィジェットの設定を変更する"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"ホームの設定とショートカットの読み取りをアプリに許可します。"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"ホームの設定とショートカットの書き込み"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"ホームの設定とショートカットの変更をアプリに許可します。"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」から電話をかけることはできません"</string>
<string name="gadget_error_text" msgid="740356548025791839">"ウィジェットを読み込めません"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"ウィジェットの設定"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"タップして設定を完了してください"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"フォルダの名前を「<xliff:g id="NAME">%1$s</xliff:g>」に変更しました"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"フォルダ: <xliff:g id="NAME">%1$s</xliff:g>、<xliff:g id="SIZE">%2$d</xliff:g> 件のアイテム"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"フォルダ: <xliff:g id="NAME">%1$s</xliff:g>、<xliff:g id="SIZE">%2$d</xliff:g> 件以上のアイテム"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"壁紙"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"壁紙とスタイル"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"ホーム画面を編集"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ホームの設定"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"管理者により無効にされています"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"ホーム画面の回転を許可"</string>
@@ -161,13 +161,14 @@
<string name="work_profile_toggle_label" msgid="3081029915775481146">"仕事用プロファイル"</string>
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"仕事用アプリはバッジ付きで表示され、IT 管理者に公開されます"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
- <string name="work_apps_paused_title" msgid="3040901117349444598">"仕事用アプリの一時停止"</string>
+ <string name="work_apps_paused_title" msgid="3040901117349444598">"仕事用アプリは一時停止されています"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"仕事用アプリからの通知は届きません"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"仕事用アプリでは、通知の送信、バッテリーの使用、位置情報の取得が無効になっています"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"仕事用アプリは OFF になっています。仕事用アプリでは、通知の送信、バッテリーの使用、位置情報の取得が無効になっています"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"電話やテキスト メッセージを受信しなくなり、仕事用アプリからの通知も届きません"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"仕事用アプリはバッジが付き、IT 管理者に公開されます"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"仕事用アプリを一時停止"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"仕事用アプリを ON にする"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"停止解除"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"フィルタ"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"スマートフォンを検索"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"タブレットを探す"</string>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index c563e36..7e79faa 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"მთავარი გვერდი"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"ეკრანის გაყოფა"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s-ის აპის ინფო"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"აპთა წყვილის შენახვა"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"შეხებით აირჩიეთ და გეჭიროთ ვიჯეტის გადასაადგილებლად."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"ორმაგი შეხებით აირჩიეთ და გეჭიროთ ვიჯეტის გადასაადგილებლად ან მორგებული მოქმედებების გამოსაყენებლად."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"ხანგრძლივად შეეხეთ ვიჯეტს მთავარ ეკრანზე მის გადასაადგილებლად"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"მთავარ ეკრანზე დამატება"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ვიჯეტი დამატებულია მთავარ ეკრანზე"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"შეთავაზებები"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ვიჯეტი}other{# ვიჯეტი}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# მალსახმობი}other{# მალსახმობი}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"პირადი"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"სამსახური"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"მიმოწერები"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"ჩანიშვნა"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ადვილად მისაწვდომი სასარგებლო ინფორმაცია"</string>
<string name="widget_education_content" msgid="1731667670753497052">"იმისთვის, რომ ინფორმაცია აპების გაუხსნელად მიიღოთ, შეგიძლიათ, მთავარ ეკრანზე ვიჯეტები დაამატოთ"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"შეეხეთ ვიჯეტის პარამეტრების შესაცვლელად"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"აპისთვის მთავარი ეკრანის პარამეტრებისა და მალსახმობების წაკითხვის უფლების მიცემა."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"მთავარი ეკრანის პარამეტრებისა და მალსახმობების ჩაწერა"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"აპისთვის მთავარი ეკრანის პარამეტრებისა და მალსახმობების შეცვლის უფლების მიცემა."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ს არ აქვს სატელეფონო ზარების განხორციელების უფლება"</string>
<string name="gadget_error_text" msgid="740356548025791839">"ვიჯეტის ჩატვირთვა ვერ ხერხდება"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"ვიჯეტის პარამეტრები"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"შეეხეთ დაყენების დასასრულებლად"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"საქაღალდეს შეეცვალა სახელი „<xliff:g id="NAME">%1$s</xliff:g>“-ად"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"საქაღალდე: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ერთეული"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"საქაღალდე: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ან მეტი ერთეული"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"ფონები"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ფონი და სტილი"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"მთავარი ეკრანის რედაქტირება"</string>
<string name="settings_button_text" msgid="8873672322605444408">"მთავარი გვერდის პარამეტრები"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"გათიშულია თქვენი ადმინისტრატორის მიერ"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"მთავარი ეკრანის შეტრიალების დაშვება"</string>
@@ -159,15 +159,16 @@
<string name="all_apps_personal_tab" msgid="4190252696685155002">"პირადი"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"სამსახური"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"სამსახურის პროფილი"</string>
- <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"სამსახურის აპები ბეჯით არის მონიშნული და ხილულია IT ადმინისტრატორისთვის"</string>
+ <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"სამსახურის აპები ბეჯით არის მონიშნული და ხილულია თქვენი IT ადმინისტრატორისთვის"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"გასაგებია"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"სამსახურის აპები დაპაუზებულია"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"თქვენ არ მიიღებთ შეტყობინებებს თქვენი სამსახურის აპებიდან"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"თქვენს სამსახურის აპებს არ შეუძლია თქვენთვის შეტყობინებების გამოგზავნა, თქვენი ბატარეის გამოყენება, ან თქვენს მდებარეობაზე წვდომა"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"სამსახურის აპები გამორთულია. თქვენს სამსახურის აპებს არ შეუძლია თქვენთვის შეტყობინებების გამოგზავნა, თქვენი ბატარეის გამოყენება, ან თქვენს მდებარეობაზე წვდომა"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"თქვენ არ მიიღებთ სატელეფონო ზარებს, ტექსტურ შეტყობინებებს ან შეტყობინებებს თქვენი სამსახურის აპებიდან"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"სამსახურის აპები ბეჯით არის მონიშნული და ხილულია IT ადმინისტრატორისთვის"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"გასაგებია"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"სამსახურის აპების დაპაუზება"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"სამსახურის აპების ჩართვა"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"პაუზის გაუქმება"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"ფილტრი"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"მოიძიეთ თქვენს ტელეფონში"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"ძიება თქვენს ტაბლეტში"</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index 1a28773..cb514d8 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Негізгі экран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Экранды бөлу"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s қолданбасы туралы ақпарат"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Қолданбаларды жұптау әрекетін сақтау"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Виджетті жылжыту үшін басып тұрыңыз."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Виджетті жылжыту үшін екі рет түртіңіз де, ұстап тұрыңыз немесе арнаулы әрекеттерді пайдаланыңыз."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Негізгі экран бойынша жылжыту үшін виджетті басып ұстаңыз."</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Негізгі экранға қосу"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджеті негізгі экранға енгізілді."</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Ұсыныстар"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}other{# виджет}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# таңбаша}other{# таңбаша}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Жеке виджеттер"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Жұмыс виджеттері"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Әңгімелер"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Ескертпе жазу"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Саусақпен түртсеңіз болғаны – пайдалы ақпарат көз алдыңызда"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Қолданбаларды ашпай-ақ ақпарат алу үшін негізгі экранға тиісті виджеттерді қосыңыз."</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Виджет параметрлерін өзгерту үшін түртіңіз."</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Қолданбаға негізгі экрандағы параметрлер мен таңбашаларды оқуға мүмкіндік береді."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"негізгі экран параметрлері мен таңбашаларын жазу"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Қолданбаға негізгі экрандағы параметрлер мен таңбашаларды өзгертуге мүмкіндік береді."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> арқылы телефон қоңырауларын соғуға рұқсат етілмеген"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Виджетті жүктеу мүмкін емес."</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Виджет параметрлері"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Реттеуді аяқтау үшін түртіңіз."</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Қалта атауы <xliff:g id="NAME">%1$s</xliff:g> болып өзгертілді"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Қалта: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> элемент бар"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Қалта: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> не одан көп элемент бар"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Тұсқағаздар"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Тұсқағаз және стиль"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Негізгі экранды өзгерту"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Негізгі экран параметрлері"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Әкімші өшірді"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Негізгі экранды бұруға рұқсат ету"</string>
@@ -151,7 +151,7 @@
<string name="action_decrease_width" msgid="1374549771083094654">"Енін азайту"</string>
<string name="action_decrease_height" msgid="282377193880900022">"Биіктігін азайту"</string>
<string name="widget_resized" msgid="9130327887929620">"Виджет өлшемінің ені <xliff:g id="NUMBER_0">%1$s</xliff:g>, биіктігі <xliff:g id="NUMBER_1">%2$s</xliff:g> болып өзгертілді"</string>
- <string name="action_deep_shortcut" msgid="2864038805849372848">"Таңбашалар"</string>
+ <string name="action_deep_shortcut" msgid="2864038805849372848">"Жылдам пәрмендер"</string>
<string name="shortcuts_menu_with_notifications_description" msgid="2676582286544232849">"Таңбашалар мен хабарландырулар"</string>
<string name="action_dismiss_notification" msgid="5909461085055959187">"Бас тарту"</string>
<string name="accessibility_close" msgid="2277148124685870734">"Жабу"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Жұмыс қолданбаларының танымбелгілері бар және олар әкімшіңізге көрінеді."</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Түсінікті"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Жұмыс қолданбалары кідіртілді"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Жұмыс қолданбаларынан хабарландырулар алмайсыз."</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Жұмыс қолданбалары сізге хабарландырулар жібере, батареяңызды немесе локацияңызды пайдалана алмайды."</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Жұмыс қолданбалары өшірулі. Олар сізге хабарландырулар жібере, батареяңызды немесе локацияңызды пайдалана алмайды."</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Жұмыс қолданбаларынан телефон қоңырауларын, мәтіндік хабарлар немесе хабарландырулар алмайсыз."</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Жұмыс қолданбаларының танымбелгілері бар және олар әкімшіңізге көрінеді."</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Түсінікті"</string>
- <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Жұмыс қолданбаларын тоқтата тұру"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Жұмыс қолданбаларын қосу"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Жұмыс қолданбаларын кідірту"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Қайта қосу"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Сүзгі"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Телефоннан іздеу"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Планшеттен іздеу"</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index fcde08f..bdb9f0d 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"អេក្រង់ដើម"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"មុខងារបំបែកអេក្រង់"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"ព័ត៌មានកម្មវិធីសម្រាប់ %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"រក្សាទុកគូកម្មវិធី"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"ចុចឱ្យជាប់ដើម្បីផ្លាស់ទីធាតុក្រាហ្វិក។"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"ចុចពីរដង រួចសង្កត់ឱ្យជាប់ ដើម្បីផ្លាស់ទីធាតុក្រាហ្វិក ឬប្រើសកម្មភាពតាមបំណង។"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"ចុចលើធាតុក្រាហ្វិកឱ្យជាប់ ដើម្បីផ្លាស់ទីវាជុំវិញអេក្រង់ដើម"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"បញ្ចូលទៅក្នុងអេក្រង់ដើម"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"បានបញ្ចូលធាតុក្រាហ្វិក <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ទៅអេក្រង់ដើម"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"ការណែនាំ"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ធាតុក្រាហ្វិក #}other{ធាតុក្រាហ្វិក #}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{ផ្លូវកាត់ #}other{ផ្លូវកាត់ #}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"ផ្ទាល់ខ្លួន"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ការងារ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"ការសន្ទនា"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"ការកត់ត្រា"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ទទួលបានព័ត៌មានដែលមានប្រយោជន៍យ៉ាងងាយស្រួល"</string>
<string name="widget_education_content" msgid="1731667670753497052">"ដើម្បីទទួលបានព័ត៌មានដោយមិនចាំបាច់បើកកម្មវិធី អ្នកអាចបញ្ចូលធាតុក្រាហ្វិកទៅក្នុងអេក្រង់ដើមរបស់អ្នក"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ចុចដើម្បីប្ដូរការកំណត់ធាតុក្រាហ្វិក"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"អនុញ្ញាតឱ្យកម្មវិធីអានការកំណត់ និងផ្លូវកាត់នៅក្នុងអេក្រង់ដើម។"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"សរសេរការកំណត់ និងផ្លូវកាត់សម្រាប់អេក្រង់ដើម"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"អនុញ្ញាតឱ្យកម្មវិធីប្ដូរការកំណត់ និងផ្លូវកាត់នៅក្នុងអេក្រង់ដើម។"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> មិនត្រូវបានអនុញ្ញាតឲ្យធ្វើការហៅទូរស័ព្ទទេ"</string>
<string name="gadget_error_text" msgid="740356548025791839">"មិនអាចផ្ទុកធាតុក្រាហ្វិកបានទេ"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"ការកំណត់ធាតុក្រាហ្វិក"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"ចុចដើម្បីបញ្ចប់ការរៀបចំ"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"បានប្ដូរឈ្មោះថតជា <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"ថត៖ <xliff:g id="NAME">%1$s</xliff:g>, ធាតុ <xliff:g id="SIZE">%2$d</xliff:g>"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ថត៖ <xliff:g id="NAME">%1$s</xliff:g>, ធាតុ <xliff:g id="SIZE">%2$d</xliff:g> ឬច្រើនជាងនេះ"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"ផ្ទាំងរូបភាព"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ផ្ទាំងរូបភាព និងរចនាប័ទ្ម"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"កែអេក្រង់ដើម"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ការកំណត់ទំព័រដើម"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"បានបិទដំណើរការដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"អនុញ្ញាតការបងិ្វលអេក្រង់ដើម"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"កម្មវិធីការងារត្រូវបានដាក់គ្រឿងសម្គាល់ ហើយអ្នកគ្រប់គ្រងផ្នែកព័ត៌មានវិទ្យារបស់អ្នកអាចមើលឃើញ"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"យល់ហើយ"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"កម្មវិធីការងារត្រូវបានផ្អាក"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"អ្នកនឹងមិនទទួលបានការជូនដំណឹងពីកម្មវិធីការងាររបស់អ្នកទេ"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"កម្មវិធីការងាររបស់អ្នកមិនអាចផ្ញើការជូនដំណឹងទៅអ្នក ប្រើប្រាស់ថ្មរបស់អ្នក ឬចូលប្រើទីតាំងរបស់អ្នកបានទេ"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"កម្មវិធីការងារត្រូវបានបិទ។ កម្មវិធីការងាររបស់អ្នកមិនអាចផ្ញើការជូនដំណឹងទៅអ្នក ប្រើប្រាស់ថ្មរបស់អ្នក ឬចូលប្រើទីតាំងរបស់អ្នកបានទេ"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"អ្នកនឹងមិនទទួលបានការហៅទូរសព្ទ សារជាអក្សរ ឬការជូនដំណឹងពីកម្មវិធីការងាររបស់អ្នកទេ"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"កម្មវិធីការងារត្រូវបានដាក់គ្រឿងសម្គាល់ ហើយអ្នកគ្រប់គ្រងផ្នែកព័ត៌មានវិទ្យារបស់អ្នកអាចមើលឃើញ"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"យល់ហើយ"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ផ្អាកកម្មវិធីការងារ"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"បើកកម្មវិធីការងារ"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"ឈប់ផ្អាក"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"តម្រង"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"ស្វែងរកក្នុងទូរសព្ទរបស់អ្នក"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"ស្វែងរកក្នុងថេប្លេតរបស់អ្នក"</string>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index e15b94e..a35a70b 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"ಹೋಮ್"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ಗಾಗಿ ಆ್ಯಪ್ ಮಾಹಿತಿ"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"ಆ್ಯಪ್ ಜೋಡಿ ಉಳಿಸಿ"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"ವಿಜೆಟ್ ಸರಿಸಲು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"ವಿಜೆಟ್ ಸರಿಸಲು ಅಥವಾ ಕಸ್ಟಮ್ ಕ್ರಿಯೆಗಳನ್ನು ಬಳಸಲು ಡಬಲ್-ಟ್ಯಾಪ್ ಮಾಡಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ ಸುತ್ತ ವಿಜೆಟ್ ಅನ್ನು ಸರಿಸಲು, ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಒತ್ತಿ ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ಗೆ ಸೇರಿಸಿ"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"ಹೋಮ್ಸ್ಕ್ರೀನ್ಗೆ <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ವಿಜೆಟ್ ಅನ್ನು ಸೇರಿಸಲಾಗಿದೆ"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"ಸಲಹೆಗಳು"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ವಿಜೆಟ್}one{# ವಿಜೆಟ್ಗಳು}other{# ವಿಜೆಟ್ಗಳು}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ಶಾರ್ಟ್ಕಟ್}one{# ಶಾರ್ಟ್ಕಟ್ಗಳು}other{# ಶಾರ್ಟ್ಕಟ್ಗಳು}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,17 +50,18 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"ವೈಯಕ್ತಿಕ"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ಕೆಲಸ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"ಸಂಭಾಷಣೆಗಳು"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"ಟಿಪ್ಪಣಿ ತೆಗೆದುಕೊಳ್ಳುವುದು"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ನಿಮ್ಮ ಬೆರಳ ತುದಿಯಲ್ಲಿ ಉಪಯುಕ್ತ ಮಾಹಿತಿ"</string>
<string name="widget_education_content" msgid="1731667670753497052">"ಆ್ಯಪ್ಗಳನ್ನು ತೆರೆಯದೆಯೇ ಮಾಹಿತಿಯನ್ನು ಪಡೆಯಲು, ನಿಮ್ಮ ಹೋಮ್ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ನೀವು ವಿಜೆಟ್ಗಳನ್ನು ಸೇರಿಸಬಹುದು"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ವಿಜೆಟ್ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="widget_education_close_button" msgid="8676165703104836580">"ಅರ್ಥವಾಯಿತು"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"ವಿಜೆಟ್ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಬದಲಾಯಿಸಿ"</string>
- <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಹುಡುಕಿ"</string>
+ <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"ಆ್ಯಪ್ಗಳನ್ನು ಹುಡುಕಿ"</string>
<string name="all_apps_loading_message" msgid="5813968043155271636">"ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ..."</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" ಹೊಂದಿಕೆಯ ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್ಗಳು ಕಂಡುಬಂದಿಲ್ಲ"</string>
<string name="label_application" msgid="8531721983832654978">"ಆ್ಯಪ್"</string>
<string name="all_apps_label" msgid="5015784846527570951">"ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳು"</string>
- <string name="notifications_header" msgid="1404149926117359025">"ಅಧಿಸೂಚನೆಗಳು"</string>
+ <string name="notifications_header" msgid="1404149926117359025">"ನೋಟಿಫಿಕೇಶನ್ಗಳು"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"ಶಾರ್ಟ್ಕಟ್ ಸರಿಸಲು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"ಶಾರ್ಟ್ಕಟ್ ಸರಿಸಲು ಅಥವಾ ಕಸ್ಟಮ್ ಕ್ರಿಯೆಗಳನ್ನು ಬಳಸಲು ಡಬಲ್-ಟ್ಯಾಪ್ ಮಾಡಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
<string name="out_of_space" msgid="6455557115204099579">"ಈ ಹೋಮ್ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ಸ್ಥಳಾವಕಾಶವಿಲ್ಲ"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ಸೆಟ್ಟಿಂಗ್ಗಳು ಮತ್ತು ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಓದಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ ಸೆಟ್ಟಿಂಗ್ಗಳು ಮತ್ತು ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಬರೆಯಿರಿ"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ಸೆಟ್ಟಿಂಗ್ಗಳು ಮತ್ತು ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"ಫೋನ್ ಕರೆಗಳನ್ನು ಮಾಡಲು <xliff:g id="APP_NAME">%1$s</xliff:g> ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ"</string>
<string name="gadget_error_text" msgid="740356548025791839">"ವಿಜೆಟ್ ಅನ್ನು ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"ವಿಜೆಟ್ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"ಸೆಟಪ್ ಪೂರ್ಣಗೊಳಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
@@ -99,19 +99,19 @@
<string name="folder_renamed" msgid="1794088362165669656">"ಫೋಲ್ಡರ್ ಅನ್ನು <xliff:g id="NAME">%1$s</xliff:g> ಗೆ ಮರುಹೆಸರಿಸಲಾಗಿದೆ"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"ಫೋಲ್ಡರ್: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ಐಟಂಗಳು"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ಫೋಲ್ಡರ್: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ಅಥವಾ ಹೆಚ್ಚಿನ ಐಟಂಗಳು"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"ವಾಲ್ಪೇಪರ್ಗಳು"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ವಾಲ್ಪೇಪರ್ ಮತ್ತು ಶೈಲಿ"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ಮುಖಪುಟ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದ್ದಾರೆ"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ ತಿರುಗುವಿಕೆಯನ್ನು ಅನುಮತಿಸಿ"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"ಫೋನ್ ತಿರುಗಿಸಿದಾಗ"</string>
- <string name="notification_dots_title" msgid="9062440428204120317">"ಅಧಿಸೂಚನೆ ಡಾಟ್ಗಳು"</string>
+ <string name="notification_dots_title" msgid="9062440428204120317">"ನೋಟಿಫಿಕೇಶನ್ ಡಾಟ್ಗಳು"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"ಆನ್ ಆಗಿದೆ"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"ಆಫ್ ಆಗಿದೆ"</string>
- <string name="title_missing_notification_access" msgid="7503287056163941064">"ಅಧಿಸೂಚನೆ ಪ್ರವೇಶ ಅಗತ್ಯವಿದೆ"</string>
- <string name="msg_missing_notification_access" msgid="281113995110910548">"ಅಧಿಸೂಚನೆ ಚುಕ್ಕೆಗಳನ್ನು ತೋರಿಸಲು, <xliff:g id="NAME">%1$s</xliff:g> ಗೆ ಅಪ್ಲಿಕೇಶನ್ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆನ್ ಮಾಡಿ"</string>
+ <string name="title_missing_notification_access" msgid="7503287056163941064">"ನೋಟಿಫಿಕೇಶನ್ ಆ್ಯಕ್ಸೆಸ್ ಅಗತ್ಯವಿದೆ"</string>
+ <string name="msg_missing_notification_access" msgid="281113995110910548">"ನೋಟಿಫಿಕೇಶನ್ ಚುಕ್ಕೆಗಳನ್ನು ತೋರಿಸಲು, <xliff:g id="NAME">%1$s</xliff:g> ಗೆ ಆ್ಯಪ್ ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು ಆನ್ ಮಾಡಿ"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಬದಲಾಯಿಸಿ"</string>
- <string name="notification_dots_service_title" msgid="4284221181793592871">"ಅಧಿಸೂಚನೆ ಡಾಟ್ಗಳನ್ನು ತೋರಿಸಿ"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"ನೋಟಿಫಿಕೇಶನ್ ಡಾಟ್ಗಳನ್ನು ತೋರಿಸಿ"</string>
<string name="developer_options_title" msgid="700788437593726194">"ಡೆವಲಪರ್ ಆಯ್ಕೆಗಳು"</string>
<string name="auto_add_shortcuts_label" msgid="4926805029653694105">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ಗೆ ಆ್ಯಪ್ ಐಕಾನ್ಗಳನ್ನು ಸೇರಿಸಿ"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ಹೊಸ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗೆ"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳನ್ನು ಬ್ಯಾಡ್ಜ್ ಮಾಡಲಾಗಿದೆ ಮತ್ತು ಅವುಗಳು ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರಿಗೆ ಗೋಚರಿಸುತ್ತವೆ"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"ಸರಿ"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"ನಿಮ್ಮ ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳಿಂದ ನೀವು ಅಧಿಸೂಚನೆಗಳನ್ನು ಸ್ವೀಕರಿಸುವುದಿಲ್ಲ"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"ನಿಮ್ಮ ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳಿಗೆ ನಿಮಗೆ ಅಧಿಸೂಚನೆಗಳನ್ನು ಕಳುಹಿಸಲು, ನಿಮ್ಮ ಬ್ಯಾಟರಿಯನ್ನು ಬಳಸಲು ಅಥವಾ ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಾಗದು"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳು ಆಫ್ ಆಗಿವೆ. ನಿಮ್ಮ ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳು ನಿಮಗೆ ಅಧಿಸೂಚನೆಗಳನ್ನು ಕಳುಹಿಸಲು, ನಿಮ್ಮ ಬ್ಯಾಟರಿಯನ್ನು ಬಳಸಲು ಅಥವಾ ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"ನಿಮ್ಮ ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳಿಂದ ನೀವು ಫೋನ್ ಕರೆಗಳು, ಪಠ್ಯ ಸಂದೇಶಗಳು ಅಥವಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ಸ್ವೀಕರಿಸುವುದಿಲ್ಲ"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳು ಬ್ಯಾಡ್ಜ್ ಮಾಡಲಾಗಿದೆ ಮತ್ತು ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರಿಗೆ ಗೋಚರಿಸುತ್ತದೆ"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"ಅರ್ಥವಾಯಿತು"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳನ್ನು ವಿರಾಮಗೊಳಿಸಿ"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳನ್ನು ಆನ್ ಮಾಡಿ"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"ವಿರಾಮವನ್ನು ರದ್ದುಗೊಳಿಸಿ"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"ಫಿಲ್ಟರ್"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ಹುಡುಕಿ"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಹುಡುಕಿ"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 48ca19d..955af0b 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"홈"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"화면 분할"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s 앱 정보"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"앱 페어링 저장"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"길게 터치하여 위젯을 이동하세요."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"두 번 탭한 다음 길게 터치하여 위젯을 이동하거나 맞춤 작업을 사용하세요."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"홈 화면에서 위젯을 이동하려면 길게 터치하세요."</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"홈 화면에 추가"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> 위젯이 홈 화면에 추가됨"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"추천"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{위젯 #개}other{위젯 #개}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{바로가기 #개}other{바로가기 #개}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"개인 위젯"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"직장 위젯"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"대화"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"메모"</string>
<string name="widget_education_header" msgid="4874760613775913787">"빠르게 유용한 정보 확인"</string>
<string name="widget_education_content" msgid="1731667670753497052">"앱을 열지 않고 정보를 확인하려면 홈 화면에 위젯을 추가하세요."</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"탭하여 위젯 설정 변경"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"앱이 홈에 있는 설정 및 바로가기를 읽을 수 있도록 허용합니다."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"홈 설정 및 바로가기 쓰기"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"앱이 홈에 있는 설정 및 바로가기를 변경할 수 있도록 허용합니다."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 전화를 걸 수 없습니다."</string>
<string name="gadget_error_text" msgid="740356548025791839">"위젯을 로드할 수 없습니다."</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"위젯 설정"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"탭하여 설정을 완료하세요."</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"폴더 이름 변경: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"폴더: <xliff:g id="NAME">%1$s</xliff:g>, 항목 <xliff:g id="SIZE">%2$d</xliff:g>개"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"폴더: <xliff:g id="NAME">%1$s</xliff:g>, 항목 <xliff:g id="SIZE">%2$d</xliff:g>개 이상"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"배경화면"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"배경화면 및 스타일"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"홈 화면 수정"</string>
<string name="settings_button_text" msgid="8873672322605444408">"홈 설정"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"관리자가 사용 중지함"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"홈 화면 회전 허용"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"직장 앱에는 배지가 있으며, IT 관리자는 직장 앱을 확인할 수 있습니다"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"확인"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"직장 앱이 일시중지됨"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"직장 앱에서 보내는 알림을 받지 않게 됩니다."</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"직장 앱에서 알림을 보내거나 배터리를 사용하거나 위치 정보에 액세스할 수 없습니다."</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"직장 앱이 꺼져 있습니다. 직장 앱에서 알림을 보내거나 배터리를 사용하거나 위치 정보에 액세스할 수 없습니다."</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"전화, 문자 메시지 또는 직장 앱에서 보내는 알림을 수신하지 않습니다."</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"직장 앱에는 배지가 있으며, IT 관리자는 직장 앱을 확인할 수 있습니다."</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"확인"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"직장 앱 일시중지"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"직장 앱 사용 설정"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"일시중지 해제"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"필터"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"휴대전화 속 항목 검색"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"태블릿 속 항목 검색"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index a2a3f0c..7d77440 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Башкы экран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Экранды бөлүү"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s колдонмосу жөнүндө маалымат"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Эки колдонмону бир маалда пайдаланууну сактоо"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Виджетти кое бербей басып туруп жылдырыңыз."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Виджетти жылдыруу үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Башкы экранга жылдыруу үчүн виджетти коё бербей басып туруңуз"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Башкы экранга кошуу"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджети башкы экранга кошулду"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Сунуштар"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}other{# виджет}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ыкчам баскыч}other{# ыкчам баскыч}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Жеке виджеттер"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Жумуш"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Сүйлөшүүлөр"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Эскертме жазуу"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Керектүү маалымат манжаңыздын учунда"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Бир нерсе билүү үчүн колдонмолорду улам ачып убара болбостон, башкы экранга виджеттерди кошуп коюңуз."</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Виджеттин параметрлерин өзгөртүү үчүн таптап коюңуз"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Колдонмого үйдүн параметрлерин жана ыкчам баскычтарын окууга уруксат берет."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"үйдүн параметрлерин жана ыкчам баскычтарын жазуу"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Колдонмого үйдүн параметрлерин жана ыкчам баскычтарын өзгөртүүгө уруксат берет."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> телефон чалууларды аткарууга уруксаты жок"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Виджет жүктөлбөй жатат"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Виджеттин параметрлери"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Аягына чейин тууралоо үчүн басып коюңуз"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Фолдердин аты <xliff:g id="NAME">%1$s</xliff:g> деп өзгөртүлдү"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"<xliff:g id="NAME">%1$s</xliff:g> папкасындагы объекттер: <xliff:g id="SIZE">%2$d</xliff:g>"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"<xliff:g id="NAME">%1$s</xliff:g> папкасындагы объекттер: <xliff:g id="SIZE">%2$d</xliff:g> же андан көбүрөөк"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Тушкагаздар"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Тушкагаз жана стиль"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Башкы экранды түзөтүү"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Башкы бет параметрлери"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Администраторуңуз өчүрүп койгон"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Башкы экранды бурууга уруксат берүү"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Жумуш колдонмолору белгиленип, аларды IT администраторлору көрөт"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Түшүндүм"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Жумуш колдонмолору тындырылды"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Жумуш колдонмолоруңуздан билдирмелерди албайсыз"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Жумуш колдонмолору билдирмелерди жөнөтүп, түзмөгүңүздүн батареясын керектеп же кайда жүргөнүңүздү көрө албайт"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Жумуш колдонмолору өчүк жана билдирмелерди жөнөтүп, түзмөгүңүздүн батареясын керектеп же кайда жүргөнүңүздү көрө албайт"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Жумуш колдонмолоруңуздан телефон чалууларды, текст түрүндөгү билдирүүлөрдү же билдирмелерди албайсыз"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Жумуш колдонмолору белгиленип, аларды IT администраторлору көрөт"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Түшүндүм"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Жумуш колдонмолорун тындыруу"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Жумуш колдонмолорун күйгүзүү"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Улантуу"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Чыпкалоо"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Телефондо издөө"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Планшетте издөө"</string>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 2de7cc1..9c26cfa 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"ໂຮມສະກຣີນ"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"ແບ່ງໜ້າຈໍ"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"ຂໍ້ມູນແອັບສຳລັບ %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"ບັນທຶກຈັບຄູ່ແອັບ"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"ແຕະຄ້າງໄວ້ເພື່ອຍ້າຍວິດເຈັດ."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"ແຕະສອງເທື່ອຄ້າງໄວ້ເພື່ອຍ້າຍວິດເຈັດ ຫຼື ໃຊ້ຄຳສັ່ງກຳນົດເອງ."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"ແຕະໃສ່ວິດເຈັດຄ້າງໄວ້ເພື່ອຍ້າຍມັນໄປມາຢູ່ໂຮມສະກຣີນ"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"ເພີ່ມໃສ່ໂຮມສະກຣີນ"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"ເພີ່ມວິດເຈັດ <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ໃສ່ໂຮມສະກຣີນແລ້ວ"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"ການແນະນຳ"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ວິດເຈັດ}other{# ວິດເຈັດ}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ທາງລັດ}other{# ທາງລັດ}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"ສ່ວນຕົວ"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ວຽກ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"ການສົນທະນາ"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"ການຈົດບັນທຶກ"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ຂໍ້ມູນທີ່ເປັນປະໂຫຍດຢູ່ປາຍນິ້ວຂອງທ່ານ"</string>
<string name="widget_education_content" msgid="1731667670753497052">"ເພື່ອຮັບຂໍ້ມູນໂດຍບໍ່ຕ້ອງເປີດແອັບ, ທ່ານສາມາດເພີ່ມວິດເຈັດໃສ່ໂຮມສະກຣີນຂອງທ່ານໄດ້"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ແຕະເພື່ອປ່ຽນການຕັ້ງຄ່າວິດເຈັດ"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"ອະນຸຍາດໃຫ້ແອັບອ່ານການຕັ້ງຄ່າ ແລະ ທາງລັດໃນໜ້າຫຼັກ."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"ຂຽນການຕັ້ງຄ່າໜ້າຫຼັກ ແລະ ທາງລັດ"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"ອະນຸຍາດໃຫ້ແອັບປ່ຽນການຕັ້ງຄ່າ ແລະ ທາງລັດໃນໜ້າຫຼັກ."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ່ໄດ້ຮັບອະນຸຍາດໃຫ້ໂທ"</string>
<string name="gadget_error_text" msgid="740356548025791839">"ບໍ່ສາມາດໂຫຼດວິດເຈັດໄດ້"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"ການຕັ້ງຄ່າວິດເຈັດ"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"ແຕະເພື່ອຕັ້ງຄ່າໃຫ້ແລ້ວ"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"ປ່ຽນຊື່ໂຟນເດີເປັນ <xliff:g id="NAME">%1$s</xliff:g> ແລ້ວ"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"ໂຟນເດີ: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ລາຍການ"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ໂຟນເດີ: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ຫຼື ລາຍການເພີ່ມເຕີມ"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"ພາບພື້ນຫຼັງ"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ຮູບພື້ນຫຼັງ ແລະ ຮູບແບບ"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"ແກ້ໄຂໂຮມສະກຣີນ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ການຕັ້ງຄ່າໜ້າຫຼັກ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ຖືກປິດການນຳໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"ອະນຸຍາດໃຫ້ໝຸນໜ້າຈໍຢູ່ໂຮມສະກຣີນໄດ້"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"ແອັບບ່ອນເຮັດວຽກແມ່ນຖືກຕິດປ້າຍ ແລະ ສະແດງໃຫ້ຜູ້ເບິ່ງແຍງໄອທີຂອງທ່ານເຫັນ"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"ເຂົ້າໃຈແລ້ວ"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"ຢຸດແອັບວຽກໄວ້ຊົ່ວຄາວແລ້ວ"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"ທ່ານຈະບໍ່ໄດ້ຮັບການແຈ້ງເຕືອນຈາກແອັບບ່ອນເຮັດວຽກຂອງທ່ານ"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"ແອັບບ່ອນເຮັດວຽກຂອງທ່ານຈະບໍ່ສາມາດສົ່ງການແຈ້ງເຕືອນຫາທ່ານ, ໃຊ້ແບັດເຕີຣີຂອງທ່ານ ຫຼື ເຂົ້າເຖິງສະຖານທີ່ຂອງທ່ານໄດ້"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"ແອັບບ່ອນເຮັດວຽກຖືກປິດໄວ້ຢູ່. ແອັບບ່ອນເຮັດວຽກຂອງທ່ານຈະບໍ່ສາມາດສົ່ງການແຈ້ງເຕືອນໃຫ້ທ່ານ, ໃຊ້ແບັດເຕີຣີຂອງທ່ານ ຫຼື ເຂົ້າເຖິງສະຖານທີ່ຂອງທ່ານໄດ້"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"ທ່ານຈະບໍ່ໄດ້ຮັບສາຍໂທເຂົ້າ, ຂໍ້ຄວາມ ຫຼື ການແຈ້ງເຕືອນຈາກແອັບບ່ອນເຮັດວຽກຂອງທ່ານ"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"ແອັບບ່ອນເຮັດວຽກແມ່ນຖືກຕິດປ້າຍ ແລະ ສະແດງໃຫ້ຜູ້ເບິ່ງແຍງໄອທີຂອງທ່ານເຫັນ"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"ເຂົ້າໃຈແລ້ວ"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ຢຸດແອັບບ່ອນເຮັດວຽກຊົ່ວຄາວ"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ເປີດໃຊ້ແອັບບ່ອນເຮັດວຽກ"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"ຍົກເລີກການຢຸດຊົ່ວຄາວ"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"ກັ່ນຕອງ"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"ຊອກຫາໂທລະສັບຂອງທ່ານ"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"ຊອກຫາແທັບເລັດຂອງທ່ານ"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 93f3d3f..7d69c57 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Pagrindinis"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Išskaidyto ekrano režimas"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Programos „%1$s“ informacija"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Išsaugoti programų porą"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Dukart pal. ir palaik., kad perkeltumėte valdiklį."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dukart palieskite ir palaikykite, kad perkeltumėte valdiklį ar naudotumėte tinkintus veiksmus."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Paliesdami ir palaikydami valdiklį galite judėti pagrindiniame ekrane"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Pridėti prie pagrindinio ekrano"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Valdiklis „<xliff:g id="WIDGET_NAME">%1$s</xliff:g>“ pridėtas prie pagrindinio ekrano"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Pasiūlymai"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# valdiklis}one{# valdiklis}few{# valdikliai}many{# valdiklio}other{# valdiklių}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# spartusis klavišas}one{# spartusis klavišas}few{# spartieji klavišai}many{# sparčiojo klavišo}other{# sparčiųjų klavišų}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Asmeniniai"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Darbas"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Pokalbiai"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Užrašų kūrimas"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Lengvai pasiekiama naudinga informacija"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Jei norite gauti informacijos neatidarę programų, galite pridėti valdiklių pagrindiniame ekrane"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Palieskite, kad pakeistumėte valdiklio nustatymus"</string>
@@ -69,7 +70,7 @@
<string name="all_apps_search_results" msgid="5889367432531296759">"Paieškos rezultatai"</string>
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Asmeninių programų sąrašas"</string>
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Darbo programų sąrašas"</string>
- <string name="remove_drop_target_label" msgid="7812859488053230776">"Ištrinti"</string>
+ <string name="remove_drop_target_label" msgid="7812859488053230776">"Pašalinti"</string>
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Pašalinti"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Programos inform."</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Įdiegti"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Programai leidžiama skaityti pagrindinio ekrano nustatymus ir sparčiuosius klavišus."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"rašyti pagrindinio ekrano nustatymus ir sparčiuosius klavišus"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Programai leidžiama keisti pagrindinio ekrano nustatymus ir sparčiuosius klavišus."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ neleidžiama skambinti"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Nepavyko įkelti valdiklio"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Valdiklio nustatymai"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Palieskite, kad užbaigtumėte sąranką"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Aplankas pervardytas kaip „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Aplankas: „<xliff:g id="NAME">%1$s</xliff:g>“, elementų: <xliff:g id="SIZE">%2$d</xliff:g>"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Aplankas: „<xliff:g id="NAME">%1$s</xliff:g>“, elementų: <xliff:g id="SIZE">%2$d</xliff:g> ar daugiau"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Ekrano fonai"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Ekrano fonas ir stilius"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Redaguoti pagrindinį ekraną"</string>
<string name="settings_button_text" msgid="8873672322605444408">"„Home“ nustatymai"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Išjungė administratorius"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Leisti pasukti pagrindinį ekraną"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Darbo programos yra pažymėtos ženkleliu ir matomos IT administratoriui"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Supratau"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Darbo programos pristabdytos"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Negausite pranešimų iš darbo programų"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Darbo programos negali siųsti jums pranešimų, naudoti jūsų akumuliatoriaus ar pasiekti jūsų vietovės"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Darbo programos išjungtos. Darbo programos negali siųsti jums pranešimų, naudoti jūsų akumuliatoriaus ar pasiekti jūsų vietovės"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Negausite telefonų skambučių, teksto pranešimų ar pranešimų iš darbo programų"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Darbo programos yra pažymėtos ženkleliu ir matomos IT administratoriui"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Supratau"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pristabdyti darbo programas"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Įjungti darbo programas"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Atšaukti pristabdymą"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtruoti"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Paieška telefone"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Paieška planšetiniame kompiuteryje"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index cf6f259..6dc9564 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Sākums"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Sadalīt ekrānu"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s: informācija par lietotni"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Saglabāt lietotņu pāri"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Lai pārvietotu logrīku, pieskarieties un turiet."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Lai pārvietotu logrīku, uz tā veiciet dubultskārienu un turiet. Varat arī veikt pielāgotas darbības."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Pieskarieties logrīkam un turiet to, lai to pārvietotu pa sākuma ekrānu."</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Pievienot sākuma ekrānam"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Logrīks “<xliff:g id="WIDGET_NAME">%1$s</xliff:g>” ir pievienots sākuma ekrānam"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Ieteikumi"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# logrīks}zero{# logrīku}one{# logrīks}other{# logrīki}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# saīsne}zero{# saīšņu}one{# saīsne}other{# saīsnes}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personīgs"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Darba"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Sarunas"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Piezīmju pierakstīšana"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Ērta piekļuve noderīgai informācijai"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Lai iegūtu informāciju, neatverot lietotnes, varat pievienot sākuma ekrānam logrīkus"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Pieskarieties, lai mainītu logrīka iestatījumus."</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Ļauj lietotnei lasīt iestatījumus un saīsnes sākuma ekrānā."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"sākuma ekrāna iestatījumu un saīšņu rakstīšana"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Ļauj lietotnei mainīt iestatījumus un saīsnes sākuma ekrānā."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"Lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g> nav atļauts veikt tālruņa zvanus."</string>
<string name="gadget_error_text" msgid="740356548025791839">"Nevar ielādēt logrīku."</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Logrīka iestatījumi"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Pieskarieties, lai pabeigtu iestatīšanu"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Mape pārdēvēta par: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Mape <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> vienumi"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Mape <xliff:g id="NAME">%1$s</xliff:g>, vienumu skaits mapē: vismaz <xliff:g id="SIZE">%2$d</xliff:g>"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Fona tapetes"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Fona tapete un stils"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Rediģēt sākuma ekrānu"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Sākumlapas iestatījumi"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Atspējojis administrators"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Atļaut sākuma ekrāna pagriešanu"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Darba lietotnēm ir pievienota emblēma, un tās ir redzamas jūsu IT administratoram"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Labi"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Darba lietotnes ir apturētas"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Nesaņemsiet paziņojumus no darba lietotnēm."</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Jūsu darba lietotnes nevar sūtīt jums paziņojumus, izmantot akumulatoru un piekļūt jūsu atrašanās vietai."</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Darba lietotnes ir izslēgtas. Jūsu darba lietotnes nevar sūtīt jums paziņojumus, izmantot akumulatoru un piekļūt jūsu atrašanās vietai."</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Nesaņemsiet tālruņa zvanus, īsziņas un paziņojumus no darba lietotnēm."</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Darba lietotnēm ir pievienota emblēma, un tās ir redzamas jūsu IT administratoram"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Labi"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pārtraukt darba lietotņu darbību"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Ieslēgt darba lietotnes"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Atsākt"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrs"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Meklēšana tālrunī"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Meklēšana planšetdatorā"</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 12bd5fd..eff0e15 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Почетен екран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Поделен екран"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Податоци за апликација за %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Зачувај го парот апликации"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Допрете и задржете за да преместите виџет."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Допрете двапати и задржете за да преместите виџет или користете приспособени дејства."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Допрете го и задржете го виџетот за да го движите наоколу на почетниот екран"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Додај на почетниот екран"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Виџетот <xliff:g id="WIDGET_NAME">%1$s</xliff:g> е додаден на почетниот екран"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Предлози"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виџет}one{# виџет}other{# виџети}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# кратенка}one{# кратенка}other{# кратенки}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Лични"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Работни"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Разговори"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Фаќање белешки"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Корисни информации на дофат на прстите"</string>
<string name="widget_education_content" msgid="1731667670753497052">"За да добивате информации без да ги отворате апликациите, може да додадете виџети на почетниот екран"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Допрете за да ги промените поставките за виџетот"</string>
@@ -81,9 +82,8 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Овозможува апликацијата да ги чита поставките и кратенките на почетната страница."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"да пишува поставки и кратенки на почетна страница"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Овозможува апликацијата да ги менува поставките и кратенките на почетната страница."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> нема дозвола за телефонски повици"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Не може да се вчита виџетот"</string>
- <string name="gadget_setup_text" msgid="8348374825537681407">"Поставки за виџет"</string>
+ <string name="gadget_setup_text" msgid="8348374825537681407">"Поставки за виџетот"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Допрете за да го завршите поставувањето"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ова е системска апликација и не може да се деинсталира."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Изменете го името"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Папката е преименувана во <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Папка: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ставки"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Папка: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> или повеќе ставки"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Тапети"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Тапет и стил"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Изменете го почетниот екран"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Поставки за почетен екран"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Оневозможено од администраторот"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Дозволи ротирање на почетниот екран"</string>
@@ -162,14 +162,15 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Работните апликации имаат значка и се видливи за IT-администраторот"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Сфатив"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Работните апликации се паузирани"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Нема да примате известувања од работните апликации"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Работните апликации не може да ви испраќаат известувања, да ја користат батеријата или да пристапуваат до вашата локација"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Работните апликации се исклучени. Не може да ви испраќаат известувања, да ја користат батеријата или да пристапуваат до вашата локација"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Нема да добивате телефонски повици, текстуални пораки или известувања од работните апликации"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Работните апликации имаат значка и се видливи за IT-администраторот"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Сфатив"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Паузирај ги работните апликации"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Вклучете ги работните апликации"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Прекини ја паузата"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Филтер"</string>
- <string name="search_pref_screen_title" msgid="3258959643336315962">"Пребарувајте на телефонот"</string>
- <string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Пребарувајте на таблетот"</string>
+ <string name="search_pref_screen_title" msgid="3258959643336315962">"Пребарување низ телефонот"</string>
+ <string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Пребарување низ таблетот"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"Не успеа: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index af36000..d7feb3c 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"ഹോം"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"സ്ക്രീൻ വിഭജന മോഡ്"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s എന്നതിന്റെ ആപ്പ് വിവരങ്ങൾ"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"ആപ്പ് ജോടി സംരക്ഷിക്കുക"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"വിജറ്റ് നീക്കാൻ സ്പർശിച്ച് പിടിക്കുക."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"വിജറ്റ് നീക്കാൻ ഡബിൾ ടാപ്പ് ചെയ്യൂ, ഹോൾഡ് ചെയ്യൂ അല്ലെങ്കിൽ ഇഷ്ടാനുസൃത പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കൂ."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"ഹോം സ്ക്രീനിന് ചുറ്റും വിജറ്റ് നീക്കാൻ അതിൽ സ്പർശിച്ച് പിടിക്കുക"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"ഹോം സ്ക്രീനിലേക്ക് ചേർക്കുക"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> വിജറ്റ് ഹോം സ്ക്രീനിലേക്ക് ചേർത്തു"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"നിർദ്ദേശങ്ങൾ"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# വിജറ്റ്}other{# വിജറ്റുകൾ}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# കുറുക്കുവഴി}other{# കുറുക്കുവഴികൾ}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"വ്യക്തിപരം"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ജോലി"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"സംഭാഷണങ്ങൾ"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"കുറിപ്പ് രേഖപ്പെടുത്തൽ"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ഉപകാരപ്രദമായ വിവരങ്ങൾ നിങ്ങളുടെ വിരൽത്തുമ്പിൽ"</string>
<string name="widget_education_content" msgid="1731667670753497052">"ആപ്പുകൾ തുറക്കാതെ വിവരങ്ങൾ ലഭിക്കാൻ, നിങ്ങൾക്ക് ഹോം സ്ക്രീനിലേക്ക് വിജറ്റുകൾ ചേർക്കാം"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"വിജറ്റ് ക്രമീകരണം മാറ്റാൻ ടാപ്പ് ചെയ്യുക"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"ഹോമിലെ ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും വായിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"ഹോം ക്രമീകരണവും കുറുക്കുവഴികളും എഴുതുക"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"ഹോമിലെ ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും മാറ്റാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"ഫോൺ കോൾ ചെയ്യാൻ <xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനെ അനുവദിച്ചിട്ടില്ല"</string>
<string name="gadget_error_text" msgid="740356548025791839">"വിജറ്റ് ലോഡ് ചെയ്യാനാകുന്നില്ല"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"വിജറ്റ് ക്രമീകരണം"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"സജ്ജീകരണം പൂർത്തിയാക്കാൻ ടാപ്പ് ചെയ്യുക"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"ഫോൾഡറിന്റെ പേര് <xliff:g id="NAME">%1$s</xliff:g> എന്നായി മാറ്റി"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"ഫോൾഡർ: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ഇനങ്ങൾ"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ഫോൾഡർ: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> അല്ലെങ്കിൽ അതിലധികം ഇനങ്ങൾ"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"വാൾപേപ്പർ"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"വാൾപേപ്പറും സ്റ്റൈലും"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"ഹോം സ്ക്രീൻ എഡിറ്റ് ചെയ്യുക"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ഹോം ക്രമീകരണം"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"അഡ്മിൻ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"ഹോം സ്ക്രീൻ റൊട്ടേഷൻ അനുവദിക്കുക"</string>
@@ -119,7 +119,7 @@
<string name="abandoned_clean_this" msgid="7610119707847920412">"നീക്കംചെയ്യുക"</string>
<string name="abandoned_search" msgid="891119232568284442">"തിരയുക"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"ഈ അപ്ലിക്കേഷൻ ഇൻസ്റ്റാളുചെയ്തിട്ടില്ല"</string>
- <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ഈ ഐക്കണുവേണ്ടി അപ്ലിക്കേഷൻ ഇൻസ്റ്റാളുചെയ്തിട്ടില്ല. നിങ്ങൾക്കത് നീക്കംചെയ്യാനാകും അല്ലെങ്കിൽ അപ്ലിക്കേഷനുവേണ്ടി തിരഞ്ഞുകൊണ്ട് അത് സ്വമേധയാ ഇൻസ്റ്റാളുചെയ്യുക."</string>
+ <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ഈ ഐക്കണുവേണ്ടി അപ്ലിക്കേഷൻ ഇൻസ്റ്റാളുചെയ്തിട്ടില്ല. നിങ്ങൾക്കത് നീക്കംചെയ്യാനാകും അല്ലെങ്കിൽ അപ്ലിക്കേഷനുവേണ്ടി തിരഞ്ഞുകൊണ്ട് അത് സ്വയമേവ ഇൻസ്റ്റാളുചെയ്യുക."</string>
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ഇൻസ്റ്റാൾ ചെയ്യുന്നു, <xliff:g id="PROGRESS">%2$s</xliff:g> പൂർത്തിയായി"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ഡൗൺലോഡ് ചെയ്യുന്നു, <xliff:g id="PROGRESS">%2$s</xliff:g> പൂർത്തിയായി"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"ഇൻസ്റ്റാൾ ചെയ്യാൻ <xliff:g id="NAME">%1$s</xliff:g> കാക്കുന്നു"</string>
@@ -157,17 +157,18 @@
<string name="accessibility_close" msgid="2277148124685870734">"അടയ്ക്കൂ"</string>
<string name="notification_dismissed" msgid="6002233469409822874">"അറിയിപ്പ് നിരസിച്ചു"</string>
<string name="all_apps_personal_tab" msgid="4190252696685155002">"വ്യക്തിപരം"</string>
- <string name="all_apps_work_tab" msgid="4884822796154055118">"ഔദ്യോഗികം"</string>
+ <string name="all_apps_work_tab" msgid="4884822796154055118">"Work"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"ഔദ്യോഗിക ആപ്പുകൾക്ക് ബാഡ്ജ് നൽകിയിരിക്കുന്നു, അവ നിങ്ങളുടെ ഐടി അഡ്മിന് കാണാനുമാകും"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"മനസ്സിലായി"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"ഔദ്യോഗിക ആപ്പുകൾ തൽക്കാലം നിർത്തിയിരിക്കുന്നു"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"ഔദ്യോഗിക ആപ്പുകളിൽ നിന്ന് നിങ്ങൾക്ക് അറിയിപ്പുകളൊന്നും ലഭിക്കില്ല"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"നിങ്ങൾക്ക് അറിയിപ്പുകൾ അയയ്ക്കാനോ ബാറ്ററി ഉപയോഗിക്കാനോ ലൊക്കേഷൻ ആക്സസ് ചെയ്യാനോ നിങ്ങളുടെ ഔദ്യോഗിക ആപ്പുകൾക്ക് കഴിയില്ല"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"ഔദ്യോഗിക ആപ്പുകൾ ഓഫാണ്. നിങ്ങൾക്ക് അറിയിപ്പുകൾ അയയ്ക്കാനോ ബാറ്ററി ഉപയോഗിക്കാനോ ലൊക്കേഷൻ ആക്സസ് ചെയ്യാനോ നിങ്ങളുടെ ഔദ്യോഗിക ആപ്പുകൾക്ക് കഴിയില്ല"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"വർക്ക് ആപ്പുകളിൽ നിന്ന് നിങ്ങൾക്ക് ഫോൺ കോളുകളും ടെക്സ്റ്റ് മെസേജുകളും അറിയിപ്പുകളും ലഭിക്കില്ല"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"ഔദ്യോഗിക ആപ്പുകൾക്ക് ബാഡ്ജ് നൽകിയിരിക്കുന്നു, അവ നിങ്ങളുടെ ഐടി അഡ്മിന് കാണാനും കഴിയും"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"മനസ്സിലായി"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ഔദ്യോഗിക ആപ്പുകൾ താൽക്കാലികമായി നിർത്തുക"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ഔദ്യോഗിക ആപ്പുകൾ ഓണാക്കുക"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"താൽക്കാലികമായി നിർത്തിയത് മാറ്റുക"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"ഫിൽട്ടർ ചെയ്യുക"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"നിങ്ങളുടെ ഫോണിലുള്ളവ തിരയുക"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"നിങ്ങളുടെ ടാബ്ലെറ്റിലുള്ളവ തിരയുക"</string>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index be82db3..716bd85 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Нүүр"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Дэлгэцийг хуваах"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s-н аппын мэдээлэл"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Апп хослуулалтыг хадгалах"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Виджетийг зөөх бол хүрээд, удаан дарна уу."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Виджетийг зөөх эсвэл захиалгат үйлдлийг ашиглахын тулд хоёр товшоод, удаан дарна уу."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Виджетийг үндсэн нүүрний эргэн тойронд зөөхийн тулд түүнд хүрээд, удаан дарна уу"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Үндсэн нүүрэнд нэмэх"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджетийг үндсэн нүүрэнд нэмсэн"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Зөвлөмжүүд"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}other{# виджет}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# товчлол}other{# товчлол}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Хувийн виджетүүд"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Ажил"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Харилцан яриа"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Тэмдэглэл хөтлөх"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Хэрэгтэй мэдээллээ хурууныхаа үзүүрээр аваарай"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Аппуудыг нээлгүйгээр мэдээлэл авахын тулд та үндсэн нүүрэндээ виджетүүд нэмэх боломжтой"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Жижиг хэрэгслийн тохиргоог өөрчлөхийн тулд товшино уу"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Аппад нүүрэн дэх тохиргоо болон товчлолыг уншихыг зөвшөөрнө."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"нүүрний тохиргоо болон товчлолыг бичих"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Аппад нүүрэн дэх тохиргоо болон товчлолыг өөрчлөхийг зөвшөөрнө."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> утасны дуудлага хийх боломжгүй"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Жижиг хэрэгслийг ачаалах боломжгүй"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Виджетийн тохиргоо"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Тохируулгыг дуусгахын тулд товшино уу"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Фолдерын нэр <xliff:g id="NAME">%1$s</xliff:g> болов"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Фолдер: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> зүйл"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Фолдер: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> эсвэл үүнээс олон зүйл"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Дэлгэцийн зураг"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Дэлгэцийн зураг, загвар"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Үндсэн нүүрийг засах"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Нүүр хуудасны тохиргоо"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Таны админ идэвхгүй болгосон"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Үндсэн нүүрийг эргүүлэхийг зөвшөөрөх"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Ажлын аппуудыг тэмдэглэсэн бөгөөд танай IT админд харагдана"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Ойлголоо"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Ажлын аппуудыг түр зогсоосон"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Та ажлын аппуудаасаа мэдэгдэл хүлээн авахгүй"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Таны ажлын аппууд танд мэдэгдэл илгээх, таны батарейг ашиглах эсвэл байршилд тань хандах боломжгүй"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Ажлын аппууд унтраалттай байна. Таны ажлын аппууд танд мэдэгдэл илгээх, таны батарейг ашиглах эсвэл байршилд тань хандах боломжгүй"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Та ажлын аппуудаасаа утасны дуудлага, мессеж эсвэл мэдэгдэл хүлээн авахгүй"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Ажлын аппуудыг тэмдэглэсэн бөгөөд танай IT админд харагдана"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Ойлголоо"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Ажлын аппуудыг түр зогсоох"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Ажлын аппуудыг асаах"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Түр зогсоохоо болих"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Шүүлтүүр"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Утаснаасаа хайх"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Таблетнаасаа хайх"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 513e608..c73295d 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -29,16 +29,16 @@
<string name="home_screen" msgid="5629429142036709174">"होम"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"स्प्लिट स्क्रीन"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s साठी ॲपशी संबंधित माहिती"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"ॲपची जोडी सेव्ह करा"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"विजेट हलवण्यासाठी स्पर्श करा आणि धरून ठेवा."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"विजेट हलवण्यासाठी किंवा कस्टम कृती वापरण्यासाठी दोनदा टॅप करा आणि धरून ठेवा."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d रूंद बाय %2$d उंच"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट"</string>
- <string name="add_item_request_drag_hint" msgid="8730547755622776606">"होम स्क्रीनवर ते हलवण्यासाठी विजेटला स्पर्श करा आणि धरून ठेवा"</string>
+ <string name="add_item_request_drag_hint" msgid="8730547755622776606">"होम स्क्रीनवर हलवण्यासाठी विजेटला स्पर्श करून धरून ठेवा"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"होम स्क्रीनवर जोडा"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> हे विजेट तुमच्या होम स्क्रीनवर जोडले आहे"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"सूचना"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# विजेट}other{# विजेट}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# शॉर्टकट}other{# शॉर्टकट}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"वैयक्तिक"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ऑफिस"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"संभाषणे"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"टिपा घेणे"</string>
<string name="widget_education_header" msgid="4874760613775913787">"तुमच्यासाठी सहज उपलब्ध असलेली माहिती"</string>
<string name="widget_education_content" msgid="1731667670753497052">"ॲप्स न उघडता माहिती मिळवण्यासाठी, तुम्ही तुमच्या होम स्क्रीनवर विजेट जोडू शकता"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"विजेट सेटिंग्ज बदलण्यासाठी टॅप करा"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"अॅपला होममधील सेटिंग्ज आणि शॉर्टकट वाचण्याची अनुमती देते."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"होम सेटिंग्ज आणि शॉर्टकट लिहा"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"अॅपला होममधील सेटिंग्ज आणि शॉर्टकट बदलण्याची अनुमती देते."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ला फोन कॉल करण्याची अनुमती नाही"</string>
<string name="gadget_error_text" msgid="740356548025791839">"विजेट लोड करू शकत नाही"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"विजेटची सेटिंग्ज"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"सेटअप पूर्ण करण्यासाठी टॅप करा"</string>
@@ -89,9 +89,9 @@
<string name="folder_hint_text" msgid="5174843001373488816">"नाव संपादित करा"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> अक्षम केला आहे"</string>
<string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} संबंधित # सूचना आहे}other{{app_name} संबंधित # सूचना आहेत}}"</string>
- <string name="default_scroll_format" msgid="7475544710230993317">"%2$d पैकी %1$d पृष्ठ"</string>
+ <string name="default_scroll_format" msgid="7475544710230993317">"%2$d पैकी %1$d पेज"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%2$d पैकी %1$d मुख्य स्क्रीन"</string>
- <string name="workspace_new_page" msgid="257366611030256142">"नवीन मुख्य स्क्रीन पृष्ठ"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"नवीन होम स्क्रीन पेज"</string>
<string name="folder_opened" msgid="94695026776264709">"फोल्डर उघडले, <xliff:g id="WIDTH">%1$d</xliff:g> बाय <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="4625795376335528256">"फोल्डर बंद करण्यासाठी टॅप करा"</string>
<string name="folder_tap_to_rename" msgid="4017685068016979677">"पुनर्नामित करणे सेव्ह करण्यासाठी टॅप करा"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"फोल्डरचे नाव बदलून <xliff:g id="NAME">%1$s</xliff:g> असे ठेवले"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"फोल्डर: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> आयटम"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"फोल्डर: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> किंवा त्याहून अधिक आयटम"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"वॉलपेपर"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"वॉलपेपर आणि शैली"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"होम स्क्रीन संपादित करा"</string>
<string name="settings_button_text" msgid="8873672322605444408">"होम सेटिंग्ज"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"आपल्या प्रशासकाने अक्षम केले"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"होम स्क्रीन फिरवण्याची अनुमती द्या"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"कार्य ॲप्स ही बॅज केलेली असून तुमच्या आयटी ॲडमिनला दृश्यमान आहेत"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"समजले"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"कार्य ॲप्स थांबवली आहेत"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"तुम्हाला तुमच्या कार्य अॅप्सवरून सूचना मिळणार नाहीत"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"तुमची कार्य ॲप्स तुम्हाला सूचना पाठवू शकत नाहीत, तुमची बॅटरी वापरू शकत नाहीत किंवा तुमचे स्थान अॅक्सेस करू शकत नाहीत"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"कामाशी संबंधित ॲप्स बंद आहेत. तुमचे कामाशी संबंधित ॲप्स तुम्हाला सूचना पाठवू शकत नाहीत, तुमची बॅटरी वापरू शकत नाहीत किंवा तुमचे स्थान अॅक्सेस करू शकत नाहीत"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"तुम्हाला तुमच्या कार्य अॅप्सवरून फोन कॉल, एसएमएस किंवा सूचना मिळणार नाहीत"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"कार्य ॲप्स ही बॅज केलेली असून तुमच्या आयटी ॲडमिनला दृश्यमान आहेत"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"समजले"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"कार्य ॲप्स थांबवा"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"कार्य ॲप्स सुरू करा"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"अनपॉझ करा"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"फिल्टर"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"तुमच्या फोनमध्ये शोधा"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"तुमच्या टॅबलेटमध्ये शोधा"</string>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index c41c70b..e4a2e57 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Rumah"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Skrin pisah"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Maklumat apl untuk %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Simpan gandingan apl"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Sentuh & tahan untuk menggerakkan widget."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ketik dua kali & tahan untuk menggerakkan widget atau menggunakan tindakan tersuai."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Sentuh & tahan widget untuk menggerakkan widget di sekitar skrin utama"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Tambahkan pada skrin utama"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ditambahkan pada skrin utama"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Cadangan"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# pintasan}other{# pintasan}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Peribadi"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Tempat kerja"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Perbualan"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Pengambilan nota"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Maklumat berguna di hujung jari anda"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Untuk mendapatkan maklumat tanpa membuka apl, anda boleh menambahkan widget pada skrin utama anda"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Ketik untuk menukar tetapan widget"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Membenarkan apl membaca tetapan dan pintasan di skrin utama."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"menulis tetapan dan pintasan skrin utama"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Membenarkan apl menukar tetapan dan pintasan di skrin utama."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak dibenarkan membuat panggilan telefon"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Tidak dapat memuatkan widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Tetapan widget"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Ketik untuk menyelesaikan persediaan"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Folder dinamakan semula kepada <xliff:g id="NAME">%1$s</xliff:g>"</string>
<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> item"</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> atau lebih banyak item"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Hiasan latar"</string>
- <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Kertas dinding & gaya"</string>
+ <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Hiasan latar & gaya"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Edit Skrin Utama"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Tetapan skrin utama"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Dilumpuhkan oleh pentadbir anda"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Benarkan putaran skrin utama"</string>
@@ -162,14 +162,15 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Apl kerja mempunyai lencana dan kelihatan kepada pentadbir IT anda"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Apl kerja dijeda"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Anda tidak akan menerima pemberitahuan daripada apl kerja anda"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Apl kerja anda tidak boleh menghantar pemberitahuan kepada anda, menggunakan bateri anda atau mengakses lokasi anda"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Apl kerja dimatikan. Apl kerja anda tidak boleh menghantar pemberitahuan kepada anda, menggunakan bateri anda atau mengakses lokasi anda"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Anda tidak akan menerima panggilan telefon, mesej teks atau pemberitahuan daripada apl kerja anda"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Apl kerja mempunyai lencana dan kelihatan kepada pentadbir IT anda"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Jeda apl kerja"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Hidupkan apl kerja"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Nyahjeda"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Tapis"</string>
- <string name="search_pref_screen_title" msgid="3258959643336315962">"Cari telefon anda"</string>
- <string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Cari tablet anda"</string>
+ <string name="search_pref_screen_title" msgid="3258959643336315962">"Cari pada telefon"</string>
+ <string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Cari pada tablet anda"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"Gagal: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 7cccad4..1ec09f5 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"ပင်မစာမျက်နှာ"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"မျက်နှာပြင် ခွဲ၍ပြသခြင်း"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s အတွက် အက်ပ်အချက်အလက်"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"အက်ပ်တွဲချိတ်ခြင်း သိမ်းရန်"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"ဝိဂျက်ကို ရွှေ့ရန် တို့ပြီး ဖိထားပါ။"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"ဝိဂျက်ကို ရွှေ့ရန် (သို့) စိတ်ကြိုက်လုပ်ဆောင်ချက်များကို သုံးရန် နှစ်ချက်တို့ပြီး ဖိထားပါ။"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"ပင်မစာမျက်နှာတွင်ရွှေ့ရန် ဝိဂျက်ကို တို့ထိ၍ ဖိထားပါ"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"ပင်မစာမျက်နှာတွင် ထည့်ရန်"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ဝိဂျက်ကို ပင်မစာမျက်နှာတွင် ထည့်လိုက်ပြီ"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"အကြံပြုချက်"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ဝိဂျက် # ခု}other{ဝိဂျက် # ခု}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{ဖြတ်လမ်းလင့်ခ် # ခု}other{ဖြတ်လမ်းလင့်ခ် # ခု}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>၊ <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"ကိုယ်ပိုင်"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"အလုပ်"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"စကားဝိုင်းများ"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"မှတ်စုလိုက်ခြင်း"</string>
<string name="widget_education_header" msgid="4874760613775913787">"အသုံးဝင်သော အချက်အလက်များကို အလွယ်တကူ ရယူလိုက်ပါ"</string>
<string name="widget_education_content" msgid="1731667670753497052">"အက်ပ်မဖွင့်ဘဲ အချက်အလက်များရယူရန် ပင်မစာမျက်နှာတွင် ဝိဂျက်များ ထည့်နိုင်သည်"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ဝိဂျက် ဆက်တင်များကို ပြောင်းရန် တို့ပါ"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"ပင်မတွင်ရှိသော ဆက်တင်များနှင့် ဖြတ်လမ်းလင့်ခ်များကို အက်ပ်အား ဖတ်ခွင့်ပြုနိုင်သည်။"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"ပင်မဆက်တင်နှင့် ဖြတ်လမ်းလင့်ခ်များ ရေးသားခြင်း"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"ပင်မတွင်ရှိသော ဆက်တင်များနှင့် ဖြတ်လမ်းလင့်ခ်များကို အက်ပ်အား ပြောင်းခွင့်ပြုနိုင်သည်။"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g>သည် ဖုန်းခေါ်ဆိုခွင့် မရှိပါ"</string>
<string name="gadget_error_text" msgid="740356548025791839">"ဝိဂျက်ကို ဖွင့်၍မရပါ"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"ဝိဂျက်ဆက်တင်များ"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"စနစ်ထည့်သွင်းခြင်း အပြီးသတ်ရန် တို့ပါ"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"ပြောင်းလဲလိုက်သော အကန့်အမည် <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"ဖိုင်တွဲ - <xliff:g id="NAME">%1$s</xliff:g>၊ <xliff:g id="SIZE">%2$d</xliff:g> ဖိုင်များ"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ဖိုင်တွဲ - <xliff:g id="NAME">%1$s</xliff:g>၊ <xliff:g id="SIZE">%2$d</xliff:g> သို့မဟုတ် နောက်ထပ်ဖိုင်များ"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"နောက်ခံများ"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"နောက်ခံနှင့် ပုံစံ"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"ပင်မစာမျက်နှာ တည်းဖြတ်ရန်"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ပင်မဆက်တင်များ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"သင့်စီမံခန့်ခွဲသူက ပိတ်လိုက်ပါသည်"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"ပင်မစာမျက်နှာလှည့်ခြင်းကို ခွင့်ပြုခြင်း"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"အလုပ်သုံးအက်ပ်များကို တံဆိပ်တပ်ထားပြီး သင်၏ IT စီမံခန့်ခွဲသူက မြင်နိုင်ပါသည်"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"ရပါပြီ"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"အလုပ်သုံးအက်ပ်များကို ခေတ္တရပ်ထားသည်"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"သင်၏ အလုပ်သုံးအက်ပ်များမှ အကြောင်းကြားချက်များကို ရရှိမည်မဟုတ်ပါ"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"သင်၏ အလုပ်သုံးအက်ပ်များက အကြောင်းကြားချက်များ ပို့ခြင်း၊ သင့်ဘက်ထရီ သုံးခြင်း (သို့) သင့်တည်နေရာ သုံးခြင်းတို့ မပြုလုပ်နိုင်ပါ"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"အလုပ်သုံးအက်ပ်များ ပိတ်ထားသည်။ သင်၏ အလုပ်သုံးအက်ပ်များက အကြောင်းကြားချက်များ ပို့ခြင်း၊ သင့်ဘက်ထရီ သုံးခြင်း (သို့) သင့်တည်နေရာ သုံးခြင်းတို့ မပြုလုပ်နိုင်ပါ"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"သင်၏ အလုပ်သုံးအက်ပ်များမှ ဖုန်းခေါ်ဆိုမှု၊ မိုဘိုင်းမက်ဆေ့ဂျ် (သို့) အကြောင်းကြားချက်များ ရရှိမည်မဟုတ်ပါ"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"အလုပ်သုံးအက်ပ်များကို တံဆိပ်တပ်ထားပြီး သင်၏ IT စီမံခန့်ခွဲသူက မြင်နိုင်ပါသည်"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"နားလည်ပြီ"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"အလုပ်သုံးအက်ပ်များကို ခဏရပ်ရန်"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"အလုပ်သုံးအက်ပ်များ ဖွင့်ရန်"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"ပြန်ဖွင့်ရန်"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"စစ်ထုတ်ရန်"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"သင့်ဖုန်းတွင် ရှာခြင်း"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"သင့်တက်ဘလက်ကို ရှာခြင်း"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 1d8d153..7266a81 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Startskjerm"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Delt skjerm"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Appinformasjon for %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Lagre apptilkoblingen"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Trykk og hold for å flytte en modul."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dobbelttrykk og hold inne for å flytte en modul eller bruke tilpassede handlinger."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Trykk og hold på modulen for å bevege den rundt på startskjermen"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Legg til på startskjermen"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-modulen er lagt til på startskjermen"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Forslag"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# modul}other{# moduler}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# snarvei}other{# snarveier}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personlige"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Jobb"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Samtaler"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Notatskriving"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Lett tilgjengelig nyttig informasjon"</string>
<string name="widget_education_content" msgid="1731667670753497052">"For å se informasjon uten å åpne apper kan du legge til moduler på startskjermen"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Trykk for å endre modulinnstillinger"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Lar appen lese innstillingene og snarveiene på startsiden."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"angi startsideinnstillinger og -snarveier"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Lar appen endre innstillingene og snarveiene på startsiden."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> har ikke tillatelse til å ringe"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Kan ikke laste inn modulen"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Modulinnstillinger"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Trykk for å fullføre konfigureringen"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Mappen heter nå <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Mappe: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> elementer"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Mappe: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> eller flere elementer"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Bakgrunner"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Bakgrunn og stil"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Endre startsiden"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Startsideinnstillinger"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administratoren har slått av funksjonen"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Tillat at startskjermen roterer"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Jobbapper er merket og synlige for IT-administratoren"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Greit"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Jobbapper er satt på pause"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Du får ikke varsler fra jobbappene dine"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Jobbapper kan ikke sende deg varsler, bruke batteriet eller få tilgang til posisjonen din"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Jobbapper er av. De kan ikke sende deg varsler, bruke batteriet eller få tilgang til posisjonen din"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Du får ikke telefonanrop, tekstmeldinger eller varsler fra jobbappene dine"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Jobbapper er merket og synlige for IT-administratoren din"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Greit"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Sett jobbapper på pause"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Slå på jobbapper"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Gjenoppta"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Søk på telefonen"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Søk på nettbrettet"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index f07f16c..a73f2a3 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"होम"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"स्प्लिट स्क्रिन"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s का हकमा एपसम्बन्धी जानकारी"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"एपको पेयर सेभ गर्नुहोस्"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"कुनै विजेट सार्न डबल ट्याप गरेर छोइराख्नुहोस्।"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"कुनै विजेट सार्न वा आफ्नो रोजाइका कारबाही प्रयोग गर्न डबल ट्याप गरेर छोइराख्नुहोस्।"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"विजेटलाई होम स्क्रिनमा यताउता सार्न त्यसमा टच एन्ड होल्ड गर्नुहोस्"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"होम स्क्रिनमा राख्नुहोस्"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"होम स्क्रिनमा <xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट हालियो"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"सुझावहरू"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# विजेट}other{# वटा विजेट}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# सर्टकट}other{# वटा सर्टकट}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,12 +50,13 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"व्यक्तिगत"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"कामसम्बन्धी"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"वार्तालापहरू"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"नोट लेख्ने कार्य"</string>
<string name="widget_education_header" msgid="4874760613775913787">"उपयोगी जानकारी सजिलै प्राप्त गर्नुहोस्"</string>
<string name="widget_education_content" msgid="1731667670753497052">"एपहरू नखोलिकनै जानकारी प्राप्त गर्न तपाईं आफ्नो होम स्क्रिनमा विजेटहरू हाल्न सक्नुहुन्छ"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"विजेटका सेटिङ बदल्न ट्याप गर्नुहोस्"</string>
<string name="widget_education_close_button" msgid="8676165703104836580">"बुझेँ"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"विजेटका सेटिङ बदल्नुहोस्"</string>
- <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"खोजसम्बन्धी एपहरू"</string>
+ <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"एपहरू खोज्नुहोस्"</string>
<string name="all_apps_loading_message" msgid="5813968043155271636">"एपहरू लोड गर्दै…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" सँग मिल्दो कुनै एप भेटिएन"</string>
<string name="label_application" msgid="8531721983832654978">"एप"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"एपलाई होम स्क्रिनबाट सेटिङ र सर्टकटहरू रिड गर्ने अनुमति दिन्छ।"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"होम स्क्रिनका सेटिङ र सर्टकटहरू राइट गरियोस्"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"एपलाई होम स्क्रिनबाट सेटिङ र सर्टकट बदल्ने अनुमति दिन्छ"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले फोन कलहरू गर्न अनुमति छैन"</string>
<string name="gadget_error_text" msgid="740356548025791839">"विजेट लोड गर्न सकिएन"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"विजेटका सेटिङ"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"सेटअप पूरा गर्न ट्याप गर्नुहोस्"</string>
@@ -99,12 +99,12 @@
<string name="folder_renamed" msgid="1794088362165669656">"फोल्डर <xliff:g id="NAME">%1$s</xliff:g> मा पुनःनामाकरण गरियो।"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"फोल्डर: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> वस्तुहरू"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"फोल्डर: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> वा सोभन्दा बढी वस्तुहरू"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"वालपेपरहरु"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"वालपेपर तथा शैली"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"होम स्क्रिन बदल्नुहोस्"</string>
<string name="settings_button_text" msgid="8873672322605444408">"होम पेजका सेटिङहरू"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"तपाईँको प्रशासकद्वारा असक्षम गरिएको"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"होम स्क्रिन रोटेट हुन दिइयोस्"</string>
- <string name="allow_rotation_desc" msgid="8662546029078692509">"फोनलाई घुमाइँदा"</string>
+ <string name="allow_rotation_desc" msgid="8662546029078692509">"फोन घुमाउँदा"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"सूचनाको प्रतीक जनाउने थोप्लाहरू"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"सक्रिय"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"निष्क्रिय"</string>
@@ -157,19 +157,20 @@
<string name="accessibility_close" msgid="2277148124685870734">"बन्द गर्नुहोस्"</string>
<string name="notification_dismissed" msgid="6002233469409822874">"सूचना खारेज गरियो"</string>
<string name="all_apps_personal_tab" msgid="4190252696685155002">"व्यक्तिगत"</string>
- <string name="all_apps_work_tab" msgid="4884822796154055118">"कार्यसम्बन्धी"</string>
+ <string name="all_apps_work_tab" msgid="4884822796154055118">"कामसम्बन्धी"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"कार्य प्रोफाइल"</string>
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"कामसम्बन्धी एपहरूमा ब्याज अङ्कित हुन्छ र तपाईंका IT एड्मिन ती एप हेर्न सक्छन्"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"बुझेँ"</string>
- <string name="work_apps_paused_title" msgid="3040901117349444598">"कार्यसम्बन्धी एपहरू पज गरिएका छन्"</string>
+ <string name="work_apps_paused_title" msgid="3040901117349444598">"कामसम्बन्धी एपहरू पज गरिएका छन्"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"तपाईं कामसम्बन्धी एपबाट सूचनाहरू प्राप्त गर्नु हुने छैन"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"तपाईंका कामसम्बन्धी एपहरूले तपाईंलाई सूचना पठाउन, तपाईंको डिभाइसको ब्याट्री प्रयोग गर्न वा तपाईंको लोकेसन हेर्न सक्दैनन्"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"कामसम्बन्धी एपहरू अफ गरिएका छन्। तपाईंका कामसम्बन्धी एपहरूले तपाईंलाई सूचना पठाउन, तपाईंको डिभाइसको ब्याट्री प्रयोग गर्न वा तपाईंको लोकेसन हेर्न सक्दैनन्"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"तपाईं कामसम्बन्धी एपबाट फोन कल, टेक्स्ट म्यासेज वा सूचनाहरू प्राप्त गर्नु हुने छैन"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"कामसम्बन्धी एपमा ब्याज अङ्कित हुन्छ र तपाईंका IT एड्मिन ती एप हेर्न सक्नुहुन्छ"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"बुझेँ"</string>
- <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"कामसम्बन्धी एपहरू अस्थायी रूपमा रोक्का गर्नुहोस्"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"कामसम्बन्धी एपहरू अन गर्नुहोस्"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"कामसम्बन्धी एपहरू पज गर्नुहोस्"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"सुचारु गर्नुहोस्"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"फिल्टर"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"आफ्नो फोन खोज्नुहोस्"</string>
- <string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"आफ्नो ट्याब्लेट खोज्नुहोस्"</string>
+ <string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"आफ्नो ट्याबलेटमा खोज्नुहोस्"</string>
<string name="remote_action_failed" msgid="1383965239183576790">"कार्य पूरा गर्न सकिएन: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 5685643..8d2aa21 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Startscherm"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Gesplitst scherm"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"App-info voor %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"App-paar opslaan"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Tik en houd vast om een widget te verplaatsen."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dubbeltik en houd vast om een widget te verplaatsen of aangepaste acties te gebruiken."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Tik op de widget en houd vast om deze te verplaatsen op het startscherm"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Toevoegen aan startscherm"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> toegevoegd aan startscherm"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggesties"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# snelkoppeling}other{# snelkoppelingen}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Persoonlijk"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Werk"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Gesprekken"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Aantekeningen maken"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Nuttige informatie binnen handbereik"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Als je informatie wilt krijgen zonder apps te openen, kun je widgets toevoegen aan je startscherm"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tik om de widgetinstellingen te wijzigen"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"De app toestaan de instellingen en snelkoppelingen op het startscherm te lezen."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"instellingen en snelkoppelingen op startscherm wijzigen"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"De app toestaan de instellingen en snelkoppelingen op het startscherm te wijzigen."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> mag niet bellen"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Kan widget niet laden"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Widgetinstellingen"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Tik om instellen af te ronden"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"De naam van de map is gewijzigd in <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Map: <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">"Map: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> of meer items"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Achtergrond"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Achtergrond en stijl"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Startscherm bewerken"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Instellingen start"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Uitgezet door je beheerder"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Draaien van startscherm toestaan"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Werk-apps hebben badges en zijn zichtbaar voor je IT-beheerder"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Werk-apps zijn onderbroken"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Je krijgt geen meldingen van je werk-apps"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Je werk-apps kunnen je geen meldingen sturen, je batterij niet gebruiken en geen toegang krijgen tot je locatie"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Werk-apps staan uit. Je werk-apps kunnen geen meldingen sturen, je batterij niet gebruiken en hebben geen toegang tot je locatie."</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Je krijgt geen telefoongesprekken, tekstberichten of meldingen van je werk-apps"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Werk-apps hebben badges en zijn zichtbaar voor je IT-beheerder"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Werk-apps pauzeren"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Werk-apps aanzetten"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Hervatten"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filteren"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Zoeken op je telefoon"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Zoeken op je tablet"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index e4e5877..555913e 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -27,8 +27,9 @@
<string name="safemode_widget_error" msgid="4863470563535682004">"ନିରାପଦ ମୋଡରେ ୱିଜେଟ୍ ଅକ୍ଷମ କରାଗଲା"</string>
<string name="shortcut_not_available" msgid="2536503539825726397">"ଶର୍ଟକଟ୍ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="home_screen" msgid="5629429142036709174">"ହୋମ"</string>
- <string name="recent_task_option_split_screen" msgid="6690461455618725183">"ସ୍କ୍ରିନକୁ ସ୍ପ୍ଲିଟ୍ କରନ୍ତୁ"</string>
+ <string name="recent_task_option_split_screen" msgid="6690461455618725183">"ସ୍କ୍ରିନକୁ ସ୍ପ୍ଲିଟ କରନ୍ତୁ"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ପାଇଁ ଆପ ସୂଚନା"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"ଆପ ପେୟାର ସେଭ କରନ୍ତୁ"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ।"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ଦୁଇଥର-ଟାପ୍ କରି ଧରି ରଖନ୍ତୁ କିମ୍ବା କଷ୍ଟମ୍ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,9 +38,8 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"ହୋମ ସ୍କ୍ରିନର ଆଖପାଖରେ ୱିଜେଟକୁ ମୁଭ କରିବା ପାଇଁ ଏହାକୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"ହୋମ ସ୍କ୍ରିନରେ ଯୋଗ କରନ୍ତୁ"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>ର ୱିଜେଟ ହୋମ ସ୍କ୍ରିନରେ ଯୋଡ଼ାଗଲା"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
- <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{#ଟି ୱିଜେଟ୍}other{#ଟି ୱିଜେଟ୍}}"</string>
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"ପରାମର୍ଶଗୁଡ଼ିକ"</string>
+ <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ୱିଜେଟ}other{# ୱିଜେଟ}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{#ଟି ସର୍ଟକଟ୍}other{#ଟି ସର୍ଟକଟ୍}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"ୱିଜେଟ୍"</string>
@@ -50,12 +50,13 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"ବ୍ୟକ୍ତିଗତ"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ୱାର୍କ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"ନୋଟ-ଟେକିଂ"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ଉପଯୋଗୀ ସୂଚନା ଆପଣଙ୍କ ପାଖରେ ସହଜରେ ଉପଲବ୍ଧ"</string>
<string name="widget_education_content" msgid="1731667670753497052">"ଆପ୍ସକୁ ନଖୋଲି ସୂଚନା ପାଇବା ପାଇଁ, ଆପଣ ଆପଣଙ୍କ ହୋମ ସ୍କ୍ରିନରେ ୱିଜେଟଗୁଡ଼ିକୁ ଯୋଗ କରିପାରିବେ"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ୱିଜେଟ ସେଟିଂସ ପରିବର୍ତ୍ତନ କରିବାକୁ ଟାପ କରନ୍ତୁ"</string>
<string name="widget_education_close_button" msgid="8676165703104836580">"ବୁଝିଗଲି"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"ୱିଜେଟ ସେଟିଂସ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
- <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"ଆପ୍ ଖୋଜନ୍ତୁ"</string>
+ <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"ଆପ ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
<string name="all_apps_loading_message" msgid="5813968043155271636">"ଆପ୍ ଲୋଡ୍ ହେଉଛି..."</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" ସହିତ ମେଳ ହେଉଥିବା କୌଣସି ଆପ୍ ମିଳିଲା ନାହିଁ"</string>
<string name="label_application" msgid="8531721983832654978">"ଆପ୍"</string>
@@ -69,7 +70,7 @@
<string name="all_apps_search_results" msgid="5889367432531296759">"ସନ୍ଧାନ ଫଳାଫଳ"</string>
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"ବ୍ୟକ୍ତିଗତ ଆପ୍ ତାଲିକା"</string>
<string name="all_apps_button_work_label" msgid="7270707118948892488">"କାର୍ଯ୍ୟକାରୀ ଆପ୍ ତାଲିକା"</string>
- <string name="remove_drop_target_label" msgid="7812859488053230776">"ବାହାର କରନ୍ତୁ"</string>
+ <string name="remove_drop_target_label" msgid="7812859488053230776">"କାଢ଼ି ଦିଅନ୍ତୁ"</string>
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"ଅନଇନଷ୍ଟଲ କରନ୍ତୁ"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"ଆପ୍ ସୂଚନା"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ଇନଷ୍ଟଲ୍ କରନ୍ତୁ"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"ହୋମରେ ଥିବା ସେଟିଂସ ଏବଂ ସର୍ଟକଟଗୁଡ଼ିକୁ ପଢ଼ିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ।"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"ହୋମ ସେଟିଂସ ଏବଂ ସର୍ଟକଟଗୁଡ଼ିକୁ ଲେଖନ୍ତୁ"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"ହୋମରେ ଥିବା ସେଟିଂସ ଏବଂ ସର୍ଟକଟଗୁଡ଼ିକୁ ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ।"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"ଫୋନ୍ କଲ୍ କରିବାକୁ <xliff:g id="APP_NAME">%1$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ"</string>
<string name="gadget_error_text" msgid="740356548025791839">"ୱିଜେଟ୍ ଲୋଡ୍ କରାଯାଇପାରିବ ନାହିଁ"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"ୱିଜେଟ ସେଟିଂସ"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"ସେଟଅପ ସମ୍ପୂର୍ଣ୍ଣ କରିବାକୁ ଟାପ କରନ୍ତୁ"</string>
@@ -99,12 +99,12 @@
<string name="folder_renamed" msgid="1794088362165669656">"ଫୋଲ୍ଡରର ନାମ <xliff:g id="NAME">%1$s</xliff:g>କୁ ବଦଳାଗଲା"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"ଫୋଲ୍ଡର୍: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ଆଇଟମଗୁଡ଼ିକ"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ଫୋଲ୍ଡର୍: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> କିମ୍ବା ଅଧିକ ଆଇଟମ୍"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"ୱାଲପେପର୍"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ୱାଲପେପର ଏବଂ ଷ୍ଟାଇଲ"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"ହୋମ ସ୍କ୍ରିନକୁ ଏଡିଟ କରନ୍ତୁ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ହୋମ ସେଟିଂସ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ଆପଣଙ୍କ ଆଡମିନଙ୍କ ଦ୍ୱାରା ଅକ୍ଷମ କରାଯାଇଛି"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"ହୋମ ସ୍କ୍ରିନ ରୋଟେସନକୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
- <string name="allow_rotation_desc" msgid="8662546029078692509">"ଯେତେବେଳେ ଫୋନକୁ ବୁଲାଯାଇଥାଏ"</string>
+ <string name="allow_rotation_desc" msgid="8662546029078692509">"ଯେତେବେଳେ ଫୋନକୁ ରୋଟେଟ କରାଯାଇଥାଏ"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"ବିଜ୍ଞପ୍ତି ଡଟ୍ସ"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"ଚାଲୁ"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"ବନ୍ଦ କରନ୍ତୁ"</string>
@@ -159,15 +159,16 @@
<string name="all_apps_personal_tab" msgid="4190252696685155002">"ବ୍ୟକ୍ତିଗତ"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"ୱାର୍କ"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"ୱର୍କ ପ୍ରୋଫାଇଲ୍"</string>
- <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"ୱାର୍କ ଆପ୍ସ ବ୍ୟାଜ୍ କରାଯାଇଛି ଏବଂ ସେଗୁଡ଼ିକ ଆପଣଙ୍କ IT ଆଡମିନଙ୍କୁ ଦୃଶ୍ୟମାନ ହେଉଛି"</string>
+ <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"ୱାର୍କ ଆପ୍ସକୁ ବେଜ କରାଯାଇଛି ଏବଂ ସେଗୁଡ଼ିକ ଆପଣଙ୍କ IT ଆଡମିନଙ୍କୁ ଦେଖାଯାଉଛି"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"ବୁଝିଗଲି"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"ୱାର୍କ ଆପ୍ସ ବିରତ କରାଯାଇଛି"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"ଆପଣ ଆପଣଙ୍କ ୱାର୍କ ଆପ୍ସରୁ ବିଜ୍ଞପ୍ତି ପାଇବେ ନାହିଁ"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"ଆପଣଙ୍କ ୱାର୍କ ଆପ୍ସ ଆପଣଙ୍କୁ ବିଜ୍ଞପ୍ତି ପଠାଇପାରିବ ନାହିଁ, ଆପଣଙ୍କ ବ୍ୟାଟେରୀକୁ ବ୍ୟବହାର କରିପାରିବ ନାହିଁ କିମ୍ବା ଆପଣଙ୍କର ଲୋକେସନକୁ ଆକ୍ସେସ କରିପାରିବ ନାହିଁ"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"ୱାର୍କ ଆପଗୁଡ଼ିକ ବନ୍ଦ ଅଛି। ଆପଣଙ୍କ ୱାର୍କ ଆପଗୁଡ଼ିକ ଆପଣଙ୍କୁ ବିଜ୍ଞପ୍ତି ପଠାଇପାରିବ ନାହିଁ, ଆପଣଙ୍କ ବ୍ୟାଟେରୀକୁ ବ୍ୟବହାର କରିପାରିବ ନାହିଁ କିମ୍ବା ଆପଣଙ୍କର ଲୋକେସନକୁ ଆକ୍ସେସ୍ କରିପାରିବ ନାହିଁ"</string>
- <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"ୱାର୍କ ଆପ୍ସ ବ୍ୟାଜ୍ କରାଯାଇଛି ଏବଂ ଆପଣଙ୍କ IT ଆଡମିନଙ୍କୁ ଦେଖାଯାଉଛି"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"ଆପଣ ଆପଣଙ୍କ ୱାର୍କ ଆପ୍ସରୁ ଫୋନ କଲ, ଟେକ୍ସଟ ମେସେଜ କିମ୍ବା ବିଜ୍ଞପ୍ତି ପାଇବେ ନାହିଁ"</string>
+ <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"ୱାର୍କ ଆପ୍ସ ବ୍ୟାଜ କରାଯାଇଛି ଏବଂ ସେଗୁଡ଼ିକ ଆପଣଙ୍କ IT ଆଡମିନଙ୍କୁ ଦୃଶ୍ୟମାନ ହେଉଛି"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"ବୁଝିଗଲି"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ୱାର୍କ ଆପ୍ସ ବିରତ କରନ୍ତୁ"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ୱାର୍କ ଆପଗୁଡ଼ିକୁ ଚାଲୁ କରନ୍ତୁ"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"ପୁଣି ଚାଲୁ କରନ୍ତୁ"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"ଫିଲ୍ଟର୍"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"ଆପଣଙ୍କ ଫୋନରେ ସନ୍ଧାନ କରନ୍ତୁ"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"ଆପଣଙ୍କ ଟାବଲେଟରେ ସନ୍ଧାନ କରନ୍ତୁ"</string>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 1a78d95..e6e3f07 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"ਮੁੱਖ ਪੰਨਾ"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ਲਈ ਐਪ ਜਾਣਕਾਰੀ"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"ਐਪ ਜੋੜਾਬੱਧ ਰੱਖਿਅਤ ਕਰੋ"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"ਕਿਸੇ ਵਿਜੇਟ ਨੂੰ ਲਿਜਾਉਣ ਲਈ ਸਪਰਸ਼ ਕਰਕੇ ਰੱਖੋ।"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"ਵਿਜੇਟ ਲਿਜਾਉਣ ਲਈ ਜਾਂ ਵਿਉਂਂਤੀਆਂ ਕਾਰਵਾਈਆਂ ਵਰਤਣ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰਕੇ ਦਬਾ ਕੇ ਰੱਖੋ।"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"ਵਿਜੇਟ ਨੂੰ ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਇੱਧਰ-ਉੱਧਰ ਲਿਜਾਉਣ ਲਈ ਸਪਰਸ਼ ਕਰ ਕੇ ਦਬਾਈ ਰੱਖੋ"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ਵਿਜੇਟ ਨੂੰ ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"ਸੁਝਾਅ"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ਵਿਜੇਟ}one{# ਵਿਜੇਟ}other{# ਵਿਜੇਟ}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ਸ਼ਾਰਟਕੱਟ}one{# ਸ਼ਾਰਟਕੱਟ}other{# ਸ਼ਾਰਟਕੱਟ}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"ਨਿੱਜੀ"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ਕਾਰਜ-ਸਥਾਨ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"ਗੱਲਾਂਬਾਤਾਂ"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"ਨੋਟ ਬਣਾਉਣਾ"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ਮਹੱਤਵਪੂਰਨ ਜਾਣਕਾਰੀ ਤੁਰੰਤ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
<string name="widget_education_content" msgid="1731667670753497052">"ਐਪਾਂ ਨੂੰ ਖੋਲ੍ਹੇ ਬਿਨਾਂ ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ, ਤੁਸੀਂ ਆਪਣੀ ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਵਿਜੇਟ ਸ਼ਾਮਲ ਕਰ ਸਕਦੇ ਹੋ"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ਵਿਜੇਟ ਸੈਟਿੰਗਾਂ ਨੂੰ ਬਦਲਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"ਐਪ ਨੂੰ ਹੋਮ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"ਹੋਮ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਲਿਖੋ"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"ਐਪ ਨੂੰ ਹੋਮ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਬਦਲਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਫ਼ੋਨ ਕਾਲਾਂ ਕਰਨ ਦੀ ਆਗਿਆ ਨਹੀਂ ਹੈ"</string>
<string name="gadget_error_text" msgid="740356548025791839">"ਵਿਜੇਟ ਨੂੰ ਲੋਡ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"ਵਿਜੇਟ ਸੈਟਿੰਗਾਂ"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"ਸੈੱਟਅੱਪ ਪੂਰਾ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"ਫੋਲਡਰ ਨੂੰ <xliff:g id="NAME">%1$s</xliff:g> ਮੁੜ ਨਾਮ ਦਿੱਤਾ ਗਿਆ"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"ਫੋਲਡਰ: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ਆਈਟਮਾਂ"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ਫੋਲਡਰ: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ਜਾਂ ਹੋਰ ਆਈਟਮਾਂ"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"ਵਾਲਪੇਪਰ"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ਵਾਲਪੇਪਰ ਅਤੇ ਸਟਾਈਲ"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"ਹੋਮ ਸਕ੍ਰੀਨ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ਹੋਮ ਸੈਟਿੰਗਾਂ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਅਯੋਗ ਬਣਾਈ ਗਈ"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"ਹੋਮ ਸਕ੍ਰੀਨ ਨੂੰ ਘੁਮਾਉਣ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
@@ -159,15 +159,16 @@
<string name="all_apps_personal_tab" msgid="4190252696685155002">"ਨਿੱਜੀ"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"ਕੰਮ ਸੰਬੰਧੀ"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
- <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਨੂੰ ਬੈਜ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਅਤੇ ਇਹ ਤੁਹਾਡੇ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਦਿਸਣਗੀਆਂ"</string>
+ <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਨੂੰ ਬੈਜ ਕੀਤਾ ਗਿਆ ਹੈ ਅਤੇ ਇਹ ਤੁਹਾਡੇ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਦਿਸਣਗੀਆਂ"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"ਸਮਝ ਲਿਆ"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਨੂੰ ਰੋਕਿਆ ਗਿਆ ਹੈ"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"ਤੁਹਾਨੂੰ ਆਪਣੀਆਂ ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਤੋਂ ਸੂਚਨਾਵਾਂ ਪ੍ਰਾਪਤ ਨਹੀਂ ਹੋਣਗੀਆਂ"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"ਤੁਹਾਡੀਆਂ ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਤੁਹਾਨੂੰ ਸੂਚਨਾਵਾਂ ਨਹੀਂ ਭੇਜ ਸਕਦੀਆਂ, ਤੁਹਾਡੀ ਬੈਟਰੀ ਨਹੀਂ ਵਰਤ ਸਕਦੀਆਂ ਜਾਂ ਤੁਹਾਡੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕਰ ਸਕਦੀਆਂ"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਬੰਦ ਹਨ। ਤੁਹਾਡੀਆਂ ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਤੁਹਾਨੂੰ ਸੂਚਨਾਵਾਂ ਨਹੀਂ ਭੇਜ ਸਕਦੀਆਂ, ਤੁਹਾਡੀ ਬੈਟਰੀ ਨਹੀਂ ਵਰਤ ਸਕਦੀਆਂ ਜਾਂ ਤੁਹਾਡੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕਰ ਸਕਦੀਆਂ"</string>
- <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਨੂੰ ਬੈਜ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਅਤੇ ਇਹ ਤੁਹਾਡੇ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਦਿਸਣਗੀਆਂ"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"ਤੁਹਾਨੂੰ ਆਪਣੀਆਂ ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਤੋਂ ਫ਼ੋਨ ਕਾਲਾਂ, ਲਿਖਤ ਸੁਨੇਹੇ ਜਾਂ ਸੂਚਨਾਵਾਂ ਪ੍ਰਾਪਤ ਨਹੀਂ ਹੋਣਗੀਆਂ"</string>
+ <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਨੂੰ ਬੈਜ ਕੀਤਾ ਗਿਆ ਹੈ ਅਤੇ ਇਹ ਤੁਹਾਡੇ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਦਿਸਣਗੀਆਂ"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"ਸਮਝ ਲਿਆ"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਰੋਕੋ"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਚਾਲੂ ਕਰੋ"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"ਰੋਕ ਹਟਾਓ"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"ਫਿਲਟਰ"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"ਆਪਣਾ ਫ਼ੋਨ ਖੋਜੋ"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"ਆਪਣਾ ਟੈਬਲੈੱਟ ਖੋਜੋ"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index ea379d2..739ef6c 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -29,16 +29,16 @@
<string name="home_screen" msgid="5629429142036709174">"Ekran główny"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Podziel ekran"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacje o aplikacji: %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Zapisz parę aplikacji"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Naciśnij i przytrzymaj, aby przenieść widżet."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Naciśnij dwukrotnie i przytrzymaj, aby przenieść widżet lub użyć działań niestandardowych."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"Szerokość %1$d, wysokość %2$d"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Widżet <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Kliknij i przytrzymaj widżet, aby poruszać nim po ekranie głównym"</string>
+ <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Aby poruszać widżetem po ekranie głównym, kliknij go i przytrzymaj"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Dodaj do ekranu głównego"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widżet <xliff:g id="WIDGET_NAME">%1$s</xliff:g> został dodany do ekranu głównego"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugestie"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widżet}few{# widżety}many{# widżetów}other{# widżetu}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# skrót}few{# skróty}many{# skrótów}other{# skrótu}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Osobiste"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Służbowe"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Rozmowy"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Notatki"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Użyteczne informacje w zasięgu ręki"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Możesz dodać widżety do ekranu głównego, aby uzyskiwać informacje bez otwierania aplikacji"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Kliknij, aby zmienić ustawienia widżetu"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Umożliwia aplikacji odczytywanie ustawień i skrótów na ekranie głównym."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"Zapisuje ustawienia i skróty na ekranie głównym"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Umożliwia aplikacji zmianę ustawień i skrótów na ekranie głównym."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> nie może wykonywać połączeń telefonicznych"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Nie udało się załadować widżetu"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Ustawienia widżetu"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Kliknij, aby dokończyć konfigurację"</string>
@@ -99,15 +99,15 @@
<string name="folder_renamed" msgid="1794088362165669656">"Nazwa folderu zmieniona na <xliff:g id="NAME">%1$s</xliff:g>"</string>
<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> elementy"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Folder: <xliff:g id="NAME">%1$s</xliff:g>, liczba elementów: <xliff:g id="SIZE">%2$d</xliff:g> lub więcej"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Tapety"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Tapeta i styl"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Edytuj ekran główny"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Ustawienia ekranu głównego"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Funkcja wyłączona przez administratora"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Zezwalaj na obrót ekranu głównego"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Po obróceniu telefonu"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Kropki powiadomień"</string>
- <string name="notification_dots_desc_on" msgid="1679848116452218908">"Włączono"</string>
- <string name="notification_dots_desc_off" msgid="1760796511504341095">"Wyłączono"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Włączone"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Wyłączone"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Wymagany jest dostęp do powiadomień"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Aby pokazywać kropki powiadomień, włącz powiadomienia aplikacji <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Zmień ustawienia"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Aplikacje służbowe mają plakietki i są widoczne dla administratora IT"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Aplikacje służbowe zostały wstrzymane"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Nie będziesz otrzymywać powiadomień z aplikacji służbowych"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Aplikacje służbowe nie mogą wysyłać powiadomień, używać baterii ani uzyskiwać dostępu do Twojej lokalizacji"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Aplikacje służbowe są wyłączone i nie mogą wysyłać powiadomień, używać baterii ani uzyskiwać dostępu do Twojej lokalizacji"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Nie będziesz otrzymywać połączeń telefonicznych, SMS-ów ani powiadomień z aplikacji służbowych"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Aplikacje służbowe mają plakietki i są widoczne dla administratora IT"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Wstrzymaj aplikacje służbowe"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Włącz aplikacje służbowe"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Cofnij wstrzymywanie"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtruj"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Przeszukuj telefon"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Przeszukuj tablet"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index b56f857..76c65a4 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Página inicial"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ecrã dividido"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informações da app para %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Guardar par de apps"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Toque sem soltar para mover um widget."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toque duas vezes sem soltar para mover um widget ou utilizar ações personalizadas."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -49,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Pessoais"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabalho"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversas"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Tomar notas"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Informações úteis à sua disposição"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Para obter informações sem abrir apps, pode adicionar widgets ao seu ecrã principal"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Toque para alterar as definições do widget"</string>
@@ -80,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Permite que a app leia as definições e os atalhos no ecrã principal."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"escrever definições e atalhos do ecrã principal"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Permite que a app altere as definições e os atalhos no ecrã principal."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"O <xliff:g id="APP_NAME">%1$s</xliff:g> não tem autorização para efetuar chamadas telefónicas"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Não é possível carregar o widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Definições de widget"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Toque para concluir a configuração"</string>
@@ -98,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Nome de pasta alterado para <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Pasta: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> itens"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Pasta: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ou mais itens"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Imagens de fundo"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Imagem fundo/estilo"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Editar ecrã principal"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Definições de início"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Desativada pelo gestor"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Permitir rotação do ecrã principal"</string>
@@ -160,13 +161,14 @@
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Perfil de trabalho"</string>
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"As apps de trabalho têm um emblema e estão visíveis para o seu administrador de TI"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
- <string name="work_apps_paused_title" msgid="3040901117349444598">"As apps de trabalho estão suspensas."</string>
+ <string name="work_apps_paused_title" msgid="3040901117349444598">"As apps de trabalho estão suspensas"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Não vai receber notificações das apps de trabalho"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"As apps de trabalho não podem enviar-lhe notificações, utilizar a bateria ou aceder à sua localização"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"As apps de trabalho estão desativadas. As apps de trabalho não podem enviar-lhe notificações, utilizar a bateria ou aceder à sua localização"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Não vai receber chamadas, mensagens de texto nem notificações das apps de trabalho"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"As apps de trabalho têm um emblema e estão visíveis para o seu administrador de TI"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pausar apps de trabalho"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Ativar apps de trabalho"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Retomar"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrar"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Pesquise no telemóvel"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Pesquise no tablet"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index b2f420c..e23f459 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Início"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Tela dividida"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informações do app %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Salvar par de apps"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Toque e pressione para mover um widget."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toque duas vezes e mantenha a tela pressionada para mover um widget ou usar ações personalizadas."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Toque no widget e o pressione para definir a posição dele na tela inicial"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Adicionar à tela inicial"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> adicionado à tela inicial"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugestões"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# atalho}one{# atalho}other{# atalhos}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Pessoais"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabalho"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversas"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Anotações"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Informações úteis ao seu alcance"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Para ver informações sem precisar abrir os apps, adicione widgets à sua tela inicial"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Toque para mudar as configurações do widget"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Permite que o app leia as configurações e os atalhos na tela inicial."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"gravar configurações e atalhos da tela inicial"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Permite que o app mude as configurações e os atalhos na tela inicial."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> não tem permissão para fazer chamadas"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Não é possível carregar o widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Configurações de widget"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Toque para concluir a configuração"</string>
@@ -99,14 +99,14 @@
<string name="folder_renamed" msgid="1794088362165669656">"Pasta renomeada para <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Pasta: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> itens"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Pasta: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ou mais itens"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Planos de fundo"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Plano de fundo e estilo"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Editar tela inicial"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Configurações da tela inicial"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Desativado pelo administrador"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Permitir a rotação da tela inicial"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Quando o smartphone for girado"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Pontos de notificação"</string>
- <string name="notification_dots_desc_on" msgid="1679848116452218908">"Ativado"</string>
+ <string name="notification_dots_desc_on" msgid="1679848116452218908">"Ativados"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"Desativado"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Acesso a notificações necessário"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Para mostrar pontos de notificação, ative as notificações de app para <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Os apps de trabalho são identificados e ficam visíveis para o adm. de TI"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Ok"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Os apps de trabalho foram pausados"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Você não vai receber notificações dos seus apps de trabalho"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Os apps de trabalho não podem enviar notificações, usar a bateria nem acessar o local"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Os apps de trabalho estão desativados. Eles não podem enviar notificações, usar a bateria nem acessar o local"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Você não vai receber ligações, mensagens de texto ou notificações dos seus apps de trabalho"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Os apps de trabalho são identificados e ficam visíveis para o adm. de TI"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Ok"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pausar apps de trabalho"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Ativar apps de trabalho"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Ativar"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrar"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Pesquisar no smartphone"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Pesquisar no tablet"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 1af20f3..fc9c5d1 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Pagina de pornire"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ecran împărțit"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informații despre aplicație pentru %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Salvează perechea de aplicații"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Atinge și ține apăsat pentru a muta un widget."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Atinge de două ori și ține apăsat pentru a muta un widget sau folosește acțiuni personalizate."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Atinge lung widgetul pentru a-l muta pe ecranul de pornire"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Adaugă pe ecranul de pornire"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widgetul <xliff:g id="WIDGET_NAME">%1$s</xliff:g> a fost adăugat pe ecranul de pornire"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugestii"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}few{# widgeturi}other{# de widgeturi}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# comandă rapidă}few{# comenzi rapide}other{# de comenzi rapide}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g> <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personale"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Serviciu"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversații"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Luare de notițe"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Informații utile la îndemâna ta"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Pentru a primi informații fără să deschizi aplicațiile, poți adăuga widgeturi pe ecranul de pornire"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Atinge ca să schimbi setările pentru widgeturi"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Permite aplicației să citească setările și comenzile rapide de pe ecranul de pornire."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"scrie setările și comenzile rapide de pe ecranul de pornire"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Permite aplicației să modifice setările și comenzile rapide de pe ecranul de pornire."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> nu are permisiunea de a apela"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Widgetul nu poate fi încărcat"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Setări pentru widget"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Atinge pentru a finaliza configurarea"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Dosar redenumit <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Dosar: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> elemente"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Dosar: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> sau mai multe elemente"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Imagini de fundal"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Imagine de fundal și stil"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Editează ecranul de pornire"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Setări ecran de pornire"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Dezactivată de administrator"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Permite rotirea ecranului de pornire"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Aplicațiile pentru lucru sunt marcate și vizibile pentru administratorul IT"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Aplicațiile pentru lucru sunt întrerupte"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Nu vei primi notificări de la aplicațiile pentru lucru"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Aplicațiile pentru lucru nu pot să-ți trimită notificări, să folosească bateria sau să-ți acceseze locația"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Aplicațiile pentru lucru sunt dezactivate. Acestea nu pot să-ți trimită notificări, să folosească bateria sau să-ți acceseze locația."</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Nu vei primi apeluri telefonice, mesaje text sau notificări de la aplicațiile pentru lucru"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Aplicațiile pentru lucru sunt marcate și vizibile pentru administratorul IT"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Întrerupe aplicațiile pentru lucru"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Activează aplicațiile pentru lucru"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Anulează întreruperea"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtru"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Caută pe telefon"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Caută pe tabletă"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 345eed5..b3ff865 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Главный экран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Разделить экран"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Сведения о приложении \"%1$s\""</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Сохранить настройки одновременного использования двух приложений"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Чтобы переместить виджет, нажмите на него и удерживайте"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Чтобы использовать специальные действия или перенести виджет, нажмите на него дважды и удерживайте."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Нажмите на виджет и удерживайте его, чтобы переместить в нужное место на главном экране."</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Добавить на главный экран"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Виджет \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\" добавлен на главный экран"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Подсказки"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}one{# виджет}few{# виджета}many{# виджетов}other{# виджета}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ярлык}one{# ярлык}few{# ярлыка}many{# ярлыков}other{# ярлыка}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Личные виджеты"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Рабочие виджеты"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Разговоры"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Создание заметок"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Вся нужная информация перед глазами"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Чтобы не открывать приложения каждый раз, когда нужна информация, добавьте виджеты на главный экран."</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Нажмите, чтобы изменить настройки виджета"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Приложение получит доступ к данным о настройках и ярлыках на главном экране."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"Изменение настроек и ярлыков на главном экране"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Приложение сможет изменять настройки и ярлыки на главном экране."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"Приложение <xliff:g id="APP_NAME">%1$s</xliff:g> не может делать телефонные звонки"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Не удается загрузить виджет."</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Настройки виджета"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Нажмите, чтобы завершить настройку."</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Папка переименована в \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Папка \"<xliff:g id="NAME">%1$s</xliff:g>\" (объектов: <xliff:g id="SIZE">%2$d</xliff:g>)"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Папка \"<xliff:g id="NAME">%1$s</xliff:g>\" (объектов: <xliff:g id="SIZE">%2$d</xliff:g> или больше)"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Обои"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Обои и стиль"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Изменить главный экран"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Главный экран"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Функция отключена администратором"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Разрешить поворачивать главный экран"</string>
@@ -159,15 +159,16 @@
<string name="all_apps_personal_tab" msgid="4190252696685155002">"Личные"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"Рабочие"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Рабочий профиль"</string>
- <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"У рабочих приложений есть специальная пометка. Они видны системному администратору."</string>
+ <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"У рабочих приложений есть специальный значок. Они видны системному администратору."</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"ОК"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Рабочие приложения приостановлены"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Вы не будете получать уведомления от рабочих приложений."</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Рабочие приложения не могут отправлять уведомления, расходовать заряд батареи и получать доступ к данным о вашем местоположении."</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Рабочие приложения отключены. Они не могут отправлять уведомления, расходовать заряд батареи и получать доступ к вашему местоположению."</string>
- <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"У рабочих приложений есть специальная пометка. Они видны системному администратору."</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Вы не будете получать вызовы, текстовые сообщения и уведомления от рабочих приложений."</string>
+ <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"У рабочих приложений есть специальный значок. Они видны системному администратору."</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"ОК"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Приостановить рабочие приложения"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Включить рабочие приложения"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Возобновить"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Фильтр"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Поиск на телефоне"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Поиск на планшете"</string>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index 67700a9..6f93989 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"මුල් පිටුව"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"බෙදුම් තිරය"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s සඳහා යෙදුම් තතු"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"යෙදුම් යුගල සුරකින්න"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"විජට් එකක් ගෙන යාමට ස්පර්ශ කර අල්ලා ගෙන සිටින්න."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"විජට් එකක් ගෙන යාමට හෝ අභිරුචි ක්රියා භාවිත කිරීමට දෙවරක් තට්ටු කර අල්ලා ගෙන සිටින්න."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"විජට් එක මුල් පිටු තිරය වටා ගෙන යාමට විජට් එක ස්පර්ශ කර අල්ලාගෙන සිටින්න"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"මුල් තිරය වෙත එක් කරන්න"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> විජට්ටුව මුල් පිටු තිරය වෙත එක් කරන ලදි"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"යෝජනා"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{විජට් #}one{විජට් #}other{විජට් #}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{කෙටි මං #}one{කෙටි මං #}other{කෙටි මං #}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"පුද්ගලික"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"කාර්යාලය"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"සංවාද"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"සටහන් කර ගැනීම"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ප්රයෝජනවත් තොරතුරු ඔබගේ ඇඟිලි තුඩු අග"</string>
<string name="widget_education_content" msgid="1731667670753497052">"යෙදුම් විවෘත නොකර තොරතුරු ලබා ගැනීම සඳහා, ඔබට ඔබගේ මුල් තිරයට විජට් එක් කළ හැකිය"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"විජට් සැකසීම් වෙනස් කිරීමට තට්ටු කරන්න"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"මුල් පිටුවේ ඇති සැකසීම් සහ කෙටි මං කියවීමට යෙදුමට ඉඩ දෙයි."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"මුල් පිටු සැකසීම් සහ කෙටි මං ලියන්න"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"මුල් පිටුවේ සැකසීම් සහ කෙටි මං ඉවත් කිරීමට යෙදුමට ඉඩ දෙයි."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> හට දුරකථන ඇමතුම් සිදු කිරීමට ඉඩ නොදේ"</string>
<string name="gadget_error_text" msgid="740356548025791839">"විජට් පූරණය කළ නොහැකිය"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"විජට් සැකසීම්"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"පිහිටුවීම අවසන් කිරීමට තට්ටු කරන්න"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"<xliff:g id="NAME">%1$s</xliff:g> වෙත ෆෝල්ඩරය නැවත නම් කෙරිණි"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"ෆෝල්ඩරය: <xliff:g id="NAME">%1$s</xliff:g>, අයිතම <xliff:g id="SIZE">%2$d</xliff:g>"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ෆෝල්ඩර: <xliff:g id="NAME">%1$s</xliff:g>, අයිතම <xliff:g id="SIZE">%2$d</xliff:g>ක් හෝ වැඩි ගණනක්"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"වෝල්පේපර"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"වෝල්පේපරය සහ මෝස්තරය"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"මුල් තිරය සංස්කරණය කරන්න"</string>
<string name="settings_button_text" msgid="8873672322605444408">"නිවසේ සැකසීම්"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ඔබගේ පරිපාලක විසින් අබල කරන ලදී"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"මුල් තිරය කරකැවීමට ඉඩ දෙන්න"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"කාර්යාල යෙදුම්වලට ලාංඡන යොදා ඇති අතර ඔබගේ IT පරිපාලකට දෘශ්යමාන වේ"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"තේරුණා"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"කාර්යාල යෙදුම් විරාම කර ඇත"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"ඔබට ඔබේ කාර්යාල යෙදුම්වලින් දැනුම්දීම් නොලැබෙනු ඇත"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"ඔබගේ කාර්යාල යෙදුම්වලට ඔබට දැනුම්දීම් එවීමට, ඔබගේ බැටරිය භාවිත කිරීමට හෝ ඔබගේ ස්ථානයට ප්රවේශ වීමට නොහැකිය"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"කාර්යාල යෙදුම් ක්රියාවිරහිතයි. ඔබගේ කාර්යාල යෙදුම්වලට ඔබට දැනුම්දීම් එවීමට, ඔබගේ බැටරිය භාවිත කිරීමට හෝ ඔබගේ ස්ථානයට ප්රවේශ වීමට නොහැකිය"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"ඔබට ඔබේ කාර්යාල යෙදුම්වලින් දුරකථන ඇමතුම්, පෙළ පණිවිඩ, හෝ දැනුම්දීම් නොලැබෙනු ඇත"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"කාර්යාල යෙදුම්වලට ලාංඡන යොදා ඇති අතර ඔබගේ IT පරිපාලකට දෘශ්යමාන වේ"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"තේරුණා"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"කාර්යාල යෙදුම් විරාම කරන්න"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"කාර්යාල යෙදුම් ක්රියාත්මක කරන්න"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"විරාම නොකරන්න"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"පෙරහන"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"ඔබගේ දුරකථනය සොයන්න"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"ඔබගේ ටැබ්ලටය සොයන්න"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index a7c7c58..742d726 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Domov"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Rozdeliť obrazovku"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informácie o aplikácii pre %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Uložiť pár aplikácií"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Pridržaním presuňte miniaplikáciu."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvojitým klepnutím a pridržaním presuňte miniaplikáciu alebo použite vlastné akcie."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Pridržaním môžete miniaplikáciu posúvať po ploche"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Pridať na plochu"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Na plochu bola pridaná miniaplikácia <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Návrhy"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# miniaplikácia}few{# miniaplikácie}many{# widgets}other{# miniaplikácií}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# odkaz}few{# odkazy}many{# shortcuts}other{# odkazov}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Osobné"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Práca"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Konverzácie"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Zapisovanie poznámok"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Užitočné informácie poruke"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Ak chcete získavať informácie bez otvárania aplikácií, môžete si na plochu pridať miniaplikácie"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Klepnutím zmeňte nastavenia miniaplikácie"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Povoľuje aplikácii čítať nastavenia a odkazy na ploche."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"zápis nastavení a odkazov plochy"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Povoľuje aplikácii meniť nastavenia a odkazy na ploche."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> nemá povolenie uskutočňovať telefonické hovory"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Miniaplikáciu sa nepodarilo načítať"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Nastavenia miniaplikácie"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Nastavenie dokončíte klepnutím"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Priečinok bol premenovaný na <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Priečinok: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> položky"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Priečinok: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> alebo viac položiek"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Tapety"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Tapeta a štýl"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Upraviť plochu"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Nastavenia plochy"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Zakázané vaším správcom"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Povoliť otáčanie plochy"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Pracovné aplikácie majú odznak a zobrazujú sa správcovi IT"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Dobre"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Pracovné aplikácie sú pozastavené"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Nebudete dostávať upozornenia z pracovných aplikácií"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Pracovné aplikácie nemôžu posielať upozornenia ani používať batériu či polohu."</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Pracovné aplikácie sú vypnuté. Nemôžu posielať upozornenia ani používať batériu či polohu."</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Nebudete prijímať telefonické hovory ani dostávať textové správy či upozornenia z pracovných aplikácií"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Pracovné aplikácie majú odznak a zobrazujú sa správcovi IT"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Dobre"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pozastaviť pracovné aplikácie"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Zapnúť pracovné aplikácie"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Zrušiť pozastavenie"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrujte"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Vyhľadávanie v telefóne"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Vyhľadávanie v tablete"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index ff49ffe..57289d3 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Začetni zaslon"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Razdeljen zaslon"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Podatki o aplikaciji za: %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Shrani par aplikacij"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Pridržite pripomoček, da ga premaknete."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvakrat se dotaknite pripomočka in ga pridržite, da ga premaknete, ali pa uporabite dejanja po meri."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Dotaknite se pripomočka in ga pridržite, če ga želite premikati po začetnem zaslonu."</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Dodaj na začetni zaslon"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Pripomoček »<xliff:g id="WIDGET_NAME">%1$s</xliff:g>« je dodan na začetni zaslon."</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Predlogi"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# pripomoček}one{# pripomoček}two{# pripomočka}few{# pripomočki}other{# pripomočkov}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# bližnjica}one{# bližnjica}two{# bližnjici}few{# bližnjice}other{# bližnjic}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Osebni"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Služba"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Pogovori"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Ustvarjanje zapiskov"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Koristne informacije na dosegu prstov"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Če si želite podatke ogledati brez odpiranja aplikacij, lahko na začetni zaslon dodate pripomočke."</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Dotaknite se, če želite spremeniti nastavitve pripomočka."</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Aplikaciji dovoli branje nastavitev in bližnjic na začetnem zaslonu."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"zapisovanje nastavitev in bližnjic začetnega zaslona"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Aplikaciji dovoli spreminjanje nastavitev in bližnjic na začetnem zaslonu."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"Aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> ni dovoljeno opravljanje klicev"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Pripomočka ni mogoče naložiti."</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Nastavitve pripomočka"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Dotaknite se, da dokončate postopek nastavitve."</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Mapa je preimenovana v <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Mapa: <xliff:g id="NAME">%1$s</xliff:g>, št. elementov: <xliff:g id="SIZE">%2$d</xliff:g>"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Mapa: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ali več elementov"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Ozadja"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Zaslonsko ozadje in slog"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Urejanje začetnega zaslona"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Domače nastavitve"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogočil skrbnik."</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Dovoli sukanje začetnega zaslona"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Delovne aplikacije so označene z značko in vidne skrbniku za IT."</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Razumem"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Delovne aplikacije so začasno zaustavljene"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Obvestil iz delovnih aplikacij ne boste prejemali."</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Delovne aplikacije ne smejo pošiljati obvestil, porabljati energije baterije ali dostopati do lokacije."</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Delovne aplikacije so izklopljene in ne smejo pošiljati obvestil, porabljati energije baterije ali dostopati do lokacije."</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Telefonskih klicev, sporočil SMS in obvestil iz delovnih aplikacij ne boste prejemali."</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Delovne aplikacije so označene z značko in vidne skrbniku za IT."</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"V redu"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Začasno zaustavi delovne aplikacije"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Vklopi delovne aplikacije"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Znova aktiviraj"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtriranje"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Iskanje po telefonu"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Iskanje po tabličnem računalniku"</string>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 1bba697..7dee8aa 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Ekrani bazë"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ekrani i ndarë"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacioni i aplikacionit për %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Ruaj çiftin e aplikacioneve"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Prek dhe mbaj shtypur një miniaplikacion për ta zhvendosur."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Trokit dy herë dhe mbaje shtypur një miniapliikacion për ta zhvendosur atë ose për të përdorur veprimet e personalizuara."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Prek dhe mbaj të shtypur miniaplikacionin për ta lëvizur atë nëpër ekranin bazë"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Shto në ekranin bazë"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Miniaplikacioni <xliff:g id="WIDGET_NAME">%1$s</xliff:g> u shtua në ekranin bazë"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugjerime"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# miniaplikacion}other{# miniaplikacione}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# shkurtore}other{# shkurtore}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personale"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Puna"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Bisedat"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Mbajtja e shënimeve"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Informacione të dobishme në majë të gishtave të tu"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Për të marrë informacione pa i hapur aplikacionet, mund të shtosh miniaplikacione në ekranin bazë"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Trokit për të ndryshuar cilësimet e miniaplikacionit"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Lejon aplikacionin që të lexojë cilësimet dhe shkurtoret në ekranin bazë."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"shkruaj cilësimet dhe shkurtoret e ekranit bazë"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Lejon aplikacionin që të ndryshojë cilësimet dhe shkurtoret në ekranin bazë."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk lejohet të kryejë telefonata"</string>
<string name="gadget_error_text" msgid="740356548025791839">"S\'mund të ngarkohet miniaplikacioni"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Cilësimet e miniaplikacionit"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Trokit për të përfunduar konfigurimin"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Dosja u riemërtua në <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Dosja: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> artikuj"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Dosja: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ose më shumë artikuj"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Imazhet e sfondit"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Imazhi i sfondit dhe stili"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Modifiko ekranin bazë"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Cilësimet e ekranit bazë"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Çaktivizuar nga administratori"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Lejo rrotullimin e ekranit bazë"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Aplikacionet e punës janë të shënuara dhe të dukshme për administratorin e teknologjisë së informacionit"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"E kuptova"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Aplikacionet e punës janë vendosur në pauzë"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Nuk do të marrësh njoftime nga aplikacionet e punës"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Aplikacionet e tua të punës nuk mund të të dërgojnë njoftime, të përdorin baterinë tënde apo të kenë qasje në vendndodhjen tënde"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Aplikacionet e punës janë joaktive. Aplikacionet e tua të punës nuk mund të të dërgojnë njoftime, të përdorin baterinë tënde apo të kenë qasje në vendndodhjen tënde"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Nuk do të marrësh telefonata, mesazhe me tekst ose njoftime nga aplikacionet e punës"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Aplikacionet e punës janë të shënuara dhe të dukshme për administratorin e teknologjisë së informacionit"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"E kuptova"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Vendos në pauzë aplikacionet e punës"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Aktivizo aplikacionet e punës"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Hiq nga pauza"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtro"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Kërko në telefonin tënd"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Kërko në tabletin tënd"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 667eaf5..7121c53 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Почетни екран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Подељени екран"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Информације о апликацији за: %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Сачувај пар апликација"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Додирните и задржите ради померања виџета."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Двапут додирните и задржите да бисте померали виџет или користите прилагођене радње."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Додирните и задржите виџет да бисте га померали по почетном екрану"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Додај на почетни екран"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Додали сте виџет <xliff:g id="WIDGET_NAME">%1$s</xliff:g> на почетни екран"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Предлози"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виџет}one{# виџет}few{# виџета}other{# виџета}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# пречица}one{# пречица}few{# пречице}other{# пречица}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Лично"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Посао"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Конверзације"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Прављење бележака"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Корисне информације надохват руке"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Да бисте пронашли информације без отварања апликација, можете да додате виџете на почетни екран"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Додирните да бисте променили подешавања виџета"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Дозвољава апликацији да чита подешавања и пречице на почетном екрану."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"уписивање подешавања и пречица на почетном екрану"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Дозвољава апликацији да мења подешавања и пречице на почетном екрану."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> нема дозволу за упућивање телефонских позива"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Учитавање виџета није успело"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Подешавања виџета"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Додирните да бисте довршили подешавање"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Фолдер је преименован у <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Фолдер: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ставке"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Фолдер: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> или више ставки"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Позадине"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Позадина и стил"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Измени почетни екран"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Подешавања почетног екрана"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Администратор је онемогућио"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Дозволи ротацију почетног екрана"</string>
@@ -156,18 +156,19 @@
<string name="action_dismiss_notification" msgid="5909461085055959187">"Одбаци"</string>
<string name="accessibility_close" msgid="2277148124685870734">"Затвори"</string>
<string name="notification_dismissed" msgid="6002233469409822874">"Обавештење је одбачено"</string>
- <string name="all_apps_personal_tab" msgid="4190252696685155002">"Личне"</string>
- <string name="all_apps_work_tab" msgid="4884822796154055118">"Пословне"</string>
+ <string name="all_apps_personal_tab" msgid="4190252696685155002">"Лично"</string>
+ <string name="all_apps_work_tab" msgid="4884822796154055118">"Посао"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Пословни профил"</string>
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Пословне апликације су означене значком и ИТ администратор може да их види"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Важи"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Пословне апликације су паузиране"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Нећете добијати обавештења из пословних апликација"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Пословне апликације не могу да вам шаљу обавештења, користе батерију нити приступају локацији"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Пословне апликације су искључене. Пословне апликације не могу да вам шаљу обавештења, користе батерију нити приступају локацији"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Нећете примати телефонске позиве, текстуалне поруке нити обавештења из пословних апликација"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Пословне апликације су означене значком и ИТ администратор може да их види"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Важи"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Паузирај пословне апликације"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Укључи пословне апликације"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Поново активирај"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Филтер"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Претражите телефон"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Претражите таблет"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 3ebea21..aeaf708 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Startskärm"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Delad skärm"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Appinformation för %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Spara appar som ska användas tillsammans"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Tryck länge för att flytta en widget."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Tryck snabbt två gånger och håll kvar för att flytta en widget eller använda anpassade åtgärder."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Tryck länge på widgeten om du vill flytta den på startskärmen"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Lägg till på startskärmen"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget för <xliff:g id="WIDGET_NAME">%1$s</xliff:g> har lagts till på startskärmen"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Förslag"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgetar}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# genväg}other{# genvägar}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Privata"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Arbete"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Konversationer"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Anteckna"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Användbar information nära till hands"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Om du vill ha information utan att öppna appar kan du lägga till widgetar på startskärmen"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tryck för att ändra inställningarna för widgeten"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Tillåter att appen läser inställningar och genvägar på startskärmen."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"skriva inställningar och genvägar på startskärmen"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Tillåter att appen ändrar inställningar och genvägar på startskärmen."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> har inte behörighet att ringa samtal"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Det gick inte att läsa in widgeten"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Widgetinställningar"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Tryck för att slutföra konfigureringen"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Mappen har bytt namn till <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Mapp: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> objekt"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Mapp: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> eller fler objekt"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Bakgrunder"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Bakgrund och utseende"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Redigera startskärm"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Startinställningar"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Inaktiverat av administratören"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Tillåt rotering av startskärmen"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Jobbappar är märkta och synliga för IT-administratören"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Jobbappar har pausats"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Du får inga aviseringar från dina jobbappar"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Dina jobbappar kan inte skicka aviseringar, använda batteriet eller komma åt din plats"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Jobbappar är inaktiverade. Dina jobbappar kan inte skicka aviseringar, använda batteriet eller komma åt din plats"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Du får inga telefonsamtal, sms eller aviseringar från dina jobbappar"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Jobbappar är märkta och synliga för IT-administratören"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pausa jobbappar"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Aktivera jobbappar"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Återuppta"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Sök på telefonen"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Sök på surfplattan"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index f4ac880..5be3bf3 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Skrini ya kwanza"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Gawa skrini"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Maelezo ya programu ya %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Hifadhi jozi ya programu"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Gusa na ushikilie ili usogeze wijeti."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Gusa mara mbili na ushikilie ili usogeze wijeti au utumie vitendo maalum."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Gusa na ushikilie wijeti ili uisogeze kwenye skrini ya kwanza"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Weka kwenye skrini ya kwanza"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Umeongeza wijeti ya <xliff:g id="WIDGET_NAME">%1$s</xliff:g> kwenye skrini ya kwanza"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Mapendekezo"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{Wijeti #}other{Wijeti #}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{Njia # ya mkato}other{Njia # za mkato}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Binafsi"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Kazini"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Mazungumzo"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Kuandika madokezo"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Maelezo muhimu, popote ulipo"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Ili upate maelezo bila kufungua programu, unaweza kuweka wijeti kwenye skrini yako ya kwanza"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Gusa ili ubadilishe mipangilio ya wijeti"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Huruhusu programu kusoma mipangilio na njia za mikato katika skrini ya kwanza."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"kuandika mipangilio ya skrini ya kwanza na njia za mkato"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Huruhusu programu kubadilisha mipangilio na njia za mkato katika skrini ya kwanza."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> hairuhusiwi kupiga simu"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Imeshindwa kupakia wijeti"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Mipangilio ya wijeti"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Gusa ili umalize kuweka mipangilio"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Folda imebadilishwa jina kuwa <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Folda: <xliff:g id="NAME">%1$s</xliff:g>, vipengee <xliff:g id="SIZE">%2$d</xliff:g>"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Folda: <xliff:g id="NAME">%1$s</xliff:g>, vipengee <xliff:g id="SIZE">%2$d</xliff:g> au zaidi"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Mandhari"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Mandhari na mtindo"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Badilisha Skrini ya Kwanza"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Mipangilio ya mwanzo"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Imezimwa na msimamizi wako"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Ruhusu kipengele cha kuzungusha skrini ya kwanza"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Programu za kazini zina beji na msimamizi wako wa TEHAMA anaziona"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Nimeelewa"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Programu za kazini zimesimamishwa"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Hutaweza kupokea arifa kutoka kwenye programu zako za kazini"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Programu zako za kazini haziwezi kukutumia arifa, kutumia betri yako au kufikia maelezo ya mahali ulipo"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Programu za kazini zimezimwa. Programu zako za kazini haziwezi kukutumia arifa, kutumia betri yako au kufikia maelezo ya mahali ulipo"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Hutaweza kupokea simu, ujumbe wa maandishi au arifa kutoka kwenye programu zako za kazini"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Programu za kazini zina beji na msimamizi wako wa TEHAMA anaziona"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Nimeelewa"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Simamisha programu za kazini"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Washa programu za kazini"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Acha kusimamisha"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Kichujio"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Tafuta kwenye simu yako"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Tafuta kwenye kompyuta kibao yako"</string>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index e0c44c8..ec287f5 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"முகப்பு"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"திரைப் பிரிப்பு"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$sக்கான ஆப்ஸ் தகவல்கள்"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"ஆப்ஸ் ஜோடியைச் சேமி"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"விட்ஜெட்டை நகர்த்தத் தொட்டுப் பிடிக்கவும்."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"விட்ஜெட்டை நகர்த்த இருமுறை தட்டிப் பிடிக்கவும் அல்லது பிரத்தியேகச் செயல்களைப் பயன்படுத்தவும்."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"முகப்புத் திரையைச் சுற்றி விட்ஜெட்டை நகர்த்த அதைத் தொட்டுப் பிடியுங்கள்"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"முகப்புத் திரையில் சேர்"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> விட்ஜெட் முகப்புத் திரையில் சேர்க்கப்பட்டது"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"பரிந்துரைகள்"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# விட்ஜெட்}other{# விட்ஜெட்டுகள்}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ஷார்ட்கட்}other{# ஷார்ட்கட்கள்}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"தனிப்பட்டவை"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"பணி"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"உரையாடல்கள்"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"குறிப்பெடுத்தல்"</string>
<string name="widget_education_header" msgid="4874760613775913787">"விரல்நுனியில் பயனுள்ள தகவல்களைப் பெறுங்கள்"</string>
<string name="widget_education_content" msgid="1731667670753497052">"முகப்புத் திரையில் விட்ஜெட்டுகளைச் சேர்த்து ஆப்ஸைத் திறக்காமலேயே தகவல்களைப் பெறலாம்"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"விட்ஜெட் அமைப்புகளை மாற்றத் தட்டவும்"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"முகப்புத் திரையிலுள்ள அமைப்புகளையும் ஷார்ட்கட்களையும் படிக்க ஆப்ஸை அனுமதிக்கும்."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"முகப்புத் திரையின் அமைப்புகளையும் ஷார்ட்கட்களையும் எழுதுதல்"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"முகப்புத் திரையிலுள்ள அமைப்புகளையும் ஷார்ட்கட்களையும் மாற்ற ஆப்ஸை அனுமதிக்கும்."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"ஃபோன் அழைப்புகள் செய்ய, <xliff:g id="APP_NAME">%1$s</xliff:g> அனுமதிக்கப்படவில்லை"</string>
<string name="gadget_error_text" msgid="740356548025791839">"விட்ஜெட்டை ஏற்ற முடியவில்லை"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"விட்ஜெட் அமைப்புகள்"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"அமைவை நிறைவுசெய்யத் தட்டவும்"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"ஃபோல்டர் <xliff:g id="NAME">%1$s</xliff:g> என மறுபெயரிடப்பட்டது"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"ஃபோல்டர்: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ஃபைல்கள்"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ஃபோல்டர்: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> அல்லது அதற்கு அதிகமான ஃபைல்கள்"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"வால்பேப்பர்கள்"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"வால்பேப்பர் & ஸ்டைல்"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"முகப்புத் திரையில் மாற்று"</string>
<string name="settings_button_text" msgid="8873672322605444408">"முகப்பு அமைப்புகள்"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"உங்கள் நிர்வாகி முடக்கியுள்ளார்"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"முகப்புத் திரை சுழற்சியை அனுமதித்தல்"</string>
@@ -159,15 +159,16 @@
<string name="all_apps_personal_tab" msgid="4190252696685155002">"தனிப்பட்டவை"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"பணி"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"பணிக் கணக்கு"</string>
- <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"பணி ஆப்ஸில் பேட்ஜ் இடப்பட்டுள்ளன. உங்கள் IT நிர்வாகியால் அவற்றைப் பார்க்க முடியும்"</string>
+ <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"பணி ஆப்ஸில் பேட்ஜ் இடப்பட்டிருக்கும், உங்கள் IT நிர்வாகியால் பணி ஆப்ஸைப் பார்க்க முடியும்"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"முடிந்தது"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"பணி ஆப்ஸ் இடைநிறுத்தப்பட்டுள்ளன"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"உங்கள் பணி ஆப்ஸிலிருந்து அறிவிப்புகளைப் பெறமாட்டீர்கள்"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"பணி ஆப்ஸால் உங்களுக்கு அறிவிப்புகளை அனுப்பவோ பேட்டரியைப் பயன்படுத்தவோ உங்கள் இருப்பிடத்தை அணுகவோ முடியாது"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"பணி ஆப்ஸ் முடக்கப்பட்டுள்ளன. அவற்றால் உங்களுக்கு அறிவிப்புகளை அனுப்பவோ பேட்டரியைப் பயன்படுத்தவோ உங்கள் இருப்பிடத்தை அணுகவோ முடியாது"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"உங்கள் பணி ஆப்ஸிலிருந்து மொபைல் அழைப்புகள், மெசேஜ்கள், அறிவிப்புகள் ஆகியவற்றைப் பெறமாட்டீர்கள்"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"பணி ஆப்ஸ் பேட்ஜ் குறியிடப்பட்டுள்ளன. மேலும் உங்கள் IT நிர்வாகியால் அவற்றைப் பார்க்க முடியும்"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"சரி"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"பணி ஆப்ஸை இடைநிறுத்து"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"பணி ஆப்ஸை இயக்கு"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"மீண்டும் இயக்கு"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"வடிப்பான்"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"உங்கள் மொபைலில் தேடுதல்"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"உங்கள் டேப்லெட்டில் தேடுதல்"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 8617a28..032a241 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -27,18 +27,18 @@
<string name="safemode_widget_error" msgid="4863470563535682004">"సురక్షిత మోడ్లో విడ్జెట్లు నిలిపివేయబడ్డాయి"</string>
<string name="shortcut_not_available" msgid="2536503539825726397">"షార్ట్కట్ అందుబాటులో లేదు"</string>
<string name="home_screen" msgid="5629429142036709174">"మొదటి ట్యాబ్"</string>
- <string name="recent_task_option_split_screen" msgid="6690461455618725183">"స్క్రీన్ను విభజించు"</string>
+ <string name="recent_task_option_split_screen" msgid="6690461455618725183">"స్ప్లిట్ స్క్రీన్"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s కోసం యాప్ సమాచారం"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"యాప్ పెయిర్ను సేవ్ చేయండి"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"విడ్జెట్ను తరలించడానికి తాకి & నొక్కి ఉంచండి."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"విడ్జెట్ను తరలించడానికి లేదా అనుకూల చర్యలను ఉపయోగించడానికి రెండుసార్లు నొక్కండి & హోల్డ్ చేయి."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d వెడల్పు X %2$d ఎత్తు"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> విడ్జెట్"</string>
- <string name="add_item_request_drag_hint" msgid="8730547755622776606">"విడ్జెట్ను మొదటి స్క్రీన్ చుట్టూ తిప్పడానికి దాన్ని తాకి, & నొక్కి ఉంచండి"</string>
+ <string name="add_item_request_drag_hint" msgid="8730547755622776606">"విడ్జెట్ను మొదటి స్క్రీన్లో తిప్పడానికి దాన్ని తాకి, & నొక్కి పట్టుకోండి"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"మొదటి స్క్రీన్కు జోడించండి"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"మొదటి స్క్రీన్కు <xliff:g id="WIDGET_NAME">%1$s</xliff:g> విడ్జెట్ జోడించబడింది"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"సూచనలు"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# విడ్జెట్}other{# విడ్జెట్లు}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# షార్ట్కట్}other{# షార్ట్కట్లు}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"వ్యక్తిగత గ్యాడ్జెట్స్"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ఆఫీస్"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"సంభాషణలు"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"నోట్-టేకింగ్"</string>
<string name="widget_education_header" msgid="4874760613775913787">"మీ చేతివేళ్ల మీద ఉపయోగకరమైన సమాచారం"</string>
<string name="widget_education_content" msgid="1731667670753497052">"యాప్లను తెరవకుండా సమాచారాన్ని పొందడానికి, మీరు మీ మొదటి స్క్రీన్కు విడ్జెట్లను జోడించవచ్చు"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"విడ్జెట్ సెట్టింగ్లను మార్చడానికి ట్యాప్ చేయండి"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"హోమ్లో సెట్టింగ్లు, షార్ట్కట్లను చదవడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"హోమ్ సెట్టింగ్లు, షార్ట్కట్లను రాయండి"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"హోమ్లో సెట్టింగ్లు, షార్ట్కట్లను మార్చడానికి యాప్ను అనుమతిస్తుంది."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"ఫోన్ కాల్స్ను చేసేందుకు <xliff:g id="APP_NAME">%1$s</xliff:g>కి అనుమతి లేదు"</string>
<string name="gadget_error_text" msgid="740356548025791839">"విడ్జెట్ను లోడ్ చేయడం సాధ్యం కాలేదు"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"విడ్జెట్ సెట్టింగ్లు"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"సెటప్ను ముగించడానికి ట్యాప్ చేయండి"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"ఫోల్డర్ పేరు <xliff:g id="NAME">%1$s</xliff:g>గా మార్చబడింది"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"ఫోల్డర్: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ఐటెమ్లు"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"ఫోల్డర్: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> లేదా అంతకంటే ఎక్కువ ఐటెమ్లు"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"వాల్పేపర్లు"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"వాల్పేపర్ & స్టయిల్"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"మొదటి స్క్రీన్ను ఎడిట్ చేయండి"</string>
<string name="settings_button_text" msgid="8873672322605444408">"మొదటి స్క్రీన్ సెట్టింగ్లు"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"మీ నిర్వాహకులు నిలిపివేసారు"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"మొదటి స్క్రీన్ రొటేషన్ను అనుమతించండి"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"వర్క్ యాప్లకు బ్యాడ్జ్ ఉంటుంది, అవి మీ IT అడ్మిన్కు కనిపిస్తాయి"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"అర్థమైంది"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"వర్క్ యాప్లు పాజ్ చేయబడ్డాయి"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"మీ వర్క్ యాప్ల నుండి మీకు నోటిఫికేషన్లు అందవు"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"మీకు నోటిఫికేషన్లు పంపడం, మీ బ్యాటరీని ఉపయోగించడం, లేదా మీ లొకేషన్ను యాక్సెస్ చేయడం మీ వర్క్ యాప్లకు సాధ్యపడదు"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"వర్క్ యాప్లు ఆఫ్లో ఉన్నాయి. మీకు నోటిఫికేషన్లు పంపడం, మీ బ్యాటరీని ఉపయోగించడం, లేదా మీ లొకేషన్ను యాక్సెస్ చేయడం మీ వర్క్ యాప్లకు సాధ్యపడదు"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"మీ వర్క్ యాప్ల నుండి మీకు ఫోన్ కాల్స్, టెక్స్ట్ మెసేజ్లు, లేదా నోటిఫికేషన్లు అందవు"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"వర్క్ యాప్లకు బ్యాడ్జ్ ఉంటుంది, అవి మీ IT అడ్మిన్కు కనిపిస్తాయి"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"అర్థమైంది"</string>
- <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"వర్క్ యాప్లను పాజ్ చేయి"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"వర్క్ యాప్లను ఆన్ చేయి"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"వర్క్ యాప్లను పాజ్ చేయండి"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"పాజ్ నుండి తీసివేయండి"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"ఫిల్టర్ చేయి"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"మీ ఫోన్లో సెర్చ్ చేయండి"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"మీ టాబ్లెట్లో సెర్చ్ చేయండి"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 24ed95d..fe79b12 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -27,8 +27,9 @@
<string name="safemode_widget_error" msgid="4863470563535682004">"มีการปิดใช้งานวิดเจ็ตในเซฟโหมด"</string>
<string name="shortcut_not_available" msgid="2536503539825726397">"ทางลัดไม่พร้อมใช้งาน"</string>
<string name="home_screen" msgid="5629429142036709174">"หน้าแรก"</string>
- <string name="recent_task_option_split_screen" msgid="6690461455618725183">"แบ่งหน้าจอ"</string>
+ <string name="recent_task_option_split_screen" msgid="6690461455618725183">"แยกหน้าจอ"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"ข้อมูลแอปสำหรับ %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"บันทึกคู่แอป"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"แตะค้างไว้เพื่อย้ายวิดเจ็ต"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"แตะสองครั้งค้างไว้เพื่อย้ายวิดเจ็ตหรือใช้การดำเนินการที่กำหนดเอง"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"แตะวิดเจ็ตค้างไว้เพื่อย้ายไปรอบๆ หน้าจอหลัก"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"เพิ่มลงในหน้าจอหลัก"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"เพิ่มวิดเจ็ต <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ลงในหน้าจอหลักแล้ว"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"คำแนะนำ"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{วิดเจ็ต # รายการ}other{วิดเจ็ต # รายการ}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{ทางลัด # รายการ}other{ทางลัด # รายการ}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"ส่วนตัว"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"งาน"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"การสนทนา"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"การจดบันทึก"</string>
<string name="widget_education_header" msgid="4874760613775913787">"เข้าถึงข้อมูลที่เป็นประโยชน์ได้จากปลายนิ้ว"</string>
<string name="widget_education_content" msgid="1731667670753497052">"หากต้องการรับข้อมูลโดยไม่เปิดแอป ให้เพิ่มวิดเจ็ตลงในหน้าจอหลัก"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"แตะเพื่อเปลี่ยนการตั้งค่าวิดเจ็ต"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"อนุญาตให้แอปอ่านการตั้งค่าและทางลัดในหน้าแรก"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"เขียนการตั้งค่าและทางลัดในหน้าแรก"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"อนุญาตให้แอปเปลี่ยนการตั้งค่าและทางลัดในหน้าแรก"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ไม่ได้รับอนุญาตให้โทรออก"</string>
<string name="gadget_error_text" msgid="740356548025791839">"โหลดวิดเจ็ตไม่ได้"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"การตั้งค่าวิดเจ็ต"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"แตะเพื่อสิ้นสุดการตั้งค่า"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"เปลี่ยนชื่อโฟลเดอร์เป็น <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"โฟลเดอร์: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> รายการ"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"โฟลเดอร์: <xliff:g id="NAME">%1$s</xliff:g>, อย่างน้อย <xliff:g id="SIZE">%2$d</xliff:g> รายการ"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"วอลเปเปอร์"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"วอลเปเปอร์และรูปแบบ"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"แก้ไขหน้าจอหลัก"</string>
<string name="settings_button_text" msgid="8873672322605444408">"การตั้งค่าหน้าจอหลัก"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ปิดใช้โดยผู้ดูแลระบบ"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"อนุญาตให้หมุนหน้าจอหลัก"</string>
@@ -161,13 +161,14 @@
<string name="work_profile_toggle_label" msgid="3081029915775481146">"โปรไฟล์งาน"</string>
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"แอปงานจะติดป้ายไว้และผู้ดูแลระบบไอทีจะมองเห็น"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"รับทราบ"</string>
- <string name="work_apps_paused_title" msgid="3040901117349444598">"แอปงานปิดอยู่"</string>
+ <string name="work_apps_paused_title" msgid="3040901117349444598">"แอปงานหยุดชั่วคราว"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"คุณจะไม่ได้รับการแจ้งเตือนจากแอปงาน"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"แอปงานจะส่งการแจ้งเตือน ใช้แบตเตอรี่ หรือเข้าถึงตำแหน่งของคุณไม่ได้"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"แอปงานปิดอยู่ แอปงานจะส่งการแจ้งเตือน ใช้แบตเตอรี่ หรือเข้าถึงตำแหน่งของคุณไม่ได้"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"คุณจะไม่ได้รับสายโทรเข้า, SMS หรือการแจ้งเตือนจากแอปงาน"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"แอปงานจะติดป้ายไว้และผู้ดูแลระบบไอทีจะมองเห็น"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"รับทราบ"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"หยุดแอปงานชั่วคราว"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"เปิดแอปงาน"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"ยกเลิกการหยุดชั่วคราว"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"ตัวกรอง"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"ค้นหาในโทรศัพท์"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"ค้นหาในแท็บเล็ต"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 7567bbb..fe4aac1 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Home"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Split screen"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Impormasyon ng app para sa %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"I-save ang pares ng app"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Pindutin nang matagal para ilipat ang widget."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"I-double tap at pindutin nang matagal para ilipat ang widget o gumamit ng mga custom na pagkilos."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Pindutin nang matagal ang widget para ilipat-lipat ito sa home screen"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Idagdag sa home screen"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Idinagdag sa home screen ang widget na <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Mga Suhestyon"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# na widget}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# shortcut}one{# shortcut}other{# na shortcut}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Personal"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabaho"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Mga Pag-uusap"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Pagtatala"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Abot-kamay na mahalagang impormasyon"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Para makakuha ng impormasyon nang hindi nagbubukas ng mga app, puwede kang magdagdag ng mga widget sa iyong home screen"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"I-tap para baguhin ang mga setting ng widget"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Binibigyang-daan ang app na basahin ang mga setting at shortcut sa home."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"magsulat ng mga setting at shortcut ng home"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Binibigyang-daan ang app na baguhin ang mga setting at shortcut sa home."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"Hindi pinahihintulutang tumawag ang <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Hindi ma-load ang widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Mga setting ng widget"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"I-tap para tapusin ang pag-set up"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Pinalitan ang pangalan ng folder ng <xliff:g id="NAME">%1$s</xliff:g>"</string>
<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> (na) item"</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> o higit pang item"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Mga Wallpaper"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Wallpaper & istilo"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"I-edit ang Home Screen"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Mga setting ng Home"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Na-disable ng iyong admin"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Payagan ang pag-rotate ng home screen"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"May badge at nakikita ng iyong IT admin ang mga app para sa trabaho"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Naka-pause ang mga app para sa trabaho"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Hindi ka makakatanggap ng mga notification mula sa iyong mga app para sa trabaho"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Ang mga app mo para sa trabaho ay hindi makakapagpadala sa iyo ng mga notification, makakagamit ng baterya mo, o makaka-access ng iyong lokasyon"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Naka-off ang mga app para sa trabaho. Ang mga app mo para sa trabaho ay hindi makakapagpadala sa iyo ng mga notification, makakagamit ng baterya mo, o makaka-access ng iyong lokasyon"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Hindi ka makakatanggap ng mga tawag sa telepono, text message, o notification mula sa iyong mga app para sa trabaho"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"May badge at nakikita ng iyong IT admin ang mga app para sa trabaho"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"I-pause ang mga app para sa trabaho"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"I-on ang mga app para sa trabaho"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"I-unpause"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Maghanap sa iyong telepono"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Maghanap sa iyong tablet"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index df6a7e7..8a836e6 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Ana ekran"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Bölünmüş ekran"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s uygulama bilgileri"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Uygulama çiftini kaydedin"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Widget\'ı taşımak için dokunup basılı tutun."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Widget\'ı taşımak veya özel işlemleri kullanmak için iki kez dokunup basılı tutun."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Ana ekranda taşımak için widget\'a dokunup basılı tutun"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Ana ekrana ekle"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget\'ı ana ekrana eklendi"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Öneriler"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# kısayol}other{# kısayol}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Kişisel"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"İş"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Görüşmeler"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Not alma"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Faydalı bilgiler parmaklarınızın ucunda"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Uygulama açmadan bilgi almak için ana ekranınıza widget ekleyebilirsiniz"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Widget ayarlarını değiştirmek için dokunun"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Uygulamaya ana ekrandaki ayarları ve kısayolları okuma izni verir."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"ana ekran ayarlarını ve kısayollarını yaz"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Uygulamaya ana ekrandaki ayarları ve kısayolları değiştirme izni verir."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulamasının telefon etmesine izin verilmiyor"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Widget yüklenemiyor"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Widget ayarları"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Kurulumu tamamlamak için dokunun"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Klasörün adı <xliff:g id="NAME">%1$s</xliff:g> olarak değiştirildi"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Klasör: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> öğe"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Klasör: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> veya daha fazla öğe"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Duvar Kağıtları"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Duvar kağıdı ve stil"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Ana ekranı düzenleyin"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Ana ekran ayarları"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Yöneticiniz tarafından devre dışı bırakıldı"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Ana ekranı döndürmeye izin ver"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"İş uygulamaları rozetle işaretlenmiş olup BT yöneticisi tarafından görülebilir"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Anladım"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"İş uygulamaları duraklatıldı"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"İş uygulamalarınızdan bildirim almazsınız"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"İş uygulamaları size bildirim gönderemez, pilinizi kullanamaz veya konum bilginize erişemez"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"İş uygulamaları kapalı. İş uygulamalarınız size bildirim gönderemez, pilinizi kullanamaz veya konum bilginize erişemez"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"İş uygulamalarınızdan telefon araması, kısa mesaj veya bildirim almazsınız"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"İş uygulamaları rozetle işaretlenmiş olup BT yöneticisi tarafından görülebilir"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Anladım"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"İş uygulamalarını duraklat"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"İş uygulamalarını aç"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Devam ettir"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtre"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"telefonunuzda arama yapmak"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Tabletinizde arama yapma"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 5ef5b65..5dc5d8e 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Головний екран"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Розділити екран"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Інформація про додаток для %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Зберегти пару додатків"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Натисніть і втримуйте, щоб перемістити віджет."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Двічі натисніть і втримуйте віджет, щоб перемістити його або виконати інші дії."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Натисніть і втримуйте віджет, щоб перемістити його в потрібне місце на головному екрані"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Додати на головний екран"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Віджет <xliff:g id="WIDGET_NAME">%1$s</xliff:g> додано на головний екран"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Пропозиції"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# віджет}one{# віджет}few{# віджети}many{# віджетів}other{# віджета}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ярлик}one{# ярлик}few{# ярлики}many{# ярликів}other{# ярлика}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Особисті"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Робочі"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Розмови"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Створення нотаток"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Корисна інформація завжди під рукою"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Щоб отримувати інформацію, не відкриваючи додатки, ви можете додати на головний екран віджети"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Натисніть, щоб змінити налаштування віджета"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Дозволяє додатку читати налаштування та ярлики на головному екрані."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"записувати налаштування та ярлики головного екрана"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Дозволяє додатку змінювати налаштування та ярлики на головному екрані."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> не має дозволу телефонувати"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Не вдається завантажити віджет"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Налаштування віджета"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Торкніться, щоб завершити налаштування"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Папку перейменовано на <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Папка \"<xliff:g id="NAME">%1$s</xliff:g>\", елементів: <xliff:g id="SIZE">%2$d</xliff:g>"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Папка \"<xliff:g id="NAME">%1$s</xliff:g>\", елементів: <xliff:g id="SIZE">%2$d</xliff:g> або більше"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Фонові малюнки"</string>
- <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Оформлення та стиль"</string>
+ <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Оформлення і стиль"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Редагувати головний екран"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Налаштування головного екрана"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Вимкнув адміністратор"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Дозволити обертання головного екрана"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Робочі додатки мають спеціальну позначку. Їх бачить системний адміністратор."</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Робочі додатки призупинено"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Ви не отримуватимете сповіщення від робочих додатків"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Ваші робочі додатки не можуть надсилати сповіщення, використовувати заряд акумулятора й отримувати доступ до геоданих"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Робочі додатки вимкнено. Вони не можуть надсилати сповіщення, використовувати заряд акумулятора й отримувати доступ до геоданих."</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Ви не отримуватимете телефонні виклики, текстові повідомлення, а також сповіщення від робочих додатків"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Робочі додатки мають спеціальну позначку. Їх бачить системноий адміністратор."</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Зрозуміло"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Призупинити робочі додатки"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Увімкнути робочі додатки"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Відновити"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Фільтр"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Пошук на телефоні"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Пошук на планшеті"</string>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index e3c10c6..3994810 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"ہوم"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"اسپلٹ اسکرین"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s کے لیے ایپ کی معلومات"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"ایپس کے جوڑے کو محفوظ کریں"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"ویجیٹ منتقل کرنے کے لیے ٹچ کریں اور پکڑ کر رکھیں۔"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"ویجیٹ کو منتقل کرنے یا حسب ضرورت کارروائیاں استعمال کرنے کے لیے دوبار تھپتھپائیں اور پکڑ کر رکھیں۔"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"ویجیٹ کو ہوم اسکرین کے چاروں طرف منتقل کرنے کے لیے اسے ٹچ کریں اور دبائے رکھیں"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"ہوم اسکرین میں شامل کریں"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ویجیٹ کو ہوم اسکرین میں شامل کیا گیا"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"تجاویز"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ویجیٹ}other{# ویجیٹس}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# شارٹ کٹ}other{# شارٹ کٹس}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>، <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"ذاتی"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"دفتری ویجیٹس"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"گفتگوئیں"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"نوٹ لکھنا"</string>
<string name="widget_education_header" msgid="4874760613775913787">"مفید معلومات کو آسانی سے حاصل کریں"</string>
<string name="widget_education_content" msgid="1731667670753497052">"ایپس کو کھولے بغیر معلومات حاصل کرنے کے لیے آپ اپنی ہوم اسکرین پر ویجیٹس شامل کر سکتے ہیں"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ویجیٹ ترتیبات تبدیل کرنے کے لیے تھپتھپائیں"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"اس سے ایپ کو ہوم اسکرین میں ترتیبات اور شارٹ کٹس کو پڑھنے کی اجازت ملتی ہے۔"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"ہوم ترتیبات اور شارٹ کٹس کو لکھیں"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"اس سے ایپ کو ہوم اسکرین میں ترتیبات اور شارٹ کٹس کو تبدیل کرنے کی اجازت ملتی ہے۔"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> کو فون کالیں کرنے کی اجازت نہیں ہے"</string>
<string name="gadget_error_text" msgid="740356548025791839">"ویجیٹ لوڈ نہیں کیا جا سکتا"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"ویجیٹ کی ترتیبات"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"سیٹ اپ مکمل کرنے کیلئے تھپتھپائیں"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"فولڈر کا نام تبدیل کر کے <xliff:g id="NAME">%1$s</xliff:g> کر دیا گیا"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"فولڈر: <xliff:g id="NAME">%1$s</xliff:g>، <xliff:g id="SIZE">%2$d</xliff:g> آئٹمز"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"فولڈر: <xliff:g id="NAME">%1$s</xliff:g>، <xliff:g id="SIZE">%2$d</xliff:g> یا مزید آئٹمز"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"وال پیپرز"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"وال پیپر اور طرز"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"ہوم اسکرین میں ترمیم کریں"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ہوم ترتیبات"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"آپ کے منتظم کی طرف سے غیر فعال کر دیا گیا"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"ہوم اسکرین گھمانے کی اجازت دیں"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"ورک ایپس پر بَیج لگا ہوتا ہے اور آپ کا IT منتظم انہیں دیکھ سکتا ہے"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"سمجھ آ گئی"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"ورک ایپس موقوف ہیں"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"آپ کو اپنی ورک ایپس سے اطلاعات موصول نہیں ہوں گی"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"آپ کی ورک ایپس آپ کو اطلاعات نہیں بھیج سکتیں، آپ کی بیٹری کا استعمال یا آپ کے مقام تک رسائی حاصل نہیں کر سکتی ہیں"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"ورک ایپس آف ہیں۔ آپ کی ورک ایپس آپ کو اطلاعات نہیں بھیج سکتیں، آپ کی بیٹری استعمال یا آپ کے مقام تک رسائی حاصل نہیں کر سکتی ہیں"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"آپ کو اپنی ورک ایپس سے فون کالز، ٹیکسٹ پیغامات یا اطلاعات موصول نہیں ہوں گی"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"ورک ایپس پر بَیج لگا ہوتا ہے اور آپ کا IT منتظم انہیں دیکھ سکتا ہے"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"سمجھ آ گئی"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ورک ایپس موقوف کریں"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ورک ایپس آن کریں"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"چلائیں"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"فلٹر"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"اپنے فون پر تلاش کریں"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"اپنے ٹیبلیٹ پر تلاش کریں"</string>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 79860f3..405c4ef 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Bosh ekran"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ekranni ikkiga ajratish"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ilovasi axboroti"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Ilova juftini saqlash"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Vidjetni bosib turgan holatda suring."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ikki marta bosib va bosib turgan holatda vidjetni tanlang yoki maxsus amaldan foydalaning."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Bosh ekranda surish uchun vidjet ustiga bosib turing"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Bosh ekranga chiqarish"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidjeti bosh ekranga qoʻshildi"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Takliflar"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ta vidjet}other{# ta vidjet}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ta yorliq}other{# ta yorliq}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Shaxsiy"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Ish"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Suhbatlar"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Qayd olish"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Barcha kerakli axborot doim yoningizda"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Kerakli ilovalarni ochmasdan turib ulardan axborot olish uchun vidjetlarni bosh ekranga chiqaring"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Vidjet sozlamalarini oʻzgartirish uchun bosing"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Ilovaga bosh ekrandagi yorliqlar va sozlamalarni oʻqish uchun ruxsat beradi."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"Bosh ekrandagi sozlamalar va yorliqlarni oʻzgartirish"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Ilova bosh ekrandagi yorliqlar va sozlamalarni oʻzgartirishi mumkin."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga qo‘ng‘iroqlarni amalga oshirishga ruxsat berilmagan"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Vidjet yuklanmadi"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Vidjet sozlamalari"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Sozlashni yakunlash uchun bosing"</string>
@@ -99,15 +99,15 @@
<string name="folder_renamed" msgid="1794088362165669656">"Jild nomi <xliff:g id="NAME">%1$s</xliff:g>ga o‘zgartirildi"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Jild: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> fayllar"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Jild: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> va undan ortiq fayllar"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Fon rasmlari"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Fon rasmi va uslubi"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Bosh ekranni tahrirlash"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Bosh ekran sozlamalari"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administrator tomonidan o‘chirilgan"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Bosh ekranni burishga ruxsat"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Telefon burilganda"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Bildirishnoma belgilari"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Yoniq"</string>
- <string name="notification_dots_desc_off" msgid="1760796511504341095">"Yoqilmagan"</string>
+ <string name="notification_dots_desc_off" msgid="1760796511504341095">"Oʻchiq"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Bildirishnomalarga ruxsat berilmagan"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"Bildirishnoma belgilarini ko‘rsatish uchun <xliff:g id="NAME">%1$s</xliff:g> ilovasida bildirishnomalarni yoqing"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Sozlamalarni o‘zgartirish"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Ishga oid ilovalarning maxsus belgisi bor hamda ular administratoringizga koʻrinadi"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Ishga oid ilovalar pauza qilingan"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Ishga oid ilovalardan bildirishnomalar kelmaydi"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Ishga oid ilovalar batareya sarfi haqida bildirishnomalar yubora olmaydi va joylashuv axborotidan foydalana olmaydi"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Ishga oid ilovalar faolsizlantirilgan. Ular batareya sarfi haqida bildirishnomalar yubora olmaydi va joylashuv axborotidan foydalana olmaydi"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Ishga oid ilovalardan telefon chaqiruvi, SMS xabar yoki bildirishnoma kelmaydi"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Ishga oid ilovalarning maxsus belgisi bor hamda ular administratoringizga koʻrinadi"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Ishga oid ilovalarni pauza qilish"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Ishga oid ilovalarni yoqish"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Pauzadan chiqarish"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Saralash"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Telefondan qidirish"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Planshetingizni qidiring"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index e128e2c..075a7b0 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Màn hình chính"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Chia đôi màn hình"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Thông tin ứng dụng cho %1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Lưu cặp ứng dụng"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Chạm và giữ để di chuyển một tiện ích."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Nhấn đúp và giữ để di chuyển một tiện ích hoặc sử dụng các thao tác tùy chỉnh."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Chạm và giữ tiện ích để di chuyển tiện ích đó xung quanh màn hình chính"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Thêm vào màn hình chính"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Đã thêm tiện ích <xliff:g id="WIDGET_NAME">%1$s</xliff:g> vào màn hình chính"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Nội dung đề xuất"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# tiện ích}other{# tiện ích}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# lối tắt}other{# lối tắt}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Cá nhân"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Công việc"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Cuộc trò chuyện"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Ghi chú"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Thông tin hữu ích ngay trong tầm tay bạn"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Để nhận thông tin mà không cần mở các ứng dụng, bạn có thể thêm tiện ích vào màn hình chính"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Nhấn để thay đổi chế độ cài đặt tiện ích"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Cho phép ứng dụng đọc các chế độ cài đặt và lối tắt trên màn hình chính."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"ghi lối tắt và các chế độ cài đặt trên màn hình chính"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Cho phép ứng dụng thay đổi các chế độ cài đặt và lối tắt trên màn hình chính."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> không được phép thực hiện cuộc gọi điện thoại"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Không thể tải tiện ích"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Cài đặt tiện ích"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Nhấn để hoàn tất thiết lập"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Đã đổi tên thư mục thành <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Thư mục: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> mục"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Thư mục: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> mục trở lên"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Hình nền"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Hình nền và phong cách"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Chỉnh sửa Màn hình chính"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Cài đặt màn hình chính"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Bị tắt bởi quản trị viên của bạn"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Cho phép xoay màn hình chính"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Các ứng dụng công việc được gắn huy hiệu và quản trị viên CNTT có thể nhìn thấy"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"OK"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Đã tạm dừng các ứng dụng công việc"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Bạn sẽ không nhận được thông báo từ các ứng dụng công việc"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Các ứng dụng công việc không thể gửi thông báo cho bạn, sử dụng pin hoặc truy cập thông tin vị trí của bạn"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Ứng dụng công việc đang tắt. Các ứng dụng công việc không thể gửi thông báo cho bạn, sử dụng pin hoặc truy cập thông tin vị trí của bạn"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Bạn sẽ không nhận được tin nhắn văn bản, cuộc gọi điện thoại hoặc thông báo từ các ứng dụng công việc"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Các ứng dụng công việc được gắn huy hiệu và quản trị viên CNTT có thể nhìn thấy"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Tôi hiểu"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Tạm dừng các ứng dụng công việc"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Bật ứng dụng công việc"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Bỏ tạm dừng"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Bộ lọc"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Tìm trên điện thoại"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Tìm kiếm trong máy tính bảng của bạn"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 860dbe4..e525c02 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"主屏幕"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"分屏"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s 的应用信息"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"保存应用对"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"轻触并按住即可移动微件。"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"点按两次并按住微件即可移动该微件或使用自定义操作。"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"轻触并按住此微件即可在主屏幕上随意移动它"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"添加到主屏幕"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"已将“<xliff:g id="WIDGET_NAME">%1$s</xliff:g>”微件添加到主屏幕"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"建议"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 个微件}other{# 个微件}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# 个快捷方式}other{# 个快捷方式}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>,<xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"个人"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"工作"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"对话"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"记事"</string>
<string name="widget_education_header" msgid="4874760613775913787">"实用信息触手可及"</string>
<string name="widget_education_content" msgid="1731667670753497052">"要想不打开应用就能获取信息,您可以将相应微件添加到主屏幕"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"点按即可更改微件设置"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"允许此应用读取主屏幕中的设置和快捷方式。"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"写入主屏幕设置和快捷方式"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"允许此应用更改主屏幕中的设置和快捷方式。"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"不允许使用“<xliff:g id="APP_NAME">%1$s</xliff:g>”拨打电话"</string>
<string name="gadget_error_text" msgid="740356548025791839">"无法加载微件"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"微件设置"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"点按即可完成设置"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"已将文件夹重命名为“<xliff:g id="NAME">%1$s</xliff:g>”"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"文件夹:<xliff:g id="NAME">%1$s</xliff:g>,<xliff:g id="SIZE">%2$d</xliff:g> 个项目"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"文件夹:<xliff:g id="NAME">%1$s</xliff:g>,<xliff:g id="SIZE">%2$d</xliff:g> 个或更多项目"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"壁纸"</string>
- <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"壁纸和样式"</string>
+ <string name="styles_wallpaper_button_text" msgid="8216961355289236794">"壁纸与个性化"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"修改主屏幕"</string>
<string name="settings_button_text" msgid="8873672322605444408">"主屏幕设置"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"已被您的管理员停用"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"允许旋转主屏幕"</string>
@@ -159,15 +159,16 @@
<string name="all_apps_personal_tab" msgid="4190252696685155002">"个人"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"工作"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"工作资料"</string>
- <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"工作应用带有标志,您的 IT 管理员可以看到此类应用"</string>
+ <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"工作应用都有相应的标志,且您的 IT 管理员可以看到它们"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"知道了"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"工作应用已暂停"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"您将不会收到来自工作应用的通知"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"工作应用无法向您发送通知、不能耗用电池电量,也无法获取您的位置信息"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"工作应用已关闭。工作应用无法向您发送通知、不能耗用电池电量,也无法获取您的位置信息"</string>
- <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"工作应用带有标志,您的 IT 管理员可以看到工作应用"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"您将不会收到来自工作应用的来电、短信或通知"</string>
+ <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"工作应用都有相应的标志,且您的 IT 管理员可以看到它们"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"知道了"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"暂停工作应用"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"开启工作应用"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"取消暂停"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"过滤器"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"手机内搜索"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"平板电脑内搜索"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index e3ba417..0f0960e 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"主畫面"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"分割螢幕"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s 的應用程式資料"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"儲存應用程式配對"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"輕觸並按住即可移動小工具。"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"㩒兩下之後㩒住,就可以郁小工具或者用自訂操作。"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"按住小工具即可移到主畫面的任何位置"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"加去主畫面"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"已經將「<xliff:g id="WIDGET_NAME">%1$s</xliff:g>」小工具加咗去主畫面"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"建議"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 個小工具}other{# 個小工具}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# 個捷徑}other{# 個捷徑}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>、<xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"個人"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"工作"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"對話"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"做筆記"</string>
<string name="widget_education_header" msgid="4874760613775913787">"實用資訊,唾手可得"</string>
<string name="widget_education_content" msgid="1731667670753497052">"只要將小工具新增至主畫面,就可以直接查看資料,無需開啟應用程式"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"輕按即可變更小工具設定"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"允許應用程式讀取主畫面中的設定和捷徑。"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"寫入主畫面設定和捷徑"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"允許應用程式變更主畫面中的設定和捷徑。"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"不允許 <xliff:g id="APP_NAME">%1$s</xliff:g> 撥打電話"</string>
<string name="gadget_error_text" msgid="740356548025791839">"無法載入小工具"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"小工具設定"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"輕按即可完成設定"</string>
@@ -99,12 +99,12 @@
<string name="folder_renamed" msgid="1794088362165669656">"資料夾已重新命名為「<xliff:g id="NAME">%1$s</xliff:g>」"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"資料夾:<xliff:g id="NAME">%1$s</xliff:g>,<xliff:g id="SIZE">%2$d</xliff:g> 個項目"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"資料夾:<xliff:g id="NAME">%1$s</xliff:g>,<xliff:g id="SIZE">%2$d</xliff:g> 個或以上的項目"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"桌布"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"桌布和樣式"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"編輯主畫面"</string>
<string name="settings_button_text" msgid="8873672322605444408">"主畫面設定"</string>
- <string name="msg_disabled_by_admin" msgid="6898038085516271325">"已由您的管理員停用"</string>
+ <string name="msg_disabled_by_admin" msgid="6898038085516271325">"已由你的管理員停用"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"允許旋轉主畫面"</string>
- <string name="allow_rotation_desc" msgid="8662546029078692509">"當手機旋轉時"</string>
+ <string name="allow_rotation_desc" msgid="8662546029078692509">"隨手機旋轉"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"通知圓點"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"開啟"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"關閉"</string>
@@ -119,12 +119,12 @@
<string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
<string name="abandoned_search" msgid="891119232568284442">"搜尋"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"尚未安裝這個應用程式"</string>
- <string name="abandoned_promise_explanation" msgid="3990027586878167529">"您尚未安裝這個圖示代表的應用程式。您可以移除這個圖示,也可以搜尋該應用程式並手動安裝。"</string>
+ <string name="abandoned_promise_explanation" msgid="3990027586878167529">"你尚未安裝這個圖示代表的應用程式。你可以移除這個圖示,也可以搜尋該應用程式並手動安裝。"</string>
<string name="app_installing_title" msgid="5864044122733792085">"正在安裝「<xliff:g id="NAME">%1$s</xliff:g>」(已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"正在下載 <xliff:g id="NAME">%1$s</xliff:g>,已完成 <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"正在等待安裝 <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="dialog_update_title" msgid="114234265740994042">"必須更新應用程式"</string>
- <string name="dialog_update_message" msgid="4176784553982226114">"您尚未更新這個圖示代表的應用程式。您可以手動更新以重新啟用此快速鍵,或者移除圖示。"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"你尚未更新這個圖示代表的應用程式。你可以手動更新以重新啟用此快速鍵,或者移除圖示。"</string>
<string name="dialog_update" msgid="2178028071796141234">"更新"</string>
<string name="dialog_remove" msgid="6510806469849709407">"移除"</string>
<string name="widgets_list" msgid="796804551140113767">"小工具清單"</string>
@@ -159,15 +159,16 @@
<string name="all_apps_personal_tab" msgid="4190252696685155002">"個人"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"工作"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"工作設定檔"</string>
- <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"工作應用程式均加有標誌。您的 IT 管理員可以看到這些應用程式"</string>
+ <string name="work_profile_edu_work_apps" msgid="7895468576497746520">"工作應用程式均加有標誌。你的 IT 管理員可以看到這些應用程式"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"知道了"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"已暫停工作應用程式"</string>
- <string name="work_apps_paused_body" msgid="261634750995824906">"工作應用程式無法向您傳送通知、使用電池電量或存取您的位置"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"已暫停工作應用程式。工作應用程式無法向您傳送通知、使用電池電量或存取您的位置"</string>
- <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"工作應用程式均加有標誌。您的 IT 管理員可以看到這些應用程式"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"你不會收到工作應用程式的通知"</string>
+ <string name="work_apps_paused_body" msgid="261634750995824906">"工作應用程式無法向你傳送通知、使用電池電量或存取你的位置"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"你不會收到工作應用程式的來電、短訊或通知"</string>
+ <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"工作應用程式均加有標誌。你的 IT 管理員可以看到這些應用程式"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"知道了"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"暫停工作應用程式"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"開啟工作應用程式"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"取消暫停"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"篩選器"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"搜尋手機內容"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"搜尋平板電腦內容"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index fc00cc8..cf40155 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"主畫面"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"分割畫面"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"「%1$s」的應用程式資訊"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"儲存應用程式配對"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"按住即可移動小工具。"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"輕觸兩下並按住即可移動小工具或使用自訂操作。"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"按住小工具即可將它移到主畫面上的任何位置"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"新增至主畫面"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"已將「<xliff:g id="WIDGET_NAME">%1$s</xliff:g>」小工具新增到主畫面"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"建議"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 項小工具}other{# 項小工具}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# 個捷徑}other{# 個捷徑}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>、<xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"個人"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"工作"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"對話"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"做筆記"</string>
<string name="widget_education_header" msgid="4874760613775913787">"實用資訊隨手可得"</string>
<string name="widget_education_content" msgid="1731667670753497052">"只要將小工具新增到主畫面,就可以直接查看資訊,不必開啟應用程式"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"輕觸即可變更小工具設定"</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"允許應用程式讀取主畫面中的設定和捷徑。"</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"寫入主畫面設定和捷徑"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"允許應用程式變更主畫面中的設定和捷徑。"</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> 無法撥打電話"</string>
<string name="gadget_error_text" msgid="740356548025791839">"無法載入小工具"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"小工具設定"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"輕觸即可完成設定"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"已將資料夾重新命名為「<xliff:g id="NAME">%1$s</xliff:g>」"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"資料夾:<xliff:g id="NAME">%1$s</xliff:g>,<xliff:g id="SIZE">%2$d</xliff:g> 個項目"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"資料夾:<xliff:g id="NAME">%1$s</xliff:g>,<xliff:g id="SIZE">%2$d</xliff:g> 個以上的項目"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"桌布"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"桌布和樣式"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"編輯主畫面"</string>
<string name="settings_button_text" msgid="8873672322605444408">"主畫面設定"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"已由你的管理員停用"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"允許旋轉主畫面"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"工作應用程式會加上標記,且你的 IT 管理員可以看到這類應用程式"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"我知道了"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"系統已暫停工作應用程式"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"你將不會收到工作應用程式的通知"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"工作應用程式不會消耗電量、無法傳送通知,也無法存取你的位置資訊"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"工作應用程式已關閉。工作應用程式不會消耗電量、無法傳送通知,也無法存取你的位置資訊"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"你將不會收到工作應用程式的訊息或通知,也無法使用工作應用程式接聽來電"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"工作應用程式會加上標記,且你的 IT 管理員可以看到這類應用程式"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"我知道了"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"暫停工作應用程式"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"開啟工作應用程式"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"取消暫停"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"篩選器"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"搜尋手機內容"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"搜尋平板電腦內容"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 0688385..6ccc4be 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -29,6 +29,7 @@
<string name="home_screen" msgid="5629429142036709174">"Ikhaya"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Hlukanisa isikrini"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Ulwazi lwe-App ye-%1$s"</string>
+ <string name="save_app_pair" msgid="5647523853662686243">"Londoloza i-app ebhangqiwe"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"Thinta uphinde ubambe ukuze uhambise iwijethi."</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"Thepha kabili uphinde ubambe ukuze uhambise iwijethi noma usebenzise izindlela ezingokwezifiso."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -37,8 +38,7 @@
<string name="add_item_request_drag_hint" msgid="8730547755622776606">"Thinta uphinde ubambe iwijethi ukuyihambisa kusikrini sasekhaya"</string>
<string name="add_to_home_screen" msgid="9168649446635919791">"Faka kusikrini sasekhaya"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Iwijethi ye-<xliff:g id="WIDGET_NAME">%1$s</xliff:g> yengezwe kusikrini sasekhaya"</string>
- <!-- no translation found for suggested_widgets_header_title (1844314680798145222) -->
- <skip />
+ <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Iziphakamiso"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{iwijethi #}one{amawijethi #}other{amawijethi #}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{isinqamuleli #}one{izinqamuleli #}other{izinqamuleli #}}"</string>
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
@@ -50,6 +50,7 @@
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"Okwabantu siqu"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Umsebenzi"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Izingxoxo"</string>
+ <string name="widget_category_note_taking" msgid="3469689394504266039">"Ukuthatha amanothi"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Ulwazi oluwusizo phambi nje kwakho"</string>
<string name="widget_education_content" msgid="1731667670753497052">"Ukuze uthole ulwazi ngaphandle kokuvula ama-app, ungakwazi ukwengeza amawijethi kusikrini sakho sasekhaya"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Thepha ukuze ushintshe amasethingi ewijethi"</string>
@@ -59,7 +60,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"Ilayisha izinhlelo zokusebenza..."</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Azikho izinhlelo zokusebenza ezitholiwe ezifana ne-\"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="label_application" msgid="8531721983832654978">"Uhlelo lokusebenza"</string>
- <string name="all_apps_label" msgid="5015784846527570951">"Zonke izinhlelo zokusebenza"</string>
+ <string name="all_apps_label" msgid="5015784846527570951">"Wonke ama-app"</string>
<string name="notifications_header" msgid="1404149926117359025">"Izaziso"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Thinta uphinde ubambe ukuze uhambise isinqamuleli."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Thepha kabili uphinde ubambe ukuze uhambise isinqamuleli noma usebenzise izenzo ezingokwezifiso."</string>
@@ -81,7 +82,6 @@
<string name="permdesc_read_settings" msgid="4208061150510996676">"Ivumela i-app ukuthi ifunde amasethingi nezinqamuleli ekhaya."</string>
<string name="permlab_write_settings" msgid="4820028712156303762">"bhala amasethingi wasekhaya nezinqamuleli"</string>
<string name="permdesc_write_settings" msgid="726859348127868466">"Ivumela ama-app ukushintsha amasethingi nezinqamuleli ekhaya."</string>
- <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> ayivunyelwe ukwenza amakholi wefoni"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Ayikwazi ukulayisha iwijethi"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Amasethingi ewijethi"</string>
<string name="gadget_complete_setup_text" msgid="309040266978007925">"Thepha ukuze uqede ukusetha"</string>
@@ -99,8 +99,8 @@
<string name="folder_renamed" msgid="1794088362165669656">"Ifolda iqanjwe kabusha ngo-<xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format_exact" msgid="8626242716117004803">"Ifolda: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> izinto"</string>
<string name="folder_name_format_overflow" msgid="4270108890534995199">"Ifolda: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> noma izinto eziningi"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Izithombe zangemuva"</string>
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Isithombe sangemuva nesitayela"</string>
+ <string name="edit_home_screen" msgid="8947858375782098427">"Hlela Isikrini Sasekhaya"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Amasethingi asekhaya"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Kukhutshazwe umlawuli wakho"</string>
<string name="allow_rotation_title" msgid="7222049633713050106">"Vumela ukuzungezisa kwesikrini sasekhaya"</string>
@@ -162,12 +162,13 @@
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Ama-app omsebenzi anebheji futhi ayabonakala kumphathi wakho we-IT"</string>
<string name="work_profile_edu_accept" msgid="6069788082535149071">"Ngiyezwa"</string>
<string name="work_apps_paused_title" msgid="3040901117349444598">"Izinhlelo zokusebenza zomsebenzi ziphunyuziwe"</string>
+ <string name="work_apps_paused_info_body" msgid="1687828929959237477">"Ngeke uze uthole izaziso kua-app akho"</string>
<string name="work_apps_paused_body" msgid="261634750995824906">"Ama-app akho omsebenzi awakwazi ukukuthumela izaziso, ukusebenzisa ibhethri lakho, noma ukufinyelela indawo yakho"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Ama-app omsebenzi avaliwe. Ama-app akho omsebenzi awakwazi ukukuthumela izaziso, ukusebenzisa ibhethri lakho, noma ukufinyelela indawo yakho"</string>
+ <string name="work_apps_paused_telephony_unavailable_body" msgid="8358872357502756790">"Ngeke uthole amakholi wefoni, imilayezo yombhalo, noma izaziso ezivela kuma-app"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Ama-app omsebenzi anebheji futhi ayabonakala kumphathi wakho we-IT"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Ngiyezwa"</string>
<string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Misa ama-app omsebenzi"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Vula ama-app omsebenzi"</string>
+ <string name="work_apps_enable_btn_text" msgid="1736198302467317371">"Susa ukumisa"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Hlunga"</string>
<string name="search_pref_screen_title" msgid="3258959643336315962">"Sesha ifoni yakho"</string>
<string name="search_pref_screen_title_tablet" msgid="5220319680451343959">"Sesha ithebulethi yakho"</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index e4650b2..f046eca 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -36,7 +36,6 @@
<attr name="workspaceShadowColor" format="color" />
<attr name="workspaceAmbientShadowColor" format="color" />
<attr name="workspaceKeyShadowColor" format="color" />
- <attr name="workspaceStatusBarScrim" format="reference" />
<attr name="widgetsTheme" format="reference" />
<attr name="iconOnlyShortcutColor" format="color" />
<attr name="eduHalfSheetBGColor" format="color" />
@@ -86,6 +85,8 @@
<enum name="taskbar" value="5" />
<enum name="search_result_tall" value="6" />
<enum name="search_result_small" value="7" />
+ <enum name="prediction_row" value="8" />
+ <enum name="search_result_app_row" value="9" />
</attr>
<attr name="centerVertically" format="boolean" />
</declare-styleable>
@@ -202,9 +203,24 @@
<attr name="demoModeLayoutId" format="reference" />
<attr name="isScalable" format="boolean" />
<attr name="devicePaddingId" format="reference" />
+
<!-- File that contains the specs for the workspace.
Needs FeatureFlags.ENABLE_RESPONSIVE_WORKSPACE enabled -->
<attr name="workspaceSpecsId" format="reference" />
+ <attr name="workspaceSpecsTwoPanelId" format="reference" />
+ <!-- File that contains the specs for all apps.
+ Needs FeatureFlags.ENABLE_RESPONSIVE_WORKSPACE enabled -->
+ <attr name="allAppsSpecsId" format="reference" />
+ <attr name="allAppsSpecsTwoPanelId" format="reference" />
+ <!-- File that contains the specs for the workspace.
+ Needs FeatureFlags.ENABLE_RESPONSIVE_WORKSPACE enabled -->
+ <attr name="folderSpecsId" format="reference" />
+ <attr name="folderSpecsTwoPanelId" format="reference" />
+ <!-- File that contains the specs for hotseat bar.
+ Needs FeatureFlags.ENABLE_RESPONSIVE_WORKSPACE enabled -->
+ <attr name="hotseatSpecsId" format="reference" />
+ <attr name="hotseatSpecsTwoPanelId" format="reference" />
+
<!-- By default all categories are enabled -->
<attr name="deviceCategory" format="integer">
<!-- Enable on phone only -->
@@ -244,7 +260,7 @@
</declare-styleable>
<!-- Responsive grids attributes -->
- <declare-styleable name="WorkspaceSpec">
+ <declare-styleable name="ResponsiveSpec">
<attr name="specType" format="integer">
<enum name="height" value="0" />
<enum name="width" value="1" />
@@ -252,10 +268,32 @@
<attr name="maxAvailableSize" format="dimension" />
</declare-styleable>
- <declare-styleable name="SpecSize">
+ <declare-styleable name="WorkspaceSpec">
+ <attr name="specType" />
+ <attr name="maxAvailableSize" />
+ </declare-styleable>
+
+ <declare-styleable name="FolderSpec">
+ <attr name="specType" />
+ <attr name="maxAvailableSize" />
+ </declare-styleable>
+
+ <declare-styleable name="AllAppsSpec">
+ <attr name="specType" />
+ <attr name="maxAvailableSize" />
+ </declare-styleable>
+
+ <declare-styleable name="HotseatSpec">
+ <attr name="specType" />
+ <attr name="maxAvailableSize" />
+ </declare-styleable>
+
+ <declare-styleable name="SizeSpec">
<attr name="fixedSize" format="dimension" />
<attr name="ofAvailableSpace" format="float" />
<attr name="ofRemainderSpace" format="float" />
+ <attr name="matchWorkspace" format="boolean" />
+ <attr name="maxSize" format="dimension" />
</declare-styleable>
<declare-styleable name="ProfileDisplayOption">
@@ -564,4 +602,9 @@
<!-- The icon drawable of a widget category. -->
<attr name="sectionDrawable" format="reference" />
</declare-styleable>
+
+ <declare-styleable name="ArrowTipView">
+ <attr name="arrowTipBackground" format="color" />
+ <attr name="arrowTipTextColor" format="color" />
+ </declare-styleable>
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 5a6698b..cd9c9de 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -84,6 +84,8 @@
<string name="window_manager_proxy_class" translatable="false"></string>
<string name="secondary_display_predictions_class" translatable="false"></string>
<string name="widget_holder_factory_class" translatable="false"></string>
+ <string name="taskbar_search_session_controller_class" translatable="false"></string>
+ <string name="taskbar_model_callbacks_factory_class" translatable="false"></string>
<!-- View ID to use for QSB widget -->
<item type="id" name="qsb_widget" />
@@ -102,8 +104,6 @@
<!-- Default packages -->
<string name="wallpaper_picker_package" translatable="false"></string>
- <string name="custom_activity_picker" translatable="false">
- com.android.customization.picker.CustomizationPickerActivity</string>
<string name="local_colors_extraction_class" translatable="false"></string>
<string name="search_session_manager_class" translatable="false"></string>
@@ -217,4 +217,31 @@
<!-- Whether the floating rotation button should be on the left/right in the device's natural
orientation -->
<bool name="floating_rotation_button_position_left">true</bool>
+
+ <!-- Mapping of visual icon size to XML value http://b/235886078 -->
+ <dimen name="iconSize48dp">52dp</dimen>
+ <dimen name="iconSize50dp">55dp</dimen>
+ <dimen name="iconSize52dp">57dp</dimen>
+ <dimen name="iconSize54dp">59dp</dimen>
+ <dimen name="iconSize56dp">61dp</dimen>
+ <dimen name="iconSize58dp">63dp</dimen>
+ <dimen name="iconSize60dp">66dp</dimen>
+ <dimen name="iconSize66dp">72dp</dimen>
+ <dimen name="iconSize72dp">79dp</dimen>
+
+ <!-- Icon size steps in dp -->
+ <integer-array name="icon_size_steps">
+ <item>@dimen/iconSize48dp</item>
+ <item>@dimen/iconSize50dp</item>
+ <item>@dimen/iconSize52dp</item>
+ <item>@dimen/iconSize54dp</item>
+ <item>@dimen/iconSize56dp</item>
+ <item>@dimen/iconSize58dp</item>
+ <item>@dimen/iconSize60dp</item>
+ <item>@dimen/iconSize66dp</item>
+ <item>@dimen/iconSize72dp</item>
+ </integer-array>
+
+ <!-- Used for custom widgets -->
+ <array name="custom_widget_providers"/>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 786088e..c6fce28 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -385,6 +385,9 @@
<dimen name="taskbar_button_margin_split">0dp</dimen>
<dimen name="taskbar_button_margin_6_5">0dp</dimen>
+ <!-- Bubble bar (placeholders to compile in Launcher3 without Quickstep) -->
+ <dimen name="bubblebar_hotseat_adjustment_threshold">0dp</dimen>
+
<!-- Size of the maximum radius for the enforced rounded rectangles. -->
<dimen name="enforced_rounded_corner_max_radius">16dp</dimen>
@@ -411,6 +414,7 @@
<dimen name="split_instructions_elevation">1dp</dimen>
<dimen name="split_instructions_horizontal_padding">24dp</dimen>
<dimen name="split_instructions_vertical_padding">12dp</dimen>
+ <dimen name="split_instructions_drawable_padding">10dp</dimen>
<dimen name="split_instructions_bottom_margin_phone_landscape">24dp</dimen>
<dimen name="split_instructions_bottom_margin_phone_portrait">60dp</dimen>
@@ -438,4 +442,8 @@
<!-- Folder spaces -->
<dimen name="folder_top_padding_default">24dp</dimen>
<dimen name="folder_footer_horiz_padding">20dp</dimen>
+
+ <!-- Default Ime height. Used only for logging purposes.
+ Assume this is default keyboard height in EN locale in case the keyboard height is not known when queried.-->
+ <dimen name="default_ime_height">300dp</dimen>
</resources>
diff --git a/res/values/id.xml b/res/values/id.xml
index 7b812de..872ae2f 100644
--- a/res/values/id.xml
+++ b/res/values/id.xml
@@ -43,4 +43,6 @@
<item type="id" name="saved_floating_widget_foreground" />
<item type="id" name="saved_floating_widget_background" />
+ <item type="id" name="dismiss_view" />
+
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c2eb373..1b46b4d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -250,8 +250,6 @@
<!-- Strings for the customization mode -->
<!-- Text for wallpaper change button [CHAR LIMIT=30]-->
- <string name="wallpaper_button_text">Wallpapers</string>
- <!-- Text for wallpaper change button [CHAR LIMIT=30]-->
<string name="styles_wallpaper_button_text">Wallpaper & style</string>
<!-- Text for edit home screen button [CHAR LIMIT=30]-->
<string name="edit_home_screen">Edit Home Screen</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index c41f0e8..4cb6414 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -32,7 +32,8 @@
<style name="LauncherTheme" parent="@style/BaseLauncherTheme">
<item name="android:textColorSecondary">#DE000000</item>
<item name="allAppsScrimColor">?attr/materialColorSurfaceDim</item>
- <item name="allappsHeaderProtectionColor">@color/popup_color_tertiary_light</item>
+ <item name="allappsHeaderProtectionColor">
+ @color/material_color_surface_container_highest</item>
<item name="allAppsNavBarScrimColor">#66FFFFFF</item>
<item name="popupColorPrimary">@color/popup_color_primary_light</item>
<item name="popupColorSecondary">@color/popup_color_secondary_light</item>
@@ -50,7 +51,6 @@
<item name="workspaceShadowColor">#B0000000</item>
<item name="workspaceAmbientShadowColor">#40000000</item>
<item name="workspaceKeyShadowColor">#89000000</item>
- <item name="workspaceStatusBarScrim">@drawable/workspace_bg</item>
<item name="widgetsTheme">@style/WidgetContainerTheme</item>
<item name="folderPaginationColor">@color/folder_pagination_color_light</item>
<item name="folderPreviewColor">@color/folder_preview_light</item>
@@ -137,7 +137,6 @@
<item name="workspaceAmbientShadowColor">@android:color/transparent</item>
<item name="workspaceKeyShadowColor">@android:color/transparent</item>
<item name="isWorkspaceDarkText">true</item>
- <item name="workspaceStatusBarScrim">@null</item>
<item name="workspaceAccentColor">@color/workspace_accent_color_dark</item>
<item name="dropTargetHoverTextColor">@color/drop_target_hover_text_color_dark</item>
<item name="dropTargetHoverButtonColor">@color/drop_target_hover_button_color_dark</item>
@@ -151,6 +150,7 @@
<item name="android:colorControlHighlight">#19FFFFFF</item>
<item name="android:colorPrimary">#FF212121</item>
<item name="allAppsScrimColor">?attr/materialColorSurfaceDim</item>
+ <item name="allappsHeaderProtectionColor">@color/material_color_surface_container_low</item>
<item name="allAppsNavBarScrimColor">#80000000</item>
<item name="popupColorPrimary">@color/popup_color_primary_dark</item>
<item name="popupColorSecondary">@color/popup_color_secondary_dark</item>
@@ -188,7 +188,6 @@
<item name="workspaceAmbientShadowColor">@android:color/transparent</item>
<item name="workspaceKeyShadowColor">@android:color/transparent</item>
<item name="isWorkspaceDarkText">true</item>
- <item name="workspaceStatusBarScrim">@null</item>
<item name="workspaceAccentColor">@color/workspace_accent_color_dark</item>
<item name="dropTargetHoverTextColor">@color/drop_target_hover_text_color_dark</item>
<item name="dropTargetHoverButtonColor">@color/drop_target_hover_button_color_dark</item>
@@ -426,4 +425,8 @@
<item name="horizontalPadding">16dp</item>
</style>
+ <style name="ArrowTipStyle">
+ <item name="arrowTipBackground">@color/arrow_tip_view_bg</item>
+ <item name="arrowTipTextColor">@color/arrow_tip_view_content</item>
+ </style>
</resources>
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 31f9bfe..b845c88 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -133,6 +133,8 @@
public static final int TYPE_TASKBAR_OVERLAYS =
TYPE_TASKBAR_ALL_APPS | TYPE_TASKBAR_EDUCATION_DIALOG;
+ public static final int TYPE_ALL_EXCEPT_ON_BOARD_POPUP = TYPE_ALL & ~TYPE_ON_BOARD_POPUP;
+
protected boolean mIsOpen;
public AbstractFloatingView(Context context, AttributeSet attrs) {
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index 7131452..7b0d71b 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -11,6 +11,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
+import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.appwidget.AppWidgetProviderInfo;
@@ -26,12 +27,14 @@
import android.widget.ImageButton;
import android.widget.ImageView;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Px;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
import com.android.launcher3.celllayout.CellPosMapper.CellPos;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
import com.android.launcher3.logging.InstanceId;
@@ -47,15 +50,18 @@
import java.util.List;
public class AppWidgetResizeFrame extends AbstractFloatingView implements View.OnKeyListener {
- private static final int SNAP_DURATION = 150;
+ private static final int SNAP_DURATION_MS = 150;
private static final float DIMMED_HANDLE_ALPHA = 0f;
private static final float RESIZE_THRESHOLD = 0.66f;
+ private static final int RESIZE_TRANSITION_DURATION_MS = 150;
private static final String KEY_RECONFIGURABLE_WIDGET_EDUCATION_TIP_SEEN =
"launcher.reconfigurable_widget_education_tip_seen";
private static final Rect sTmpRect = new Rect();
private static final Rect sTmpRect2 = new Rect();
+ private static final int[] sDragLayerLoc = new int[2];
+
private static final int HANDLE_COUNT = 4;
private static final int INDEX_LEFT = 0;
private static final int INDEX_TOP = 1;
@@ -124,6 +130,12 @@
private int mTopTouchRegionAdjustment = 0;
private int mBottomTouchRegionAdjustment = 0;
+ private int[] mWidgetViewWindowPos;
+ private final Rect mWidgetViewOldRect = new Rect();
+ private final Rect mWidgetViewNewRect = new Rect();
+ private final @Nullable LauncherAppWidgetHostView.CellChildViewPreLayoutListener
+ mCellChildViewPreLayoutListener;
+
private int mXDown, mYDown;
public AppWidgetResizeFrame(Context context) {
@@ -140,6 +152,18 @@
mLauncher = Launcher.getLauncher(context);
mStateAnnouncer = DragViewStateAnnouncer.createFor(this);
+ mCellChildViewPreLayoutListener = FeatureFlags.ENABLE_WIDGET_TRANSITION_FOR_RESIZING.get()
+ ? (v, left, top, right, bottom) -> {
+ if (mWidgetViewWindowPos == null) {
+ mWidgetViewWindowPos = new int[2];
+ }
+ v.getLocationInWindow(mWidgetViewWindowPos);
+ mWidgetViewOldRect.set(v.getLeft(), v.getTop(), v.getRight(),
+ v.getBottom());
+ mWidgetViewNewRect.set(left, top, right, bottom);
+ }
+ : null;
+
mBackgroundPadding = getResources()
.getDimensionPixelSize(R.dimen.resize_frame_background_padding);
mTouchTargetWidth = 2 * mBackgroundPadding;
@@ -260,6 +284,14 @@
}
}
+ if (FeatureFlags.ENABLE_WIDGET_TRANSITION_FOR_RESIZING.get()) {
+ mWidgetView.setCellChildViewPreLayoutListener(mCellChildViewPreLayoutListener);
+ mWidgetViewOldRect.set(mWidgetView.getLeft(), mWidgetView.getTop(),
+ mWidgetView.getRight(),
+ mWidgetView.getBottom());
+ mWidgetViewNewRect.set(mWidgetViewOldRect);
+ }
+
CellLayoutLayoutParams lp = (CellLayoutLayoutParams) mWidgetView.getLayoutParams();
ItemInfo widgetInfo = (ItemInfo) mWidgetView.getTag();
CellPos presenterPos = mLauncher.getCellPosMapper().mapModelToPresenter(widgetInfo);
@@ -344,22 +376,6 @@
resizeWidgetIfNeeded(false);
- // When the widget resizes in multi-window mode, the translation value changes to maintain
- // a center fit. These overrides ensure the resize frame always aligns with the widget view.
- getSnappedRectRelativeToDragLayer(sTmpRect);
- if (mLeftBorderActive) {
- lp.width = sTmpRect.width() + sTmpRect.left - lp.x;
- }
- if (mTopBorderActive) {
- lp.height = sTmpRect.height() + sTmpRect.top - lp.y;
- }
- if (mRightBorderActive) {
- lp.x = sTmpRect.left;
- }
- if (mBottomBorderActive) {
- lp.y = sTmpRect.top;
- }
-
// Handle invalid resize across CellLayouts in the two panel UI.
if (mCellLayout.getParent() instanceof Workspace) {
Workspace<?> workspace = (Workspace<?>) mCellLayout.getParent();
@@ -508,9 +524,13 @@
* Returns the rect of this view when the frame is snapped around the widget, with the bounds
* relative to the {@link DragLayer}.
*/
- private void getSnappedRectRelativeToDragLayer(Rect out) {
+ private void getSnappedRectRelativeToDragLayer(@NonNull Rect out) {
float scale = mWidgetView.getScaleToFit();
- mDragLayer.getViewRectRelativeToSelf(mWidgetView, out);
+ if (FeatureFlags.ENABLE_WIDGET_TRANSITION_FOR_RESIZING.get()) {
+ getViewRectRelativeToDragLayer(out);
+ } else {
+ mDragLayer.getViewRectRelativeToSelf(mWidgetView, out);
+ }
int width = 2 * mBackgroundPadding + Math.round(scale * out.width());
int height = 2 * mBackgroundPadding + Math.round(scale * out.height());
@@ -523,7 +543,41 @@
out.bottom = out.top + height;
}
+ private void getViewRectRelativeToDragLayer(@NonNull Rect out) {
+ int[] afterPos = getViewPosRelativeToDragLayer();
+ out.set(afterPos[0], afterPos[1], afterPos[0] + mWidgetViewNewRect.width(),
+ afterPos[1] + mWidgetViewNewRect.height());
+ }
+
+ /** Returns the relative x and y values of the widget view after the layout transition */
+ private int[] getViewPosRelativeToDragLayer() {
+ mDragLayer.getLocationInWindow(sDragLayerLoc);
+ int x = sDragLayerLoc[0];
+ int y = sDragLayerLoc[1];
+
+ if (mWidgetViewWindowPos == null) {
+ mWidgetViewWindowPos = new int[2];
+ mWidgetView.getLocationInWindow(mWidgetViewWindowPos);
+ }
+
+ int leftOffset = mWidgetViewNewRect.left - mWidgetViewOldRect.left;
+ int topOffset = mWidgetViewNewRect.top - mWidgetViewOldRect.top;
+
+ return new int[] {mWidgetViewWindowPos[0] - x + leftOffset,
+ mWidgetViewWindowPos[1] - y + topOffset};
+ }
+
private void snapToWidget(boolean animate) {
+ // The widget is guaranteed to be attached to the cell layout at this point, thus setting
+ // the transition here
+ if (FeatureFlags.ENABLE_WIDGET_TRANSITION_FOR_RESIZING.get()
+ && mWidgetView.getLayoutTransition() == null) {
+ final LayoutTransition transition = new LayoutTransition();
+ transition.setDuration(RESIZE_TRANSITION_DURATION_MS);
+ transition.enableTransitionType(LayoutTransition.CHANGING);
+ mWidgetView.setLayoutTransition(transition);
+ }
+
getSnappedRectRelativeToDragLayer(sTmpRect);
int newWidth = sTmpRect.width();
int newHeight = sTmpRect.height();
@@ -585,7 +639,7 @@
updateInvalidResizeEffect(mCellLayout, pairedCellLayout, /* alpha= */ 1f,
/* springLoadedProgress= */ 0f, /* animatorSet= */ set);
}
- set.setDuration(SNAP_DURATION);
+ set.setDuration(SNAP_DURATION_MS);
set.start();
}
@@ -665,6 +719,10 @@
@Override
protected void handleClose(boolean animate) {
+ if (FeatureFlags.ENABLE_WIDGET_TRANSITION_FOR_RESIZING.get()) {
+ mWidgetView.clearCellChildViewPreLayoutListener();
+ mWidgetView.setLayoutTransition(null);
+ }
mDragLayer.removeView(this);
}
diff --git a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
index ec874b9..55b8fcc 100644
--- a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
+++ b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
@@ -1,28 +1,12 @@
package com.android.launcher3;
-import static android.os.Process.myUserHandle;
-
-import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.database.Cursor;
import android.util.Log;
-import androidx.annotation.NonNull;
-import androidx.annotation.WorkerThread;
-
-import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.model.LoaderTask;
-import com.android.launcher3.model.ModelDbController;
-import com.android.launcher3.model.WidgetsModel;
-import com.android.launcher3.model.data.LauncherAppWidgetInfo;
-import com.android.launcher3.pm.UserCache;
import com.android.launcher3.provider.RestoreDbTask;
-import com.android.launcher3.util.ContentWriter;
-import com.android.launcher3.util.IntArray;
import com.android.launcher3.widget.LauncherWidgetHolder;
public class AppWidgetsRestoredReceiver extends BroadcastReceiver {
@@ -47,131 +31,4 @@
}
}
}
-
- /**
- * Updates the app widgets whose id has changed during the restore process.
- */
- @WorkerThread
- public static void restoreAppWidgetIds(Context context, ModelDbController controller,
- int[] oldWidgetIds, int[] newWidgetIds, @NonNull AppWidgetHost host) {
- if (WidgetsModel.GO_DISABLE_WIDGETS) {
- Log.e(TAG, "Skipping widget ID remap as widgets not supported");
- host.deleteHost();
- return;
- }
- if (!RestoreDbTask.isPending(context)) {
- // Someone has already gone through our DB once, probably LoaderTask. Skip any further
- // modifications of the DB.
- Log.e(TAG, "Skipping widget ID remap as DB already in use");
- for (int widgetId : newWidgetIds) {
- Log.d(TAG, "Deleting widgetId: " + widgetId);
- host.deleteAppWidgetId(widgetId);
- }
- return;
- }
-
- final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
-
- Log.d(TAG, "restoreAppWidgetIds: "
- + "oldWidgetIds=" + IntArray.wrap(oldWidgetIds).toConcatString()
- + ", newWidgetIds=" + IntArray.wrap(newWidgetIds).toConcatString());
-
- // TODO(b/234700507): Remove the logs after the bug is fixed
- logDatabaseWidgetInfo(controller);
-
- for (int i = 0; i < oldWidgetIds.length; i++) {
- Log.i(TAG, "Widget state restore id " + oldWidgetIds[i] + " => " + newWidgetIds[i]);
-
- final AppWidgetProviderInfo provider = widgets.getAppWidgetInfo(newWidgetIds[i]);
- final int state;
- if (LoaderTask.isValidProvider(provider)) {
- // This will ensure that we show 'Click to setup' UI if required.
- state = LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
- } else {
- state = LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
- }
-
- // b/135926478: Work profile widget restore is broken in platform. This forces us to
- // recreate the widget during loading with the correct host provider.
- long mainProfileId = UserCache.INSTANCE.get(context)
- .getSerialNumberForUser(myUserHandle());
- long controllerProfileId = controller.getSerialNumberForUser(myUserHandle());
- String oldWidgetId = Integer.toString(oldWidgetIds[i]);
- final String where = "appWidgetId=? and (restored & 1) = 1 and profileId=?";
- String profileId = Long.toString(mainProfileId);
- final String[] args = new String[] { oldWidgetId, profileId };
- Log.d(TAG, "restoreAppWidgetIds: querying profile id=" + profileId
- + " with controller profile ID=" + controllerProfileId);
- int result = new ContentWriter(context,
- new ContentWriter.CommitParams(controller, where, args))
- .put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i])
- .put(LauncherSettings.Favorites.RESTORED, state)
- .commit();
- if (result == 0) {
- // TODO(b/234700507): Remove the logs after the bug is fixed
- Log.e(TAG, "restoreAppWidgetIds: remapping failed since the widget is not in"
- + " the database anymore");
- try (Cursor cursor = controller.getDb().query(
- Favorites.TABLE_NAME,
- new String[]{Favorites.APPWIDGET_ID},
- "appWidgetId=?", new String[]{oldWidgetId}, null, null, null)) {
- if (!cursor.moveToFirst()) {
- // The widget no long exists.
- Log.d(TAG, "Deleting widgetId: " + newWidgetIds[i] + " with old id: "
- + oldWidgetId);
- host.deleteAppWidgetId(newWidgetIds[i]);
- }
- }
- }
- }
-
- LauncherAppState app = LauncherAppState.getInstanceNoCreate();
- if (app != null) {
- app.getModel().forceReload();
- }
- }
-
- private static void logDatabaseWidgetInfo(ModelDbController controller) {
- try (Cursor cursor = controller.getDb().query(Favorites.TABLE_NAME,
- new String[]{Favorites.APPWIDGET_ID, Favorites.RESTORED, Favorites.PROFILE_ID},
- Favorites.APPWIDGET_ID + "!=" + LauncherAppWidgetInfo.NO_ID, null,
- null, null, null)) {
- IntArray widgetIdList = new IntArray();
- IntArray widgetRestoreList = new IntArray();
- IntArray widgetProfileIdList = new IntArray();
-
- if (cursor.moveToFirst()) {
- final int widgetIdColumnIndex = cursor.getColumnIndex(Favorites.APPWIDGET_ID);
- final int widgetRestoredColumnIndex = cursor.getColumnIndex(Favorites.RESTORED);
- final int widgetProfileIdIndex = cursor.getColumnIndex(Favorites.PROFILE_ID);
- while (!cursor.isAfterLast()) {
- int widgetId = cursor.getInt(widgetIdColumnIndex);
- int widgetRestoredFlag = cursor.getInt(widgetRestoredColumnIndex);
- int widgetProfileId = cursor.getInt(widgetProfileIdIndex);
-
- widgetIdList.add(widgetId);
- widgetRestoreList.add(widgetRestoredFlag);
- widgetProfileIdList.add(widgetProfileId);
- cursor.moveToNext();
- }
- }
-
- StringBuilder builder = new StringBuilder();
- builder.append("[");
- for (int i = 0; i < widgetIdList.size(); i++) {
- builder.append("[")
- .append(widgetIdList.get(i))
- .append(", ")
- .append(widgetRestoreList.get(i))
- .append(", ")
- .append(widgetProfileIdList.get(i))
- .append("]");
- }
- builder.append("]");
- Log.d(TAG, "restoreAppWidgetIds: all widget ids in database: "
- + builder.toString());
- } catch (Exception ex) {
- Log.e(TAG, "Getting widget ids from the database failed", ex);
- }
- }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index ede7e2f..c7cdfa8 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -17,6 +17,8 @@
package com.android.launcher3;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
+import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
+import static com.android.launcher3.provider.LauncherDbUtils.itemIdMatch;
import android.content.ComponentName;
import android.content.ContentValues;
@@ -30,7 +32,6 @@
import android.content.res.Resources.NotFoundException;
import android.content.res.XmlResourceParser;
import android.database.sqlite.SQLiteDatabase;
-import android.net.Uri;
import android.os.Bundle;
import android.os.Process;
import android.text.TextUtils;
@@ -44,7 +45,6 @@
import androidx.annotation.WorkerThread;
import androidx.annotation.XmlRes;
-import com.android.launcher3.LauncherProvider.SqlArguments;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
@@ -619,9 +619,7 @@
// failed to add, and less than 2 were actually added
if (folderItems.size() < 2) {
// Delete the folder
- Uri uri = Favorites.getContentUri(folderId);
- SqlArguments args = new SqlArguments(uri, null, null);
- mDb.delete(args.table, args.where, args.args);
+ mDb.delete(TABLE_NAME, itemIdMatch(folderId), null);
addedId = -1;
// If we have a single item, promote it to where the folder
@@ -634,7 +632,7 @@
copyInteger(myValues, childValues, Favorites.CELLY);
addedId = folderItems.get(0);
- mDb.update(Favorites.TABLE_NAME, childValues,
+ mDb.update(TABLE_NAME, childValues,
Favorites._ID + "=" + addedId, null);
}
}
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index 8876a1b..808cf70 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -17,12 +17,7 @@
package com.android.launcher3;
import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR;
-import android.app.WallpaperColors;
-import android.app.WallpaperManager;
-import android.app.WallpaperManager.OnColorsChangedListener;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Point;
@@ -32,6 +27,7 @@
import android.view.Display;
import android.view.View;
+import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -41,9 +37,11 @@
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.OnColorHintListener;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.TraceHelper;
+import com.android.launcher3.util.WallpaperColorHints;
import com.android.launcher3.util.WindowBounds;
/**
@@ -51,7 +49,7 @@
*/
@SuppressWarnings("NewApi")
public abstract class BaseDraggingActivity extends BaseActivity
- implements OnColorsChangedListener, DisplayInfoChangeListener {
+ implements OnColorHintListener, DisplayInfoChangeListener {
private static final String TAG = "BaseDraggingActivity";
@@ -63,8 +61,7 @@
protected boolean mIsSafeModeEnabled;
private Runnable mOnStartCallback;
- private RunnableList mOnResumeCallbacks = new RunnableList();
-
+ private final RunnableList mOnResumeCallbacks = new RunnableList();
private int mThemeRes = R.style.AppTheme;
@Override
@@ -76,10 +73,7 @@
DisplayController.INSTANCE.get(this).addChangeListener(this);
// Update theme
- if (Utilities.ATLEAST_P) {
- THREAD_POOL_EXECUTOR.execute(() -> getSystemService(WallpaperManager.class)
- .addOnColorsChangedListener(this, MAIN_EXECUTOR.getHandler()));
- }
+ WallpaperColorHints.get(this).registerOnColorHintsChangedListener(this);
int themeRes = Themes.getActivityThemeRes(this);
if (themeRes != mThemeRes) {
mThemeRes = themeRes;
@@ -97,8 +91,9 @@
mOnResumeCallbacks.add(callback);
}
+ @MainThread
@Override
- public void onColorsChanged(WallpaperColors wallpaperColors, int which) {
+ public void onColorHintsChanged(int colorHints) {
updateTheme();
}
@@ -175,10 +170,8 @@
@Override
protected void onDestroy() {
super.onDestroy();
- if (Utilities.ATLEAST_P) {
- getSystemService(WallpaperManager.class).removeOnColorsChangedListener(this);
- }
DisplayController.INSTANCE.get(this).removeChangeListener(this);
+ WallpaperColorHints.get(this).unregisterOnColorsChangedListener(this);
}
public void runOnceOnStart(Runnable action) {
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index f920d75..bd004e9 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.config.FeatureFlags.ENABLE_DOWNLOAD_APP_UX_V2;
import static com.android.launcher3.config.FeatureFlags.ENABLE_ICON_LABEL_AUTO_SCALING;
+import static com.android.launcher3.config.FeatureFlags.enableCursorHoverStates;
import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
import static com.android.launcher3.icons.BitmapInfo.FLAG_NO_BADGE;
import static com.android.launcher3.icons.BitmapInfo.FLAG_THEMED;
@@ -94,11 +95,13 @@
IconLabelDotView, DraggableView, Reorderable {
private static final int DISPLAY_WORKSPACE = 0;
- private static final int DISPLAY_ALL_APPS = 1;
+ public static final int DISPLAY_ALL_APPS = 1;
private static final int DISPLAY_FOLDER = 2;
protected static final int DISPLAY_TASKBAR = 5;
- private static final int DISPLAY_SEARCH_RESULT = 6;
- private static final int DISPLAY_SEARCH_RESULT_SMALL = 7;
+ public static final int DISPLAY_SEARCH_RESULT = 6;
+ public static final int DISPLAY_SEARCH_RESULT_SMALL = 7;
+ public static final int DISPLAY_PREDICTION_ROW = 8;
+ public static final int DISPLAY_SEARCH_RESULT_APP_ROW = 9;
private static final float MIN_LETTER_SPACING = -0.05f;
private static final int MAX_SEARCH_LOOP_COUNT = 20;
@@ -151,7 +154,7 @@
private final CheckLongPressHelper mLongPressHelper;
- private final boolean mLayoutHorizontal;
+ private boolean mLayoutHorizontal;
private final boolean mIsRtl;
private final int mIconSize;
@@ -196,6 +199,7 @@
public BubbleTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mActivity = ActivityContext.lookupContext(context);
+ FastBitmapDrawable.setFlagHoverEnabled(enableCursorHoverStates());
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.BubbleTextView, defStyle, 0);
@@ -210,8 +214,9 @@
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
defaultIconSize = grid.iconSizePx;
- setCenterVertically(grid.isScalableGrid);
- } else if (mDisplay == DISPLAY_ALL_APPS) {
+ setCenterVertically(grid.iconCenterVertically);
+ } else if (mDisplay == DISPLAY_ALL_APPS || mDisplay == DISPLAY_PREDICTION_ROW
+ || mDisplay == DISPLAY_SEARCH_RESULT_APP_ROW) {
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
setCompoundDrawablePadding(grid.allAppsIconDrawablePaddingPx);
defaultIconSize = grid.allAppsIconSizePx;
@@ -269,7 +274,7 @@
mDotParams.scale = 0f;
mForceHideDot = false;
setBackground(null);
- if (FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get()
+ if (Flags.enableTwolineAllapps() || FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get()
|| FeatureFlags.ENABLE_TWOLINE_DEVICESEARCH.get()) {
setMaxLines(1);
}
@@ -394,15 +399,16 @@
}
protected boolean shouldUseTheme() {
- return mDisplay == DISPLAY_WORKSPACE || mDisplay == DISPLAY_FOLDER
- || mDisplay == DISPLAY_TASKBAR;
+ return (mDisplay == DISPLAY_WORKSPACE || mDisplay == DISPLAY_FOLDER
+ || mDisplay == DISPLAY_TASKBAR) && Themes.isThemedIconEnabled(getContext());
}
/**
* Only if actual text can be displayed in two line, the {@code true} value will be effective.
*/
protected boolean shouldUseTwoLine() {
- return (FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get() && mDisplay == DISPLAY_ALL_APPS)
+ return ((Flags.enableTwolineAllapps() || FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get())
+ && mDisplay == DISPLAY_ALL_APPS)
|| (FeatureFlags.ENABLE_TWOLINE_DEVICESEARCH.get()
&& mDisplay == DISPLAY_SEARCH_RESULT);
}
@@ -424,10 +430,10 @@
}
}
- /** This is used for testing to forcefully set the display to ALL_APPS */
+ /** This is used for testing to forcefully set the display. */
@VisibleForTesting
- public void setDisplayAllApps() {
- mDisplay = DISPLAY_ALL_APPS;
+ public void setDisplay(int display) {
+ mDisplay = display;
}
/**
@@ -631,6 +637,11 @@
}
}
+ @VisibleForTesting
+ public boolean getForceHideDot() {
+ return mForceHideDot;
+ }
+
private boolean hasDot() {
return mDotInfo != null;
}
@@ -660,6 +671,18 @@
}
/**
+ * Sets whether the layout is horizontal.
+ */
+ public void setLayoutHorizontal(boolean layoutHorizontal) {
+ if (mLayoutHorizontal == layoutHorizontal) {
+ return;
+ }
+
+ mLayoutHorizontal = layoutHorizontal;
+ applyCompoundDrawables(getIconOrTransparentColor());
+ }
+
+ /**
* Sets whether to vertically center the content.
*/
public void setCenterVertically(boolean centerVertically) {
@@ -985,10 +1008,14 @@
if (!mIsIconVisible) {
resetIconScale();
}
- Drawable icon = visible ? mIcon : new ColorDrawable(Color.TRANSPARENT);
+ Drawable icon = getIconOrTransparentColor();
applyCompoundDrawables(icon);
}
+ private Drawable getIconOrTransparentColor() {
+ return mIsIconVisible ? mIcon : new ColorDrawable(Color.TRANSPARENT);
+ }
+
/** Sets the icon visual state to disabled or not. */
public void setIconDisabled(boolean isDisabled) {
if (mIcon != null) {
@@ -1080,8 +1107,13 @@
}
public boolean isDisplaySearchResult() {
- return mDisplay == DISPLAY_SEARCH_RESULT ||
- mDisplay == DISPLAY_SEARCH_RESULT_SMALL;
+ return mDisplay == DISPLAY_SEARCH_RESULT
+ || mDisplay == DISPLAY_SEARCH_RESULT_SMALL
+ || mDisplay == DISPLAY_SEARCH_RESULT_APP_ROW;
+ }
+
+ public int getIconDisplay() {
+ return mDisplay;
}
@Override
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 108e557..3d715e5 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -35,7 +35,7 @@
import androidx.annotation.VisibleForTesting;
-import com.android.launcher3.anim.Interpolators;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragOptions;
@@ -258,7 +258,7 @@
dragLayer.animateView(d.dragView, to, scale, 0.1f, 0.1f,
DRAG_VIEW_DROP_DURATION,
- Interpolators.DEACCEL_2, onAnimationEndRunnable,
+ Interpolators.DECELERATE_2, onAnimationEndRunnable,
DragLayer.ANIMATION_END_DISAPPEAR, null);
}
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 61b2748..08e5def 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -18,8 +18,8 @@
import static android.animation.ValueAnimator.areAnimatorsEnabled;
+import static com.android.app.animation.Interpolators.DECELERATE_1_5;
import static com.android.launcher3.LauncherState.EDIT_MODE;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5;
import static com.android.launcher3.dragndrop.DraggableView.DRAGGABLE_ICON;
import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_REORDER_BOUNCE_OFFSET;
@@ -60,9 +60,9 @@
import androidx.core.graphics.ColorUtils;
import androidx.core.view.ViewCompat;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.accessibility.DragAndDropAccessibilityDelegate;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
import com.android.launcher3.celllayout.CellPosMapper.CellPos;
import com.android.launcher3.celllayout.ReorderAlgorithm;
@@ -245,6 +245,7 @@
// the user where a dragged item will land when dropped.
setWillNotDraw(false);
setClipToPadding(false);
+ setClipChildren(false);
mActivity = ActivityContext.lookupContext(context);
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
@@ -272,7 +273,7 @@
mReorderPreviewAnimationMagnitude = (REORDER_PREVIEW_MAGNITUDE * deviceProfile.iconSizePx);
// Initialize the data structures used for the drag visualization.
- mEaseOutInterpolator = Interpolators.DEACCEL_2_5; // Quint ease out
+ mEaseOutInterpolator = Interpolators.DECELERATE_QUINT; // Quint ease out
mDragCell[0] = mDragCell[1] = -1;
mDragCellSpan[0] = mDragCellSpan[1] = -1;
for (int i = 0; i < mDragOutlines.length; i++) {
@@ -382,8 +383,7 @@
private void resetCellSizeInternal(DeviceProfile deviceProfile) {
switch (mContainerType) {
case FOLDER:
- mBorderSpace = new Point(deviceProfile.folderCellLayoutBorderSpacePx,
- deviceProfile.folderCellLayoutBorderSpacePx);
+ mBorderSpace = new Point(deviceProfile.folderCellLayoutBorderSpacePx);
break;
case HOTSEAT:
mBorderSpace = new Point(deviceProfile.hotseatBorderSpace,
@@ -1606,7 +1606,7 @@
ValueAnimator va = ObjectAnimator.ofFloat(this, ANIMATION_PROGRESS,
animationProgress, 0);
a = va;
- a.setInterpolator(DEACCEL_1_5);
+ a.setInterpolator(DECELERATE_1_5);
a.setDuration(REORDER_ANIMATION_DURATION);
a.start();
}
@@ -2736,11 +2736,13 @@
}
public boolean isOccupied(int x, int y) {
- if (x < mCountX && y < mCountY) {
+ if (x >= 0 && x < mCountX && y >= 0 && y < mCountY) {
return mOccupied.cells[x][y];
- } else {
+ }
+ if (BuildConfig.IS_STUDIO_BUILD) {
throw new RuntimeException("Position exceeds the bound of this CellLayout");
}
+ return true;
}
@Override
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index fa1cbd6..c05afc9 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -16,13 +16,13 @@
package com.android.launcher3;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.InvariantDeviceProfile.INDEX_DEFAULT;
import static com.android.launcher3.InvariantDeviceProfile.INDEX_LANDSCAPE;
import static com.android.launcher3.InvariantDeviceProfile.INDEX_TWO_PANEL_LANDSCAPE;
import static com.android.launcher3.InvariantDeviceProfile.INDEX_TWO_PANEL_PORTRAIT;
import static com.android.launcher3.Utilities.dpiFromPx;
import static com.android.launcher3.Utilities.pxFromSp;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ICON_OVERLAP_FACTOR;
import static com.android.launcher3.icons.GraphicsUtils.getShapePath;
@@ -53,13 +53,20 @@
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.IconNormalizer;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.responsive.AllAppsSpecs;
+import com.android.launcher3.responsive.CalculatedAllAppsSpec;
+import com.android.launcher3.responsive.CalculatedFolderSpec;
+import com.android.launcher3.responsive.CalculatedHotseatSpec;
+import com.android.launcher3.responsive.CalculatedWorkspaceSpec;
+import com.android.launcher3.responsive.FolderSpecs;
+import com.android.launcher3.responsive.HotseatSpecs;
+import com.android.launcher3.responsive.WorkspaceSpecs;
import com.android.launcher3.uioverrides.ApiWrapper;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
+import com.android.launcher3.util.IconSizeSteps;
import com.android.launcher3.util.ResourceHelper;
import com.android.launcher3.util.WindowBounds;
-import com.android.launcher3.workspace.CalculatedWorkspaceSpec;
-import com.android.launcher3.workspace.WorkspaceSpecs;
import java.io.PrintWriter;
import java.util.Locale;
@@ -80,6 +87,7 @@
public final InvariantDeviceProfile inv;
private final Info mInfo;
private final DisplayMetrics mMetrics;
+ private final IconSizeSteps mIconSizeSteps;
// Device properties
public final boolean isTablet;
@@ -104,14 +112,18 @@
public final float aspectRatio;
- public final boolean isScalableGrid;
+ private final boolean mIsScalableGrid;
private final int mTypeIndex;
// Responsive grid
private final boolean mIsResponsiveGrid;
- private WorkspaceSpecs mWorkspaceSpecs;
private CalculatedWorkspaceSpec mResponsiveWidthSpec;
private CalculatedWorkspaceSpec mResponsiveHeightSpec;
+ private CalculatedAllAppsSpec mAllAppsResponsiveWidthSpec;
+ private CalculatedAllAppsSpec mAllAppsResponsiveHeightSpec;
+ private CalculatedFolderSpec mResponsiveFolderWidthSpec;
+ private CalculatedFolderSpec mResponsiveFolderHeightSpec;
+ private CalculatedHotseatSpec mResponsiveHotseatSpec;
/**
* The maximum amount of left/right workspace padding as a percentage of the screen width.
@@ -152,14 +164,15 @@
public int iconSizePx;
public int iconTextSizePx;
public int iconDrawablePaddingPx;
- public int iconDrawablePaddingOriginalPx;
+ private final int mIconDrawablePaddingOriginalPx;
+ public boolean iconCenterVertically;
public float cellScaleToFit;
public int cellWidthPx;
public int cellHeightPx;
public int workspaceCellPaddingXPx;
- public int cellYPaddingPx;
+ public int cellYPaddingPx = -1;
// Folder
public float folderLabelTextScale;
@@ -169,7 +182,7 @@
public int folderIconOffsetYPx;
// Folder content
- public int folderCellLayoutBorderSpacePx;
+ public Point folderCellLayoutBorderSpacePx;
public int folderContentPaddingLeftRight;
public int folderContentPaddingTop;
@@ -192,9 +205,11 @@
public int hotseatBarEndOffset;
public int hotseatQsbSpace;
public int springLoadedHotseatBarTopMarginPx;
- // Start is the side next to the nav bar, end is the side next to the workspace
- public final int hotseatBarSidePaddingStartPx;
- public final int hotseatBarSidePaddingEndPx;
+ // These 2 values are only used for isVerticalBar
+ // Padding between edge of screen and hotseat
+ public final int mHotseatBarEdgePaddingPx;
+ // Space between hotseat and workspace (not used in responsive)
+ public final int mHotseatBarWorkspaceSpacePx;
public int hotseatQsbWidth; // only used when isQsbInline
public final int hotseatQsbHeight;
public final int hotseatQsbVisualHeight;
@@ -204,6 +219,9 @@
private final int mMinHotseatQsbWidthPx;
private final int mMaxHotseatIconSpacePx;
public final int inlineNavButtonsEndSpacingPx;
+ // Space required for the bubble bar between the hotseat and the edge of the screen. If there's
+ // not enough space, the hotseat will adjust itself for the bubble bar.
+ private final int mBubbleBarSpaceThresholdPx;
// Bottom sheets
public int bottomSheetTopPadding;
@@ -281,6 +299,7 @@
public final int taskbarIconSize;
// If true, used to layout taskbar in 3 button navigation mode.
public final boolean startAlignTaskbar;
+ public final boolean isTransientTaskbar;
// DragController
public int flingToDeleteThresholdVelocity;
@@ -304,9 +323,12 @@
mInsets.set(windowBounds.insets);
// TODO(b/241386436): shouldn't change any launcher behaviour
- mIsResponsiveGrid = inv.workspaceSpecsId != INVALID_RESOURCE_HANDLE;
+ mIsResponsiveGrid = inv.workspaceSpecsId != INVALID_RESOURCE_HANDLE
+ && inv.allAppsSpecsId != INVALID_RESOURCE_HANDLE
+ && inv.folderSpecsId != INVALID_RESOURCE_HANDLE
+ && inv.hotseatSpecsId != INVALID_RESOURCE_HANDLE;
- isScalableGrid = inv.isScalable && !isVerticalBarLayout() && !isMultiWindowMode;
+ mIsScalableGrid = inv.isScalable && !isVerticalBarLayout() && !isMultiWindowMode;
// Determine device posture.
mInfo = info;
isTablet = info.isTablet(windowBounds);
@@ -322,6 +344,8 @@
final Resources res = context.getResources();
mMetrics = res.getDisplayMetrics();
+ mIconSizeSteps = mIsResponsiveGrid ? new IconSizeSteps(res) : null;
+
// Determine sizes.
widthPx = windowBounds.bounds.width();
heightPx = windowBounds.bounds.height();
@@ -343,15 +367,11 @@
}
}
- if (mIsResponsiveGrid) {
- mWorkspaceSpecs = new WorkspaceSpecs(new ResourceHelper(context, inv.workspaceSpecsId));
- mResponsiveWidthSpec = mWorkspaceSpecs.getCalculatedWidthSpec(inv.numColumns,
- availableWidthPx);
- mResponsiveHeightSpec = mWorkspaceSpecs.getCalculatedHeightSpec(inv.numRows,
- availableHeightPx);
- }
-
- if (DisplayController.isTransientTaskbar(context)) {
+ isTransientTaskbar = DisplayController.isTransientTaskbar(context);
+ if (!isTaskbarPresent) {
+ taskbarIconSize = taskbarHeight = stashedTaskbarHeight = taskbarBottomMargin = 0;
+ startAlignTaskbar = false;
+ } else if (isTransientTaskbar) {
float invTransientIconSizeDp = inv.transientTaskbarIconSize[mTypeIndex];
taskbarIconSize = pxFromDp(invTransientIconSizeDp, mMetrics);
taskbarHeight = Math.round((taskbarIconSize * ICON_VISIBLE_AREA_FACTOR)
@@ -373,8 +393,6 @@
edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
workspaceContentScale = res.getFloat(R.dimen.workspace_content_scale);
- desiredWorkspaceHorizontalMarginPx = getHorizontalMarginPx(inv, res);
- desiredWorkspaceHorizontalMarginOriginalPx = desiredWorkspaceHorizontalMarginPx;
gridVisualizationPaddingX = res.getDimensionPixelSize(
R.dimen.grid_visualization_horizontal_cell_spacing);
gridVisualizationPaddingY = res.getDimensionPixelSize(
@@ -407,7 +425,7 @@
folderLabelTextScale = res.getFloat(R.dimen.folder_label_text_scale);
- if (isScalableGrid && inv.folderStyle != INVALID_RESOURCE_HANDLE) {
+ if (mIsScalableGrid && inv.folderStyle != INVALID_RESOURCE_HANDLE) {
TypedArray folderStyle = context.obtainStyledAttributes(inv.folderStyle,
R.styleable.FolderStyle);
// These are re-set in #updateFolderCellSize if the grid is not scalable
@@ -418,19 +436,19 @@
folderContentPaddingTop = folderStyle.getDimensionPixelSize(
R.styleable.FolderStyle_folderTopPadding, 0);
- folderCellLayoutBorderSpacePx = folderStyle.getDimensionPixelSize(
+
+ int gutter = folderStyle.getDimensionPixelSize(
R.styleable.FolderStyle_folderBorderSpace, 0);
+ folderCellLayoutBorderSpacePx = new Point(gutter, gutter);
folderFooterHeightPx = folderStyle.getDimensionPixelSize(
R.styleable.FolderStyle_folderFooterHeight, 0);
folderStyle.recycle();
- } else {
- folderCellLayoutBorderSpacePx = 0;
+ } else if (!mIsResponsiveGrid) {
+ folderCellLayoutBorderSpacePx = new Point(0, 0);
folderFooterHeightPx = res.getDimensionPixelSize(R.dimen.folder_footer_height_default);
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));
@@ -449,7 +467,7 @@
cellStyle = context.obtainStyledAttributes(R.style.CellStyleDefault,
R.styleable.CellStyle);
}
- iconDrawablePaddingOriginalPx = cellStyle.getDimensionPixelSize(
+ mIconDrawablePaddingOriginalPx = cellStyle.getDimensionPixelSize(
R.styleable.CellStyle_iconDrawablePadding, 0);
cellStyle.recycle();
@@ -480,7 +498,7 @@
|| inv.inlineQsb[INDEX_TWO_PANEL_LANDSCAPE]
: inv.inlineQsb[INDEX_DEFAULT] || inv.inlineQsb[INDEX_LANDSCAPE])
&& hotseatQsbHeight > 0;
- isQsbInline = isScalableGrid && inv.inlineQsb[mTypeIndex] && canQsbInline;
+ isQsbInline = mIsScalableGrid && inv.inlineQsb[mTypeIndex] && canQsbInline;
areNavButtonsInline = isTaskbarPresent && !isGestureMode;
numShownHotseatIcons =
@@ -489,36 +507,56 @@
numShownAllAppsColumns =
isTwoPanels ? inv.numDatabaseAllAppsColumns : inv.numAllAppsColumns;
- int hotseatBarBottomSpace = pxFromDp(inv.hotseatBarBottomSpace[mTypeIndex], mMetrics);
+ int hotseatBarBottomSpace;
int minQsbMargin = res.getDimensionPixelSize(R.dimen.min_qsb_margin);
- hotseatQsbSpace = pxFromDp(inv.hotseatQsbSpace[mTypeIndex], mMetrics);
- // Have a little space between the inset and the QSB
- if (mInsets.bottom + minQsbMargin > hotseatBarBottomSpace) {
- int availableSpace = hotseatQsbSpace - (mInsets.bottom - hotseatBarBottomSpace);
- // Only change the spaces if there is space
- if (availableSpace > 0) {
- // Make sure there is enough space between hotseat/QSB and QSB/navBar
- if (availableSpace < minQsbMargin * 2) {
- minQsbMargin = availableSpace / 2;
- hotseatQsbSpace = minQsbMargin;
- } else {
- hotseatQsbSpace -= minQsbMargin;
- }
- }
- hotseatBarBottomSpacePx = mInsets.bottom + minQsbMargin;
-
+ if (mIsResponsiveGrid) {
+ HotseatSpecs hotseatSpecs =
+ HotseatSpecs.create(new ResourceHelper(context,
+ isTwoPanels ? inv.hotseatSpecsTwoPanelId : inv.hotseatSpecsId));
+ mResponsiveHotseatSpec =
+ isVerticalBarLayout() ? hotseatSpecs.getCalculatedWidthSpec(widthPx)
+ : hotseatSpecs.getCalculatedHeightSpec(heightPx);
+ hotseatQsbSpace = mResponsiveHotseatSpec.getHotseatQsbSpace();
+ hotseatBarBottomSpace =
+ isVerticalBarLayout() ? 0 : mResponsiveHotseatSpec.getEdgePadding();
+ mHotseatBarEdgePaddingPx =
+ isVerticalBarLayout() ? mResponsiveHotseatSpec.getEdgePadding() : 0;
+ mHotseatBarWorkspaceSpacePx = 0;
} else {
- hotseatBarBottomSpacePx = hotseatBarBottomSpace;
+ hotseatQsbSpace = pxFromDp(inv.hotseatQsbSpace[mTypeIndex], mMetrics);
+ hotseatBarBottomSpace = pxFromDp(inv.hotseatBarBottomSpace[mTypeIndex], mMetrics);
+ mHotseatBarEdgePaddingPx =
+ isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
+ mHotseatBarWorkspaceSpacePx =
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_side_padding);
+ }
+
+ if (!isVerticalBarLayout()) {
+ // Have a little space between the inset and the QSB
+ if (mInsets.bottom + minQsbMargin > hotseatBarBottomSpace) {
+ int availableSpace = hotseatQsbSpace - (mInsets.bottom - hotseatBarBottomSpace);
+
+ // Only change the spaces if there is space
+ if (availableSpace > 0) {
+ // Make sure there is enough space between hotseat/QSB and QSB/navBar
+ if (availableSpace < minQsbMargin * 2) {
+ minQsbMargin = availableSpace / 2;
+ hotseatQsbSpace = minQsbMargin;
+ } else {
+ hotseatQsbSpace -= minQsbMargin;
+ }
+ }
+ hotseatBarBottomSpacePx = mInsets.bottom + minQsbMargin;
+
+ } else {
+ hotseatBarBottomSpacePx = hotseatBarBottomSpace;
+ }
}
springLoadedHotseatBarTopMarginPx = res.getDimensionPixelSize(
R.dimen.spring_loaded_hotseat_top_margin);
- hotseatBarSidePaddingEndPx =
- res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_side_padding);
- // Add a bit of space between nav bar and hotseat in vertical bar layout.
- hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
- updateHotseatSizes(pxFromDp(inv.iconSize[INDEX_DEFAULT], mMetrics));
+ updateHotseatSizes(pxFromDp(inv.iconSize[mTypeIndex], mMetrics));
if (areNavButtonsInline && !isPhone) {
inlineNavButtonsEndSpacingPx =
res.getDimensionPixelSize(inv.inlineNavButtonsEndSpacing);
@@ -535,6 +573,46 @@
hotseatBarEndOffset = 0;
}
+ mBubbleBarSpaceThresholdPx =
+ res.getDimensionPixelSize(R.dimen.bubblebar_hotseat_adjustment_threshold);
+
+ // Needs to be calculated after hotseatBarSizePx is correct,
+ // for the available height to be correct
+ if (mIsResponsiveGrid) {
+ WorkspaceSpecs workspaceSpecs = WorkspaceSpecs.create(
+ new ResourceHelper(context,
+ isTwoPanels ? inv.workspaceSpecsTwoPanelId : inv.workspaceSpecsId));
+ int availableResponsiveWidth =
+ availableWidthPx - (isVerticalBarLayout() ? hotseatBarSizePx : 0);
+ int numColumns = getPanelCount() * inv.numColumns;
+ // don't use availableHeightPx because it subtracts mInsets.bottom
+ int availableResponsiveHeight = heightPx - mInsets.top
+ - (isVerticalBarLayout() ? 0 : hotseatBarSizePx);
+ mResponsiveWidthSpec = workspaceSpecs.getCalculatedWidthSpec(numColumns,
+ availableResponsiveWidth);
+ mResponsiveHeightSpec = workspaceSpecs.getCalculatedHeightSpec(inv.numRows,
+ availableResponsiveHeight);
+
+ AllAppsSpecs allAppsSpecs = AllAppsSpecs.create(
+ new ResourceHelper(context,
+ isTwoPanels ? inv.allAppsSpecsTwoPanelId : inv.allAppsSpecsId));
+ mAllAppsResponsiveWidthSpec = allAppsSpecs.getCalculatedWidthSpec(numColumns,
+ mResponsiveWidthSpec.getAvailableSpace(), mResponsiveWidthSpec);
+ mAllAppsResponsiveHeightSpec = allAppsSpecs.getCalculatedHeightSpec(inv.numRows,
+ mResponsiveHeightSpec.getAvailableSpace(), mResponsiveHeightSpec);
+
+ FolderSpecs folderSpecs = FolderSpecs.create(
+ new ResourceHelper(context,
+ isTwoPanels ? inv.folderSpecsTwoPanelId : inv.folderSpecsId));
+ mResponsiveFolderWidthSpec = folderSpecs.getCalculatedWidthSpec(inv.numFolderColumns,
+ mResponsiveWidthSpec.getAvailableSpace(), mResponsiveWidthSpec);
+ mResponsiveFolderHeightSpec = folderSpecs.getCalculatedHeightSpec(inv.numFolderRows,
+ mResponsiveHeightSpec.getAvailableSpace(), mResponsiveHeightSpec);
+ }
+
+ desiredWorkspaceHorizontalMarginPx = getHorizontalMarginPx(inv, res);
+ desiredWorkspaceHorizontalMarginOriginalPx = desiredWorkspaceHorizontalMarginPx;
+
overviewTaskMarginPx = res.getDimensionPixelSize(R.dimen.overview_task_margin);
overviewTaskIconSizePx = res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_size);
overviewTaskIconDrawableSizePx =
@@ -542,7 +620,9 @@
overviewTaskIconDrawableSizeGridPx =
res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_drawable_size_grid);
overviewTaskThumbnailTopMarginPx = overviewTaskIconSizePx + overviewTaskMarginPx;
- overviewActionsTopMarginPx = res.getDimensionPixelSize(R.dimen.overview_actions_top_margin);
+ // Don't add margin with floating search bar to minimize risk of overlapping.
+ overviewActionsTopMarginPx = FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get() ? 0
+ : res.getDimensionPixelSize(R.dimen.overview_actions_top_margin);
overviewPageSpacing = res.getDimensionPixelSize(R.dimen.overview_page_spacing);
overviewActionsButtonSpacing = res.getDimensionPixelSize(
R.dimen.overview_actions_button_spacing);
@@ -555,21 +635,7 @@
// Calculate all of the remaining variables.
extraSpace = updateAvailableDimensions(res);
- // Now that we have all of the variables calculated, we can tune certain sizes.
- 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);
- DevicePaddings devicePaddings = new DevicePaddings(context, inv.devicePaddingId);
- DevicePadding padding = devicePaddings.getDevicePadding(unscaledExtraSpace);
- maxEmptySpace = padding.getMaxEmptySpacePx();
-
- int paddingWorkspaceTop = padding.getWorkspaceTopPadding(unscaledExtraSpace);
- int paddingWorkspaceBottom = padding.getWorkspaceBottomPadding(unscaledExtraSpace);
- int paddingHotseatBottom = padding.getHotseatBottomPadding(unscaledExtraSpace);
-
- workspaceTopPadding = Math.round(paddingWorkspaceTop * cellScaleToFit);
- workspaceBottomPadding = Math.round(paddingWorkspaceBottom * cellScaleToFit);
- }
+ calculateAndSetWorkspaceVerticalPadding(context, inv, extraSpace);
int cellLayoutPadding =
isTwoPanels ? cellLayoutBorderSpacePx.x / 2 : res.getDimensionPixelSize(
@@ -588,6 +654,10 @@
// Hotseat and QSB width depends on updated cellSize and workspace padding
recalculateHotseatWidthAndBorderSpace();
+ if (mIsResponsiveGrid && isVerticalBarLayout()) {
+ hotseatBorderSpace = cellLayoutBorderSpacePx.y;
+ }
+
// AllApps height calculation depends on updated cellSize
if (isTablet) {
int collapseHandleHeight =
@@ -650,23 +720,48 @@
}
private int getHorizontalMarginPx(InvariantDeviceProfile idp, Resources res) {
+ if (mIsResponsiveGrid) {
+ return mResponsiveWidthSpec.getStartPaddingPx();
+ }
+
if (isVerticalBarLayout()) {
return 0;
}
- return isScalableGrid
+ return mIsScalableGrid
? pxFromDp(idp.horizontalMargin[mTypeIndex], mMetrics)
: res.getDimensionPixelSize(R.dimen.dynamic_grid_left_right_margin);
}
+ private void calculateAndSetWorkspaceVerticalPadding(Context context,
+ InvariantDeviceProfile inv,
+ int extraSpace) {
+ if (mIsResponsiveGrid) {
+ workspaceTopPadding = mResponsiveHeightSpec.getStartPaddingPx();
+ workspaceBottomPadding = mResponsiveHeightSpec.getEndPaddingPx();
+ } else if (mIsScalableGrid && inv.devicePaddingId != INVALID_RESOURCE_HANDLE) {
+ // Paddings were created assuming no scaling, so we first unscale the extra space.
+ int unscaledExtraSpace = (int) (extraSpace / cellScaleToFit);
+ DevicePaddings devicePaddings = new DevicePaddings(context, inv.devicePaddingId);
+ DevicePadding padding = devicePaddings.getDevicePadding(unscaledExtraSpace);
+ maxEmptySpace = padding.getMaxEmptySpacePx();
+
+ int paddingWorkspaceTop = padding.getWorkspaceTopPadding(unscaledExtraSpace);
+ int paddingWorkspaceBottom = padding.getWorkspaceBottomPadding(unscaledExtraSpace);
+
+ workspaceTopPadding = Math.round(paddingWorkspaceTop * cellScaleToFit);
+ workspaceBottomPadding = Math.round(paddingWorkspaceBottom * cellScaleToFit);
+ }
+ }
+
/** Updates hotseatCellHeightPx and hotseatBarSizePx */
private void updateHotseatSizes(int hotseatIconSizePx) {
// Ensure there is enough space for folder icons, which have a slightly larger radius.
- hotseatCellHeightPx = (int) Math.ceil(hotseatIconSizePx * ICON_OVERLAP_FACTOR);
+ hotseatCellHeightPx = getIconSizeWithOverlap(hotseatIconSizePx);
if (isVerticalBarLayout()) {
- hotseatBarSizePx = hotseatIconSizePx + hotseatBarSidePaddingStartPx
- + hotseatBarSidePaddingEndPx;
+ hotseatBarSizePx = hotseatIconSizePx + mHotseatBarEdgePaddingPx
+ + mHotseatBarWorkspaceSpacePx;
} else if (isQsbInline) {
hotseatBarSizePx = Math.max(hotseatIconSizePx, hotseatQsbVisualHeight)
+ hotseatBarBottomSpacePx;
@@ -683,7 +778,7 @@
* necessary.
*/
public void recalculateHotseatWidthAndBorderSpace() {
- if (!isScalableGrid) return;
+ if (!mIsScalableGrid) return;
int columns = inv.hotseatColumnSpan[mTypeIndex];
float hotseatWidthPx = getIconToIconWidthForColumns(columns);
@@ -728,7 +823,6 @@
hotseatBorderSpace = calculateHotseatBorderSpace(maxHotseatIconsWidthPx,
(isQsbInline ? 1 : 0) + /* border between nav buttons and first icon */ 1);
} while (hotseatBorderSpace < mMinHotseatIconSpacePx && numShownHotseatIcons > 1);
-
}
private Point getCellLayoutBorderSpace(InvariantDeviceProfile idp) {
@@ -736,12 +830,16 @@
}
private Point getCellLayoutBorderSpace(InvariantDeviceProfile idp, float scale) {
- if (!isScalableGrid) {
- return new Point(0, 0);
- }
+ int horizontalSpacePx = 0;
+ int verticalSpacePx = 0;
- int horizontalSpacePx = pxFromDp(idp.borderSpaces[mTypeIndex].x, mMetrics, scale);
- int verticalSpacePx = pxFromDp(idp.borderSpaces[mTypeIndex].y, mMetrics, scale);
+ if (mIsResponsiveGrid) {
+ horizontalSpacePx = mResponsiveWidthSpec.getGutterPx();
+ verticalSpacePx = mResponsiveHeightSpec.getGutterPx();
+ } else if (mIsScalableGrid) {
+ horizontalSpacePx = pxFromDp(idp.borderSpaces[mTypeIndex].x, mMetrics, scale);
+ verticalSpacePx = pxFromDp(idp.borderSpaces[mTypeIndex].y, mMetrics, scale);
+ }
return new Point(horizontalSpacePx, verticalSpacePx);
}
@@ -807,54 +905,29 @@
float workspaceCellPaddingY = getCellSize().y - iconSizePx - iconDrawablePaddingPx
- iconTextHeight;
+ if (mIsResponsiveGrid) {
+ // Hide text only if doesn't fit inside the cell for responsive grid
+ if (workspaceCellPaddingY < 0) {
+ iconTextSizePx = 0;
+ iconDrawablePaddingPx = 0;
+ int iconSizeWithOverlap = getIconSizeWithOverlap(iconSizePx);
+ cellYPaddingPx = Math.max(0, getCellSize().y - iconSizeWithOverlap) / 2;
+ autoResizeAllAppsCells();
+ }
+
+ return;
+ }
+
// We want enough space so that the text is closer to its corresponding icon.
if (workspaceCellPaddingY < iconTextHeight) {
iconTextSizePx = 0;
iconDrawablePaddingPx = 0;
- cellHeightPx = (int) Math.ceil(iconSizePx * ICON_OVERLAP_FACTOR);
+ cellHeightPx = getIconSizeWithOverlap(iconSizePx);
autoResizeAllAppsCells();
}
}
/**
- * Re-computes the all-apps cell size to be independent of workspace
- */
- public void autoResizeAllAppsCells() {
- int textHeight = Utilities.calculateTextHeight(allAppsIconTextSizePx);
- int topBottomPadding = textHeight;
- allAppsCellHeightPx = allAppsIconSizePx + allAppsIconDrawablePaddingPx
- + textHeight + (topBottomPadding * 2);
- }
-
- private void updateAllAppsContainerWidth(Resources res) {
- int cellLayoutHorizontalPadding =
- (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right) / 2;
- if (isTablet) {
- int usedWidth = (allAppsCellWidthPx * numShownAllAppsColumns)
- + (allAppsBorderSpacePx.x * (numShownAllAppsColumns - 1))
- + allAppsLeftRightPadding * 2;
- allAppsLeftRightMargin = Math.max(1, (availableWidthPx - usedWidth) / 2);
- } else {
- allAppsLeftRightPadding =
- desiredWorkspaceHorizontalMarginPx + cellLayoutHorizontalPadding;
- }
- }
-
- private void setupAllAppsStyle(Context context) {
- TypedArray allAppsStyle;
- if (inv.allAppsStyle != INVALID_RESOURCE_HANDLE) {
- allAppsStyle = context.obtainStyledAttributes(inv.allAppsStyle,
- R.styleable.AllAppsStyle);
- } else {
- allAppsStyle = context.obtainStyledAttributes(R.style.AllAppsStyleDefault,
- R.styleable.AllAppsStyle);
- }
- allAppsLeftRightPadding = allAppsStyle.getDimensionPixelSize(
- R.styleable.AllAppsStyle_horizontalPadding, 0);
- allAppsStyle.recycle();
- }
-
- /**
* Returns the amount of extra (or unused) vertical space.
*/
private int updateAvailableDimensions(Resources res) {
@@ -862,11 +935,15 @@
float invIconTextSizeSp = inv.iconTextSize[mTypeIndex];
iconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mMetrics));
iconTextSizePx = pxFromSp(invIconTextSizeSp, mMetrics);
+ iconCenterVertically = mIsScalableGrid || mIsResponsiveGrid;
updateIconSize(1f, res);
-
updateWorkspacePadding();
+ if (mIsResponsiveGrid) {
+ return 0;
+ }
+
// Check to see if the icons fit within the available height.
float usedHeight = getCellLayoutHeightSpecification();
final int maxHeight = getCellLayoutHeight();
@@ -875,7 +952,7 @@
boolean shouldScale = scaleY < 1f;
float scaleX = 1f;
- if (isScalableGrid) {
+ if (mIsScalableGrid) {
// We scale to fit the cellWidth and cellHeight in the available space.
// The benefit of scalable grids is that we can get consistent aspect ratios between
// devices.
@@ -906,6 +983,29 @@
+ cellLayoutPaddingPx.left + cellLayoutPaddingPx.right;
}
+ private int getNormalizedIconDrawablePadding() {
+ // TODO(b/235886078): workaround needed because of this bug
+ // Icons are 10% larger on XML than their visual size,
+ // so remove that extra space to get labels closer to the correct padding
+ int iconVisibleSizePx = (int) Math.round(ICON_VISIBLE_AREA_FACTOR * iconSizePx);
+ return Math.max(0, mIconDrawablePaddingOriginalPx - ((iconSizePx - iconVisibleSizePx) / 2));
+ }
+
+ private int getNormalizedFolderChildDrawablePaddingPx(int textHeight) {
+ // TODO(b/235886078): workaround needed because of this bug
+ // Icons are 10% larger on XML than their visual size,
+ // so remove that extra space to get labels closer to the correct padding
+ int drawablePadding = (folderCellHeightPx - folderChildIconSizePx - textHeight) / 3;
+
+ int iconVisibleSizePx = Math.round(ICON_VISIBLE_AREA_FACTOR * folderChildIconSizePx);
+ int iconSizeDiff = folderChildIconSizePx - iconVisibleSizePx;
+ return Math.max(0, drawablePadding - iconSizeDiff / 2);
+ }
+
+ private int getIconSizeWithOverlap(int iconSize) {
+ return (int) Math.ceil(iconSize * ICON_OVERLAP_FACTOR);
+ }
+
/**
* Updating the iconSize affects many aspects of the launcher layout, such as: iconSizePx,
* iconTextSizePx, iconDrawablePaddingPx, cellWidth/Height, allApps* variants,
@@ -918,10 +1018,37 @@
// Workspace
final boolean isVerticalLayout = isVerticalBarLayout();
- iconDrawablePaddingPx = (int) (iconDrawablePaddingOriginalPx * iconScale);
cellLayoutBorderSpacePx = getCellLayoutBorderSpace(inv, scale);
- if (isScalableGrid) {
+ if (mIsResponsiveGrid) {
+ cellWidthPx = mResponsiveWidthSpec.getCellSizePx();
+ cellHeightPx = mResponsiveHeightSpec.getCellSizePx();
+
+ if (cellWidthPx < iconSizePx) {
+ // get a smaller icon size
+ iconSizePx = mIconSizeSteps.getIconSmallerThan(cellWidthPx);
+ }
+
+ // TODO(b/296400197): isVerticalBar shouldn't show labels anymore
+ iconDrawablePaddingPx = getNormalizedIconDrawablePadding();
+ int iconTextHeight = Utilities.calculateTextHeight(iconTextSizePx);
+ int cellContentHeight = iconSizePx + iconDrawablePaddingPx + iconTextHeight;
+
+ while (iconSizePx > mIconSizeSteps.minimumIconSize()
+ && cellContentHeight > cellHeightPx) {
+ iconDrawablePaddingPx -= cellContentHeight - cellHeightPx;
+ if (iconDrawablePaddingPx < 0) {
+ // get a smaller icon size
+ iconSizePx = mIconSizeSteps.getNextLowerIconSize(iconSizePx);
+ iconDrawablePaddingPx = getNormalizedIconDrawablePadding();
+ }
+ // calculate new cellContentHeight
+ cellContentHeight = iconSizePx + iconDrawablePaddingPx + iconTextHeight;
+ }
+
+ cellYPaddingPx = Math.max(0, cellHeightPx - cellContentHeight) / 2;
+ } else if (mIsScalableGrid) {
+ iconDrawablePaddingPx = (int) (getNormalizedIconDrawablePadding() * iconScale);
cellWidthPx = pxFromDp(inv.minCellSize[mTypeIndex].x, mMetrics, scale);
cellHeightPx = pxFromDp(inv.minCellSize[mTypeIndex].y, mMetrics, scale);
@@ -980,8 +1107,9 @@
desiredWorkspaceHorizontalMarginPx =
(int) (desiredWorkspaceHorizontalMarginOriginalPx * scale);
} else {
+ iconDrawablePaddingPx = (int) (getNormalizedIconDrawablePadding() * iconScale);
cellWidthPx = iconSizePx + iconDrawablePaddingPx;
- cellHeightPx = (int) Math.ceil(iconSizePx * ICON_OVERLAP_FACTOR)
+ cellHeightPx = getIconSizeWithOverlap(iconSizePx)
+ iconDrawablePaddingPx
+ Utilities.calculateTextHeight(iconTextSizePx);
int cellPaddingY = (getCellSize().y - cellHeightPx) / 2;
@@ -996,7 +1124,15 @@
}
// All apps
- updateAllAppsIconSize(scale, res);
+ if (mIsResponsiveGrid) {
+ updateAllAppsWithResponsiveMeasures();
+ } else {
+ updateAllAppsIconSize(scale, res);
+ }
+ updateAllAppsContainerWidth();
+ if (isVerticalBarLayout()) {
+ hideWorkspaceLabelsIfNotEnoughSpace();
+ }
updateHotseatSizes(iconSizePx);
@@ -1021,14 +1157,14 @@
* This method calculates the space between the icons to achieve a certain width.
*/
private int calculateHotseatBorderSpace(float hotseatWidthPx, int numExtraBorder) {
+ int numBorders = (numShownHotseatIcons - 1 + numExtraBorder);
+ if (numBorders <= 0) return 0;
+
float hotseatIconsTotalPx = iconSizePx * numShownHotseatIcons;
- int hotseatBorderSpacePx =
- (int) (hotseatWidthPx - hotseatIconsTotalPx)
- / (numShownHotseatIcons - 1 + numExtraBorder);
+ int hotseatBorderSpacePx = (int) (hotseatWidthPx - hotseatIconsTotalPx) / numBorders;
return Math.min(hotseatBorderSpacePx, mMaxHotseatIconSpacePx);
}
-
/**
* Updates the iconSize for allApps* variants.
*/
@@ -1042,10 +1178,10 @@
+ allAppsBorderSpacePx.y;
// but width is just the cell,
// the border is added in #updateAllAppsContainerWidth
- if (isScalableGrid) {
+ if (mIsScalableGrid) {
allAppsIconSizePx = pxFromDp(inv.allAppsIconSize[mTypeIndex], mMetrics);
allAppsIconTextSizePx = pxFromSp(inv.allAppsIconTextSize[mTypeIndex], mMetrics);
- allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx;
+ allAppsIconDrawablePaddingPx = getNormalizedIconDrawablePadding();
allAppsCellWidthPx = pxFromDp(inv.allAppsCellSize[mTypeIndex].x, mMetrics, scale);
if (allAppsCellWidthPx < allAppsIconSizePx) {
@@ -1082,22 +1218,70 @@
res.getDimensionPixelSize(R.dimen.all_apps_icon_drawable_padding);
allAppsCellWidthPx = allAppsIconSizePx + (2 * allAppsIconDrawablePaddingPx);
}
+ }
- updateAllAppsContainerWidth(res);
- if (isVerticalBarLayout()) {
- hideWorkspaceLabelsIfNotEnoughSpace();
+ private void updateAllAppsWithResponsiveMeasures() {
+ allAppsIconSizePx = iconSizePx;
+ allAppsIconTextSizePx = iconTextSizePx;
+ allAppsIconDrawablePaddingPx = iconDrawablePaddingPx;
+
+ allAppsBorderSpacePx = new Point(
+ mAllAppsResponsiveWidthSpec.getGutterPx(),
+ mAllAppsResponsiveHeightSpec.getGutterPx()
+ );
+ allAppsCellHeightPx = mAllAppsResponsiveHeightSpec.getCellSizePx()
+ + mAllAppsResponsiveHeightSpec.getGutterPx();
+ allAppsCellWidthPx = mAllAppsResponsiveWidthSpec.getCellSizePx();
+ allAppsLeftRightPadding = mAllAppsResponsiveWidthSpec.getStartPaddingPx();
+ }
+
+ /**
+ * Re-computes the all-apps cell size to be independent of workspace
+ */
+ public void autoResizeAllAppsCells() {
+ int textHeight = Utilities.calculateTextHeight(allAppsIconTextSizePx);
+ int topBottomPadding = textHeight;
+ allAppsCellHeightPx = allAppsIconSizePx + allAppsIconDrawablePaddingPx
+ + textHeight + (topBottomPadding * 2);
+ }
+
+ private void updateAllAppsContainerWidth() {
+ int cellLayoutHorizontalPadding =
+ (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right) / 2;
+ if (isTablet) {
+ int usedWidth = (allAppsCellWidthPx * numShownAllAppsColumns)
+ + (allAppsBorderSpacePx.x * (numShownAllAppsColumns - 1))
+ + allAppsLeftRightPadding * 2;
+ allAppsLeftRightMargin = Math.max(1, (availableWidthPx - usedWidth) / 2);
+ } else {
+ allAppsLeftRightPadding =
+ Math.max(0, desiredWorkspaceHorizontalMarginPx + cellLayoutHorizontalPadding
+ - (allAppsBorderSpacePx.x / 2));
}
}
+ private void setupAllAppsStyle(Context context) {
+ TypedArray allAppsStyle = context.obtainStyledAttributes(
+ inv.allAppsStyle != INVALID_RESOURCE_HANDLE ? inv.allAppsStyle
+ : R.style.AllAppsStyleDefault, R.styleable.AllAppsStyle);
+
+ allAppsLeftRightPadding = allAppsStyle.getDimensionPixelSize(
+ R.styleable.AllAppsStyle_horizontalPadding, 0);
+ allAppsStyle.recycle();
+ }
+
private void updateAvailableFolderCellDimensions(Resources res) {
updateFolderCellSize(1f, res);
+ // Responsive grid doesn't need to scale the folder
+ if (mIsResponsiveGrid) return;
+
// For usability we can't have the folder use the whole width of the screen
Point totalWorkspacePadding = getTotalWorkspacePadding();
// Check if the folder fit within the available height.
float contentUsedHeight = folderCellHeightPx * inv.numFolderRows
- + ((inv.numFolderRows - 1) * folderCellLayoutBorderSpacePx)
+ + ((inv.numFolderRows - 1) * folderCellLayoutBorderSpacePx.y)
+ folderFooterHeightPx
+ folderContentPaddingTop;
int contentMaxHeight = availableHeightPx - totalWorkspacePadding.y;
@@ -1105,7 +1289,7 @@
// Check if the folder fit within the available width.
float contentUsedWidth = folderCellWidthPx * inv.numFolderColumns
- + ((inv.numFolderColumns - 1) * folderCellLayoutBorderSpacePx)
+ + ((inv.numFolderColumns - 1) * folderCellLayoutBorderSpacePx.x)
+ folderContentPaddingLeftRight * 2;
int contentMaxWidth = availableWidthPx - totalWorkspacePadding.x;
float scaleX = contentMaxWidth / contentUsedWidth;
@@ -1125,7 +1309,45 @@
int textHeight = Utilities.calculateTextHeight(folderChildTextSizePx);
- if (isScalableGrid) {
+ if (mIsResponsiveGrid) {
+ folderCellWidthPx = mResponsiveFolderWidthSpec.getCellSizePx();
+
+ // Height
+ folderCellHeightPx = mResponsiveFolderHeightSpec.getCellSizePx();
+ folderContentPaddingTop = mResponsiveFolderHeightSpec.getStartPaddingPx();
+ folderFooterHeightPx = mResponsiveFolderHeightSpec.getEndPaddingPx();
+
+ folderCellLayoutBorderSpacePx = new Point(mResponsiveFolderWidthSpec.getGutterPx(),
+ mResponsiveFolderHeightSpec.getGutterPx());
+
+ folderContentPaddingLeftRight = mResponsiveFolderWidthSpec.getStartPaddingPx();
+
+ // Reduce icon width if it's wider than the expected folder cell width
+ if (folderCellWidthPx < folderChildIconSizePx) {
+ folderChildIconSizePx = mIconSizeSteps.getIconSmallerThan(folderCellWidthPx);
+ }
+
+ // Recalculating padding and cell height
+ folderChildDrawablePaddingPx = getNormalizedFolderChildDrawablePaddingPx(textHeight);
+ int folderCellContentHeight = folderChildIconSizePx + folderChildDrawablePaddingPx
+ + textHeight;
+
+ // Reduce the icon in height when it's taller than the expected cell height
+ while (folderChildIconSizePx > mIconSizeSteps.minimumIconSize()
+ && folderCellContentHeight > folderCellHeightPx) {
+ folderChildDrawablePaddingPx -= folderCellContentHeight - folderCellHeightPx;
+ if (folderChildDrawablePaddingPx < 0) {
+ // get a smaller icon size
+ folderChildIconSizePx = mIconSizeSteps.getNextLowerIconSize(
+ folderChildIconSizePx);
+ folderChildDrawablePaddingPx =
+ getNormalizedFolderChildDrawablePaddingPx(textHeight);
+ }
+ // calculate new cellContentHeight
+ folderCellContentHeight = folderChildIconSizePx + folderChildDrawablePaddingPx
+ + textHeight;
+ }
+ } else if (mIsScalableGrid) {
if (inv.folderStyle == INVALID_RESOURCE_HANDLE) {
folderCellWidthPx = roundPxValueFromFloat(getCellSize().x * scale);
folderCellHeightPx = roundPxValueFromFloat(getCellSize().y * scale);
@@ -1135,11 +1357,15 @@
}
folderContentPaddingTop = roundPxValueFromFloat(folderContentPaddingTop * scale);
- folderCellLayoutBorderSpacePx = roundPxValueFromFloat(
- folderCellLayoutBorderSpacePx * scale);
+ folderCellLayoutBorderSpacePx = new Point(
+ roundPxValueFromFloat(folderCellLayoutBorderSpacePx.x * scale),
+ roundPxValueFromFloat(folderCellLayoutBorderSpacePx.y * scale)
+ );
folderFooterHeightPx = roundPxValueFromFloat(folderFooterHeightPx * scale);
- folderContentPaddingLeftRight = folderCellLayoutBorderSpacePx;
+ folderContentPaddingLeftRight = folderCellLayoutBorderSpacePx.x;
+
+ folderChildDrawablePaddingPx = getNormalizedFolderChildDrawablePaddingPx(textHeight);
} else {
int cellPaddingX = (int) (res.getDimensionPixelSize(R.dimen.folder_cell_x_padding)
* scale);
@@ -1156,10 +1382,8 @@
res.getDimensionPixelSize(R.dimen.folder_footer_height_default)
* scale);
+ folderChildDrawablePaddingPx = getNormalizedFolderChildDrawablePaddingPx(textHeight);
}
-
- folderChildDrawablePaddingPx = Math.max(0,
- (folderCellHeightPx - folderChildIconSizePx - textHeight) / 3);
}
public void updateInsets(Rect insets) {
@@ -1288,22 +1512,37 @@
private void updateWorkspacePadding() {
Rect padding = workspacePadding;
if (isVerticalBarLayout()) {
- padding.top = 0;
- padding.bottom = edgeMarginPx;
- if (isSeascape()) {
- padding.left = hotseatBarSizePx;
- padding.right = hotseatBarSidePaddingStartPx;
+ if (mIsResponsiveGrid) {
+ padding.top = mResponsiveHeightSpec.getStartPaddingPx();
+ padding.bottom = Math.max(0,
+ mResponsiveHeightSpec.getEndPaddingPx() - mInsets.bottom);
+ if (isSeascape()) {
+ padding.left = hotseatBarSizePx + mResponsiveWidthSpec.getEndPaddingPx();
+ padding.right = mResponsiveWidthSpec.getStartPaddingPx();
+ } else {
+ padding.left = mResponsiveWidthSpec.getStartPaddingPx();
+ padding.right = hotseatBarSizePx + mResponsiveWidthSpec.getEndPaddingPx();
+ }
} else {
- padding.left = hotseatBarSidePaddingStartPx;
- padding.right = hotseatBarSizePx;
+ padding.top = 0;
+ padding.bottom = edgeMarginPx;
+ if (isSeascape()) {
+ padding.left = hotseatBarSizePx;
+ padding.right = mHotseatBarEdgePaddingPx;
+ } else {
+ padding.left = mHotseatBarEdgePaddingPx;
+ padding.right = hotseatBarSizePx;
+ }
}
} else {
// Pad the bottom of the workspace with hotseat bar
// and leave a bit of space in case a widget go all the way down
- int paddingBottom = hotseatBarSizePx + workspaceBottomPadding
- + workspacePageIndicatorHeight - mWorkspacePageIndicatorOverlapWorkspace
- - mInsets.bottom;
- int paddingTop = workspaceTopPadding + (isScalableGrid ? 0 : edgeMarginPx);
+ int paddingBottom = hotseatBarSizePx + workspaceBottomPadding - mInsets.bottom;
+ if (!mIsResponsiveGrid) {
+ paddingBottom +=
+ workspacePageIndicatorHeight - mWorkspacePageIndicatorOverlapWorkspace;
+ }
+ int paddingTop = workspaceTopPadding + (mIsScalableGrid ? 0 : edgeMarginPx);
int paddingSide = desiredWorkspaceHorizontalMarginPx;
padding.set(paddingSide, paddingTop, paddingSide, paddingBottom);
@@ -1325,6 +1564,32 @@
paddings.bottom -= insets.bottom;
}
+
+ /**
+ * Returns the new border space that should be used between hotseat icons after adjusting it to
+ * the bubble bar.
+ *
+ * <p>If there's no adjustment needed, this method returns {@code 0}.
+ */
+ public float getHotseatAdjustedBorderSpaceForBubbleBar(Context context) {
+ // only need to adjust when QSB is on top of the hotseat.
+ if (isQsbInline) {
+ return 0;
+ }
+
+ // no need to adjust if there's enough space for the bubble bar to the right of the hotseat.
+ if (getHotseatLayoutPadding(context).right > mBubbleBarSpaceThresholdPx) {
+ return 0;
+ }
+
+ // The adjustment is shrinking the hotseat's width by 1 icon on either side.
+ int iconsWidth =
+ iconSizePx * numShownHotseatIcons + hotseatBorderSpace * (numShownHotseatIcons - 1);
+ int newWidth = iconsWidth - 2 * iconSizePx;
+ // Evenly space the icons within the boundaries of the new width.
+ return (float) (newWidth - iconSizePx * numShownHotseatIcons) / (numShownHotseatIcons - 1);
+ }
+
/**
* Returns the padding for hotseat view
*/
@@ -1336,18 +1601,20 @@
// in vertical bar layout.
// Workspace icons are moved up by a small factor. The variable diffOverlapFactor
// is set to account for that difference.
- float diffOverlapFactor = iconSizePx * (ICON_OVERLAP_FACTOR - 1) / 2;
+ float diffOverlapFactor = mIsResponsiveGrid ? 0
+ : iconSizePx * (ICON_OVERLAP_FACTOR - 1) / 2;
+
int paddingTop = Math.max((int) (mInsets.top + cellLayoutPaddingPx.top
- diffOverlapFactor), 0);
int paddingBottom = Math.max((int) (mInsets.bottom + cellLayoutPaddingPx.bottom
+ diffOverlapFactor), 0);
if (isSeascape()) {
- hotseatBarPadding.set(mInsets.left + hotseatBarSidePaddingStartPx, paddingTop,
- hotseatBarSidePaddingEndPx, paddingBottom);
+ hotseatBarPadding.set(mInsets.left + mHotseatBarEdgePaddingPx, paddingTop,
+ mHotseatBarWorkspaceSpacePx, paddingBottom);
} else {
- hotseatBarPadding.set(hotseatBarSidePaddingEndPx, paddingTop,
- mInsets.right + hotseatBarSidePaddingStartPx, paddingBottom);
+ hotseatBarPadding.set(mHotseatBarWorkspaceSpacePx, paddingTop,
+ mInsets.right + mHotseatBarEdgePaddingPx, paddingBottom);
}
} else if (isTaskbarPresent) {
// Center the QSB vertically with hotseat
@@ -1379,7 +1646,7 @@
hotseatBarPadding.right = endSpacing;
}
- } else if (isScalableGrid) {
+ } else if (mIsScalableGrid) {
int sideSpacing = (availableWidthPx - hotseatQsbWidth) / 2;
hotseatBarPadding.set(sideSpacing,
0,
@@ -1404,6 +1671,25 @@
return hotseatBarPadding;
}
+ /** The margin between the edge of all apps and the edge of the first icon. */
+ public int getAllAppsIconStartMargin() {
+ int allAppsSpacing;
+ if (isVerticalBarLayout()) {
+ // On phones, the landscape layout uses a different setup.
+ allAppsSpacing = workspacePadding.left + workspacePadding.right;
+ } else {
+ allAppsSpacing = allAppsLeftRightPadding * 2 + allAppsLeftRightMargin * 2;
+ }
+
+ int cellWidth = DeviceProfile.calculateCellWidth(
+ availableWidthPx - allAppsSpacing,
+ 0 /* borderSpace */,
+ numShownAllAppsColumns);
+ int iconVisibleSize = Math.round(ICON_VISIBLE_AREA_FACTOR * allAppsIconSizePx);
+ int iconAlignmentMargin = (cellWidth - iconVisibleSize) / 2;
+ return allAppsLeftRightPadding + iconAlignmentMargin;
+ }
+
private int getAdditionalQsbSpace() {
return isQsbInline ? hotseatQsbWidth + hotseatBorderSpace : 0;
}
@@ -1464,7 +1750,7 @@
/** Gets the space that the overview actions will take, including bottom margin. */
public int getOverviewActionsClaimedSpace() {
- int overviewActionsSpace = isTablet && FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get()
+ int overviewActionsSpace = isTablet && FeatureFlags.enableGridOnlyOverview()
? 0
: (overviewActionsTopMarginPx + overviewActionsHeight);
return overviewActionsSpace + getOverviewActionsClaimedSpaceBelow();
@@ -1599,7 +1885,7 @@
writer.println(prefix + "\taspectRatio:" + aspectRatio);
writer.println(prefix + "\tisResponsiveGrid:" + mIsResponsiveGrid);
- writer.println(prefix + "\tisScalableGrid:" + isScalableGrid);
+ writer.println(prefix + "\tisScalableGrid:" + mIsScalableGrid);
writer.println(prefix + "\tinv.numRows: " + inv.numRows);
writer.println(prefix + "\tinv.numColumns: " + inv.numColumns);
@@ -1639,8 +1925,10 @@
writer.println(prefix + pxToDpStr("folderChildTextSizePx", folderChildTextSizePx));
writer.println(prefix + pxToDpStr("folderChildDrawablePaddingPx",
folderChildDrawablePaddingPx));
- writer.println(prefix + pxToDpStr("folderCellLayoutBorderSpacePx",
- folderCellLayoutBorderSpacePx));
+ writer.println(prefix + pxToDpStr("folderCellLayoutBorderSpacePx.x",
+ folderCellLayoutBorderSpacePx.x));
+ writer.println(prefix + pxToDpStr("folderCellLayoutBorderSpacePx.y",
+ folderCellLayoutBorderSpacePx.y));
writer.println(prefix + pxToDpStr("folderContentPaddingLeftRight",
folderContentPaddingLeftRight));
writer.println(prefix + pxToDpStr("folderTopPadding", folderContentPaddingTop));
@@ -1672,10 +1960,10 @@
writer.println(prefix + "\tinv.hotseatColumnSpan: " + inv.hotseatColumnSpan[mTypeIndex]);
writer.println(prefix + pxToDpStr("hotseatCellHeightPx", hotseatCellHeightPx));
writer.println(prefix + pxToDpStr("hotseatBarBottomSpacePx", hotseatBarBottomSpacePx));
- writer.println(prefix + pxToDpStr("hotseatBarSidePaddingStartPx",
- hotseatBarSidePaddingStartPx));
- writer.println(prefix + pxToDpStr("hotseatBarSidePaddingEndPx",
- hotseatBarSidePaddingEndPx));
+ writer.println(prefix + pxToDpStr("mHotseatBarEdgePaddingPx",
+ mHotseatBarEdgePaddingPx));
+ writer.println(prefix + pxToDpStr("mHotseatBarWorkspaceSpacePx",
+ mHotseatBarWorkspaceSpacePx));
writer.println(prefix + pxToDpStr("hotseatBarEndOffset", hotseatBarEndOffset));
writer.println(prefix + pxToDpStr("hotseatQsbSpace", hotseatQsbSpace));
writer.println(prefix + pxToDpStr("hotseatQsbHeight", hotseatQsbHeight));
@@ -1753,6 +2041,17 @@
getWorkspaceSpringLoadScale(context)));
writer.println(prefix + pxToDpStr("getCellLayoutHeight()", getCellLayoutHeight()));
writer.println(prefix + pxToDpStr("getCellLayoutWidth()", getCellLayoutWidth()));
+ if (mIsResponsiveGrid) {
+ writer.println(prefix + "\tmResponsiveHeightSpec:" + mResponsiveHeightSpec.toString());
+ writer.println(prefix + "\tmResponsiveWidthSpec:" + mResponsiveWidthSpec.toString());
+ writer.println(prefix + "\tmAllAppsResponsiveHeightSpec:"
+ + mAllAppsResponsiveHeightSpec.toString());
+ writer.println(prefix + "\tmAllAppsResponsiveWidthSpec:"
+ + mAllAppsResponsiveWidthSpec.toString());
+ writer.println(prefix + "\tmResponsiveFolderHeightSpec:" + mResponsiveFolderHeightSpec);
+ writer.println(prefix + "\tmResponsiveFolderWidthSpec:" + mResponsiveFolderWidthSpec);
+ writer.println(prefix + "\tmResponsiveHotseatSpec:" + mResponsiveHotseatSpec);
+ }
}
/** Returns a reduced representation of this DeviceProfile. */
@@ -1898,5 +2197,4 @@
mIsGestureMode, mViewScaleProvider, mOverrideProvider);
}
}
-
}
diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java
index addcac9..8bdf61a 100644
--- a/src/com/android/launcher3/DropTargetBar.java
+++ b/src/com/android/launcher3/DropTargetBar.java
@@ -30,7 +30,7 @@
import android.view.ViewPropertyAnimator;
import android.widget.FrameLayout;
-import com.android.launcher3.anim.Interpolators;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragController.DragListener;
import com.android.launcher3.dragndrop.DragOptions;
@@ -42,7 +42,7 @@
implements DragListener, Insettable {
protected static final int DEFAULT_DRAG_FADE_DURATION = 175;
- protected static final TimeInterpolator DEFAULT_INTERPOLATOR = Interpolators.ACCEL;
+ protected static final TimeInterpolator DEFAULT_INTERPOLATOR = Interpolators.ACCELERATE;
private final Runnable mFadeAnimationEndRunnable =
() -> updateVisibility(DropTargetBar.this);
diff --git a/src/com/android/launcher3/ExtendedEditText.java b/src/com/android/launcher3/ExtendedEditText.java
index f94a3c5..8ec5c18 100644
--- a/src/com/android/launcher3/ExtendedEditText.java
+++ b/src/com/android/launcher3/ExtendedEditText.java
@@ -21,6 +21,7 @@
import android.graphics.Rect;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.inputmethod.InputMethodManager;
@@ -37,6 +38,8 @@
* Note: AppCompatEditText doesn't fully support #displayCompletions and #onCommitCompletion
*/
public class ExtendedEditText extends EditText {
+ private static final String TAG = "ExtendedEditText";
+
private final Set<OnFocusChangeListener> mOnFocusChangeListeners = new HashSet<>();
private boolean mForceDisableSuggestions = false;
@@ -71,14 +74,9 @@
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
// If this is a back key, propagate the key back to the listener
- if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
- if (TextUtils.isEmpty(getText())) {
- hideKeyboard();
- }
- if (mBackKeyListener != null) {
- return mBackKeyListener.onBackKey();
- }
- return false;
+ if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP
+ && mBackKeyListener != null) {
+ return mBackKeyListener.onBackKey();
}
return super.onKeyPreIme(keyCode, event);
}
@@ -89,9 +87,17 @@
return false;
}
- public void showKeyboard() {
+ /**
+ * Synchronously shows the soft input method.
+ *
+ * @param shouldFocus whether this EditText should also request focus.
+ * @return true if the keyboard is shown correctly and focus is given to this view (if
+ * applicable).
+ */
+ public boolean showKeyboard(boolean shouldFocus) {
onKeyboardShown();
- showSoftInput();
+ boolean focusResult = !shouldFocus || requestFocus();
+ return focusResult && showSoftInputInternal();
}
public void hideKeyboard() {
@@ -104,10 +110,15 @@
.keyboardStateManager().setKeyboardState(SHOW);
}
- private boolean showSoftInput() {
- return requestFocus() &&
- getContext().getSystemService(InputMethodManager.class)
- .showSoftInput(this, InputMethodManager.SHOW_IMPLICIT);
+ private boolean showSoftInputInternal() {
+ boolean result = false;
+ InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
+ if (imm != null) {
+ result = imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT);
+ } else {
+ Log.w(TAG, "Failed to retrieve InputMethodManager from the system.");
+ }
+ return result;
}
public void dispatchBackKey() {
diff --git a/src/com/android/launcher3/FastScrollRecyclerView.java b/src/com/android/launcher3/FastScrollRecyclerView.java
index c16b319..67ed55d 100644
--- a/src/com/android/launcher3/FastScrollRecyclerView.java
+++ b/src/com/android/launcher3/FastScrollRecyclerView.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import static com.android.launcher3.testing.shared.TestProtocol.SCROLL_FINISHED_MESSAGE;
+
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
@@ -170,7 +172,8 @@
super.onScrollStateChanged(state);
if (state == SCROLL_STATE_IDLE) {
- AccessibilityManagerCompat.sendScrollFinishedEventToTest(getContext());
+ AccessibilityManagerCompat.sendTestProtocolEventToTest(getContext(),
+ SCROLL_FINISHED_MESSAGE);
}
}
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 03afba1..3b12b86 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -16,6 +16,12 @@
package com.android.launcher3;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
+import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_BUBBLE_ADJUSTMENT_ANIM;
+
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
@@ -27,6 +33,10 @@
import android.view.ViewGroup;
import android.widget.FrameLayout;
+import com.android.launcher3.util.HorizontalInsettableView;
+import com.android.launcher3.util.MultiTranslateDelegate;
+import com.android.launcher3.views.ActivityContext;
+
/**
* View class that represents the bottom row of the home screen.
*/
@@ -34,6 +44,7 @@
// Ratio of empty space, qsb should take up to appear visually centered.
public static final float QSB_CENTER_FACTOR = .325f;
+ private static final int BUBBLE_BAR_ADJUSTMENT_ANIMATION_DURATION_MS = 250;
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mHasVerticalHotseat;
@@ -72,9 +83,36 @@
}
public void resetLayout(boolean hasVerticalHotseat) {
+ ActivityContext activityContext = ActivityContext.lookupContext(getContext());
+ boolean bubbleBarEnabled = activityContext.isBubbleBarEnabled();
+ boolean hasBubbles = activityContext.hasBubbles();
removeAllViewsInLayout();
mHasVerticalHotseat = hasVerticalHotseat;
DeviceProfile dp = mActivity.getDeviceProfile();
+
+ if (bubbleBarEnabled) {
+ float adjustedBorderSpace = dp.getHotseatAdjustedBorderSpaceForBubbleBar(getContext());
+ if (hasBubbles && Float.compare(adjustedBorderSpace, 0f) != 0) {
+ getShortcutsAndWidgets().setTranslationProvider(child -> {
+ int index = getShortcutsAndWidgets().indexOfChild(child);
+ float borderSpaceDelta = adjustedBorderSpace - dp.hotseatBorderSpace;
+ return dp.iconSizePx + index * borderSpaceDelta;
+ });
+ if (mQsb instanceof HorizontalInsettableView) {
+ HorizontalInsettableView insettableQsb = (HorizontalInsettableView) mQsb;
+ final float insetFraction = (float) dp.iconSizePx / dp.hotseatQsbWidth;
+ // post this to the looper so that QSB has a chance to redraw itself, e.g.
+ // after device rotation
+ mQsb.post(() -> insettableQsb.setHorizontalInsets(insetFraction));
+ }
+ } else {
+ getShortcutsAndWidgets().setTranslationProvider(null);
+ if (mQsb instanceof HorizontalInsettableView) {
+ ((HorizontalInsettableView) mQsb).setHorizontalInsets(0);
+ }
+ }
+ }
+
resetCellSize(dp);
if (hasVerticalHotseat) {
setGridSize(1, dp.numShownHotseatIcons);
@@ -83,6 +121,62 @@
}
}
+ /**
+ * Adjust the hotseat icons for the bubble bar.
+ *
+ * <p>When the bubble bar becomes visible, if needed, this method animates the hotseat icons
+ * to reduce the spacing between them and make room for the bubble bar. The QSB width is
+ * animated as well to align with the hotseat icons.
+ *
+ * <p>When the bubble bar goes away, any adjustments that were previously made are reversed.
+ */
+ public void adjustForBubbleBar(boolean isBubbleBarVisible) {
+ DeviceProfile dp = mActivity.getDeviceProfile();
+ float adjustedBorderSpace = dp.getHotseatAdjustedBorderSpaceForBubbleBar(getContext());
+ if (Float.compare(adjustedBorderSpace, 0f) == 0) {
+ return;
+ }
+
+ ShortcutAndWidgetContainer icons = getShortcutsAndWidgets();
+ AnimatorSet animatorSet = new AnimatorSet();
+ float borderSpaceDelta = adjustedBorderSpace - dp.hotseatBorderSpace;
+
+ // update the translation provider for future layout passes of hotseat icons.
+ if (isBubbleBarVisible) {
+ icons.setTranslationProvider(child -> {
+ int index = icons.indexOfChild(child);
+ return dp.iconSizePx + index * borderSpaceDelta;
+ });
+ } else {
+ icons.setTranslationProvider(null);
+ }
+
+ for (int i = 0; i < icons.getChildCount(); i++) {
+ View child = icons.getChildAt(i);
+ float tx = isBubbleBarVisible ? dp.iconSizePx + i * borderSpaceDelta : 0;
+ if (child instanceof Reorderable) {
+ MultiTranslateDelegate mtd = ((Reorderable) child).getTranslateDelegate();
+ animatorSet.play(
+ mtd.getTranslationX(INDEX_BUBBLE_ADJUSTMENT_ANIM).animateToValue(tx));
+ } else {
+ animatorSet.play(ObjectAnimator.ofFloat(child, VIEW_TRANSLATE_X, tx));
+ }
+ }
+ if (mQsb instanceof HorizontalInsettableView) {
+ HorizontalInsettableView horizontalInsettableQsb = (HorizontalInsettableView) mQsb;
+ ValueAnimator qsbAnimator = ValueAnimator.ofFloat(0f, 1f);
+ qsbAnimator.addUpdateListener(animation -> {
+ float fraction = qsbAnimator.getAnimatedFraction();
+ float insetFraction = isBubbleBarVisible
+ ? (float) dp.iconSizePx * fraction / dp.hotseatQsbWidth
+ : (float) dp.iconSizePx * (1 - fraction) / dp.hotseatQsbWidth;
+ horizontalInsettableQsb.setHorizontalInsets(insetFraction);
+ });
+ animatorSet.play(qsbAnimator);
+ }
+ animatorSet.setDuration(BUBBLE_BAR_ADJUSTMENT_ANIMATION_DURATION_MS).start();
+ }
+
@Override
public void setInsets(Rect insets) {
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 376f54d..c619bc5 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.LauncherPrefs.GRID_NAME;
import static com.android.launcher3.Utilities.dpiFromPx;
-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;
@@ -50,6 +49,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.DotRenderer;
+import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.DeviceGridState;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.testing.shared.ResourceUtils;
@@ -180,6 +180,18 @@
public int devicePaddingId = INVALID_RESOURCE_HANDLE;
@XmlRes
public int workspaceSpecsId = INVALID_RESOURCE_HANDLE;
+ @XmlRes
+ public int workspaceSpecsTwoPanelId = INVALID_RESOURCE_HANDLE;
+ @XmlRes
+ public int allAppsSpecsId = INVALID_RESOURCE_HANDLE;
+ @XmlRes
+ public int allAppsSpecsTwoPanelId = INVALID_RESOURCE_HANDLE;
+ @XmlRes
+ public int folderSpecsId = INVALID_RESOURCE_HANDLE;
+ @XmlRes
+ public int folderSpecsTwoPanelId = INVALID_RESOURCE_HANDLE;
+ public int hotseatSpecsId = INVALID_RESOURCE_HANDLE;
+ public int hotseatSpecsTwoPanelId = INVALID_RESOURCE_HANDLE;
public String dbFile;
public int defaultLayoutId;
@@ -275,12 +287,13 @@
* Reinitialize the current grid after a restore, where some grids might now be disabled.
*/
public void reinitializeAfterRestore(Context context) {
+ FileLog.d(TAG, "Reinitializing grid after restore");
String currentGridName = getCurrentGridName(context);
String currentDbFile = dbFile;
String newGridName = initGrid(context, currentGridName);
String newDbFile = dbFile;
if (!newDbFile.equals(currentDbFile)) {
- Log.d(TAG, "Restored grid is disabled : " + currentGridName
+ FileLog.d(TAG, "Restored grid is disabled : " + currentGridName
+ ", migrating to: " + newGridName
+ ", removing all other grid db files");
for (String gridDbFile : LauncherFiles.GRID_DB_FILES) {
@@ -288,7 +301,7 @@
continue;
}
if (context.getDatabasePath(gridDbFile).delete()) {
- Log.d(TAG, "Removed old grid db file: " + gridDbFile);
+ FileLog.d(TAG, "Removed old grid db file: " + gridDbFile);
}
}
setCurrentGrid(context, newGridName);
@@ -302,7 +315,7 @@
int type = displayInfo.supportedBounds.stream()
.mapToInt(bounds -> displayInfo.isTablet(bounds) ? flagTablet : flagPhone)
.reduce(0, (a, b) -> a | b);
- if ((type == (flagPhone | flagTablet)) && ENABLE_TWO_PANEL_HOME.get()) {
+ if (type == (flagPhone | flagTablet)) {
// device has profiles supporting both phone and table modes
return TYPE_MULTI_DISPLAY;
} else if (type == flagTablet) {
@@ -354,6 +367,13 @@
isScalable = closestProfile.isScalable;
devicePaddingId = closestProfile.devicePaddingId;
workspaceSpecsId = closestProfile.mWorkspaceSpecsId;
+ workspaceSpecsTwoPanelId = closestProfile.mWorkspaceSpecsTwoPanelId;
+ allAppsSpecsId = closestProfile.mAllAppsSpecsId;
+ allAppsSpecsTwoPanelId = closestProfile.mAllAppsSpecsTwoPanelId;
+ folderSpecsId = closestProfile.mFolderSpecsId;
+ folderSpecsTwoPanelId = closestProfile.mFolderSpecsTwoPanelId;
+ hotseatSpecsId = closestProfile.mHotseatSpecsId;
+ hotseatSpecsTwoPanelId = closestProfile.mHotseatSpecsTwoPanelId;
this.deviceType = deviceType;
inlineNavButtonsEndSpacing = closestProfile.inlineNavButtonsEndSpacing;
@@ -800,6 +820,13 @@
private final boolean isScalable;
private final int devicePaddingId;
private final int mWorkspaceSpecsId;
+ private final int mWorkspaceSpecsTwoPanelId;
+ private final int mAllAppsSpecsId;
+ private final int mAllAppsSpecsTwoPanelId;
+ private final int mFolderSpecsId;
+ private final int mFolderSpecsTwoPanelId;
+ private final int mHotseatSpecsId;
+ private final int mHotseatSpecsTwoPanelId;
public GridOption(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(
@@ -864,8 +891,33 @@
if (FeatureFlags.ENABLE_RESPONSIVE_WORKSPACE.get()) {
mWorkspaceSpecsId = a.getResourceId(
R.styleable.GridDisplayOption_workspaceSpecsId, INVALID_RESOURCE_HANDLE);
+ mWorkspaceSpecsTwoPanelId = a.getResourceId(
+ R.styleable.GridDisplayOption_workspaceSpecsTwoPanelId,
+ INVALID_RESOURCE_HANDLE);
+ mAllAppsSpecsId = a.getResourceId(
+ R.styleable.GridDisplayOption_allAppsSpecsId, INVALID_RESOURCE_HANDLE);
+ mAllAppsSpecsTwoPanelId = a.getResourceId(
+ R.styleable.GridDisplayOption_allAppsSpecsTwoPanelId,
+ INVALID_RESOURCE_HANDLE);
+ mFolderSpecsId = a.getResourceId(
+ R.styleable.GridDisplayOption_folderSpecsId, INVALID_RESOURCE_HANDLE);
+ mFolderSpecsTwoPanelId = a.getResourceId(
+ R.styleable.GridDisplayOption_folderSpecsTwoPanelId,
+ INVALID_RESOURCE_HANDLE);
+ mHotseatSpecsId = a.getResourceId(
+ R.styleable.GridDisplayOption_hotseatSpecsId, INVALID_RESOURCE_HANDLE);
+ mHotseatSpecsTwoPanelId = a.getResourceId(
+ R.styleable.GridDisplayOption_hotseatSpecsTwoPanelId,
+ INVALID_RESOURCE_HANDLE);
} else {
mWorkspaceSpecsId = INVALID_RESOURCE_HANDLE;
+ mWorkspaceSpecsTwoPanelId = INVALID_RESOURCE_HANDLE;
+ mAllAppsSpecsId = INVALID_RESOURCE_HANDLE;
+ mAllAppsSpecsTwoPanelId = INVALID_RESOURCE_HANDLE;
+ mFolderSpecsId = INVALID_RESOURCE_HANDLE;
+ mFolderSpecsTwoPanelId = INVALID_RESOURCE_HANDLE;
+ mHotseatSpecsId = INVALID_RESOURCE_HANDLE;
+ mHotseatSpecsTwoPanelId = INVALID_RESOURCE_HANDLE;
}
int inlineForRotation = a.getInt(R.styleable.GridDisplayOption_inlineQsb,
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 6669043..b8e7737 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -21,6 +21,7 @@
import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
import static com.android.launcher3.AbstractFloatingView.TYPE_FOLDER;
import static com.android.launcher3.AbstractFloatingView.TYPE_ICON_SURFACE;
@@ -43,7 +44,6 @@
import static com.android.launcher3.LauncherState.SPRING_LOADED;
import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.getSupportedActions;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
import static com.android.launcher3.config.FeatureFlags.FOLDABLE_SINGLE_PAGE;
import static com.android.launcher3.config.FeatureFlags.MULTI_SELECT_EDIT_MODE;
import static com.android.launcher3.config.FeatureFlags.SHOW_DOT_PAGINATION;
@@ -68,6 +68,7 @@
import static com.android.launcher3.logging.StatsLogManager.StatsLatencyLogger.LatencyType.WARM;
import static com.android.launcher3.model.ItemInstallQueue.FLAG_ACTIVITY_PAUSED;
import static com.android.launcher3.model.ItemInstallQueue.FLAG_DRAG_AND_DROP;
+import static com.android.launcher3.model.data.LauncherAppWidgetInfo.CUSTOM_WIDGET_ID;
import static com.android.launcher3.popup.SystemShortcut.APP_INFO;
import static com.android.launcher3.popup.SystemShortcut.INSTALL;
import static com.android.launcher3.popup.SystemShortcut.WIDGETS;
@@ -100,7 +101,6 @@
import android.graphics.RectF;
import android.os.Build;
import android.os.Bundle;
-import android.os.CancellationSignal;
import android.os.Parcelable;
import android.os.StrictMode;
import android.os.SystemClock;
@@ -145,7 +145,9 @@
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.allapps.BaseSearchConfig;
import com.android.launcher3.allapps.DiscoveryBounce;
+import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.PropertyListBuilder;
+import com.android.launcher3.apppairs.AppPairIcon;
import com.android.launcher3.celllayout.CellPosMapper;
import com.android.launcher3.celllayout.CellPosMapper.CellPos;
import com.android.launcher3.celllayout.CellPosMapper.TwoPanelCellPosMapper;
@@ -154,7 +156,6 @@
import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
-import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.dragndrop.LauncherDragController;
import com.android.launcher3.folder.Folder;
@@ -183,7 +184,6 @@
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.pageindicators.WorkspacePageIndicator;
import com.android.launcher3.pm.PinRequestHelper;
-import com.android.launcher3.pm.UserCache;
import com.android.launcher3.popup.ArrowPopup;
import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.popup.PopupDataProvider;
@@ -196,9 +196,12 @@
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.touch.AllAppsSwipeController;
+import com.android.launcher3.touch.ItemLongClickListener;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.ActivityResultInfo;
import com.android.launcher3.util.ActivityTracker;
+import com.android.launcher3.util.BackPressHandler;
+import com.android.launcher3.util.CannedAnimationCoordinator;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
@@ -208,7 +211,6 @@
import com.android.launcher3.util.PendingRequestArgs;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.RunnableList;
-import com.android.launcher3.util.SafeCloseable;
import com.android.launcher3.util.ScreenOnTracker;
import com.android.launcher3.util.ScreenOnTracker.ScreenOnListener;
import com.android.launcher3.util.SystemUiController;
@@ -330,10 +332,7 @@
private static final FloatProperty<Hotseat> HOTSEAT_WIDGET_SCALE =
HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_WIDGET_TRANSITION);
- private static final boolean DESKTOP_MODE_1_SUPPORTED =
- "1".equals(Utilities.getSystemProperty("persist.wm.debug.desktop_mode", "0"));
-
- private static final boolean DESKTOP_MODE_2_SUPPORTED =
+ private static final boolean DESKTOP_MODE_SUPPORTED =
"1".equals(Utilities.getSystemProperty("persist.wm.debug.desktop_mode_2", "0"));
@Thunk
@@ -411,8 +410,6 @@
protected long mLastTouchUpTime = -1;
private boolean mTouchInProgress;
- private SafeCloseable mUserChangedCallbackCloseable;
-
// New InstanceId is assigned to mAllAppsSessionLogId for each AllApps sessions.
// When Launcher is not in AllApps state mAllAppsSessionLogId will be null.
// User actions within AllApps state are logged with this InstanceId, to recreate AllApps
@@ -425,6 +422,11 @@
private StartupLatencyLogger mStartupLatencyLogger;
private CellPosMapper mCellPosMapper = CellPosMapper.DEFAULT;
+ private final CannedAnimationCoordinator mAnimationCoordinator =
+ new CannedAnimationCoordinator(this);
+
+ private final List<BackPressHandler> mBackPressedHandlers = new ArrayList<>();
+
@Override
@TargetApi(Build.VERSION_CODES.S)
protected void onCreate(Bundle savedInstanceState) {
@@ -445,8 +447,7 @@
Trace.beginAsyncSection(DISPLAY_ALL_APPS_TRACE_METHOD_NAME,
DISPLAY_ALL_APPS_TRACE_COOKIE);
}
- Object traceToken = TraceHelper.INSTANCE.beginSection(ON_CREATE_EVT,
- TraceHelper.FLAG_UI_EVENT);
+ TraceHelper.INSTANCE.beginSection(ON_CREATE_EVT);
if (DEBUG_STRICT_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
@@ -580,10 +581,7 @@
LauncherOverlayPlugin.class, false /* allowedMultiple */);
mRotationHelper.initialize();
- TraceHelper.INSTANCE.endSection(traceToken);
-
- mUserChangedCallbackCloseable = UserCache.INSTANCE.get(this).addUserChangeListener(
- () -> getStateManager().goToState(NORMAL));
+ TraceHelper.INSTANCE.endSection();
if (Utilities.ATLEAST_R) {
getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
@@ -608,6 +606,7 @@
* <li> auto cancel action mode handler
* <li> drag handler
* <li> view handler
+ * <li> registered {@link BackPressHandler}
* <li> state handler
* </ol>
*
@@ -637,7 +636,14 @@
return topView;
}
- // #4 state handler
+ // #4 Custom back handlers
+ for (BackPressHandler handler : mBackPressedHandlers) {
+ if (handler.canHandleBack()) {
+ return handler;
+ }
+ }
+
+ // #5 state handler
return new OnBackAnimationCallback() {
@Override
public void onBackInvoked() {
@@ -733,18 +739,23 @@
@Override
protected void onHandleConfigurationChanged() {
- if (!initDeviceProfile(mDeviceProfile.inv)) {
- return;
+ Trace.beginSection("Launcher#onHandleconfigurationChanged");
+ try {
+ if (!initDeviceProfile(mDeviceProfile.inv)) {
+ return;
+ }
+
+ dispatchDeviceProfileChanged();
+ reapplyUi();
+ mDragLayer.recreateControllers();
+
+ // Calling onSaveInstanceState ensures that static cache used by listWidgets is
+ // initialized properly.
+ onSaveInstanceState(new Bundle());
+ mModel.rebindCallbacks();
+ } finally {
+ Trace.endSection();
}
-
- dispatchDeviceProfileChanged();
- reapplyUi();
- mDragLayer.recreateControllers();
-
- // Calling onSaveInstanceState ensures that static cache used by listWidgets is
- // initialized properly.
- onSaveInstanceState(new Bundle());
- mModel.rebindCallbacks();
}
public void onAssistantVisibilityChanged(float visibility) {
@@ -876,7 +887,7 @@
if (widgetInfo != null) {
// Since the view was just bound, also launch the configure activity if needed
LauncherAppWidgetProviderInfo provider = mAppWidgetManager
- .getLauncherAppWidgetInfo(widgetId);
+ .getLauncherAppWidgetInfo(widgetId, info.getTargetComponent());
if (provider != null) {
new WidgetAddFlowHandler(provider)
.startConfigActivity(this, widgetInfo,
@@ -1079,15 +1090,14 @@
@Override
protected void onStart() {
- Object traceToken = TraceHelper.INSTANCE.beginSection(ON_START_EVT,
- TraceHelper.FLAG_UI_EVENT);
+ TraceHelper.INSTANCE.beginSection(ON_START_EVT);
super.onStart();
if (!mDeferOverlayCallbacks) {
mOverlayManager.onActivityStarted(this);
}
mAppWidgetHolder.setActivityStarted(true);
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
}
@Override
@@ -1258,8 +1268,7 @@
@Override
protected void onResume() {
- Object traceToken = TraceHelper.INSTANCE.beginSection(ON_RESUME_EVT,
- TraceHelper.FLAG_UI_EVENT);
+ TraceHelper.INSTANCE.beginSection(ON_RESUME_EVT);
super.onResume();
if (mDeferOverlayCallbacks) {
@@ -1269,7 +1278,7 @@
}
DragView.removeAllViews(this);
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
}
@Override
@@ -1402,9 +1411,10 @@
* @param info The data structure describing the shortcut.
* @return A View inflated from layoutResId.
*/
- public View createShortcut(ViewGroup parent, WorkspaceItemInfo info) {
- BubbleTextView favorite = (BubbleTextView) LayoutInflater.from(parent.getContext())
- .inflate(R.layout.app_icon, parent, false);
+ public View createShortcut(@Nullable ViewGroup parent, WorkspaceItemInfo info) {
+ BubbleTextView favorite =
+ (BubbleTextView) LayoutInflater.from(parent != null ? parent.getContext() : this)
+ .inflate(R.layout.app_icon, parent, false);
favorite.applyFromWorkspaceItem(info);
favorite.setOnClickListener(getItemOnClickListener());
favorite.setOnFocusChangeListener(mFocusHandler);
@@ -1418,8 +1428,7 @@
*/
protected void completeAddShortcut(Intent data, int container, int screenId, int cellX,
int cellY, PendingRequestArgs args) {
- if (args.getRequestCode() != REQUEST_CREATE_SHORTCUT
- || args.getPendingIntent().getComponent() == null) {
+ if (args.getRequestCode() != REQUEST_CREATE_SHORTCUT) {
return;
}
@@ -1492,7 +1501,8 @@
AppWidgetHostView hostView, LauncherAppWidgetProviderInfo appWidgetInfo) {
if (appWidgetInfo == null) {
- appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(appWidgetId);
+ appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(appWidgetId,
+ itemInfo.getTargetComponent());
}
if (hostView == null) {
@@ -1657,7 +1667,7 @@
if (Utilities.isRunningInTestHarness()) {
Log.d(TestProtocol.PERMANENT_DIAG_TAG, "Launcher.onNewIntent: " + intent);
}
- Object traceToken = TraceHelper.INSTANCE.beginSection(ON_NEW_INTENT_EVT);
+ TraceHelper.INSTANCE.beginSection(ON_NEW_INTENT_EVT);
super.onNewIntent(intent);
boolean alreadyOnHome = hasWindowFocus() && ((intent.getFlags() &
@@ -1673,7 +1683,8 @@
if (isActionMain) {
if (!internalStateHandled) {
// In all these cases, only animate if we're already on home
- closeOpenViews(isStarted());
+ AbstractFloatingView.closeAllOpenViewsExcept(
+ this, isStarted(), AbstractFloatingView.TYPE_LISTENER);
if (!isInState(NORMAL)) {
// Only change state, if not already the same. This prevents cancelling any
@@ -1694,6 +1705,9 @@
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onHomeIntent(internalStateHandled);
}
+ if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+ handleSplitAnimationGoingToHome();
+ }
mOverlayManager.hideOverlay(isStarted() && !isForceInvisible());
handleGestureContract(intent);
} else if (Intent.ACTION_ALL_APPS.equals(intent.getAction())) {
@@ -1704,14 +1718,28 @@
showAllAppsWorkTabFromIntent(alreadyOnHome);
}
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
+ }
+
+ /** Handle animating away split placeholder view when user taps on home button */
+ protected void handleSplitAnimationGoingToHome() {
+ // Overridden
}
protected void toggleAllAppsFromIntent(boolean alreadyOnHome) {
if (getStateManager().isInStableState(ALL_APPS)) {
getStateManager().goToState(NORMAL, alreadyOnHome);
} else {
- showAllAppsFromIntent(alreadyOnHome);
+ AbstractFloatingView.closeAllOpenViews(this);
+ getStateManager().goToState(ALL_APPS, true /* animated */,
+ new AnimationSuccessListener() {
+ @Override
+ public void onAnimationSuccess(Animator animator) {
+ if (mAppsView.getSearchUiManager().getEditText() != null) {
+ mAppsView.getSearchUiManager().getEditText().requestFocus();
+ }
+ }
+ });
}
}
@@ -1808,7 +1836,6 @@
LauncherAppState.getIDP(this).removeOnChangeListener(this);
mOverlayManager.onActivityDestroyed(this);
- mUserChangedCallbackCloseable.close();
}
public LauncherAccessibilityDelegate getAccessibilityDelegate() {
@@ -1928,16 +1955,10 @@
info.spanX = spanX;
info.spanY = spanY;
- switch (info.itemType) {
- case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:
- case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
- addAppWidgetFromDrop((PendingAddWidgetInfo) info);
- break;
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
- processShortcutFromDrop((PendingAddShortcutInfo) info);
- break;
- default:
- throw new IllegalStateException("Unknown item type: " + info.itemType);
+ if (info instanceof PendingAddWidgetInfo) {
+ addAppWidgetFromDrop((PendingAddWidgetInfo) info);
+ } else { // info can only be PendingAddShortcutInfo
+ processShortcutFromDrop((PendingAddShortcutInfo) info);
}
}
@@ -1976,8 +1997,8 @@
// In this case, we either need to start an activity to get permission to bind
// the widget, or we need to start an activity to configure the widget, or both.
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET) {
- appWidgetId = CustomWidgetManager.INSTANCE.get(this).getWidgetIdForCustomProvider(
- info.componentName);
+ appWidgetId = CustomWidgetManager.INSTANCE.get(this)
+ .allocateCustomAppWidgetId(info.componentName);
} else {
appWidgetId = getAppWidgetHolder().allocateAppWidgetId();
}
@@ -2304,8 +2325,9 @@
* <p>
* Implementation of the method from LauncherModel.Callbacks.
*/
+ @Override
public void startBinding() {
- Object traceToken = TraceHelper.INSTANCE.beginSection("startBinding");
+ TraceHelper.INSTANCE.beginSection("startBinding");
// Floating panels (except the full widget sheet) are associated with individual icons. If
// we are starting a fresh bind, close all such panels as all the icons are about
// to go away.
@@ -2323,11 +2345,12 @@
if (mHotseat != null) {
mHotseat.resetLayout(getDeviceProfile().isVerticalBarLayout());
}
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
}
@Override
public void bindScreens(IntArray orderedScreenIds) {
+ mWorkspace.mPageIndicator.setAreScreensBinding(true);
int firstScreenPosition = 0;
if (FeatureFlags.QSB_ON_FIRST_SCREEN &&
orderedScreenIds.indexOf(Workspace.FIRST_SCREEN_ID) != firstScreenPosition) {
@@ -2345,13 +2368,37 @@
mWorkspace.unlockWallpaperFromDefaultPageOnNextLayout();
}
+ /**
+ * Remove odd number because they are already included when isTwoPanels and add the pair screen
+ * if not present.
+ */
+ private IntArray filterTwoPanelScreenIds(IntArray orderedScreenIds) {
+ IntSet screenIds = IntSet.wrap(orderedScreenIds);
+ orderedScreenIds.forEach(screenId -> {
+ if (screenId % 2 == 1) {
+ screenIds.remove(screenId);
+ // In case the pair is not added, add it
+ if (!mWorkspace.containsScreenId(screenId - 1)) {
+ screenIds.add(screenId - 1);
+ }
+ }
+ });
+ return screenIds.getArray();
+ }
+
private void bindAddScreens(IntArray orderedScreenIds) {
+
if (mDeviceProfile.isTwoPanels) {
- // Some empty pages might have been removed while the phone was in a single panel
- // mode, so we want to add those empty pages back.
- IntSet screenIds = IntSet.wrap(orderedScreenIds);
- orderedScreenIds.forEach(screenId -> screenIds.add(mWorkspace.getScreenPair(screenId)));
- orderedScreenIds = screenIds.getArray();
+ if (FOLDABLE_SINGLE_PAGE.get()) {
+ orderedScreenIds = filterTwoPanelScreenIds(orderedScreenIds);
+ } else {
+ // Some empty pages might have been removed while the phone was in a single panel
+ // mode, so we want to add those empty pages back.
+ IntSet screenIds = IntSet.wrap(orderedScreenIds);
+ orderedScreenIds.forEach(
+ screenId -> screenIds.add(mWorkspace.getScreenPair(screenId)));
+ orderedScreenIds = screenIds.getArray();
+ }
}
int count = orderedScreenIds.size();
@@ -2442,7 +2489,6 @@
final View view;
switch (item.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT: {
WorkspaceItemInfo info = (WorkspaceItemInfo) item;
view = createShortcut(info);
@@ -2455,9 +2501,9 @@
break;
}
case LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR: {
- FolderInfo info = (FolderInfo) item;
- // TODO (jeremysim b/274189428): Create app pair icon
- view = null;
+ view = AppPairIcon.inflateIcon(R.layout.app_pair_icon, this,
+ (ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
+ (FolderInfo) item);
break;
}
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
@@ -2577,7 +2623,7 @@
return view;
}
- Object traceToken = TraceHelper.INSTANCE.beginSection("BIND_WIDGET_id=" + item.appWidgetId);
+ TraceHelper.INSTANCE.beginSection("BIND_WIDGET_id=" + item.appWidgetId);
try {
final LauncherAppWidgetProviderInfo appWidgetInfo;
@@ -2599,9 +2645,10 @@
}
}
} else {
- appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(item.appWidgetId);
+ appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(item.appWidgetId,
+ item.getTargetComponent());
if (appWidgetInfo == null) {
- if (item.appWidgetId <= LauncherAppWidgetInfo.CUSTOM_WIDGET_ID) {
+ if (item.appWidgetId <= CUSTOM_WIDGET_ID) {
removalReason =
"CustomWidgetManager cannot find provider from that widget id.";
} else {
@@ -2707,7 +2754,7 @@
}
prepareAppWidget(view, item);
} finally {
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
}
return view;
@@ -2800,7 +2847,7 @@
* Implementation of the method from LauncherModel.Callbacks.
*/
public void finishBindingItems(IntSet pagesBoundFirst) {
- Object traceToken = TraceHelper.INSTANCE.beginSection("finishBindingItems");
+ TraceHelper.INSTANCE.beginSection("finishBindingItems");
mWorkspace.restoreInstanceStateForRemainingPages();
setWorkspaceLoading(false);
@@ -2825,9 +2872,9 @@
mDeviceProfile.inv.numFolderColumns * mDeviceProfile.inv.numFolderRows);
getViewCache().setCacheSize(R.layout.folder_page, 2);
- TraceHelper.INSTANCE.endSection(traceToken);
-
- mWorkspace.removeExtraEmptyScreen(true);
+ TraceHelper.INSTANCE.endSection();
+ mWorkspace.removeExtraEmptyScreen(/* stripEmptyScreens= */ true);
+ mWorkspace.mPageIndicator.setAreScreensBinding(false);
}
private boolean canAnimatePageChange() {
@@ -2981,9 +3028,14 @@
public void bindAllApplications(AppInfo[] apps, int flags,
Map<PackageUserKey, Integer> packageUserKeytoUidMap) {
Preconditions.assertUIThread();
- AllAppsStore appsStore = mAppsView.getAppsStore();
+ boolean hadWorkApps = mAppsView.shouldShowTabs();
+ AllAppsStore<Launcher> appsStore = mAppsView.getAppsStore();
appsStore.setApps(apps, flags, packageUserKeytoUidMap);
PopupContainerWithArrow.dismissInvalidPopup(this);
+ if (hadWorkApps != mAppsView.shouldShowTabs()) {
+ getStateManager().goToState(NORMAL);
+ }
+
if (Utilities.ATLEAST_S) {
Trace.endAsyncSection(DISPLAY_ALL_APPS_TRACE_METHOD_NAME,
DISPLAY_ALL_APPS_TRACE_COOKIE);
@@ -3055,6 +3107,7 @@
@Override
public void bindStringCache(StringCache cache) {
mStringCache = cache;
+ mAppsView.updateWorkUI();
}
@Override
@@ -3246,25 +3299,39 @@
return new TouchController[] {getDragController(), new AllAppsSwipeController(this)};
}
- public void useFadeOutAnimationForLauncherStart(CancellationSignal signal) { }
-
public void onDragLayerHierarchyChanged() {
updateDisallowBack();
}
+ protected void addBackAnimationCallback(BackPressHandler callback) {
+ mBackPressedHandlers.add(callback);
+ }
+
+ protected void removeBackAnimationCallback(BackPressHandler callback) {
+ mBackPressedHandlers.remove(callback);
+ }
+
private void updateDisallowBack() {
- if (DESKTOP_MODE_1_SUPPORTED || DESKTOP_MODE_2_SUPPORTED) {
+ if (DESKTOP_MODE_SUPPORTED) {
// Do not disable back in launcher when prototype behavior is enabled
return;
}
LauncherRootView rv = getRootView();
if (rv != null) {
+ boolean isSplitSelectionEnabled = isSplitSelectionEnabled();
boolean disableBack = getStateManager().getState() == NORMAL
- && AbstractFloatingView.getTopOpenView(this) == null;
+ && AbstractFloatingView.getTopOpenView(this) == null
+ && !isSplitSelectionEnabled;
rv.setDisallowBackGesture(disableBack);
}
}
+ /** To be overridden by subclasses */
+ protected boolean isSplitSelectionEnabled() {
+ // Overridden
+ return false;
+ }
+
@Override
public void returnToHomescreen() {
super.returnToHomescreen();
@@ -3313,10 +3380,6 @@
return false;
}
- public DragOptions getDefaultWorkspaceDragOptions() {
- return new DragOptions();
- }
-
/**
* Animates Launcher elements during a transition to the All Apps page.
*
@@ -3388,4 +3451,24 @@
public boolean areFreeformTasksVisible() {
return false; // Base launcher does not track freeform tasks
}
+
+ @Override
+ public View.OnLongClickListener getAllAppsItemLongClickListener() {
+ return ItemLongClickListener.INSTANCE_ALL_APPS;
+ }
+
+ /**
+ * Handles an app pair launch; overridden in
+ * {@link com.android.launcher3.uioverrides.QuickstepLauncher}
+ */
+ public void launchAppPair(WorkspaceItemInfo app1, WorkspaceItemInfo app2) {
+ // Overridden
+ }
+
+ /**
+ * Returns the animation coordinator for playing one-off animations
+ */
+ public CannedAnimationCoordinator getAnimationCoordinator() {
+ return mAnimationCoordinator;
+ }
}
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 4d15ac7..9db8c82 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -17,6 +17,7 @@
package com.android.launcher3;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
+import static android.content.Context.RECEIVER_EXPORTED;
import static com.android.launcher3.LauncherPrefs.ICON_STATE;
import static com.android.launcher3.LauncherPrefs.THEMED_ICONS;
@@ -26,6 +27,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.LauncherApps;
@@ -38,7 +40,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.IconShape;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.icons.IconProvider;
@@ -62,6 +63,7 @@
public static final String ACTION_FORCE_ROLOAD = "force-reload-launcher";
public static final String KEY_ICON_STATE = "pref_icon_shape_path";
+ public static final String KEY_ALL_APPS_OVERVIEW_THRESHOLD = "pref_all_apps_overview_threshold";
// We do not need any synchronization for this variable as its only written on UI thread.
public static final MainThreadInitializedObject<LauncherAppState> INSTANCE =
@@ -104,27 +106,27 @@
});
mContext.getSystemService(LauncherApps.class).registerCallback(mModel);
+ mOnTerminateCallback.add(() ->
+ mContext.getSystemService(LauncherApps.class).unregisterCallback(mModel));
SimpleBroadcastReceiver modelChangeReceiver =
new SimpleBroadcastReceiver(mModel::onBroadcastIntent);
modelChangeReceiver.register(mContext, Intent.ACTION_LOCALE_CHANGED,
- Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
- Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
- Intent.ACTION_MANAGED_PROFILE_UNLOCKED,
- Intent.ACTION_PROFILE_INACCESSIBLE,
ACTION_DEVICE_POLICY_RESOURCE_UPDATED);
- if (FeatureFlags.IS_STUDIO_BUILD) {
- modelChangeReceiver.register(mContext, ACTION_FORCE_ROLOAD);
+ if (BuildConfig.IS_STUDIO_BUILD) {
+ mContext.registerReceiver(modelChangeReceiver, new IntentFilter(ACTION_FORCE_ROLOAD),
+ RECEIVER_EXPORTED);
}
mOnTerminateCallback.add(() -> mContext.unregisterReceiver(modelChangeReceiver));
SafeCloseable userChangeListener = UserCache.INSTANCE.get(mContext)
- .addUserChangeListener(mModel::forceReload);
+ .addUserEventListener(mModel::onUserEvent);
mOnTerminateCallback.add(userChangeListener::close);
LockedUserState.get(context).runOnUserUnlocked(() -> {
- CustomWidgetManager.INSTANCE.get(mContext)
- .setWidgetRefreshCallback(mModel::refreshAndBindWidgetsAndShortcuts);
+ CustomWidgetManager cwm = CustomWidgetManager.INSTANCE.get(mContext);
+ cwm.setWidgetRefreshCallback(mModel::refreshAndBindWidgetsAndShortcuts);
+ mOnTerminateCallback.add(() -> cwm.setWidgetRefreshCallback(null));
IconObserver observer = new IconObserver();
SafeCloseable iconChangeTracker = mIconProvider.registerIconChangeListener(
@@ -159,6 +161,7 @@
mModel = new LauncherModel(context, this, mIconCache, new AppFilter(mContext),
iconCacheFileName != null);
mOnTerminateCallback.add(mIconCache::close);
+ mOnTerminateCallback.add(mModel::destroy);
}
private void onNotificationSettingsChanged(boolean areNotificationDotsEnabled) {
@@ -180,9 +183,6 @@
*/
@Override
public void close() {
- mModel.destroy();
- mContext.getSystemService(LauncherApps.class).unregisterCallback(mModel);
- CustomWidgetManager.INSTANCE.get(mContext).setWidgetRefreshCallback(null);
mOnTerminateCallback.executeAllAndDestroy();
}
diff --git a/src/com/android/launcher3/LauncherBackupAgent.java b/src/com/android/launcher3/LauncherBackupAgent.java
index 3d2700d..2617b93 100644
--- a/src/com/android/launcher3/LauncherBackupAgent.java
+++ b/src/com/android/launcher3/LauncherBackupAgent.java
@@ -34,7 +34,7 @@
// Remove old files which might contain obsolete attributes like idp_grid_name in shared
// preference that will obstruct backup's attribute from writing to shared preferences.
if (destination.delete()) {
- FileLog.d("LauncherBackupAgent", "Removed obsolete file: " + destination);
+ FileLog.d(TAG, "onRestoreFile: Removed obsolete file " + destination);
}
super.onRestoreFile(data, size, destination, type, mode, mtime);
}
@@ -47,6 +47,7 @@
@Override
public void onRestoreFinished() {
+ FileLog.d(TAG, "onRestoreFinished: set pending for RestoreDbTask");
RestoreDbTask.setPending(this);
}
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 4e066b0..fd8f668 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -20,9 +20,7 @@
import static com.android.launcher3.LauncherAppState.ACTION_FORCE_ROLOAD;
import static com.android.launcher3.config.FeatureFlags.IS_STUDIO_BUILD;
-import static com.android.launcher3.testing.shared.TestProtocol.WORK_TAB_MISSING;
import static com.android.launcher3.testing.shared.TestProtocol.sDebugTracing;
-import static com.android.launcher3.testing.shared.TestProtocol.testLogD;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -69,7 +67,6 @@
import com.android.launcher3.pm.PackageInstallInfo;
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.shortcuts.ShortcutRequest;
-import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.PackageUserKey;
@@ -95,15 +92,6 @@
static final String TAG = "Launcher.Model";
- // Broadcast intent to track when the profile gets locked:
- // ACTION_MANAGED_PROFILE_UNAVAILABLE can be used until Android U where profile no longer gets
- // locked when paused.
- // ACTION_PROFILE_INACCESSIBLE always means that the profile is getting locked but it only
- // appeared in Android S.
- private static final String ACTION_PROFILE_LOCKED = Utilities.ATLEAST_U
- ? Intent.ACTION_PROFILE_INACCESSIBLE
- : Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE;
-
@NonNull
private final LauncherAppState mApp;
@NonNull
@@ -114,6 +102,9 @@
private LoaderTask mLoaderTask;
private boolean mIsLoaderTaskRunning;
+ // only allow this once per reboot to reload work apps
+ private boolean mShouldReloadWorkProfile = true;
+
// Indicates whether the current model data is valid or not.
// We start off with everything not loaded. After that, we assume that
// our monitoring of the package manager provides all updates and we never
@@ -143,6 +134,8 @@
@NonNull
private final ModelDelegate mModelDelegate;
+ private int mLastLoadId = -1;
+
// Runnable to check if the shortcuts permission has changed.
@NonNull
private final Runnable mDataValidationCheck = new Runnable() {
@@ -301,28 +294,6 @@
if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
// If we have changed locale we need to clear out the labels in all apps/workspace.
forceReload();
- } else if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action)
- || Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action)
- || Intent.ACTION_MANAGED_PROFILE_UNLOCKED.equals(action)
- || Intent.ACTION_PROFILE_INACCESSIBLE.equals(action)) {
- UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.WORK_TAB_MISSING, "onBroadcastIntent intentAction: " + action +
- " user: " + user);
- }
- if (user != null) {
- if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action) ||
- Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action)) {
- enqueueModelUpdateTask(new PackageUpdatedTask(
- PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE, user));
- }
-
- if (ACTION_PROFILE_LOCKED.equals(action)
- || Intent.ACTION_MANAGED_PROFILE_UNLOCKED.equals(action)) {
- enqueueModelUpdateTask(new UserLockStateChangedTask(
- user, Intent.ACTION_MANAGED_PROFILE_UNLOCKED.equals(action)));
- }
- }
} else if (ACTION_DEVICE_POLICY_RESOURCE_UPDATED.equals(action)) {
enqueueModelUpdateTask(new ReloadStringCacheTask(mModelDelegate));
} else if (IS_STUDIO_BUILD && ACTION_FORCE_ROLOAD.equals(action)) {
@@ -335,6 +306,30 @@
}
/**
+ * Called then there use a user event
+ * @see UserCache#addUserEventListener
+ */
+ public void onUserEvent(UserHandle user, String action) {
+ if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action)
+ && mShouldReloadWorkProfile) {
+ mShouldReloadWorkProfile = false;
+ forceReload();
+ } else if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action)
+ || Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action)) {
+ mShouldReloadWorkProfile = false;
+ enqueueModelUpdateTask(new PackageUpdatedTask(
+ PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE, user));
+ } else if (UserCache.ACTION_PROFILE_LOCKED.equals(action)
+ || UserCache.ACTION_PROFILE_UNLOCKED.equals(action)) {
+ enqueueModelUpdateTask(new UserLockStateChangedTask(
+ user, UserCache.ACTION_PROFILE_UNLOCKED.equals(action)));
+ } else if (UserCache.ACTION_PROFILE_ADDED.equals(action)
+ || UserCache.ACTION_PROFILE_REMOVED.equals(action)) {
+ forceReload();
+ }
+ }
+
+ /**
* Reloads the workspace items from the DB and re-binds the workspace. This should generally
* not be called as DB updates are automatically followed by UI update
*/
@@ -553,6 +548,7 @@
if (mLoaderTask != task) {
throw new CancellationException("Loader already stopped");
}
+ mLastLoadId++;
mTask = task;
mIsLoaderTaskRunning = true;
mModelLoaded = false;
@@ -563,7 +559,6 @@
synchronized (mLock) {
// Everything loaded bind the data.
mModelLoaded = true;
- testLogD(WORK_TAB_MISSING, "launcher model loaded");
}
}
@@ -722,4 +717,12 @@
return mCallbacksList.toArray(new Callbacks[mCallbacksList.size()]);
}
}
+
+ /**
+ * Returns the ID for the last model load. If the load ID doesn't match for a transaction, the
+ * transaction should be ignored.
+ */
+ public int getLastLoadId() {
+ return mLastLoadId;
+ }
}
diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt
index c98df1b..36d37c7 100644
--- a/src/com/android/launcher3/LauncherPrefs.kt
+++ b/src/com/android/launcher3/LauncherPrefs.kt
@@ -275,6 +275,9 @@
const val TASKBAR_PINNING_KEY = "TASKBAR_PINNING_KEY"
@JvmField val ICON_STATE = nonRestorableItem(LauncherAppState.KEY_ICON_STATE, "", true)
+ @JvmField
+ val ALL_APPS_OVERVIEW_THRESHOLD =
+ nonRestorableItem(LauncherAppState.KEY_ALL_APPS_OVERVIEW_THRESHOLD, 180, true)
@JvmField val THEMED_ICONS = backedUpItem(Themes.KEY_THEMED_ICONS, false, true)
@JvmField val PROMISE_ICON_IDS = backedUpItem(InstallSessionHelper.PROMISE_ICON_IDS, "")
@JvmField val WORK_EDU_STEP = backedUpItem(WorkProfileManager.KEY_WORK_EDU_STEP, 0)
@@ -373,9 +376,10 @@
}
}
-// This is hard-coded to false for now until it is time to release this optimization. It is only
-// a var because the unit tests are setting this to true so they can run.
-@VisibleForTesting var isBootAwareStartupDataEnabled: Boolean = false
+// It is a var because the unit tests are setting this to true so they can run.
+@VisibleForTesting
+var isBootAwareStartupDataEnabled: Boolean =
+ com.android.launcher3.config.FeatureFlags.ENABLE_BOOT_AWARE_STARTUP_DATA.get()
private val BOOT_AWARE_ITEMS: MutableSet<ConstantItem<*>> = mutableSetOf()
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 9abec50..440e146 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -16,21 +16,18 @@
package com.android.launcher3;
-import android.annotation.TargetApi;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.ContentProvider;
-import android.content.ContentProviderOperation;
-import android.content.ContentProviderResult;
import android.content.ContentUris;
import android.content.ContentValues;
-import android.content.OperationApplicationException;
import android.database.Cursor;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.os.Binder;
-import android.os.Build;
-import android.os.Bundle;
import android.os.Process;
import android.text.TextUtils;
import android.util.Log;
@@ -38,12 +35,11 @@
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.ModelDbController;
-import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
import com.android.launcher3.widget.LauncherWidgetHolder;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.ArrayList;
+import java.util.function.ToIntFunction;
public class LauncherProvider extends ContentProvider {
private static final String TAG = "LauncherProvider";
@@ -74,10 +70,6 @@
return true;
}
- public ModelDbController getModelDbController() {
- return LauncherAppState.getInstance(getContext()).getModel().getModelDbController();
- }
-
@Override
public String getType(Uri uri) {
SqlArguments args = new SqlArguments(uri, null, null);
@@ -91,180 +83,91 @@
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
-
SqlArguments args = new SqlArguments(uri, selection, selectionArgs);
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(args.table);
- Cursor result = getModelDbController().query(
- args.table, projection, args.where, args.args, sortOrder);
- result.setNotificationUri(getContext().getContentResolver(), uri);
- return result;
- }
-
- private void reloadLauncherIfExternal() {
- if (Binder.getCallingPid() != Process.myPid()) {
- LauncherAppState app = LauncherAppState.getInstanceNoCreate();
- if (app != null) {
- app.getModel().forceReload();
- }
- }
+ Cursor[] result = new Cursor[1];
+ executeControllerTask(controller -> {
+ result[0] = controller.query(args.table, projection, args.where, args.args, sortOrder);
+ return 0;
+ });
+ return result[0];
}
@Override
- public Uri insert(Uri uri, ContentValues initialValues) {
- // In very limited cases, we support system|signature permission apps to modify the db.
- if (Binder.getCallingPid() != Process.myPid()) {
- if (!initializeExternalAdd(initialValues)) {
- return null;
- }
- }
+ public Uri insert(Uri uri, ContentValues values) {
+ int rowId = executeControllerTask(controller -> {
+ // 1. Ensure that externally added items have a valid item id
+ int id = controller.generateNewItemId();
+ values.put(LauncherSettings.Favorites._ID, id);
- SqlArguments args = new SqlArguments(uri);
- int rowId = getModelDbController().insert(args.table, initialValues);
- if (rowId < 0) return null;
+ // 2. In the case of an app widget, and if no app widget id is specified, we
+ // attempt allocate and bind the widget.
+ Integer itemType = values.getAsInteger(Favorites.ITEM_TYPE);
+ if (itemType != null
+ && itemType.intValue() == Favorites.ITEM_TYPE_APPWIDGET
+ && !values.containsKey(Favorites.APPWIDGET_ID)) {
- uri = ContentUris.withAppendedId(uri, rowId);
- reloadLauncherIfExternal();
- return uri;
- }
+ ComponentName cn = ComponentName.unflattenFromString(
+ values.getAsString(Favorites.APPWIDGET_PROVIDER));
+ if (cn == null) {
+ return 0;
+ }
- private boolean initializeExternalAdd(ContentValues values) {
- // 1. Ensure that externally added items have a valid item id
- int id = getModelDbController().generateNewItemId();
- values.put(LauncherSettings.Favorites._ID, id);
-
- // 2. In the case of an app widget, and if no app widget id is specified, we
- // attempt allocate and bind the widget.
- Integer itemType = values.getAsInteger(LauncherSettings.Favorites.ITEM_TYPE);
- if (itemType != null &&
- itemType.intValue() == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET &&
- !values.containsKey(LauncherSettings.Favorites.APPWIDGET_ID)) {
-
- final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getContext());
- ComponentName cn = ComponentName.unflattenFromString(
- values.getAsString(Favorites.APPWIDGET_PROVIDER));
-
- if (cn != null) {
LauncherWidgetHolder widgetHolder = LauncherWidgetHolder.newInstance(getContext());
try {
int appWidgetId = widgetHolder.allocateAppWidgetId();
values.put(LauncherSettings.Favorites.APPWIDGET_ID, appWidgetId);
- if (!appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,cn)) {
+ if (!AppWidgetManager.getInstance(getContext())
+ .bindAppWidgetIdIfAllowed(appWidgetId, cn)) {
widgetHolder.deleteAppWidgetId(appWidgetId);
- return false;
+ return 0;
}
} catch (RuntimeException e) {
Log.e(TAG, "Failed to initialize external widget", e);
- return false;
+ return 0;
} finally {
// Necessary to destroy the holder to free up possible activity context
widgetHolder.destroy();
}
- } else {
- return false;
}
- }
- return true;
- }
+ SqlArguments args = new SqlArguments(uri);
+ return controller.insert(args.table, values);
+ });
- @Override
- public int bulkInsert(Uri uri, ContentValues[] values) {
- SqlArguments args = new SqlArguments(uri);
- getModelDbController().bulkInsert(args.table, values);
- reloadLauncherIfExternal();
- return values.length;
- }
-
- @TargetApi(Build.VERSION_CODES.M)
- @Override
- public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
- throws OperationApplicationException {
- try (SQLiteTransaction t = getModelDbController().newTransaction()) {
- final int numOperations = operations.size();
- final ContentProviderResult[] results = new ContentProviderResult[numOperations];
- for (int i = 0; i < numOperations; i++) {
- ContentProviderOperation op = operations.get(i);
- results[i] = op.apply(this, results, i);
- }
- t.commit();
- reloadLauncherIfExternal();
- return results;
- }
+ return rowId < 0 ? null : ContentUris.withAppendedId(uri, rowId);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SqlArguments args = new SqlArguments(uri, selection, selectionArgs);
- int count = getModelDbController().delete(args.table, args.where, args.args);
- if (count > 0) {
- reloadLauncherIfExternal();
- }
- return count;
+ return executeControllerTask(c -> c.delete(args.table, args.where, args.args));
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
SqlArguments args = new SqlArguments(uri, selection, selectionArgs);
- int count = getModelDbController().update(args.table, values, args.where, args.args);
- reloadLauncherIfExternal();
- return count;
+ return executeControllerTask(c -> c.update(args.table, values, args.where, args.args));
}
- @Override
- public Bundle call(String method, final String arg, final Bundle extras) {
- if (Binder.getCallingUid() != Process.myUid()) {
- return null;
+ private int executeControllerTask(ToIntFunction<ModelDbController> task) {
+ if (Binder.getCallingPid() == Process.myPid()) {
+ throw new IllegalArgumentException("Same process should call model directly");
}
-
- switch (method) {
- case LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG: {
- getModelDbController().clearEmptyDbFlag();
- return null;
- }
- case LauncherSettings.Settings.METHOD_DELETE_EMPTY_FOLDERS: {
- Bundle result = new Bundle();
- result.putIntArray(LauncherSettings.Settings.EXTRA_VALUE,
- getModelDbController().deleteEmptyFolders().toArray());
- return result;
- }
- case LauncherSettings.Settings.METHOD_NEW_ITEM_ID: {
- Bundle result = new Bundle();
- result.putInt(LauncherSettings.Settings.EXTRA_VALUE,
- getModelDbController().generateNewItemId());
- return result;
- }
- case LauncherSettings.Settings.METHOD_NEW_SCREEN_ID: {
- Bundle result = new Bundle();
- result.putInt(LauncherSettings.Settings.EXTRA_VALUE,
- getModelDbController().getNewScreenId());
- return result;
- }
- case LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB: {
- getModelDbController().createEmptyDB();
- return null;
- }
- case LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES: {
- getModelDbController().loadDefaultFavoritesIfNecessary();
- return null;
- }
- case LauncherSettings.Settings.METHOD_REMOVE_GHOST_WIDGETS: {
- getModelDbController().removeGhostWidgets();
- return null;
- }
- case LauncherSettings.Settings.METHOD_NEW_TRANSACTION: {
- Bundle result = new Bundle();
- result.putBinder(LauncherSettings.Settings.EXTRA_VALUE,
- getModelDbController().newTransaction());
- return result;
- }
- case LauncherSettings.Settings.METHOD_REFRESH_HOTSEAT_RESTORE_TABLE: {
- getModelDbController().refreshHotseatRestoreTable();
- return null;
- }
+ try {
+ return MODEL_EXECUTOR.submit(() -> {
+ LauncherModel model = LauncherAppState.getInstance(getContext()).getModel();
+ int count = task.applyAsInt(model.getModelDbController());
+ if (count > 0) {
+ MAIN_EXECUTOR.submit(model::forceReload);
+ }
+ return count;
+ }).get();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
}
- return null;
}
static class SqlArguments {
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 7fda326..105d5f3 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -16,10 +16,7 @@
package com.android.launcher3;
-import android.content.ContentResolver;
import android.database.sqlite.SQLiteDatabase;
-import android.net.Uri;
-import android.os.Bundle;
import android.provider.BaseColumns;
import com.android.launcher3.model.data.ItemInfo;
@@ -89,7 +86,9 @@
/**
* The gesture is an application created shortcut
+ * @deprecated This is no longer supported. Use {@link #ITEM_TYPE_DEEP_SHORTCUT} instead
*/
+ @Deprecated
public static final int ITEM_TYPE_SHORTCUT = 1;
/**
@@ -153,24 +152,6 @@
public static final String TMP_TABLE = "favorites_tmp";
/**
- * The content:// style URL for "favorites" table
- */
- public static final Uri CONTENT_URI = Uri.parse("content://"
- + LauncherProvider.AUTHORITY + "/" + TABLE_NAME);
-
- /**
- * The content:// style URL for a given row, identified by its id.
- *
- * @param id The row id.
- *
- * @return The unique content URL for the specified row.
- */
- public static Uri getContentUri(int id) {
- return Uri.parse("content://" + LauncherProvider.AUTHORITY
- + "/" + TABLE_NAME + "/" + id);
- }
-
- /**
* The container holding the favorite
* <P>Type: INTEGER</P>
*/
@@ -213,7 +194,6 @@
public static final String itemTypeToString(int type) {
switch(type) {
case ITEM_TYPE_APPLICATION: return "APP";
- case ITEM_TYPE_SHORTCUT: return "SHORTCUT";
case ITEM_TYPE_FOLDER: return "FOLDER";
case ITEM_TYPE_APPWIDGET: return "WIDGET";
case ITEM_TYPE_CUSTOM_APPWIDGET: return "CUSTOMWIDGET";
@@ -338,42 +318,8 @@
* Launcher settings
*/
public static final class Settings {
-
- public static final Uri CONTENT_URI = Uri.parse("content://" +
- LauncherProvider.AUTHORITY + "/settings");
-
- public static final String METHOD_CLEAR_EMPTY_DB_FLAG = "clear_empty_db_flag";
-
- public static final String METHOD_DELETE_EMPTY_FOLDERS = "delete_empty_folders";
-
- public static final String METHOD_NEW_ITEM_ID = "generate_new_item_id";
- public static final String METHOD_NEW_SCREEN_ID = "generate_new_screen_id";
-
- public static final String METHOD_CREATE_EMPTY_DB = "create_empty_db";
-
- public static final String METHOD_LOAD_DEFAULT_FAVORITES = "load_default_favorites";
-
- public static final String METHOD_REMOVE_GHOST_WIDGETS = "remove_ghost_widgets";
-
- public static final String METHOD_NEW_TRANSACTION = "new_db_transaction";
-
- public static final String METHOD_REFRESH_HOTSEAT_RESTORE_TABLE = "restore_hotseat_table";
-
- public static final String EXTRA_VALUE = "value";
-
- public static final String EXTRA_DB_NAME = "db_name";
-
public static final String LAYOUT_DIGEST_KEY = "launcher3.layout.provider.blob";
public static final String LAYOUT_DIGEST_LABEL = "launcher-layout";
public static final String LAYOUT_DIGEST_TAG = "ignore";
-
- public static Bundle call(ContentResolver cr, String method) {
- return call(cr, method, null /* arg */);
- }
-
- public static Bundle call(ContentResolver cr, String method, String arg) {
- return cr.call(CONTENT_URI, method, arg, null);
- }
-
}
}
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 6097fb1..d2ea7cc 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -15,8 +15,8 @@
*/
package com.android.launcher3;
-import static com.android.launcher3.anim.Interpolators.ACCEL_2;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.app.animation.Interpolators.ACCELERATE_2;
+import static com.android.app.animation.Interpolators.DECELERATE_2;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
import static com.android.launcher3.testing.shared.TestProtocol.ALL_APPS_STATE_ORDINAL;
@@ -33,6 +33,7 @@
import android.content.Context;
import android.graphics.Color;
+import android.view.View;
import android.view.animation.Interpolator;
import androidx.annotation.FloatRange;
@@ -66,6 +67,7 @@
public static final int CLEAR_ALL_BUTTON = 1 << 4;
public static final int WORKSPACE_PAGE_INDICATOR = 1 << 5;
public static final int SPLIT_PLACHOLDER_VIEW = 1 << 6;
+ public static final int FLOATING_SEARCH_BAR = 1 << 7;
// Flag indicating workspace has multiple pages visible.
public static final int FLAG_MULTI_PAGE = BaseState.getFlag(0);
@@ -90,7 +92,7 @@
public static final float NO_SCALE = 1;
protected static final PageAlphaProvider DEFAULT_ALPHA_PROVIDER =
- new PageAlphaProvider(ACCEL_2) {
+ new PageAlphaProvider(ACCELERATE_2) {
@Override
public float getPageAlpha(int pageIndex) {
return 1;
@@ -98,7 +100,7 @@
};
protected static final PageTranslationProvider DEFAULT_PAGE_TRANSLATION_PROVIDER =
- new PageTranslationProvider(DEACCEL_2) {
+ new PageTranslationProvider(DECELERATE_2) {
@Override
public float getPageTranslation(int pageIndex) {
return 0;
@@ -202,8 +204,61 @@
return 0;
}
+ /**
+ * How far from the bottom of the screen the <em>floating</em> search bar should rest in this
+ * state when the IME is not present.
+ * <p>
+ * To hide offscreen, use a negative value.
+ * <p>
+ * Note: if the provided value is non-negative but less than the current bottom insets, the
+ * insets will be applied. As such, you can use 0 to default to this.
+ */
+ public int getFloatingSearchBarRestingMarginBottom(Launcher launcher) {
+ DeviceProfile dp = launcher.getDeviceProfile();
+ return areElementsVisible(launcher, FLOATING_SEARCH_BAR) ? dp.getQsbOffsetY()
+ : -dp.hotseatQsbHeight;
+ }
+
+ /**
+ * How far from the start of the screen the <em>floating</em> search bar should rest.
+ * <p>
+ * To use original margin, return a negative value.
+ */
+ public int getFloatingSearchBarRestingMarginStart(Launcher launcher) {
+ boolean isRtl = Utilities.isRtl(launcher.getResources());
+ View qsb = launcher.getHotseat().getQsb();
+ return isRtl ? launcher.getHotseat().getRight() - qsb.getRight() : qsb.getLeft();
+ }
+
+ /**
+ * How far from the end of the screen the <em>floating</em> search bar should rest.
+ * <p>
+ * To use original margin, return a negative value.
+ */
+ public int getFloatingSearchBarRestingMarginEnd(Launcher launcher) {
+ DeviceProfile dp = launcher.getDeviceProfile();
+ if (dp.isQsbInline) {
+ int marginStart = getFloatingSearchBarRestingMarginStart(launcher);
+ return dp.widthPx - marginStart - dp.hotseatQsbWidth;
+ }
+
+ boolean isRtl = Utilities.isRtl(launcher.getResources());
+ View qsb = launcher.getHotseat().getQsb();
+ return isRtl ? qsb.getLeft() : launcher.getHotseat().getRight() - qsb.getRight();
+ }
+
+ /** Whether the <em>floating</em> search bar should use the pill UI when not focused. */
+ public boolean shouldFloatingSearchBarUsePillWhenUnfocused(Launcher launcher) {
+ return false;
+ }
+
public int getVisibleElements(Launcher launcher) {
- return HOTSEAT_ICONS | WORKSPACE_PAGE_INDICATOR | VERTICAL_SWIPE_INDICATOR;
+ int elements = HOTSEAT_ICONS | WORKSPACE_PAGE_INDICATOR | VERTICAL_SWIPE_INDICATOR;
+ // Floating search bar is visible in normal state except in landscape on phones.
+ if (!(launcher.getDeviceProfile().isPhone && launcher.getDeviceProfile().isLandscape)) {
+ elements |= FLOATING_SEARCH_BAR;
+ }
+ return elements;
}
/**
@@ -319,7 +374,7 @@
return DEFAULT_ALPHA_PROVIDER;
}
final int centerPage = launcher.getWorkspace().getNextPage();
- return new PageAlphaProvider(ACCEL_2) {
+ return new PageAlphaProvider(ACCELERATE_2) {
@Override
public float getPageAlpha(int pageIndex) {
return pageIndex != centerPage ? 0 : 1f;
@@ -336,7 +391,7 @@
return DEFAULT_PAGE_TRANSLATION_PROVIDER;
}
final float quarterPageSpacing = launcher.getWorkspace().getPageSpacing() / 4f;
- return new PageTranslationProvider(DEACCEL_2) {
+ return new PageTranslationProvider(DECELERATE_2) {
@Override
public float getPageTranslation(int pageIndex) {
boolean isRtl = launcher.getWorkspace().mIsRtl;
diff --git a/src/com/android/launcher3/MotionEventsUtils.java b/src/com/android/launcher3/MotionEventsUtils.java
index 40de003..3228ec6 100644
--- a/src/com/android/launcher3/MotionEventsUtils.java
+++ b/src/com/android/launcher3/MotionEventsUtils.java
@@ -30,6 +30,9 @@
/** {@link MotionEvent#CLASSIFICATION_MULTI_FINGER_SWIPE} is hidden. */
public static final int CLASSIFICATION_MULTI_FINGER_SWIPE = 4;
+ /** {@link MotionEvent#AXIS_GESTURE_SWIPE_FINGER_COUNT} is hidden. */
+ private static final int AXIS_GESTURE_SWIPE_FINGER_COUNT = 53;
+
@TargetApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public static boolean isTrackpadScroll(MotionEvent event) {
return ENABLE_TRACKPAD_GESTURE.get()
@@ -43,11 +46,13 @@
}
public static boolean isTrackpadThreeFingerSwipe(MotionEvent event) {
- return isTrackpadMultiFingerSwipe(event) && event.getPointerCount() == 3;
+ return isTrackpadMultiFingerSwipe(event) && event.getAxisValue(
+ AXIS_GESTURE_SWIPE_FINGER_COUNT) == 3;
}
public static boolean isTrackpadFourFingerSwipe(MotionEvent event) {
- return isTrackpadMultiFingerSwipe(event) && event.getPointerCount() == 4;
+ return isTrackpadMultiFingerSwipe(event) && event.getAxisValue(
+ AXIS_GESTURE_SWIPE_FINGER_COUNT) == 4;
}
public static boolean isTrackpadMotionEvent(MotionEvent event) {
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index af64b3b..5ce88a3 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -16,9 +16,10 @@
package com.android.launcher3;
-import static com.android.launcher3.anim.Interpolators.SCROLL;
+import static com.android.app.animation.Interpolators.SCROLL;
import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessibilityEnabled;
import static com.android.launcher3.compat.AccessibilityManagerCompat.isObservedEventType;
+import static com.android.launcher3.testing.shared.TestProtocol.SCROLL_FINISHED_MESSAGE;
import static com.android.launcher3.touch.OverScroll.OVERSCROLL_DAMP_FACTOR;
import static com.android.launcher3.touch.PagedOrientationHandler.VIEW_SCROLL_BY;
import static com.android.launcher3.touch.PagedOrientationHandler.VIEW_SCROLL_TO;
@@ -492,7 +493,8 @@
*/
protected void onPageEndTransition() {
mCurrentPageScrollDiff = 0;
- AccessibilityManagerCompat.sendScrollFinishedEventToTest(getContext());
+ AccessibilityManagerCompat.sendTestProtocolEventToTest(getContext(),
+ SCROLL_FINISHED_MESSAGE);
AccessibilityManagerCompat.sendCustomAccessibilityEvent(getPageAt(mCurrentPage),
AccessibilityEvent.TYPE_VIEW_FOCUSED, null);
if (mOnPageTransitionEndCallback != null) {
diff --git a/src/com/android/launcher3/SessionCommitReceiver.java b/src/com/android/launcher3/SessionCommitReceiver.java
index aaccb7d..d460ba8 100644
--- a/src/com/android/launcher3/SessionCommitReceiver.java
+++ b/src/com/android/launcher3/SessionCommitReceiver.java
@@ -32,6 +32,8 @@
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.util.Executors;
+import java.util.Locale;
+
/**
* BroadcastReceiver to handle session commit intent.
*/
@@ -63,9 +65,20 @@
}
InstallSessionHelper packageInstallerCompat = InstallSessionHelper.INSTANCE.get(context);
+ boolean alreadyAddedPromiseIcon =
+ packageInstallerCompat.promiseIconAddedForId(info.getSessionId());
if (TextUtils.isEmpty(info.getAppPackageName())
|| info.getInstallReason() != PackageManager.INSTALL_REASON_USER
- || packageInstallerCompat.promiseIconAddedForId(info.getSessionId())) {
+ || alreadyAddedPromiseIcon) {
+ FileLog.d(LOG,
+ String.format(Locale.ENGLISH,
+ "Removing PromiseIcon for package: %s, install reason: %d,"
+ + " alreadyAddedPromiseIcon: %s",
+ info.getAppPackageName(),
+ info.getInstallReason(),
+ alreadyAddedPromiseIcon
+ )
+ );
packageInstallerCompat.removePromiseIconId(info.getSessionId());
return;
}
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index a0ceefb..b22b690 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -21,6 +21,7 @@
import static com.android.launcher3.CellLayout.FOLDER;
import static com.android.launcher3.CellLayout.HOTSEAT;
import static com.android.launcher3.CellLayout.WORKSPACE;
+import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_BUBBLE_ADJUSTMENT_ANIM;
import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_WIDGET_CENTERING;
import android.app.WallpaperManager;
@@ -28,15 +29,19 @@
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
+import android.os.Trace;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.CellLayout.ContainerType;
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.launcher3.widget.NavigableAppWidgetHostView;
public class ShortcutAndWidgetContainer extends ViewGroup implements FolderIcon.FolderIconParent {
@@ -60,11 +65,15 @@
private final ActivityContext mActivity;
private boolean mInvertIfRtl = false;
+ @Nullable
+ private TranslationProvider mTranslationProvider = null;
+
public ShortcutAndWidgetContainer(Context context, @ContainerType int containerType) {
super(context);
mActivity = ActivityContext.lookupContext(context);
mWallpaperManager = WallpaperManager.getInstance(context);
mContainerType = containerType;
+ setClipChildren(false);
}
public void setCellDimensions(int cellWidth, int cellHeight, int countX, int countY,
@@ -154,14 +163,15 @@
mBorderSpace);
// Center the icon/folder
int cHeight = getCellContentHeight();
- int cellPaddingY = dp.isScalableGrid && mContainerType == WORKSPACE
- ? dp.cellYPaddingPx
- : (int) Math.max(0, ((lp.height - cHeight) / 2f));
+ int cellPaddingY =
+ dp.cellYPaddingPx >= 0 && mContainerType == WORKSPACE
+ ? dp.cellYPaddingPx
+ : (int) Math.max(0, ((lp.height - cHeight) / 2f));
// No need to add padding when cell layout border spacing is present.
boolean noPaddingX =
(dp.cellLayoutBorderSpacePx.x > 0 && mContainerType == WORKSPACE)
- || (dp.folderCellLayoutBorderSpacePx > 0 && mContainerType == FOLDER)
+ || (dp.folderCellLayoutBorderSpacePx.x > 0 && mContainerType == FOLDER)
|| (dp.hotseatBorderSpace > 0 && mContainerType == HOTSEAT);
int cellPaddingX = noPaddingX
? 0
@@ -181,6 +191,7 @@
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ Trace.beginSection("ShortcutAndWidgetConteiner#onLayout");
int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
@@ -188,6 +199,7 @@
layoutChild(child);
}
}
+ Trace.endSection();
}
/**
@@ -212,7 +224,27 @@
int childLeft = lp.x;
int childTop = lp.y;
+
+ // We want to get the layout position of the widget, but layout() is a final function in
+ // ViewGroup which makes it impossible to be overridden. Overriding onLayout() will have no
+ // effect since it will not be called when the transition is enabled. The only possible
+ // solution here seems to be sending the positions when CellLayout is laying out the views
+ if (child instanceof LauncherAppWidgetHostView widgetView
+ && widgetView.getCellChildViewPreLayoutListener() != null) {
+ widgetView.getCellChildViewPreLayoutListener().notifyBoundChangeOnPreLayout(child,
+ childLeft, childTop, childLeft + lp.width, childTop + lp.height);
+ }
child.layout(childLeft, childTop, childLeft + lp.width, childTop + lp.height);
+ if (mTranslationProvider != null) {
+ final float tx = mTranslationProvider.getTranslationX(child);
+ if (child instanceof Reorderable) {
+ ((Reorderable) child).getTranslateDelegate()
+ .getTranslationX(INDEX_BUBBLE_ADJUSTMENT_ANIM)
+ .setValue(tx);
+ } else {
+ child.setTranslationX(tx);
+ }
+ }
if (lp.dropped) {
lp.dropped = false;
@@ -282,4 +314,13 @@
cl.clearFolderLeaveBehind();
}
}
+
+ void setTranslationProvider(@Nullable TranslationProvider provider) {
+ mTranslationProvider = provider;
+ }
+
+ /** Provides translation values to apply when laying out child views. */
+ interface TranslationProvider {
+ float getTranslationX(View child);
+ }
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 709c57c..7b27a71 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -16,14 +16,16 @@
package com.android.launcher3;
+import static android.graphics.drawable.AdaptiveIconDrawable.getExtraInsetFraction;
+
import static com.android.launcher3.icons.BitmapInfo.FLAG_THEMED;
-import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_ICON_BADGED;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN;
-import android.annotation.TargetApi;
+import android.annotation.SuppressLint;
import android.app.ActivityManager;
+import android.app.ActivityOptions;
import android.app.Person;
import android.app.WallpaperManager;
import android.content.Context;
@@ -32,6 +34,9 @@
import android.content.pm.ShortcutInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BlendMode;
+import android.graphics.BlendModeColorFilter;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.LightingColorFilter;
@@ -42,8 +47,10 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.DeadObjectException;
@@ -58,6 +65,7 @@
import android.text.style.TtsSpan;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.Pair;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
@@ -67,10 +75,13 @@
import androidx.annotation.ChecksSdkIntAtLeast;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
import androidx.core.graphics.ColorUtils;
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
import com.android.launcher3.graphics.TintedDrawableSpan;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.icons.ShortcutCachingLogic;
import com.android.launcher3.icons.ThemedIconDrawable;
import com.android.launcher3.model.data.ItemInfo;
@@ -333,14 +344,12 @@
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);
+ float cx = r.exactCenterX();
+ float cy = r.exactCenterY();
+ r.left = Math.round(cx + (r.left - cx) * scale);
+ r.top = Math.round(cy + (r.top - cy) * scale);
+ r.right = Math.round(cx + (r.right - cx) * scale);
+ r.bottom = Math.round(cy + (r.bottom - cy) * scale);
}
}
@@ -561,100 +570,123 @@
}
/**
- * Returns the full drawable for info without any flattening or pre-processing.
- *
- * @param shouldThemeIcon If true, will theme icons when applicable
- * @param outObj this is set to the internal data associated with {@code info},
- * eg {@link LauncherActivityInfo} or {@link ShortcutInfo}.
+ * Utility method to allow background activity launch for the provided activity options
*/
- @TargetApi(Build.VERSION_CODES.TIRAMISU)
- public static Drawable getFullDrawable(Context context, ItemInfo info, int width, int height,
- boolean shouldThemeIcon, Object[] outObj) {
- Drawable icon = loadFullDrawableWithoutTheme(context, info, width, height, outObj);
- if (ATLEAST_T && icon instanceof AdaptiveIconDrawable && shouldThemeIcon) {
- AdaptiveIconDrawable aid = (AdaptiveIconDrawable) icon.mutate();
- Drawable mono = aid.getMonochrome();
- if (mono != null && Themes.isThemedIconEnabled(context)) {
- int[] colors = ThemedIconDrawable.getColors(context);
- mono = mono.mutate();
- mono.setTint(colors[1]);
- return new AdaptiveIconDrawable(new ColorDrawable(colors[0]), mono);
- }
+ public static ActivityOptions allowBGLaunch(ActivityOptions options) {
+ if (ATLEAST_U) {
+ options.setPendingIntentBackgroundActivityStartMode(
+ ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
}
- return icon;
- }
-
- private static Drawable loadFullDrawableWithoutTheme(Context context, ItemInfo info,
- int width, int height, Object[] outObj) {
- ActivityContext activity = ActivityContext.lookupContext(context);
- LauncherAppState appState = LauncherAppState.getInstance(context);
- if (info instanceof PendingAddShortcutInfo) {
- ShortcutConfigActivityInfo activityInfo =
- ((PendingAddShortcutInfo) info).getActivityInfo(context);
- outObj[0] = activityInfo;
- return activityInfo.getFullResIcon(appState.getIconCache());
- }
- if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
- LauncherActivityInfo activityInfo = context.getSystemService(LauncherApps.class)
- .resolveActivity(info.getIntent(), info.user);
- outObj[0] = activityInfo;
- return activityInfo == null ? null : LauncherAppState.getInstance(context)
- .getIconProvider().getIcon(
- activityInfo, activity.getDeviceProfile().inv.fillResIconDpi);
- } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
- List<ShortcutInfo> si = ShortcutKey.fromItemInfo(info)
- .buildRequest(context)
- .query(ShortcutRequest.ALL);
- if (si.isEmpty()) {
- return null;
- } else {
- outObj[0] = si.get(0);
- return ShortcutCachingLogic.getIcon(context, si.get(0),
- appState.getInvariantDeviceProfile().fillResIconDpi);
- }
- } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
- FolderAdaptiveIcon icon = FolderAdaptiveIcon.createFolderAdaptiveIcon(
- activity, info.id, new Point(width, height));
- if (icon == null) {
- return null;
- }
- outObj[0] = icon;
- return icon;
- } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SEARCH_ACTION
- && info instanceof ItemInfoWithIcon) {
- return ((ItemInfoWithIcon) info).bitmap.newIcon(context);
- } else {
- return null;
- }
+ return options;
}
/**
- * For apps icons and shortcut icons that have badges, this method creates a drawable that can
- * later on be rendered on top of the layers for the badges. For app icons, work profile badges
- * can only be applied. For deep shortcuts, when dragged from the pop up container, there's no
- * badge. When dragged from workspace or folder, it may contain app AND/OR work profile badge
- **/
- @TargetApi(Build.VERSION_CODES.O)
- public static Drawable getBadge(Context context, ItemInfo info, Object obj) {
+ * Returns the full drawable for info as multiple layers of AdaptiveIconDrawable. The second
+ * drawable in the Pair is the badge used with the icon.
+ *
+ * @param useTheme If true, will theme icons when applicable
+ */
+ @SuppressLint("UseCompatLoadingForDrawables")
+ @Nullable
+ @WorkerThread
+ public static <T extends Context & ActivityContext> Pair<AdaptiveIconDrawable, Drawable>
+ getFullDrawable(T context, ItemInfo info, int width, int height, boolean useTheme) {
+ useTheme &= Themes.isThemedIconEnabled(context);
LauncherAppState appState = LauncherAppState.getInstance(context);
- if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
- boolean iconBadged = (info instanceof ItemInfoWithIcon)
- && (((ItemInfoWithIcon) info).runtimeStatusFlags & FLAG_ICON_BADGED) > 0;
- if ((info.id == ItemInfo.NO_ID && !iconBadged)
- || !(obj instanceof ShortcutInfo)) {
- // The item is not yet added on home screen.
- return new ColorDrawable(Color.TRANSPARENT);
- }
- ShortcutInfo si = (ShortcutInfo) obj;
- return LauncherAppState.getInstance(appState.getContext())
- .getIconCache().getShortcutInfoBadge(si).newIcon(context, FLAG_THEMED);
- } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
- return ((FolderAdaptiveIcon) obj).getBadge();
- } else {
- return Process.myUserHandle().equals(info.user)
- ? new ColorDrawable(Color.TRANSPARENT)
- : context.getDrawable(R.drawable.ic_work_app_badge);
+ Drawable mainIcon = null;
+
+ Drawable badge = null;
+ if ((info instanceof ItemInfoWithIcon iiwi) && !iiwi.usingLowResIcon()) {
+ badge = iiwi.bitmap.getBadgeDrawable(context, useTheme);
}
+
+ if (info instanceof PendingAddShortcutInfo) {
+ ShortcutConfigActivityInfo activityInfo =
+ ((PendingAddShortcutInfo) info).getActivityInfo(context);
+ mainIcon = activityInfo.getFullResIcon(appState.getIconCache());
+ } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+ LauncherActivityInfo activityInfo = context.getSystemService(LauncherApps.class)
+ .resolveActivity(info.getIntent(), info.user);
+ if (activityInfo == null) {
+ return null;
+ }
+ mainIcon = appState.getIconProvider().getIcon(
+ activityInfo, appState.getInvariantDeviceProfile().fillResIconDpi);
+ } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+ List<ShortcutInfo> siList = ShortcutKey.fromItemInfo(info)
+ .buildRequest(context)
+ .query(ShortcutRequest.ALL);
+ if (siList.isEmpty()) {
+ return null;
+ } else {
+ ShortcutInfo si = siList.get(0);
+ mainIcon = ShortcutCachingLogic.getIcon(context, si,
+ appState.getInvariantDeviceProfile().fillResIconDpi);
+ // Only fetch badge if the icon is on workspace
+ if (info.id != ItemInfo.NO_ID && badge == null) {
+ badge = appState.getIconCache().getShortcutInfoBadge(si)
+ .newIcon(context, FLAG_THEMED);
+ }
+ }
+ } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
+ FolderAdaptiveIcon icon = FolderAdaptiveIcon.createFolderAdaptiveIcon(
+ context, info.id, new Point(width, height));
+ if (icon == null) {
+ return null;
+ }
+ mainIcon = icon;
+ badge = icon.getBadge();
+ }
+
+ if (mainIcon == null) {
+ return null;
+ }
+ AdaptiveIconDrawable result;
+ if (mainIcon instanceof AdaptiveIconDrawable aid) {
+ result = aid;
+ } else {
+ // Wrap the main icon in AID
+ try (LauncherIcons li = LauncherIcons.obtain(context)) {
+ result = li.wrapToAdaptiveIcon(mainIcon);
+ }
+ }
+ if (result == null) {
+ return null;
+ }
+
+ // Inject monochrome icon drawable
+ if (ATLEAST_T && useTheme) {
+ result.mutate();
+ int[] colors = ThemedIconDrawable.getColors(context);
+ Drawable mono = result.getMonochrome();
+
+ if (mono != null) {
+ mono.setTint(colors[1]);
+ } else if (info instanceof ItemInfoWithIcon iiwi) {
+ // Inject a previously generated monochrome icon
+ Bitmap monoBitmap = iiwi.bitmap.getMono();
+ if (monoBitmap != null) {
+ // Use BitmapDrawable instead of FastBitmapDrawable so that the colorState is
+ // preserved in constantState
+ mono = new BitmapDrawable(monoBitmap);
+ mono.setColorFilter(new BlendModeColorFilter(colors[1], BlendMode.SRC_IN));
+ // Inset the drawable according to the AdaptiveIconDrawable layers
+ mono = new InsetDrawable(mono, getExtraInsetFraction() / 2);
+ }
+ }
+ if (mono != null) {
+ result = new AdaptiveIconDrawable(new ColorDrawable(colors[0]), mono);
+ }
+ }
+
+ if (badge == null) {
+ badge = Process.myUserHandle().equals(info.user)
+ ? new ColorDrawable(Color.TRANSPARENT)
+ : context.getDrawable(useTheme
+ ? R.drawable.ic_work_app_badge_themed
+ : R.drawable.ic_work_app_badge);
+ }
+ return Pair.create(result, badge);
}
public static float squaredHypot(float x, float y) {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 73bb828..a1a3974 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -67,9 +67,9 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
import com.android.launcher3.celllayout.CellPosMapper;
@@ -562,9 +562,9 @@
// Change the interpolators such that the fade animation plays before the move animation.
// This prevents empty adjacent pages to overlay during animation
mLayoutTransition.setInterpolator(LayoutTransition.DISAPPEARING,
- Interpolators.clampToProgress(Interpolators.ACCEL_DEACCEL, 0, 0.5f));
+ Interpolators.clampToProgress(Interpolators.ACCELERATE_DECELERATE, 0, 0.5f));
mLayoutTransition.setInterpolator(LayoutTransition.CHANGE_DISAPPEARING,
- Interpolators.clampToProgress(Interpolators.ACCEL_DEACCEL, 0.5f, 1));
+ Interpolators.clampToProgress(Interpolators.ACCELERATE_DECELERATE, 0.5f, 1));
mLayoutTransition.disableTransitionType(LayoutTransition.APPEARING);
mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
@@ -731,6 +731,14 @@
});
}
+
+ /**
+ * Returns if the given screenId is already in the Workspace
+ */
+ public boolean containsScreenId(int screenId) {
+ return this.mWorkspaceScreens.containsKey(screenId);
+ }
+
/**
* Inserts extra empty pages to the end of the existing workspaces.
* Usually we add one extra empty screen, but when two panel home is enabled we add
@@ -897,9 +905,8 @@
mWorkspaceScreens.remove(emptyScreenId);
mScreenOrder.removeValue(emptyScreenId);
- int newScreenId = LauncherSettings.Settings.call(getContext().getContentResolver(),
- LauncherSettings.Settings.METHOD_NEW_SCREEN_ID)
- .getInt(LauncherSettings.Settings.EXTRA_VALUE);
+ int newScreenId = LauncherAppState.getInstance(getContext())
+ .getModel().getModelDbController().getNewScreenId();
// Launcher database isn't aware of empty pages that are already bound, so we need to
// skip those IDs manually.
while (mWorkspaceScreens.containsKey(newScreenId)) {
@@ -1840,7 +1847,6 @@
!= LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION);
boolean willBecomeShortcut =
(info.itemType == ITEM_TYPE_APPLICATION ||
- info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT ||
info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT);
return (aboveShortcut && willBecomeShortcut);
@@ -2759,7 +2765,7 @@
final PendingAddItemInfo pendingInfo = (PendingAddItemInfo) info;
boolean findNearestVacantCell = true;
- if (pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
+ if (pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
mTargetCell = findNearestArea(touchXY[0], touchXY[1], spanX, spanY,
cellLayout, mTargetCell);
float distance = cellLayout.getDistanceFromWorkspaceCellVisualCenter(
@@ -2832,8 +2838,7 @@
View view;
switch (info.itemType) {
- case ITEM_TYPE_APPLICATION:
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_SEARCH_ACTION:
if (info instanceof WorkspaceItemFactory) {
@@ -3408,7 +3413,8 @@
if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
widgetInfo = widgetHelper.findProvider(item.providerName, item.user);
} else {
- widgetInfo = widgetHelper.getLauncherAppWidgetInfo(item.appWidgetId);
+ widgetInfo = widgetHelper.getLauncherAppWidgetInfo(item.appWidgetId,
+ item.getTargetComponent());
}
if (widgetInfo != null) {
diff --git a/src/com/android/launcher3/WorkspaceLayoutManager.java b/src/com/android/launcher3/WorkspaceLayoutManager.java
index 4768773..c6c38fc 100644
--- a/src/com/android/launcher3/WorkspaceLayoutManager.java
+++ b/src/com/android/launcher3/WorkspaceLayoutManager.java
@@ -55,6 +55,7 @@
int y = presenterPos.cellY;
if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT
|| info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION) {
+ Log.d(TAG, "add predicted icon " + child.getTag().toString() + " to home screen");
int screenId = presenterPos.screenId;
x = getHotseat().getCellXFromOrder(screenId);
y = getHotseat().getCellYFromOrder(screenId);
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 565d7da..e4f34ae 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -18,6 +18,9 @@
import static androidx.dynamicanimation.animation.DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE;
+import static com.android.app.animation.Interpolators.ACCELERATE_2;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.ZOOM_OUT;
import static com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY;
import static com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_WORKSPACE_STATE;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
@@ -30,12 +33,8 @@
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.WORKSPACE_PAGE_INDICATOR;
-import static com.android.launcher3.anim.Interpolators.ACCEL_2;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.ZOOM_OUT;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
import static com.android.launcher3.graphics.Scrim.SCRIM_PROGRESS;
-import static com.android.launcher3.graphics.SysUiScrim.SYSUI_PROGRESS;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
@@ -54,6 +53,7 @@
import com.android.launcher3.LauncherState.PageAlphaProvider;
import com.android.launcher3.LauncherState.PageTranslationProvider;
import com.android.launcher3.LauncherState.ScaleAndTranslation;
+import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.anim.SpringAnimationBuilder;
@@ -196,12 +196,12 @@
state.getWorkspaceBackgroundAlpha(mLauncher), LINEAR);
SysUiScrim sysUiScrim = mLauncher.getRootView().getSysUiScrim();
- propertySetter.setFloat(sysUiScrim, SYSUI_PROGRESS,
+ propertySetter.setFloat(sysUiScrim.getSysUIProgress(), AnimatedFloat.VALUE,
state.hasFlag(FLAG_HAS_SYS_UI_SCRIM) ? 1 : 0, LINEAR);
propertySetter.setViewBackgroundColor(mLauncher.getScrimView(),
state.getWorkspaceScrimColor(mLauncher),
- config.getInterpolator(ANIM_SCRIM_FADE, ACCEL_2));
+ config.getInterpolator(ANIM_SCRIM_FADE, ACCELERATE_2));
}
public void applyChildState(LauncherState state, CellLayout cl, int childIndex) {
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index a7a25f4..758bffb 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -7,6 +7,7 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
+import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_NOT_PINNABLE;
import android.appwidget.AppWidgetProviderInfo;
import android.graphics.Point;
@@ -124,12 +125,19 @@
}
}
- if ((item instanceof WorkspaceItemFactory) || (item instanceof WorkspaceItemInfo)
- || (item instanceof PendingAddItemInfo)) {
+ if (supportAddToWorkSpace(item)) {
out.add(mActions.get(ADD_TO_WORKSPACE));
}
}
+ private boolean supportAddToWorkSpace(ItemInfo item) {
+ return (item instanceof WorkspaceItemFactory)
+ || ((item instanceof WorkspaceItemInfo)
+ && (((WorkspaceItemInfo) item).runtimeStatusFlags & FLAG_NOT_PINNABLE) == 0)
+ || ((item instanceof PendingAddItemInfo)
+ && (((PendingAddItemInfo) item).runtimeStatusFlags & FLAG_NOT_PINNABLE) == 0);
+ }
+
/**
* Returns all the accessibility actions that can be handled by the host.
*/
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 1977704..dabe84d 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -15,11 +15,16 @@
*/
package com.android.launcher3.allapps;
+import static com.android.launcher3.Flags.enableExpandingPauseWorkButton;
import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.SEARCH;
+import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_DISABLED_CARD;
+import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_EDU_CARD;
+import static com.android.launcher3.config.FeatureFlags.ALL_APPS_GONE_VISIBILITY;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_RV_PREINFLATION;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_COUNT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB;
-import static com.android.launcher3.testing.shared.TestProtocol.WORK_TAB_MISSING;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.ScrollableLayoutManager.PREDICTIVE_BACK_MIN_SCALE;
import android.animation.Animator;
@@ -69,13 +74,12 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
-import com.android.launcher3.allapps.search.DefaultSearchAdapterProvider;
+import com.android.launcher3.allapps.search.AllAppsSearchUiDelegate;
import com.android.launcher3.allapps.search.SearchAdapterProvider;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.keyboard.FocusedItemDecorator;
import com.android.launcher3.model.StringCache;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
@@ -127,16 +131,17 @@
protected final List<AdapterHolder> mAH;
protected final Predicate<ItemInfo> mPersonalMatcher = ItemInfoMatcher.ofUser(
Process.myUserHandle());
- protected final WorkProfileManager mWorkManager;
+ protected WorkProfileManager mWorkManager;
protected final Point mFastScrollerOffset = new Point();
protected final int mScrimColor;
protected final float mHeaderThreshold;
+ protected final AllAppsSearchUiDelegate mSearchUiDelegate;
// Used to animate Search results out and A-Z apps in, or vice-versa.
private final SearchTransitionController mSearchTransitionController;
private final Paint mHeaderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Rect mInsets = new Rect();
- private final AllAppsStore mAllAppsStore = new AllAppsStore();
+ private final AllAppsStore<T> mAllAppsStore;
private final RecyclerView.OnScrollListener mScrollListener =
new RecyclerView.OnScrollListener() {
@Override
@@ -189,6 +194,7 @@
public ActivityAllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mActivityContext = ActivityContext.lookupContext(context);
+ mAllAppsStore = new AllAppsStore<>(mActivityContext);
mScrimColor = Themes.getAttrColor(context, R.attr.allAppsScrimColor);
mHeaderThreshold = getResources().getDimensionPixelSize(
@@ -203,10 +209,6 @@
mNavBarScrimPaint.setColor(Themes.getNavBarScrimColor(mActivityContext));
AllAppsStore.OnUpdateListener onAppsUpdated = this::onAppsUpdated;
- if (TestProtocol.sDebugTracing) {
- Log.d(WORK_TAB_MISSING, "ActivityAllAppsContainer#init registeringListener: " +
- onAppsUpdated);
- }
mAllAppsStore.addUpdateListener(onAppsUpdated);
// This is a focus listener that proxies focus from a view into the list view. This is to
@@ -216,11 +218,21 @@
getActiveRecyclerView().requestFocus();
}
});
+ mSearchUiDelegate = createSearchUiDelegate();
initContent();
mSearchTransitionController = new SearchTransitionController(this);
}
+ /** Creates the delegate for initializing search. */
+ protected AllAppsSearchUiDelegate createSearchUiDelegate() {
+ return new AllAppsSearchUiDelegate(this);
+ }
+
+ public AllAppsSearchUiDelegate getSearchUiDelegate() {
+ return mSearchUiDelegate;
+ }
+
/**
* Initializes the view hierarchy and internal variables. Any initialization which actually uses
* these members should be done in {@link #onFinishInflate()}.
@@ -230,7 +242,7 @@
* onFinishInflate -> onPostCreate
*/
protected void initContent() {
- mMainAdapterProvider = createMainAdapterProvider();
+ mMainAdapterProvider = mSearchUiDelegate.createMainAdapterProvider();
mAH.set(AdapterHolder.MAIN, new AdapterHolder(AdapterHolder.MAIN,
new AlphabeticalAppsList<>(mActivityContext, mAllAppsStore, null)));
@@ -247,9 +259,12 @@
mFastScroller = findViewById(R.id.fast_scroller);
mFastScroller.setPopupView(findViewById(R.id.fast_scroller_popup));
- // Add the search box above everything else.
- mSearchContainer = inflateSearchBox();
- addView(mSearchContainer);
+ mSearchContainer = inflateSearchBar();
+ if (!isSearchBarFloating()) {
+ // Add the search box above everything else in this container (if the flag is enabled,
+ // it's added to drag layer in onAttach instead).
+ addView(mSearchContainer);
+ }
mSearchUiManager = (SearchUiManager) mSearchContainer;
}
@@ -280,6 +295,13 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+ if (isSearchBarFloating()) {
+ // Note: for Taskbar this is removed in TaskbarAllAppsController#cleanUpOverlay when the
+ // panel is closed. Can't do so in onDetach because we are also a child of drag layer
+ // so can't remove its views during that dispatch.
+ mActivityContext.getDragLayer().addView(mSearchContainer);
+ mSearchUiDelegate.onInitializeSearchBar();
+ }
mActivityContext.addOnDeviceProfileChangeListener(this);
}
@@ -301,7 +323,7 @@
* Temporarily force the bottom sheet to be visible on non-tablets.
*
* @param force {@code true} means bottom sheet will be visible on phones until {@code reset()}.
- **/
+ */
public void forceBottomSheetVisible(boolean force) {
mForceBottomSheetVisible = force;
updateBackgroundVisibility(mActivityContext.getDeviceProfile());
@@ -339,6 +361,7 @@
*/
public void setSearchResults(ArrayList<AdapterItem> results, int searchResultCode) {
setSearchResults(results);
+ mSearchUiDelegate.onSearchResultsChanged(results, searchResultCode);
}
private void animateToSearchState(boolean goingToSearch) {
@@ -371,7 +394,10 @@
rebindAdapters(false);
mRebindAdaptersAfterSearchAnimation = false;
}
- if (!goingToSearch) {
+
+ if (goingToSearch) {
+ mSearchUiDelegate.onAnimateToSearchStateCompleted();
+ } else {
setSearchResults(null);
if (mViewPager != null) {
mViewPager.setCurrentPage(previousPage);
@@ -410,7 +436,7 @@
* A-Z apps list.
*
* @param animate Whether to animate the header during the reset (e.g. switching profile tabs).
- **/
+ */
public void reset(boolean animate) {
reset(animate, true);
}
@@ -420,7 +446,7 @@
*
* @param animate Whether to animate the header during the reset (e.g. switching profile tabs).
* @param exitSearch Whether to force exit the search state and return to A-Z apps list.
- **/
+ */
public void reset(boolean animate, boolean exitSearch) {
for (int i = 0; i < mAH.size(); i++) {
if (mAH.get(i).mRecyclerView != null) {
@@ -438,7 +464,7 @@
updateHeaderScroll(0);
if (exitSearch) {
// Reset the search bar after transitioning home.
- mSearchUiManager.resetSearch();
+ MAIN_EXECUTOR.getHandler().post(mSearchUiManager::resetSearch);
// Animate to A-Z with 0 time to reset the animation with proper state management.
animateToSearchState(false, 0);
}
@@ -483,6 +509,9 @@
// Will be called at the end of the animation.
return;
}
+ if (currentActivePage != SEARCH) {
+ mActivityContext.hideKeyboard();
+ }
if (mAH.get(currentActivePage).mRecyclerView != null) {
mAH.get(currentActivePage).mRecyclerView.bindFastScrollbar(mFastScroller);
}
@@ -525,11 +554,16 @@
mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.WORK).mRecyclerView);
mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.SEARCH).mRecyclerView);
+ final AllAppsRecyclerView mainRecyclerView;
+ final AllAppsRecyclerView workRecyclerView;
if (mUsingTabs) {
- mAH.get(AdapterHolder.MAIN).setup(mViewPager.getChildAt(0), mPersonalMatcher);
- mAH.get(AdapterHolder.WORK).setup(mViewPager.getChildAt(1), mWorkManager.getMatcher());
- mAH.get(AdapterHolder.WORK).mRecyclerView.setId(R.id.apps_list_view_work);
- if (FeatureFlags.ENABLE_EXPANDING_PAUSE_WORK_BUTTON.get()) {
+ mainRecyclerView = (AllAppsRecyclerView) mViewPager.getChildAt(0);
+ workRecyclerView = (AllAppsRecyclerView) mViewPager.getChildAt(1);
+ mAH.get(AdapterHolder.MAIN).setup(mainRecyclerView, mPersonalMatcher);
+ mAH.get(AdapterHolder.WORK).setup(workRecyclerView, mWorkManager.getMatcher());
+ workRecyclerView.setId(R.id.apps_list_view_work);
+ if (enableExpandingPauseWorkButton()
+ || FeatureFlags.ENABLE_EXPANDING_PAUSE_WORK_BUTTON.get()) {
mAH.get(AdapterHolder.WORK).mRecyclerView.addOnScrollListener(
mWorkManager.newScrollListener());
}
@@ -540,7 +574,6 @@
mActivityContext.getStatsLogManager().logger()
.log(LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB);
}
- mActivityContext.hideKeyboard();
});
findViewById(R.id.tab_work)
.setOnClickListener((View view) -> {
@@ -548,24 +581,30 @@
mActivityContext.getStatsLogManager().logger()
.log(LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB);
}
- mActivityContext.hideKeyboard();
});
setDeviceManagementResources();
- onActivePageChanged(mViewPager.getNextPage());
+ if (mHeader.isSetUp()) {
+ onActivePageChanged(mViewPager.getNextPage());
+ }
} else {
- mAH.get(AdapterHolder.MAIN).setup(findViewById(R.id.apps_list_view), null);
+ mainRecyclerView = findViewById(R.id.apps_list_view);
+ workRecyclerView = null;
+ mAH.get(AdapterHolder.MAIN).setup(mainRecyclerView, null);
mAH.get(AdapterHolder.WORK).mRecyclerView = null;
}
+ setUpCustomRecyclerViewPool(
+ mainRecyclerView,
+ workRecyclerView,
+ mAllAppsStore.getRecyclerViewPool());
setupHeader();
- if (isSearchBarOnBottom()) {
+ if (isSearchBarFloating()) {
// Keep the scroller above the search bar.
RelativeLayout.LayoutParams scrollerLayoutParams =
(LayoutParams) mFastScroller.getLayoutParams();
- scrollerLayoutParams.addRule(RelativeLayout.ABOVE, R.id.search_container_all_apps);
- scrollerLayoutParams.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
- scrollerLayoutParams.bottomMargin = getResources().getDimensionPixelSize(
- R.dimen.fastscroll_bottom_margin_floating_search);
+ scrollerLayoutParams.bottomMargin = mSearchContainer.getHeight()
+ + getResources().getDimensionPixelSize(
+ R.dimen.fastscroll_bottom_margin_floating_search);
}
mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.MAIN).mRecyclerView);
@@ -573,6 +612,30 @@
mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.SEARCH).mRecyclerView);
}
+ /**
+ * If {@link ENABLE_ALL_APPS_RV_PREINFLATION} is enabled, wire custom
+ * {@link RecyclerView.RecycledViewPool} to main and work {@link AllAppsRecyclerView}.
+ *
+ * Then if {@link ALL_APPS_GONE_VISIBILITY} is enabled, update max pool size. This is because
+ * all apps rv's hidden visibility is changed to {@link View#GONE} from {@link View#INVISIBLE),
+ * thus we cannot rely on layout pass to update pool size.
+ */
+ private static void setUpCustomRecyclerViewPool(
+ @NonNull AllAppsRecyclerView mainRecyclerView,
+ @Nullable AllAppsRecyclerView workRecyclerView,
+ @NonNull RecyclerView.RecycledViewPool recycledViewPool) {
+ if (!ENABLE_ALL_APPS_RV_PREINFLATION.get()) {
+ return;
+ }
+ mainRecyclerView.setRecycledViewPool(recycledViewPool);
+ if (workRecyclerView != null) {
+ workRecyclerView.setRecycledViewPool(recycledViewPool);
+ }
+ if (ALL_APPS_GONE_VISIBILITY.get()) {
+ mainRecyclerView.updatePoolSize();
+ }
+ }
+
private void replaceAppsRVContainer(boolean showTabs) {
for (int i = AdapterHolder.MAIN; i <= AdapterHolder.WORK; i++) {
AdapterHolder adapterHolder = mAH.get(i);
@@ -617,11 +680,9 @@
removeCustomRules(getSearchRecyclerView());
if (!isSearchSupported()) {
layoutWithoutSearchContainer(rvContainer, showTabs);
- } else if (isSearchBarOnBottom()) {
+ } else if (isSearchBarFloating()) {
alignParentTop(rvContainer, showTabs);
alignParentTop(getSearchRecyclerView(), /* tabs= */ false);
- layoutAboveSearchContainer(rvContainer);
- layoutAboveSearchContainer(getSearchRecyclerView());
} else {
layoutBelowSearchContainer(rvContainer, showTabs);
layoutBelowSearchContainer(getSearchRecyclerView(), /* tabs= */ false);
@@ -652,7 +713,7 @@
removeCustomRules(mHeader);
if (!isSearchSupported()) {
layoutWithoutSearchContainer(mHeader, false /* includeTabsMargin */);
- } else if (isSearchBarOnBottom()) {
+ } else if (isSearchBarFloating()) {
alignParentTop(mHeader, false /* includeTabsMargin */);
} else {
layoutBelowSearchContainer(mHeader, false /* includeTabsMargin */);
@@ -692,16 +753,62 @@
}
/**
- * It is up to the search container view created by {@link #inflateSearchBox()} to use the
- * floating search bar flag to move itself to the bottom of this container. This method checks
- * if that had been done; otherwise the flag will be ignored.
- *
- * @return true if the search bar is at the bottom of the container (as opposed to the top).
- **/
- private boolean isSearchBarOnBottom() {
- return FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()
- && ((RelativeLayout.LayoutParams) mSearchContainer.getLayoutParams()).getRule(
- ALIGN_PARENT_BOTTOM) == RelativeLayout.TRUE;
+ * @return true if the search bar is floating above this container (at the bottom of the screen)
+ */
+ protected boolean isSearchBarFloating() {
+ return mSearchUiDelegate.isSearchBarFloating();
+ }
+
+ /**
+ * Whether the <em>floating</em> search bar should appear as a small pill when not focused.
+ * <p>
+ * Note: This method mirrors one in LauncherState. For subclasses that use Launcher, it likely
+ * makes sense to use that method to derive an appropriate value for the current/target state.
+ */
+ public boolean shouldFloatingSearchBarBePillWhenUnfocused() {
+ return false;
+ }
+
+ /**
+ * How far from the bottom of the screen the <em>floating</em> search bar should rest when the
+ * IME is not present.
+ * <p>
+ * To hide offscreen, use a negative value.
+ * <p>
+ * Note: if the provided value is non-negative but less than the current bottom insets, the
+ * insets will be applied. As such, you can use 0 to default to this.
+ * <p>
+ * Note: This method mirrors one in LauncherState. For subclasses that use Launcher, it likely
+ * makes sense to use that method to derive an appropriate value for the current/target state.
+ */
+ public int getFloatingSearchBarRestingMarginBottom() {
+ return 0;
+ }
+
+ /**
+ * How far from the start of the screen the <em>floating</em> search bar should rest.
+ * <p>
+ * To use original margin, return a negative value.
+ * <p>
+ * Note: This method mirrors one in LauncherState. For subclasses that use Launcher, it likely
+ * makes sense to use that method to derive an appropriate value for the current/target state.
+ */
+ public int getFloatingSearchBarRestingMarginStart() {
+ DeviceProfile dp = mActivityContext.getDeviceProfile();
+ return dp.allAppsLeftRightMargin + dp.getAllAppsIconStartMargin();
+ }
+
+ /**
+ * How far from the end of the screen the <em>floating</em> search bar should rest.
+ * <p>
+ * To use original margin, return a negative value.
+ * <p>
+ * Note: This method mirrors one in LauncherState. For subclasses that use Launcher, it likely
+ * makes sense to use that method to derive an appropriate value for the current/target state.
+ */
+ public int getFloatingSearchBarRestingMarginEnd() {
+ DeviceProfile dp = mActivityContext.getDeviceProfile();
+ return dp.allAppsLeftRightMargin + dp.getAllAppsIconStartMargin();
}
private void layoutBelowSearchContainer(View v, boolean includeTabsMargin) {
@@ -721,15 +828,6 @@
layoutParams.topMargin = topMargin;
}
- private void layoutAboveSearchContainer(View v) {
- if (!(v.getLayoutParams() instanceof RelativeLayout.LayoutParams)) {
- return;
- }
-
- RelativeLayout.LayoutParams layoutParams = (LayoutParams) v.getLayoutParams();
- layoutParams.addRule(RelativeLayout.ABOVE, R.id.search_container_all_apps);
- }
-
private void alignParentTop(View v, boolean includeTabsMargin) {
if (!(v.getLayoutParams() instanceof RelativeLayout.LayoutParams)) {
return;
@@ -783,15 +881,10 @@
}
/**
- * Inflates the search box
+ * Inflates the search bar
*/
- protected View inflateSearchBox() {
- return getLayoutInflater().inflate(R.layout.search_container_all_apps, this, false);
- }
-
- /** Creates the adapter provider for the main section. */
- protected SearchAdapterProvider<?> createMainAdapterProvider() {
- return new DefaultSearchAdapterProvider(mActivityContext);
+ protected View inflateSearchBar() {
+ return mSearchUiDelegate.inflateSearchBar();
}
/** The adapter provider for the main section. */
@@ -831,16 +924,7 @@
container.put(R.id.work_tab_state_id, state);
}
- /**
- * Sets the long click listener for icons
- */
- public void setOnIconLongClickListener(OnLongClickListener listener) {
- for (AdapterHolder holder : mAH) {
- holder.mAdapter.setOnIconLongClickListener(listener);
- }
- }
-
- public AllAppsStore getAppsStore() {
+ public AllAppsStore<T> getAppsStore() {
return mAllAppsStore;
}
@@ -852,6 +936,7 @@
public void onDeviceProfileChanged(DeviceProfile dp) {
for (AdapterHolder holder : mAH) {
holder.mAdapter.setAppsPerRow(dp.numShownAllAppsColumns);
+ holder.mAppsList.setNumAppsPerRowAllApps(dp.numShownAllAppsColumns);
if (holder.mRecyclerView != null) {
// Remove all views and clear the pool, while keeping the data same. After this
// call, all the viewHolders will be recreated.
@@ -881,17 +966,14 @@
mBottomSheetAlpha = mActivityContext.getDeviceProfile().isTablet ? 1f : alpha;
}
- private void onAppsUpdated() {
- mHasWorkApps = Stream.of(mAllAppsStore.getApps()).anyMatch(mWorkManager.getMatcher());
- if (TestProtocol.sDebugTracing) {
- Log.d(WORK_TAB_MISSING, "ActivityAllAppsContainerView#onAppsUpdated hasWorkApps: " +
- mHasWorkApps + " allApps: " + mAllAppsStore.getApps().length);
- }
+ @VisibleForTesting
+ public void onAppsUpdated() {
+ mHasWorkApps = mWorkManager.hasWorkApps();
if (!isSearching()) {
rebindAdapters();
- if (mHasWorkApps) {
- mWorkManager.reset();
- }
+ }
+ if (mHasWorkApps) {
+ mWorkManager.reset();
}
mActivityContext.getStatsLogManager().logger()
@@ -971,7 +1053,7 @@
/**
* The container for A-Z apps (the ViewPager for main+work tabs, or main RV). This is currently
* hidden while searching.
- **/
+ */
public ViewGroup getAppsRecyclerViewContainer() {
return mViewPager != null ? mViewPager : findViewById(R.id.apps_list_view);
}
@@ -996,7 +1078,7 @@
}
public LayoutInflater getLayoutInflater() {
- return LayoutInflater.from(getContext());
+ return mSearchUiDelegate.getLayoutInflater();
}
@Override
@@ -1018,7 +1100,7 @@
setPadding(grid.workspacePadding.left, 0, grid.workspacePadding.right, 0);
} else {
int topPadding = grid.allAppsTopPadding;
- if (isSearchBarOnBottom() && !grid.isTablet) {
+ if (isSearchBarFloating() && !grid.isTablet) {
topPadding += getResources().getDimensionPixelSize(
R.dimen.all_apps_additional_top_padding_floating_search);
}
@@ -1094,7 +1176,10 @@
}
}
- protected boolean shouldShowTabs() {
+ /**
+ * Returns true if the container has work apps.
+ */
+ public boolean shouldShowTabs() {
return mHasWorkApps;
}
@@ -1108,6 +1193,35 @@
return view.getGlobalVisibleRect(new Rect());
}
+ /** Called in Launcher#bindStringCache() to update the UI when cache is updated. */
+ public void updateWorkUI() {
+ setDeviceManagementResources();
+ if (mWorkManager.getWorkModeSwitch() != null) {
+ mWorkManager.getWorkModeSwitch().updateStringFromCache();
+ }
+ inflateWorkCardsIfNeeded();
+ }
+
+ private void inflateWorkCardsIfNeeded() {
+ AllAppsRecyclerView workRV = mAH.get(AdapterHolder.WORK).mRecyclerView;
+ if (workRV != null) {
+ for (int i = 0; i < workRV.getChildCount(); i++) {
+ View currentView = workRV.getChildAt(i);
+ int currentItemViewType = workRV.getChildViewHolder(currentView).getItemViewType();
+ if (currentItemViewType == VIEW_TYPE_WORK_EDU_CARD) {
+ ((WorkEduCard) currentView).updateStringFromCache();
+ } else if (currentItemViewType == VIEW_TYPE_WORK_DISABLED_CARD) {
+ ((WorkPausedCard) currentView).updateStringFromCache();
+ }
+ }
+ }
+ }
+
+ @VisibleForTesting
+ public void setWorkManager(WorkProfileManager workManager) {
+ mWorkManager = workManager;
+ }
+
@VisibleForTesting
public boolean isPersonalTabVisible() {
return isDescendantViewVisible(R.id.tab_personal);
@@ -1230,7 +1344,7 @@
final FloatingHeaderView headerView = getFloatingHeaderView();
if (hasBottomSheet) {
// Start adding header protection if search bar or tabs will attach to the top.
- if (!FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get() || mUsingTabs) {
+ if (!isSearchBarFloating() || mUsingTabs) {
mTmpRectF.set(
leftWithScale,
topWithScale,
@@ -1286,7 +1400,7 @@
/** Returns the position of the bottom edge of the header */
public int getHeaderBottom() {
int bottom = (int) getTranslationY() + mHeader.getClipTop();
- if (isSearchBarOnBottom()) {
+ if (isSearchBarFloating()) {
if (mActivityContext.getDeviceProfile().isTablet) {
return bottom + mBottomSheetBackground.getTop();
}
@@ -1304,6 +1418,7 @@
protected void onInitializeRecyclerView(RecyclerView rv) {
rv.addOnScrollListener(mScrollListener);
+ mSearchUiDelegate.onInitializeRecyclerView(rv);
}
/** Returns the instance of @{code SearchTransitionController}. */
@@ -1356,6 +1471,9 @@
if (isWork() && mWorkManager.getWorkModeSwitch() != null) {
bottomOffset = mInsets.bottom + mWorkManager.getWorkModeSwitch().getHeight();
}
+ if (isSearchBarFloating()) {
+ bottomOffset += mSearchContainer.getHeight();
+ }
mRecyclerView.setPadding(mPadding.left, mPadding.top, mPadding.right,
mPadding.bottom + bottomOffset);
}
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index 7c5c003..7edbeac 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.allapps;
+import static com.android.launcher3.config.FeatureFlags.ALL_APPS_GONE_VISIBILITY;
import static com.android.launcher3.logger.LauncherAtom.ContainerInfo;
import static com.android.launcher3.logger.LauncherAtom.SearchResultContainer;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_PERSONAL_SCROLLED_DOWN;
@@ -26,6 +27,8 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_VERTICAL_SWIPE_END;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WORK_FAB_BUTTON_COLLAPSE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WORK_FAB_BUTTON_EXTEND;
+import static com.android.launcher3.recyclerview.AllAppsRecyclerViewPoolKt.EXTRA_ICONS_COUNT;
+import static com.android.launcher3.recyclerview.AllAppsRecyclerViewPoolKt.PREINFLATE_ICONS_ROW_COUNT;
import static com.android.launcher3.util.LogConfig.SEARCH_LOGGING;
import android.content.Context;
@@ -96,8 +99,18 @@
int approxRows = (int) Math.ceil(grid.availableHeightPx / grid.allAppsIconSizePx);
pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_EMPTY_SEARCH, 1);
pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_ALL_APPS_DIVIDER, 1);
- pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_ICON, approxRows
- * (mNumAppsPerRow + 1));
+
+ // If all apps' hidden visibility is INVISIBLE, we will need to preinflate one page of
+ // all apps icons for smooth scrolling.
+ int maxPoolSizeForAppIcons = (approxRows + 1) * grid.numShownAllAppsColumns;
+ if (ALL_APPS_GONE_VISIBILITY.get()) {
+ // If all apps' hidden visibility is GONE, we need to increase prefinated icons number
+ // by [PREINFLATE_ICONS_ROW_COUNT] rows + [EXTRA_ICONS_COUNT] for fast opening all apps.
+ maxPoolSizeForAppIcons +=
+ PREINFLATE_ICONS_ROW_COUNT * grid.numShownAllAppsColumns + EXTRA_ICONS_COUNT;
+ }
+ pool.setMaxRecycledViews(
+ AllAppsGridAdapter.VIEW_TYPE_ICON, maxPoolSizeForAppIcons);
}
@Override
diff --git a/src/com/android/launcher3/allapps/AllAppsStore.java b/src/com/android/launcher3/allapps/AllAppsStore.java
index 06af970..e724858 100644
--- a/src/com/android/launcher3/allapps/AllAppsStore.java
+++ b/src/com/android/launcher3/allapps/AllAppsStore.java
@@ -15,24 +15,27 @@
*/
package com.android.launcher3.allapps;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_RV_PREINFLATION;
import static com.android.launcher3.model.data.AppInfo.COMPONENT_KEY_COMPARATOR;
import static com.android.launcher3.model.data.AppInfo.EMPTY_ARRAY;
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK;
-import static com.android.launcher3.testing.shared.TestProtocol.WORK_TAB_MISSING;
+import android.content.Context;
import android.os.UserHandle;
-import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView.RecycledViewPool;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.testing.shared.TestProtocol;
+import com.android.launcher3.recyclerview.AllAppsRecyclerViewPool;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageUserKey;
+import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList;
import java.util.Arrays;
@@ -45,8 +48,10 @@
/**
* A utility class to maintain the collection of all apps.
+ *
+ * @param <T> The type of the context.
*/
-public class AllAppsStore {
+public class AllAppsStore<T extends Context & ActivityContext> {
// Defer updates flag used to defer all apps updates to the next draw.
public static final int DEFER_UPDATES_NEXT_DRAW = 1 << 0;
@@ -56,7 +61,7 @@
private PackageUserKey mTempKey = new PackageUserKey(null, null);
private AppInfo mTempInfo = new AppInfo();
- private AppInfo[] mApps = EMPTY_ARRAY;
+ private @NonNull AppInfo[] mApps = EMPTY_ARRAY;
private final List<OnUpdateListener> mUpdateListeners = new CopyOnWriteArrayList<>();
private final ArrayList<ViewGroup> mIconContainers = new ArrayList<>();
@@ -64,20 +69,36 @@
private int mModelFlags;
private int mDeferUpdatesFlags = 0;
private boolean mUpdatePending = false;
+ private final AllAppsRecyclerViewPool mAllAppsRecyclerViewPool = new AllAppsRecyclerViewPool();
+
+ private final T mContext;
public AppInfo[] getApps() {
return mApps;
}
+ public AllAppsStore(@NonNull T context) {
+ mContext = context;
+ }
+
/**
* Sets the current set of apps and sets mapping for {@link PackageUserKey} to Uid for
* the current set of apps.
*/
- public void setApps(AppInfo[] apps, int flags, Map<PackageUserKey, Integer> map) {
- mApps = apps;
+ public void setApps(@Nullable AppInfo[] apps, int flags, Map<PackageUserKey, Integer> map) {
+ mApps = apps == null ? EMPTY_ARRAY : apps;
mModelFlags = flags;
notifyUpdate();
mPackageUserKeytoUidMap = map;
+ // Preinflate all apps RV when apps has changed, which can happen after unlocking screen,
+ // rotating screen, or downloading/upgrading apps.
+ if (ENABLE_ALL_APPS_RV_PREINFLATION.get()) {
+ mAllAppsRecyclerViewPool.preInflateAllAppsViewHolders(mContext);
+ }
+ }
+
+ RecycledViewPool getRecyclerViewPool() {
+ return mAllAppsRecyclerViewPool;
}
/**
@@ -134,9 +155,6 @@
return;
}
for (OnUpdateListener listener : mUpdateListeners) {
- if (TestProtocol.sDebugTracing) {
- Log.d(WORK_TAB_MISSING, "AllAppsStore#notifyUpdate listener: " + listener);
- }
listener.onAppsUpdated();
}
}
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index d4f152a..c09a5b9 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -15,14 +15,15 @@
*/
package com.android.launcher3.allapps;
+import static com.android.app.animation.Interpolators.DECELERATE_1_7;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.ALL_APPS_CONTENT;
+import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_BOTTOM_SHEET_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
@@ -45,6 +46,7 @@
import androidx.annotation.FloatRange;
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.Launcher;
@@ -53,7 +55,6 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.AnimatorListeners;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.config.FeatureFlags;
@@ -234,7 +235,11 @@
*/
public void setProgress(float progress) {
mProgress = progress;
- getAppsViewProgressTranslationY().setValue(mProgress * mShiftRange);
+ boolean fromBackground =
+ mLauncher.getStateManager().getCurrentStableState() == BACKGROUND_APP;
+ // Allow apps panel to shift the full screen if coming from another app.
+ float shiftRange = fromBackground ? mLauncher.getDeviceProfile().heightPx : mShiftRange;
+ getAppsViewProgressTranslationY().setValue(mProgress * shiftRange);
mLauncher.onAllAppsTransition(1 - progress);
boolean hasScrim = progress < NAV_BAR_COLOR_FORCE_UPDATE_THRESHOLD
@@ -380,7 +385,7 @@
// need to decide depending on the release velocity
Interpolator verticalProgressInterpolator = config.getInterpolator(ANIM_VERTICAL_PROGRESS,
- config.userControlled ? LINEAR : DEACCEL_1_7);
+ config.userControlled ? LINEAR : DECELERATE_1_7);
Animator anim = createSpringAnimation(mProgress, targetProgress);
anim.setInterpolator(verticalProgressInterpolator);
anim.addListener(getProgressAnimatorListener());
@@ -433,7 +438,8 @@
mAppsView = appsView;
mAppsView.setScrimView(scrimView);
- mAppsViewAlpha = new MultiValueAlpha(mAppsView, APPS_VIEW_INDEX_COUNT);
+ mAppsViewAlpha = new MultiValueAlpha(mAppsView, APPS_VIEW_INDEX_COUNT,
+ FeatureFlags.ALL_APPS_GONE_VISIBILITY.get() ? View.GONE : View.INVISIBLE);
mAppsViewAlpha.setUpdateVisibility(true);
mAppsViewTranslationY = new MultiPropertyFactory<>(
mAppsView, VIEW_TRANSLATE_Y, APPS_VIEW_INDEX_COUNT, Float::sum);
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionListener.java b/src/com/android/launcher3/allapps/AllAppsTransitionListener.java
new file mode 100644
index 0000000..4a17e29
--- /dev/null
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionListener.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps;
+
+/**
+ * An interface for listening to all-apps open-close transition
+ */
+public interface AllAppsTransitionListener {
+ /**
+ * Called when the transition starts
+ * @param toAllApps {@code true} if this transition is supposed to end in the AppApps UI
+ *
+ * @see ActivityAllAppsContainerView
+ */
+ void onAllAppsTransitionStart(boolean toAllApps);
+
+ /**
+ * Called when the transition ends
+ * @param toAllApps {@code true} if the final state is all-apps
+ *
+ * @see ActivityAllAppsContainerView
+ */
+ void onAllAppsTransitionEnd(boolean toAllApps);
+}
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 29767bf..ee4b5bc 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -69,7 +69,7 @@
// The set of apps from the system
private final List<AppInfo> mApps = new ArrayList<>();
@Nullable
- private final AllAppsStore mAllAppsStore;
+ private final AllAppsStore<T> mAllAppsStore;
// The number of results in current adapter
private int mAccessibilityResultsCount = 0;
@@ -82,22 +82,27 @@
private final ArrayList<AdapterItem> mSearchResults = new ArrayList<>();
private BaseAllAppsAdapter<T> mAdapter;
private AppInfoComparator mAppNameComparator;
- private final int mNumAppsPerRowAllApps;
+ private int mNumAppsPerRowAllApps;
private int mNumAppRowsInAdapter;
private Predicate<ItemInfo> mItemFilter;
- public AlphabeticalAppsList(Context context, @Nullable AllAppsStore appsStore,
+ public AlphabeticalAppsList(Context context, @Nullable AllAppsStore<T> appsStore,
WorkProfileManager workProfileManager) {
mAllAppsStore = appsStore;
mActivityContext = ActivityContext.lookupContext(context);
mAppNameComparator = new AppInfoComparator(context);
mWorkProviderManager = workProfileManager;
- mNumAppsPerRowAllApps = mActivityContext.getDeviceProfile().inv.numAllAppsColumns;
+ mNumAppsPerRowAllApps = mActivityContext.getDeviceProfile().numShownAllAppsColumns;
if (mAllAppsStore != null) {
mAllAppsStore.addUpdateListener(this);
}
}
+ /** Set the number of apps per row when device profile changes. */
+ public void setNumAppsPerRowAllApps(int numAppsPerRow) {
+ mNumAppsPerRowAllApps = numAppsPerRow;
+ }
+
public void updateItemFilter(Predicate<ItemInfo> itemFilter) {
this.mItemFilter = itemFilter;
onAppsUpdated();
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
index 8fa4276..769c787 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
@@ -15,10 +15,7 @@
*/
package com.android.launcher3.allapps;
-import static com.android.launcher3.touch.ItemLongClickListener.INSTANCE_ALL_APPS;
-
import android.content.Context;
-import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -27,13 +24,13 @@
import android.view.ViewGroup;
import android.widget.TextView;
-import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.Flags;
import com.android.launcher3.R;
-import com.android.launcher3.allapps.search.SearchAdapterProvider;
import com.android.launcher3.Utilities;
+import com.android.launcher3.allapps.search.SearchAdapterProvider;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.views.ActivityContext;
@@ -139,31 +136,24 @@
protected final LayoutInflater mLayoutInflater;
protected final OnClickListener mOnIconClickListener;
- protected OnLongClickListener mOnIconLongClickListener = INSTANCE_ALL_APPS;
+ protected final OnLongClickListener mOnIconLongClickListener;
protected OnFocusChangeListener mIconFocusListener;
private final int mExtraTextHeight;
public BaseAllAppsAdapter(T activityContext, LayoutInflater inflater,
AlphabeticalAppsList<T> apps, SearchAdapterProvider<?> adapterProvider) {
- Resources res = activityContext.getResources();
mActivityContext = activityContext;
mApps = apps;
mLayoutInflater = inflater;
mOnIconClickListener = mActivityContext.getItemOnClickListener();
+ mOnIconLongClickListener = mActivityContext.getAllAppsItemLongClickListener();
mAdapterProvider = adapterProvider;
mExtraTextHeight = Utilities.calculateTextHeight(
mActivityContext.getDeviceProfile().allAppsIconTextSizePx);
}
- /**
- * Sets the long click listener for icons
- */
- public void setOnIconLongClickListener(@Nullable OnLongClickListener listener) {
- mOnIconLongClickListener = listener;
- }
-
/** Checks if the passed viewType represents all apps divider. */
public static boolean isDividerViewType(int viewType) {
return isViewType(viewType, VIEW_TYPE_MASK_DIVIDER);
@@ -187,8 +177,10 @@
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case VIEW_TYPE_ICON:
- int layout = !FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get() ? R.layout.all_apps_icon
- : R.layout.all_apps_icon_twoline;
+ int layout =
+ !(Flags.enableTwolineAllapps() || FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get())
+ ? R.layout.all_apps_icon
+ : R.layout.all_apps_icon_twoline;
BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
layout, parent, false);
icon.setLongPressTimeoutFactor(1f);
@@ -198,7 +190,7 @@
// Ensure the all apps icon height matches the workspace icons in portrait mode.
icon.getLayoutParams().height =
mActivityContext.getDeviceProfile().allAppsCellHeightPx;
- if (FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get()) {
+ if (Flags.enableTwolineAllapps() || FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get()) {
icon.getLayoutParams().height += mExtraTextHeight;
}
return new ViewHolder(icon);
diff --git a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
index aefedae..5e48177 100644
--- a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
@@ -22,6 +22,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
+import com.android.launcher3.statemanager.StateManager;
/**
* AllAppsContainerView with launcher specific callbacks
@@ -53,4 +54,87 @@
public boolean isInAllApps() {
return mActivityContext.getStateManager().isInStableState(LauncherState.ALL_APPS);
}
+
+ @Override
+ public boolean shouldFloatingSearchBarBePillWhenUnfocused() {
+ if (!isSearchBarFloating()) {
+ return false;
+ }
+ Launcher launcher = mActivityContext;
+ StateManager<LauncherState> manager = launcher.getStateManager();
+ if (manager.isInTransition() && manager.getTargetState() != null) {
+ return manager.getTargetState().shouldFloatingSearchBarUsePillWhenUnfocused(launcher);
+ }
+ return manager.getCurrentStableState()
+ .shouldFloatingSearchBarUsePillWhenUnfocused(launcher);
+ }
+
+ @Override
+ public int getFloatingSearchBarRestingMarginBottom() {
+ if (!isSearchBarFloating()) {
+ return super.getFloatingSearchBarRestingMarginBottom();
+ }
+ Launcher launcher = mActivityContext;
+ StateManager<LauncherState> stateManager = launcher.getStateManager();
+
+ // We want to rest at the current state's resting position, unless we are in transition and
+ // the target state's resting position is higher (that way if we are closing the keyboard,
+ // we can stop translating at that point).
+ int currentStateMarginBottom = stateManager.getCurrentStableState()
+ .getFloatingSearchBarRestingMarginBottom(launcher);
+ int targetStateMarginBottom = -1;
+ if (stateManager.isInTransition() && stateManager.getTargetState() != null) {
+ targetStateMarginBottom = stateManager.getTargetState()
+ .getFloatingSearchBarRestingMarginBottom(launcher);
+ if (targetStateMarginBottom < 0) {
+ // Go ahead and move offscreen.
+ return targetStateMarginBottom;
+ }
+ }
+ return Math.max(targetStateMarginBottom, currentStateMarginBottom);
+ }
+
+ @Override
+ public int getFloatingSearchBarRestingMarginStart() {
+ if (!isSearchBarFloating()) {
+ return super.getFloatingSearchBarRestingMarginStart();
+ }
+
+ StateManager<LauncherState> stateManager = mActivityContext.getStateManager();
+
+ // Special case to not expand the search bar when exiting All Apps on phones.
+ if (stateManager.getCurrentStableState() == LauncherState.ALL_APPS
+ && mActivityContext.getDeviceProfile().isPhone) {
+ return LauncherState.ALL_APPS.getFloatingSearchBarRestingMarginStart(mActivityContext);
+ }
+
+ if (stateManager.isInTransition() && stateManager.getTargetState() != null) {
+ return stateManager.getTargetState()
+ .getFloatingSearchBarRestingMarginStart(mActivityContext);
+ }
+ return stateManager.getCurrentStableState()
+ .getFloatingSearchBarRestingMarginStart(mActivityContext);
+ }
+
+ @Override
+ public int getFloatingSearchBarRestingMarginEnd() {
+ if (!isSearchBarFloating()) {
+ return super.getFloatingSearchBarRestingMarginEnd();
+ }
+
+ StateManager<LauncherState> stateManager = mActivityContext.getStateManager();
+
+ // Special case to not expand the search bar when exiting All Apps on phones.
+ if (stateManager.getCurrentStableState() == LauncherState.ALL_APPS
+ && mActivityContext.getDeviceProfile().isPhone) {
+ return LauncherState.ALL_APPS.getFloatingSearchBarRestingMarginEnd(mActivityContext);
+ }
+
+ if (stateManager.isInTransition() && stateManager.getTargetState() != null) {
+ return stateManager.getTargetState()
+ .getFloatingSearchBarRestingMarginEnd(mActivityContext);
+ }
+ return stateManager.getCurrentStableState()
+ .getFloatingSearchBarRestingMarginEnd(mActivityContext);
+ }
}
diff --git a/src/com/android/launcher3/allapps/SearchTransitionController.java b/src/com/android/launcher3/allapps/SearchTransitionController.java
index b01ea53..eb1bc0a 100644
--- a/src/com/android/launcher3/allapps/SearchTransitionController.java
+++ b/src/com/android/launcher3/allapps/SearchTransitionController.java
@@ -20,12 +20,12 @@
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
+import static com.android.app.animation.Interpolators.DECELERATE_1_7;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.clampToProgress;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.clampToProgress;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
@@ -48,7 +48,7 @@
private static final String LOG_TAG = "SearchTransitionCtrl";
// Interpolator when the user taps the QSB while already in All Apps.
- private static final Interpolator INTERPOLATOR_WITHIN_ALL_APPS = DEACCEL_1_7;
+ private static final Interpolator INTERPOLATOR_WITHIN_ALL_APPS = DECELERATE_1_7;
// Interpolator when the user taps the QSB from home screen, so transition to all apps is
// happening simultaneously.
private static final Interpolator INTERPOLATOR_TRANSITIONING_TO_ALL_APPS = INSTANT;
diff --git a/src/com/android/launcher3/allapps/SearchUiManager.java b/src/com/android/launcher3/allapps/SearchUiManager.java
index 2174936..bfd8967 100644
--- a/src/com/android/launcher3/allapps/SearchUiManager.java
+++ b/src/com/android/launcher3/allapps/SearchUiManager.java
@@ -49,6 +49,14 @@
ExtendedEditText getEditText();
/**
+ * Hint to the edit text that it is about to be focused or unfocused. This can be used to start
+ * animating the edit box accordingly, e.g. after a gesture completes.
+ *
+ * @param focused true if the edit text is about to be focused, false if it will be unfocused
+ */
+ default void prepareToFocusEditText(boolean focused) {}
+
+ /**
* Sets whether EditText background should be visible
* @param maxAlpha defines the maximum alpha the background should animates to
*/
diff --git a/src/com/android/launcher3/allapps/WorkEduCard.java b/src/com/android/launcher3/allapps/WorkEduCard.java
index b4cdc96..1059097 100644
--- a/src/com/android/launcher3/allapps/WorkEduCard.java
+++ b/src/com/android/launcher3/allapps/WorkEduCard.java
@@ -76,11 +76,7 @@
super.onFinishInflate();
findViewById(R.id.action_btn).setOnClickListener(this);
- StringCache cache = mActivityContext.getStringCache();
- if (cache != null) {
- TextView title = findViewById(R.id.work_apps_paused_title);
- title.setText(cache.workProfileEdu);
- }
+ updateStringFromCache();
}
@Override
@@ -121,4 +117,12 @@
public void setPosition(int position) {
mPosition = position;
}
+
+ public void updateStringFromCache() {
+ StringCache cache = mActivityContext.getStringCache();
+ if (cache != null) {
+ TextView title = findViewById(R.id.work_apps_paused_title);
+ title.setText(cache.workProfileEdu);
+ }
+ }
}
diff --git a/src/com/android/launcher3/allapps/WorkModeSwitch.java b/src/com/android/launcher3/allapps/WorkModeSwitch.java
index 8c2fb19..144381c 100644
--- a/src/com/android/launcher3/allapps/WorkModeSwitch.java
+++ b/src/com/android/launcher3/allapps/WorkModeSwitch.java
@@ -17,7 +17,6 @@
import static com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.getTabWidth;
-import android.animation.LayoutTransition;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
@@ -36,7 +35,6 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.KeyboardInsetAnimationCallback;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.StringCache;
import com.android.launcher3.views.ActivityContext;
@@ -92,12 +90,7 @@
}
setInsets(mActivityContext.getDeviceProfile().getInsets());
- StringCache cache = mActivityContext.getStringCache();
- if (cache != null) {
- mTextView.setText(cache.workProfilePauseButton);
- }
-
- getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
+ updateStringFromCache();
}
@Override
@@ -108,7 +101,7 @@
if (lp != null) {
int bottomMargin = getResources().getDimensionPixelSize(R.dimen.work_fab_margin_bottom);
DeviceProfile dp = ActivityContext.lookupContext(getContext()).getDeviceProfile();
- if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+ if (mActivityContext.getAppsView().isSearchBarFloating()) {
bottomMargin += dp.hotseatQsbHeight;
}
@@ -213,4 +206,11 @@
public int getScrollThreshold() {
return mScrollThreshold;
}
+
+ public void updateStringFromCache(){
+ StringCache cache = mActivityContext.getStringCache();
+ if (cache != null) {
+ mTextView.setText(cache.workProfilePauseButton);
+ }
+ }
}
diff --git a/src/com/android/launcher3/allapps/WorkPausedCard.java b/src/com/android/launcher3/allapps/WorkPausedCard.java
index 26a7803..1882667 100644
--- a/src/com/android/launcher3/allapps/WorkPausedCard.java
+++ b/src/com/android/launcher3/allapps/WorkPausedCard.java
@@ -57,6 +57,10 @@
mBtn = findViewById(R.id.enable_work_apps);
mBtn.setOnClickListener(this);
+ updateStringFromCache();
+ }
+
+ public void updateStringFromCache() {
StringCache cache = mActivityContext.getStringCache();
if (cache != null) {
setWorkProfilePausedResources(cache);
diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java
index 44c233f..05ed9ba 100644
--- a/src/com/android/launcher3/allapps/WorkProfileManager.java
+++ b/src/com/android/launcher3/allapps/WorkProfileManager.java
@@ -25,7 +25,6 @@
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED;
-import static com.android.launcher3.testing.shared.TestProtocol.WORK_TAB_MISSING;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.os.Build;
@@ -47,13 +46,13 @@
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.function.Predicate;
+import java.util.stream.Stream;
/**
* Companion class for {@link ActivityAllAppsContainerView} to manage work tab and personal tab
@@ -144,10 +143,6 @@
}
private void updateCurrentState(@WorkProfileState int currentState) {
- if (TestProtocol.sDebugTracing) {
- Log.d(WORK_TAB_MISSING, "WorkProfileManager#updateCurrentState: " +
- currentState, new Throwable());
- }
mCurrentState = currentState;
if (getAH() != null) {
getAH().mAppsList.updateAdapterItems();
@@ -166,10 +161,6 @@
* Creates and attaches for profile toggle button to {@link ActivityAllAppsContainerView}
*/
public boolean attachWorkModeSwitch() {
- if (TestProtocol.sDebugTracing) {
- Log.d(WORK_TAB_MISSING, "ActivityAllAppsContainerView#attachWorkModeSwitch "
- + "mWorkModeSwitch: " + mWorkModeSwitch);
- }
if (!mAllApps.getAppsStore().hasModelFlag(
FLAG_HAS_SHORTCUT_PERMISSION | FLAG_QUIET_MODE_CHANGE_PERMISSION)) {
Log.e(TAG, "unable to attach work mode switch; Missing required permissions");
@@ -225,6 +216,10 @@
return mCurrentState != WorkProfileManager.STATE_DISABLED;
}
+ public boolean hasWorkApps() {
+ return Stream.of(mAllApps.getAppsStore().getApps()).anyMatch(mMatcher);
+ }
+
/**
* Adds work profile specific adapter items to adapterItems and returns number of items added
*/
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index 4427a49..ecbc7a9 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -160,7 +160,7 @@
* Focuses the search field to handle key events.
*/
public void focusSearchField() {
- mInput.showKeyboard();
+ mInput.showKeyboard(true /* shouldFocus */);
}
/**
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchUiDelegate.java b/src/com/android/launcher3/allapps/search/AllAppsSearchUiDelegate.java
new file mode 100644
index 0000000..2347bfd
--- /dev/null
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchUiDelegate.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.allapps.search;
+
+import android.view.LayoutInflater;
+import android.view.View;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.launcher3.R;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
+import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
+import com.android.launcher3.views.ActivityContext;
+
+import java.util.List;
+
+/** Initializes the search box and its interactions with All Apps. */
+public class AllAppsSearchUiDelegate {
+
+ protected final ActivityAllAppsContainerView<?> mAppsView;
+ protected final ActivityContext mActivityContext;
+
+ public AllAppsSearchUiDelegate(ActivityAllAppsContainerView<?> appsView) {
+ mAppsView = appsView;
+ mActivityContext = ActivityContext.lookupContext(mAppsView.getContext());
+ }
+
+ /** Invoked when an All Apps {@link RecyclerView} is initialized. */
+ public void onInitializeRecyclerView(RecyclerView rv) {
+ // Do nothing.
+ }
+
+ /** Invoked when search results are updated in All Apps. */
+ public void onSearchResultsChanged(List<AdapterItem> results, int searchResultCode) {
+ // Do nothing.
+ }
+
+ /** Invoked when transition animations to go to search is completed . */
+ public void onAnimateToSearchStateCompleted() {
+ // Do nothing
+ }
+
+ /** Invoked when the search bar has been added to All Apps. */
+ public void onInitializeSearchBar() {
+ // Do nothing.
+ }
+
+ /** Invoked when the search bar has been removed from All Apps. */
+ public void onDestroySearchBar() {
+ // Do nothing.
+ }
+
+ /** The layout inflater for All Apps and search UI. */
+ public LayoutInflater getLayoutInflater() {
+ return LayoutInflater.from(mAppsView.getContext());
+ }
+
+ /** Inflate the search bar for All Apps. */
+ public View inflateSearchBar() {
+ return getLayoutInflater().inflate(R.layout.search_container_all_apps, mAppsView, false);
+ }
+
+ /** Whether the search box is floating above the apps surface (inset by the IME). */
+ public boolean isSearchBarFloating() {
+ return false;
+ }
+
+ /** Creates the adapter provider for the main section. */
+ public SearchAdapterProvider<?> createMainAdapterProvider() {
+ return new DefaultSearchAdapterProvider(mActivityContext);
+ }
+}
diff --git a/src/com/android/launcher3/anim/AlphaUpdateListener.java b/src/com/android/launcher3/anim/AlphaUpdateListener.java
index 8dad1b4..4382174 100644
--- a/src/com/android/launcher3/anim/AlphaUpdateListener.java
+++ b/src/com/android/launcher3/anim/AlphaUpdateListener.java
@@ -53,8 +53,18 @@
}
public static void updateVisibility(View view) {
- if (view.getAlpha() < ALPHA_CUTOFF_THRESHOLD && view.getVisibility() != View.INVISIBLE) {
- view.setVisibility(View.INVISIBLE);
+ updateVisibility(view, View.INVISIBLE);
+ }
+
+ /**
+ * Update view's visibility.
+ *
+ * @param view View that needs to update visibility.
+ * @param hiddenVisibility {@link View#GONE} or {@link View#INVISIBLE}
+ */
+ public static void updateVisibility(View view, int hiddenVisibility) {
+ if (view.getAlpha() < ALPHA_CUTOFF_THRESHOLD && view.getVisibility() != hiddenVisibility) {
+ view.setVisibility(hiddenVisibility);
} else if (view.getAlpha() > ALPHA_CUTOFF_THRESHOLD
&& view.getVisibility() != View.VISIBLE) {
if (view instanceof ViewGroup) {
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index 1cc0c21..d11a51f 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -15,10 +15,10 @@
*/
package com.android.launcher3.anim;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.clampToProgress;
+import static com.android.app.animation.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.Utilities.boundToRange;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.clampToProgress;
-import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
import android.animation.Animator;
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
deleted file mode 100644
index e886543..0000000
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.anim;
-
-import android.graphics.Path;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
-import android.view.animation.OvershootInterpolator;
-import android.view.animation.PathInterpolator;
-
-import com.android.launcher3.Utilities;
-
-/**
- * Common interpolators used in Launcher
- */
-public class Interpolators {
-
- public static final Interpolator LINEAR = new LinearInterpolator();
-
- public static final Interpolator ACCEL = new AccelerateInterpolator();
- public static final Interpolator ACCEL_0_5 = new AccelerateInterpolator(0.5f);
- public static final Interpolator ACCEL_0_75 = new AccelerateInterpolator(0.75f);
- public static final Interpolator ACCEL_1_5 = new AccelerateInterpolator(1.5f);
- public static final Interpolator ACCEL_2 = new AccelerateInterpolator(2);
-
- public static final Interpolator DEACCEL = new DecelerateInterpolator();
- public static final Interpolator DEACCEL_1_5 = new DecelerateInterpolator(1.5f);
- public static final Interpolator DEACCEL_1_7 = new DecelerateInterpolator(1.7f);
- public static final Interpolator DEACCEL_2 = new DecelerateInterpolator(2);
- public static final Interpolator DEACCEL_2_5 = new DecelerateInterpolator(2.5f);
- public static final Interpolator DEACCEL_3 = new DecelerateInterpolator(3f);
-
- public static final Interpolator ACCEL_DEACCEL = new AccelerateDecelerateInterpolator();
-
- public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
-
- public static final Interpolator AGGRESSIVE_EASE = new PathInterpolator(0.2f, 0f, 0f, 1f);
- public static final Interpolator AGGRESSIVE_EASE_IN_OUT = new PathInterpolator(0.6f,0, 0.4f, 1);
-
- public static final Interpolator DECELERATED_EASE = new PathInterpolator(0, 0, .2f, 1f);
- public static final Interpolator ACCELERATED_EASE = new PathInterpolator(0.4f, 0, 1f, 1f);
- public static final Interpolator PREDICTIVE_BACK_DECELERATED_EASE =
- new PathInterpolator(0, 0, 0, 1f);
-
- /**
- * The default emphasized interpolator. Used for hero / emphasized movement of content.
- */
- public static final Interpolator EMPHASIZED = createEmphasizedInterpolator();
- public static final Interpolator EMPHASIZED_ACCELERATE = new PathInterpolator(
- 0.3f, 0f, 0.8f, 0.15f);
- public static final Interpolator EMPHASIZED_DECELERATE = new PathInterpolator(
- 0.05f, 0.7f, 0.1f, 1f);
-
- public static final Interpolator EXAGGERATED_EASE;
-
- public static final Interpolator INSTANT = t -> 1;
- /**
- * All values of t map to 0 until t == 1. This is primarily useful for setting view visibility,
- * which should only happen at the very end of the animation (when it's already hidden).
- */
- public static final Interpolator FINAL_FRAME = t -> t < 1 ? 0 : 1;
-
- static {
- Path exaggeratedEase = new Path();
- exaggeratedEase.moveTo(0, 0);
- exaggeratedEase.cubicTo(0.05f, 0f, 0.133333f, 0.08f, 0.166666f, 0.4f);
- exaggeratedEase.cubicTo(0.225f, 0.94f, 0.5f, 1f, 1f, 1f);
- EXAGGERATED_EASE = new PathInterpolator(exaggeratedEase);
- }
-
- public static final Interpolator OVERSHOOT_0_75 = new OvershootInterpolator(0.75f);
- public static final Interpolator OVERSHOOT_1_2 = new OvershootInterpolator(1.2f);
- public static final Interpolator OVERSHOOT_1_7 = new OvershootInterpolator(1.7f);
-
- public static final Interpolator TOUCH_RESPONSE_INTERPOLATOR =
- new PathInterpolator(0.3f, 0f, 0.1f, 1f);
- public static final Interpolator TOUCH_RESPONSE_INTERPOLATOR_ACCEL_DEACCEL =
- v -> ACCEL_DEACCEL.getInterpolation(TOUCH_RESPONSE_INTERPOLATOR.getInterpolation(v));
-
- /**
- * Inversion of ZOOM_OUT, compounded with an ease-out.
- */
- public static final Interpolator ZOOM_IN = new Interpolator() {
- @Override
- public float getInterpolation(float v) {
- return DEACCEL_3.getInterpolation(1 - ZOOM_OUT.getInterpolation(1 - v));
- }
- };
-
- public static final Interpolator ZOOM_OUT = new Interpolator() {
-
- private static final float FOCAL_LENGTH = 0.35f;
-
- @Override
- public float getInterpolation(float v) {
- return zInterpolate(v);
- }
-
- /**
- * This interpolator emulates the rate at which the perceived scale of an object changes
- * as its distance from a camera increases. When this interpolator is applied to a scale
- * animation on a view, it evokes the sense that the object is shrinking due to moving away
- * from the camera.
- */
- private float zInterpolate(float input) {
- return (1.0f - FOCAL_LENGTH / (FOCAL_LENGTH + input)) /
- (1.0f - FOCAL_LENGTH / (FOCAL_LENGTH + 1.0f));
- }
- };
-
- public static final Interpolator SCROLL = new Interpolator() {
- @Override
- public float getInterpolation(float t) {
- t -= 1.0f;
- return t*t*t*t*t + 1;
- }
- };
-
- public static final Interpolator SCROLL_CUBIC = new Interpolator() {
- @Override
- public float getInterpolation(float t) {
- t -= 1.0f;
- return t*t*t + 1;
- }
- };
-
- private static final float FAST_FLING_PX_MS = 10;
-
- public static Interpolator scrollInterpolatorForVelocity(float velocity) {
- return Math.abs(velocity) > FAST_FLING_PX_MS ? SCROLL : SCROLL_CUBIC;
- }
-
- /**
- * Create an OvershootInterpolator with tension directly related to the velocity (in px/ms).
- * @param velocity The start velocity of the animation we want to overshoot.
- */
- public static Interpolator overshootInterpolatorForVelocity(float velocity) {
- return new OvershootInterpolator(Math.min(Math.abs(velocity), 3f));
- }
-
- /**
- * Returns a function that runs the given interpolator such that the entire progress is set
- * between the given bounds. That is, we set the interpolation to 0 until lowerBound and reach
- * 1 by upperBound.
- */
- public static Interpolator clampToProgress(Interpolator interpolator, float lowerBound,
- float upperBound) {
- if (upperBound < lowerBound) {
- throw new IllegalArgumentException(
- String.format("upperBound (%f) must be greater than lowerBound (%f)",
- upperBound, lowerBound));
- }
- return t -> clampToProgress(interpolator, t, lowerBound, upperBound);
- }
-
- /**
- * Returns the progress value's progress between the lower and upper bounds. That is, the
- * progress will be 0f from 0f to lowerBound, and reach 1f by upperBound.
- *
- * Between lowerBound and upperBound, the progress value will be interpolated using the provided
- * interpolator.
- */
- public static float clampToProgress(
- Interpolator interpolator, float progress, float lowerBound, float upperBound) {
- if (upperBound < lowerBound) {
- throw new IllegalArgumentException(
- String.format("upperBound (%f) must be greater than lowerBound (%f)",
- upperBound, lowerBound));
- }
-
- if (progress == lowerBound && progress == upperBound) {
- return progress == 0f ? 0 : 1;
- }
- if (progress < lowerBound) {
- return 0;
- }
- if (progress > upperBound) {
- return 1;
- }
- return interpolator.getInterpolation((progress - lowerBound) / (upperBound - lowerBound));
- }
-
- /**
- * Returns the progress value's progress between the lower and upper bounds. That is, the
- * progress will be 0f from 0f to lowerBound, and reach 1f by upperBound.
- */
- public static float clampToProgress(float progress, float lowerBound, float upperBound) {
- return clampToProgress(Interpolators.LINEAR, progress, lowerBound, upperBound);
- }
-
- /**
- * Runs the given interpolator such that the interpolated value is mapped to the given range.
- * This is useful, for example, if we only use this interpolator for part of the animation,
- * such as to take over a user-controlled animation when they let go.
- */
- public static Interpolator mapToProgress(Interpolator interpolator, float lowerBound,
- float upperBound) {
- return t -> Utilities.mapRange(interpolator.getInterpolation(t), lowerBound, upperBound);
- }
-
- /**
- * Returns the reverse of the provided interpolator, following the formula: g(x) = 1 - f(1 - x).
- * In practice, this means that if f is an interpolator used to model a value animating between
- * m and n, g is the interpolator to use to obtain the specular behavior when animating from n
- * to m.
- */
- public static Interpolator reverse(Interpolator interpolator) {
- return t -> 1 - interpolator.getInterpolation(1 - t);
- }
-
- // Create the default emphasized interpolator
- private static PathInterpolator createEmphasizedInterpolator() {
- Path path = new Path();
- // Doing the same as fast_out_extra_slow_in
- path.moveTo(0f, 0f);
- path.cubicTo(0.05f, 0f, 0.133333f, 0.06f, 0.166666f, 0.4f);
- path.cubicTo(0.208333f, 0.82f, 0.25f, 1f, 1f, 1f);
- return new PathInterpolator(path);
- }
-}
diff --git a/src/com/android/launcher3/anim/KeyboardInsetAnimationCallback.java b/src/com/android/launcher3/anim/KeyboardInsetAnimationCallback.java
index b911928..39386fa 100644
--- a/src/com/android/launcher3/anim/KeyboardInsetAnimationCallback.java
+++ b/src/com/android/launcher3/anim/KeyboardInsetAnimationCallback.java
@@ -44,14 +44,30 @@
private float mInitialTranslation;
private float mTerminalTranslation;
+ private KeyboardTranslationState mKeyboardTranslationState = KeyboardTranslationState.SYSTEM;
+
+ /** Current state of the keyboard. */
+ public enum KeyboardTranslationState {
+ // We are not controlling the keyboard, and it may or may not be translating.
+ SYSTEM,
+ // We are about to gain control of the keyboard, but the current state may be transient.
+ MANUAL_PREPARED,
+ // We are manually translating the keyboard.
+ MANUAL_ONGOING
+ }
public KeyboardInsetAnimationCallback(View view) {
super(DISPATCH_MODE_STOP);
mView = view;
}
+ public KeyboardTranslationState getKeyboardTranslationState() {
+ return mKeyboardTranslationState;
+ }
+
@Override
public void onPrepare(WindowInsetsAnimation animation) {
+ mKeyboardTranslationState = KeyboardTranslationState.MANUAL_PREPARED;
mInitialTranslation = mView.getTranslationY();
}
@@ -62,6 +78,7 @@
mTerminalTranslation = mView.getTranslationY();
// Reset the translation in case the view is drawn before onProgress gets called.
mView.setTranslationY(mInitialTranslation);
+ mKeyboardTranslationState = KeyboardTranslationState.MANUAL_ONGOING;
if (mView instanceof KeyboardInsetListener) {
((KeyboardInsetListener) mView).onTranslationStart();
}
@@ -90,6 +107,10 @@
mView.setTranslationY(translationY);
}
+ if (mView instanceof KeyboardInsetListener) {
+ ((KeyboardInsetListener) mView).onKeyboardAlphaChanged(animation.getAlpha());
+ }
+
return windowInsets;
}
@@ -98,7 +119,7 @@
if (mView instanceof KeyboardInsetListener) {
((KeyboardInsetListener) mView).onTranslationEnd();
}
- super.onEnd(animation);
+ mKeyboardTranslationState = KeyboardTranslationState.SYSTEM;
}
/**
@@ -111,6 +132,13 @@
void onTranslationStart();
/**
+ * Called from {@link KeyboardInsetAnimationCallback#onProgress}
+ *
+ * @param alpha the current IME alpha
+ */
+ default void onKeyboardAlphaChanged(float alpha) {}
+
+ /**
* Called from {@link KeyboardInsetAnimationCallback#onEnd}
*/
void onTranslationEnd();
diff --git a/src/com/android/launcher3/anim/SpringAnimationBuilder.java b/src/com/android/launcher3/anim/SpringAnimationBuilder.java
index 40fa0cf..bc7b7f0 100644
--- a/src/com/android/launcher3/anim/SpringAnimationBuilder.java
+++ b/src/com/android/launcher3/anim/SpringAnimationBuilder.java
@@ -15,7 +15,7 @@
*/
package com.android.launcher3.anim;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.LINEAR;
import android.animation.Animator;
import android.animation.ValueAnimator;
diff --git a/src/com/android/launcher3/apppairs/AppPairIcon.java b/src/com/android/launcher3/apppairs/AppPairIcon.java
new file mode 100644
index 0000000..1dc4ad2
--- /dev/null
+++ b/src/com/android/launcher3/apppairs/AppPairIcon.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.apppairs;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.R;
+import com.android.launcher3.dragndrop.DraggableView;
+import com.android.launcher3.model.data.FolderInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.views.ActivityContext;
+
+import java.util.Collections;
+import java.util.Comparator;
+
+/**
+ * A {@link android.widget.FrameLayout} used to represent an app pair icon on the workspace.
+ */
+public class AppPairIcon extends FrameLayout implements DraggableView {
+
+ private ActivityContext mActivity;
+ private BubbleTextView mAppPairName;
+ private FolderInfo mInfo;
+
+ public AppPairIcon(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public AppPairIcon(Context context) {
+ super(context);
+ }
+
+ /**
+ * Builds an AppPairIcon to be added to the Launcher
+ */
+ public static AppPairIcon inflateIcon(int resId, ActivityContext activity,
+ @Nullable ViewGroup group, FolderInfo appPairInfo) {
+
+ LayoutInflater inflater = (group != null)
+ ? LayoutInflater.from(group.getContext())
+ : activity.getLayoutInflater();
+ AppPairIcon icon = (AppPairIcon) inflater.inflate(resId, group, false);
+
+ // Sort contents, so that left-hand app comes first
+ Collections.sort(appPairInfo.contents, Comparator.comparingInt(a -> a.rank));
+
+ icon.setClipToPadding(false);
+ icon.mAppPairName = icon.findViewById(R.id.app_pair_icon_name);
+
+ // TODO (jeremysim b/274189428): Replace this placeholder icon
+ WorkspaceItemInfo placeholder = new WorkspaceItemInfo();
+ placeholder.newIcon(icon.getContext());
+ icon.mAppPairName.applyFromWorkspaceItem(placeholder);
+
+ icon.mAppPairName.setText(appPairInfo.title);
+
+ icon.setTag(appPairInfo);
+ icon.setOnClickListener(activity.getItemOnClickListener());
+ icon.mInfo = appPairInfo;
+ icon.mActivity = activity;
+
+ icon.setAccessibilityDelegate(activity.getAccessibilityDelegate());
+
+ return icon;
+ }
+
+ @Override
+ public int getViewType() {
+ return DRAGGABLE_ICON;
+ }
+
+ @Override
+ public void getWorkspaceVisualDragBounds(Rect bounds) {
+ mAppPairName.getIconBounds(bounds);
+ }
+
+ public FolderInfo getInfo() {
+ return mInfo;
+ }
+}
diff --git a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
index 24cc0ac..d37b1f0 100644
--- a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
+++ b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
@@ -74,38 +74,12 @@
Log.d(TestProtocol.PERMANENT_DIAG_TAG, "sendStateEventToTest: " + stateOrdinal);
}
- public static void sendScrollFinishedEventToTest(Context context) {
+ public static void sendTestProtocolEventToTest(Context context, String testProtocolEvent) {
final AccessibilityManager accessibilityManager = getAccessibilityManagerForTest(context);
if (accessibilityManager == null) return;
- sendEventToTest(accessibilityManager, context, TestProtocol.SCROLL_FINISHED_MESSAGE, null);
+ sendEventToTest(accessibilityManager, context, testProtocolEvent, null);
}
-
- public static void sendPauseDetectedEventToTest(Context context) {
- final AccessibilityManager accessibilityManager = getAccessibilityManagerForTest(context);
- if (accessibilityManager == null) return;
-
- sendEventToTest(accessibilityManager, context, TestProtocol.PAUSE_DETECTED_MESSAGE, null);
- }
-
- public static void sendDismissAnimationEndsEventToTest(Context context) {
- final AccessibilityManager accessibilityManager = getAccessibilityManagerForTest(context);
- if (accessibilityManager == null) return;
-
- sendEventToTest(accessibilityManager, context, TestProtocol.DISMISS_ANIMATION_ENDS_MESSAGE,
- null);
- }
-
- /**
- * Notify running tests of a folder opened.
- */
- public static void sendFolderOpenedEventToTest(Context context) {
- final AccessibilityManager accessibilityManager = getAccessibilityManagerForTest(context);
- if (accessibilityManager == null) return;
-
- sendEventToTest(accessibilityManager, context, TestProtocol.FOLDER_OPENED_MESSAGE, null);
- }
-
private static void sendEventToTest(
AccessibilityManager accessibilityManager,
Context context, String eventTag, Bundle data) {
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 76574b6..2da85e1 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -27,6 +27,7 @@
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.BuildConfig;
+import com.android.launcher3.Flags;
import com.android.launcher3.Utilities;
import java.util.function.Predicate;
@@ -82,15 +83,12 @@
* <p>
*/
// TODO(Block 1): Clean up flags
- public static final BooleanFlag ENABLE_ONE_SEARCH_MOTION = getReleaseFlag(270394223,
- "ENABLE_ONE_SEARCH_MOTION", ENABLED, "Enables animations in OneSearch.");
-
public static final BooleanFlag ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES = getReleaseFlag(
- 270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", DISABLED,
+ 270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", ENABLED,
"Enable option to replace decorator-based search result backgrounds with drawables");
public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = getReleaseFlag(
- 270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", DISABLED,
+ 270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", ENABLED,
"Enable option to launch search results using the new view container transitions");
// TODO(Block 2): Clean up flags
@@ -119,7 +117,8 @@
// TODO(Block 4): Cleanup flags
public static final BooleanFlag ENABLE_FLOATING_SEARCH_BAR =
getReleaseFlag(268388460, "ENABLE_FLOATING_SEARCH_BAR", DISABLED,
- "Keep All Apps search bar at the bottom (but above keyboard if open)");
+ "Allow search bar to persist and animate across states, and attach to"
+ + " the keyboard from the bottom of the screen");
public static final BooleanFlag ENABLE_ALL_APPS_FROM_OVERVIEW =
getDebugFlag(275132633, "ENABLE_ALL_APPS_FROM_OVERVIEW", DISABLED,
@@ -131,7 +130,7 @@
// TODO(Block 5): Clean up flags
public static final BooleanFlag ENABLE_TWOLINE_DEVICESEARCH = getDebugFlag(201388851,
- "ENABLE_TWOLINE_DEVICESEARCH", TEAMFOOD,
+ "ENABLE_TWOLINE_DEVICESEARCH", ENABLED,
"Enable two line label for icons with labels on device search.");
public static final BooleanFlag ENABLE_ICON_IN_TEXT_HEADER = getDebugFlag(270395143,
@@ -143,7 +142,7 @@
// TODO(Block 6): Clean up flags
public static final BooleanFlag ENABLE_ALL_APPS_SEARCH_IN_TASKBAR = getDebugFlag(270393900,
- "ENABLE_ALL_APPS_SEARCH_IN_TASKBAR", DISABLED,
+ "ENABLE_ALL_APPS_SEARCH_IN_TASKBAR", TEAMFOOD,
"Enables Search box in Taskbar All Apps.");
public static final BooleanFlag SECONDARY_DRAG_N_DROP_TO_PIN = getDebugFlag(270395140,
@@ -156,8 +155,6 @@
"Enable the ability to generate monochromatic icons, if it is not provided by the app");
// TODO(Block 8): Clean up flags
- public static final BooleanFlag ENABLE_MATERIAL_U_POPUP = getDebugFlag(270395516,
- "ENABLE_MATERIAL_U_POPUP", ENABLED, "Switch popup UX to use material U");
// TODO(Block 9): Clean up flags
public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V2 = getReleaseFlag(270395134,
@@ -175,27 +172,30 @@
"LARGE_SCREEN_WIDGET_PICKER", ENABLED, "Enable new widget picker that takes "
+ "advantage of large screen format");
+ public static final BooleanFlag UNFOLDED_WIDGET_PICKER = getDebugFlag(301918659,
+ "UNFOLDED_WIDGET_PICKER", DISABLED, "Enable new widget picker that takes "
+ + "advantage of the unfolded foldable format");
+
public static final BooleanFlag MULTI_SELECT_EDIT_MODE = getDebugFlag(270709220,
"MULTI_SELECT_EDIT_MODE", DISABLED, "Enable new multi-select edit mode "
+ "for home screen");
+ public static final BooleanFlag SMARTSPACE_AS_A_WIDGET = getDebugFlag(299181941,
+ "SMARTSPACE_AS_A_WIDGET", DISABLED, "Enable SmartSpace as a widget");
+
// TODO(Block 10): Clean up flags
public static final BooleanFlag ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION = getDebugFlag(270614790,
"ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION", DISABLED,
"Enables predictive back animation from all apps and widgets to home");
// TODO(Block 11): Clean up flags
- public static final BooleanFlag ENABLE_TWO_PANEL_HOME = getDebugFlag(270392643,
- "ENABLE_TWO_PANEL_HOME", ENABLED,
- "Uses two panel on home screen. Only applicable on large screen devices.");
-
- public static final BooleanFlag FOLDABLE_WORKSPACE_REORDER = getDebugFlag(270395070,
- "FOLDABLE_WORKSPACE_REORDER", DISABLED,
- "In foldables, when reordering the icons and widgets, is now going to use both sides");
-
public static final BooleanFlag FOLDABLE_SINGLE_PAGE = getDebugFlag(270395274,
"FOLDABLE_SINGLE_PAGE", DISABLED, "Use a single page for the workspace");
+ public static final BooleanFlag ENABLE_PARAMETRIZE_REORDER = getDebugFlag(289420844,
+ "ENABLE_PARAMETRIZE_REORDER", DISABLED,
+ "Enables generating the reorder using a set of parameters");
+
// TODO(Block 12): Clean up flags
public static final BooleanFlag ENABLE_MULTI_INSTANCE = getDebugFlag(270396680,
"ENABLE_MULTI_INSTANCE", DISABLED,
@@ -213,6 +213,10 @@
public static final BooleanFlag ENABLE_TRANSIENT_TASKBAR = getDebugFlag(270395798,
"ENABLE_TRANSIENT_TASKBAR", ENABLED, "Enables transient taskbar.");
+ public static final BooleanFlag ENABLE_TASKBAR_NO_RECREATION = getDebugFlag(299193589,
+ "ENABLE_TASKBAR_NO_RECREATION", DISABLED,
+ "Enables taskbar with no recreation from lifecycle changes of TaskbarActivityContext.");
+
// TODO(Block 16): Clean up flags
// When enabled the promise icon is visible in all apps while installation an app.
public static final BooleanFlag PROMISE_APPS_IN_ALL_APPS = getDebugFlag(270390012,
@@ -228,6 +232,7 @@
public static final BooleanFlag ENABLE_HIDE_HEADER = getReleaseFlag(270390930,
"ENABLE_HIDE_HEADER", ENABLED, "Hide header on keyboard before typing in all apps");
+ // Aconfig migration complete for ENABLE_EXPANDING_PAUSE_WORK_BUTTON.
public static final BooleanFlag ENABLE_EXPANDING_PAUSE_WORK_BUTTON = getDebugFlag(270390779,
"ENABLE_EXPANDING_PAUSE_WORK_BUTTON", DISABLED,
"Expand and collapse pause work button while scrolling");
@@ -235,8 +240,9 @@
public static final BooleanFlag COLLECT_SEARCH_HISTORY = getReleaseFlag(270391455,
"COLLECT_SEARCH_HISTORY", DISABLED, "Allow launcher to collect search history for log");
+ // Aconfig migration complete for ENABLE_TWOLINE_ALLAPPS.
public static final BooleanFlag ENABLE_TWOLINE_ALLAPPS = getDebugFlag(270390937,
- "ENABLE_TWOLINE_ALLAPPS", TEAMFOOD, "Enables two line label inside all apps.");
+ "ENABLE_TWOLINE_ALLAPPS", DISABLED, "Enables two line label inside all apps.");
public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(270391693,
"IME_STICKY_SNACKBAR_EDU", ENABLED, "Show sticky IME edu in AllApps");
@@ -253,18 +259,22 @@
"INJECT_FALLBACK_APP_CORPUS_RESULTS", DISABLED,
"Inject fallback app corpus result when AiAi fails to return it.");
+ public static final BooleanFlag ENABLE_LONG_PRESS_NAV_HANDLE =
+ getReleaseFlag(282993230, "ENABLE_LONG_PRESS_NAV_HANDLE", TEAMFOOD,
+ "Enables long pressing on the bottom bar nav handle to trigger events.");
+
// TODO(Block 17): Clean up flags
public static final BooleanFlag ENABLE_TASKBAR_PINNING = getDebugFlag(270396583,
"ENABLE_TASKBAR_PINNING", DISABLED,
"Enables taskbar pinning to allow user to switch between transient and persistent "
+ "taskbar flavors");
- // TODO(Block 18): Clean up flags
- public static final BooleanFlag ENABLE_LAUNCH_FROM_STAGED_APP = getDebugFlag(270395567,
- "ENABLE_LAUNCH_FROM_STAGED_APP", ENABLED,
- "Enable the ability to tap a staged app during split select to launch it in full "
- + "screen");
+ public static final BooleanFlag ENABLE_BOOT_AWARE_STARTUP_DATA = getDebugFlag(251502424,
+ "ENABLE_BOOT_AWARE_STARTUP_DATA", DISABLED, "Marks LauncherPref data as (and allows it "
+ + "to) available while the device is locked. Enabling this causes a 1-time "
+ + "migration of certain SharedPreferences data. Improves startup latency.");
+ // TODO(Block 18): Clean up flags
public static final BooleanFlag ENABLE_APP_PAIRS = getDebugFlag(274189428,
"ENABLE_APP_PAIRS", DISABLED,
"Enables the ability to create and save app pairs on the Home screen for easy"
@@ -277,7 +287,7 @@
+ " is enabled or in prefix state");
public static final BooleanFlag ENABLE_SEARCH_UNINSTALLED_APPS = getReleaseFlag(270395269,
- "ENABLE_SEARCH_UNINSTALLED_APPS", DISABLED, "Search uninstalled app results.");
+ "ENABLE_SEARCH_UNINSTALLED_APPS", ENABLED, "Search uninstalled app results.");
// TODO(Block 20): Clean up flags
public static final BooleanFlag ENABLE_SCRIM_FOR_APP_LAUNCH = getDebugFlag(270393276,
@@ -287,16 +297,15 @@
"ENABLE_BACK_SWIPE_HOME_ANIMATION", ENABLED,
"Enables home animation to icon when user swipes back.");
+ public static final BooleanFlag ENABLE_DYNAMIC_TASKBAR_THRESHOLDS = getDebugFlag(294252473,
+ "ENABLE_DYNAMIC_TASKBAR_THRESHOLDS", ENABLED,
+ "Enables taskbar thresholds that scale based on screen size.");
+
// TODO(Block 21): Clean up flags
public static final BooleanFlag ENABLE_APP_ICON_FOR_INLINE_SHORTCUTS = getDebugFlag(270395087,
"ENABLE_APP_ICON_IN_INLINE_SHORTCUTS", DISABLED, "Show app icon for inline shortcut");
// TODO(Block 22): Clean up flags
- public static final BooleanFlag RECEIVE_UNFOLD_EVENTS_FROM_SYSUI = getDebugFlag(270397209,
- "RECEIVE_UNFOLD_EVENTS_FROM_SYSUI", ENABLED,
- "Enables receiving unfold animation events from sysui instead of calculating "
- + "them in launcher process using hinge sensor values.");
-
public static final BooleanFlag ENABLE_WIDGET_TRANSITION_FOR_RESIZING = getDebugFlag(268553314,
"ENABLE_WIDGET_TRANSITION_FOR_RESIZING", DISABLED,
"Enable widget transition animation when resizing the widgets");
@@ -308,13 +317,23 @@
+ "start receiving the events");
// TODO(Block 23): Clean up flags
+ // Aconfig migration complete for ENABLE_GRID_ONLY_OVERVIEW.
+ @VisibleForTesting
public static final BooleanFlag ENABLE_GRID_ONLY_OVERVIEW = getDebugFlag(270397206,
- "ENABLE_GRID_ONLY_OVERVIEW", DISABLED,
+ "ENABLE_GRID_ONLY_OVERVIEW", TEAMFOOD,
"Enable a grid-only overview without a focused task.");
+ public static boolean enableGridOnlyOverview() {
+ return ENABLE_GRID_ONLY_OVERVIEW.get() || Flags.enableGridOnlyOverview();
+ }
+ // Aconfig migration complete for ENABLE_CURSOR_HOVER_STATES.
+ @VisibleForTesting
public static final BooleanFlag ENABLE_CURSOR_HOVER_STATES = getDebugFlag(243191650,
- "ENABLE_CURSOR_HOVER_STATES", DISABLED,
+ "ENABLE_CURSOR_HOVER_STATES", TEAMFOOD,
"Enables cursor hover states for certain elements.");
+ public static boolean enableCursorHoverStates() {
+ return ENABLE_CURSOR_HOVER_STATES.get() || Flags.enableCursorHoverStates();
+ }
// TODO(Block 24): Clean up flags
public static final BooleanFlag ENABLE_NEW_MIGRATION_LOGIC = getDebugFlag(270393455,
@@ -368,10 +387,6 @@
"Use inbuilt monochrome icons if app doesn't provide one");
// TODO(Block 28): Clean up flags
- public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE = getDebugFlag(270393906,
- "ENABLE_SPLIT_FROM_WORKSPACE", ENABLED,
- "Enable initiating split screen from workspace.");
-
public static final BooleanFlag ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS =
getDebugFlag(270394122, "ENABLE_SPLIT_FROM_FULLSCREEN_SHORTCUT", DISABLED,
"Enable splitting from fullscreen app with keyboard shortcuts");
@@ -380,8 +395,12 @@
270393453, "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", DISABLED,
"Enable initiating split screen from workspace to workspace.");
+ public static final BooleanFlag ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE = getDebugFlag(
+ 279586624, "ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE", DISABLED,
+ "Enable initiating split screen from desktop mode to workspace.");
+
public static final BooleanFlag ENABLE_TRACKPAD_GESTURE = getDebugFlag(271010401,
- "ENABLE_TRACKPAD_GESTURE", DISABLED, "Enables trackpad gesture.");
+ "ENABLE_TRACKPAD_GESTURE", ENABLED, "Enables trackpad gesture.");
// TODO(Block 29): Clean up flags
public static final BooleanFlag ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT = getDebugFlag(270393897,
@@ -400,17 +419,25 @@
"USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES", DISABLED,
"Use local overrides for search request timeout");
- // TODO(Block 31)
- public static final BooleanFlag ENABLE_SPLIT_LAUNCH_DATA_REFACTOR = getDebugFlag(279494325,
- "ENABLE_SPLIT_LAUNCH_DATA_REFACTOR", ENABLED,
- "Use refactored split launching code path");
+ // TODO(Block 31): Clean up flags
- // TODO(Block 32): Empty block
-
+ // TODO(Block 32): Clean up flags
public static final BooleanFlag ENABLE_RESPONSIVE_WORKSPACE = getDebugFlag(241386436,
"ENABLE_RESPONSIVE_WORKSPACE", DISABLED,
"Enables new workspace grid calculations method.");
+ // TODO(Block 33): Clean up flags
+ public static final BooleanFlag ENABLE_ALL_APPS_RV_PREINFLATION = getDebugFlag(288161355,
+ "ENABLE_ALL_APPS_RV_PREINFLATION", ENABLED,
+ "Enables preinflating all apps icons to avoid scrolling jank.");
+
+ // TODO(Block 34): Clean up flags
+ public static final BooleanFlag ALL_APPS_GONE_VISIBILITY = getDebugFlag(291651514,
+ "ALL_APPS_GONE_VISIBILITY", ENABLED,
+ "Set all apps container view's hidden visibility to GONE instead of INVISIBLE.");
+
+ // TODO(Block 35): Empty block
+
public static class BooleanFlag {
private final boolean mCurrentValue;
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index 00f4285..213c458 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -26,7 +26,6 @@
import static com.android.launcher3.widget.WidgetSections.NO_CATEGORY;
import android.annotation.TargetApi;
-import android.app.ActivityOptions;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ClipData;
@@ -68,6 +67,7 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.pm.PinRequestHelper;
+import com.android.launcher3.uioverrides.ApiWrapper;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.views.AbstractSlideInView;
@@ -259,9 +259,7 @@
.setPackage(getPackageName())
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Launcher.ACTIVITY_TRACKER.registerCallback(listener);
- startActivity(homeIntent,
- ActivityOptions.makeCustomAnimation(this, 0, android.R.anim.fade_out)
- .toBundle());
+ startActivity(homeIntent, ApiWrapper.createFadeOutAnimOptions(this).toBundle());
logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_DRAGGED);
mFinishOnPause = true;
return false;
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 9867268..0d51d48 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -28,9 +28,9 @@
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index 366870b..f18f900 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -19,11 +19,11 @@
import static android.animation.ObjectAnimator.ofFloat;
+import static com.android.app.animation.Interpolators.DECELERATE_1_5;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.Utilities.mapRange;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5;
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
import android.animation.Animator;
@@ -42,6 +42,7 @@
import android.view.accessibility.AccessibilityManager;
import android.view.animation.Interpolator;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DropTargetBar;
import com.android.launcher3.Launcher;
@@ -49,7 +50,6 @@
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.SpringProperty;
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
@@ -340,14 +340,14 @@
if (duration < 0) {
duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
if (dist < maxDist) {
- duration *= DEACCEL_1_5.getInterpolation(dist / maxDist);
+ duration *= DECELERATE_1_5.getInterpolation(dist / maxDist);
}
duration = Math.max(duration, res.getInteger(R.integer.config_dropAnimMinDuration));
}
// Fall back to cubic ease out interpolator for the animation if none is specified
TimeInterpolator interpolator =
- motionInterpolator == null ? DEACCEL_1_5 : motionInterpolator;
+ motionInterpolator == null ? DECELERATE_1_5 : motionInterpolator;
// Animate the view
PendingAnimation anim = new PendingAnimation(duration);
@@ -475,7 +475,7 @@
@Override
public void onOverlayScrollChanged(float progress) {
- float alpha = 1 - Interpolators.DEACCEL_3.getInterpolation(progress);
+ float alpha = 1 - Interpolators.DECELERATE_3.getInterpolation(progress);
float transX = getMeasuredWidth() * progress;
if (mIsRtl) {
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 0d0717e..c2d9e02 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -20,7 +20,6 @@
import static android.view.View.MeasureSpec.makeMeasureSpec;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
-import static com.android.launcher3.Utilities.getBadge;
import static com.android.launcher3.icons.FastBitmapDrawable.getDisabledColorFilter;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -45,6 +44,7 @@
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
+import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
@@ -55,9 +55,9 @@
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.data.ItemInfo;
@@ -99,7 +99,9 @@
// Whether mAnim has started. Unlike mAnim.isStarted(), this is true even after mAnim ends.
private boolean mScaleAnimStarted;
- private Runnable mOnAnimEndCallback = null;
+ private boolean mShiftAnimStarted;
+ private Runnable mOnScaleAnimEndCallback;
+ private Runnable mOnShiftAnimEndCallback;
private int mLastTouchX;
private int mLastTouchY;
@@ -186,13 +188,26 @@
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
- if (mOnAnimEndCallback != null) {
- mOnAnimEndCallback.run();
+ if (mOnScaleAnimEndCallback != null) {
+ mOnScaleAnimEndCallback.run();
}
}
});
// Set up the shift animator.
mShiftAnim = ValueAnimator.ofFloat(0f, 1f);
+ mShiftAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mShiftAnimStarted = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mOnShiftAnimEndCallback != null) {
+ mOnShiftAnimEndCallback.run();
+ }
+ }
+ });
setDragRegion(new Rect(0, 0, width, height));
@@ -211,8 +226,14 @@
setWillNotDraw(false);
}
- public void setOnAnimationEndCallback(Runnable callback) {
- mOnAnimEndCallback = callback;
+ /** Callback invoked when the scale animation ends. */
+ public void setOnScaleAnimEndCallback(Runnable callback) {
+ mOnScaleAnimEndCallback = callback;
+ }
+
+ /** Callback invoked when the shift animation ends. */
+ public void setOnShiftAnimEndCallback(Runnable callback) {
+ mOnShiftAnimEndCallback = callback;
}
/**
@@ -223,13 +244,12 @@
public void setItemInfo(final ItemInfo info) {
// Load the adaptive icon on a background thread and add the view in ui thread.
MODEL_EXECUTOR.getHandler().postAtFrontOfQueue(() -> {
- Object[] outObj = new Object[1];
int w = mWidth;
int h = mHeight;
- Drawable dr = Utilities.getFullDrawable(mActivity, info, w, h,
- true /* shouldThemeIcon */, outObj);
-
- if (dr instanceof AdaptiveIconDrawable) {
+ Pair<AdaptiveIconDrawable, Drawable> fullDrawable = Utilities.getFullDrawable(
+ mActivity, info, w, h, true /* shouldThemeIcon */);
+ if (fullDrawable != null) {
+ AdaptiveIconDrawable adaptiveIcon = fullDrawable.first;
int blurMargin = (int) mActivity.getResources()
.getDimension(R.dimen.blur_size_medium_outline) / 2;
@@ -237,24 +257,15 @@
bounds.inset(blurMargin, blurMargin);
// Badge is applied after icon normalization so the bounds for badge should not
// be scaled down due to icon normalization.
- mBadge = getBadge(mActivity, info, outObj[0]);
+ mBadge = fullDrawable.second;
FastBitmapDrawable.setBadgeBounds(mBadge, bounds);
- // Do not draw the background in case of folder as its translucent
- final boolean shouldDrawBackground = !(dr instanceof FolderAdaptiveIcon);
-
try (LauncherIcons li = LauncherIcons.obtain(mActivity)) {
- Drawable nDr; // drawable to be normalized
- if (shouldDrawBackground) {
- nDr = dr;
- } else {
- // Since we just want the scale, avoid heavy drawing operations
- nDr = new AdaptiveIconDrawable(new ColorDrawable(Color.BLACK), null);
- }
- Utilities.scaleRectAboutCenter(bounds,
- li.getNormalizer().getScale(nDr, null, null, null));
+ // Since we just want the scale, avoid heavy drawing operations
+ Utilities.scaleRectAboutCenter(bounds, li.getNormalizer().getScale(
+ new AdaptiveIconDrawable(new ColorDrawable(Color.BLACK), null),
+ null, null, null));
}
- AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) dr;
// Shrink very tiny bit so that the clip path is smaller than the original bitmap
// that has anti aliased edges and shadows.
@@ -371,7 +382,7 @@
AnimatorSet anim = new AnimatorSet();
anim.play(ObjectAnimator.ofFloat(newContent, VIEW_ALPHA, 0, 1));
anim.play(ObjectAnimator.ofFloat(mContent, VIEW_ALPHA, 0));
- anim.setDuration(duration).setInterpolator(Interpolators.DEACCEL_1_5);
+ anim.setDuration(duration).setInterpolator(Interpolators.DECELERATE_1_5);
anim.start();
}
@@ -416,10 +427,16 @@
}
}
+ /** {@code true} if the scale animation has finished. */
public boolean isScaleAnimationFinished() {
return mScaleAnimStarted && !mScaleAnim.isRunning();
}
+ /** {@code true} if the shift animation has finished. */
+ public boolean isShiftAnimationFinished() {
+ return mShiftAnimStarted && !mShiftAnim.isRunning();
+ }
+
/**
* Move the window containing this view.
*
diff --git a/src/com/android/launcher3/dragndrop/PinItemDragListener.java b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
index af43ae8..48b5646 100644
--- a/src/com/android/launcher3/dragndrop/PinItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
@@ -31,7 +31,6 @@
import android.widget.RemoteViews;
import com.android.launcher3.DragSource;
-import com.android.launcher3.Launcher;
import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.PendingAddShortcutInfo;
@@ -72,15 +71,6 @@
}
@Override
- public boolean init(Launcher launcher, boolean alreadyOnHome) {
- super.init(launcher, alreadyOnHome);
- if (!alreadyOnHome) {
- launcher.useFadeOutAnimationForLauncherStart(mCancelSignal);
- }
- return false;
- }
-
- @Override
protected PendingItemDragHelper createDragHelper() {
final PendingAddItemInfo item;
if (mRequest.getRequestType() == PinItemRequest.REQUEST_TYPE_SHORTCUT) {
diff --git a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
index 7bdec1c..0f3cad6 100644
--- a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
+++ b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
@@ -16,6 +16,8 @@
package com.android.launcher3.dragndrop;
+import static android.content.pm.LauncherApps.EXTRA_PIN_ITEM_REQUEST;
+
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
import static com.android.launcher3.LauncherState.EDIT_MODE;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
@@ -25,6 +27,7 @@
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps.PinItemRequest;
import android.content.pm.PackageManager;
@@ -41,6 +44,7 @@
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.PinRequestHelper;
import com.android.launcher3.pm.ShortcutConfigActivityInfo;
+import com.android.launcher3.util.StartActivityParams;
import java.util.function.Supplier;
@@ -105,7 +109,11 @@
@Override
public boolean startConfigActivity(Activity activity, int requestCode) {
- return false;
+ new StartActivityParams(activity, requestCode).deliverResult(
+ activity,
+ Activity.RESULT_OK,
+ new Intent().putExtra(EXTRA_PIN_ITEM_REQUEST, mRequestSupplier.get()));
+ return true;
}
@Override
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 4ae54e6..57e1641 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -25,6 +25,7 @@
import static com.android.launcher3.config.FeatureFlags.ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_LABEL_UPDATED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED;
+import static com.android.launcher3.testing.shared.TestProtocol.FOLDER_OPENED_MESSAGE;
import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
import android.animation.Animator;
@@ -535,7 +536,7 @@
mFolderName.selectAll();
}
}
- mFolderName.showKeyboard();
+ mFolderName.showKeyboard(true /* shouldFocus */);
mFolderName.displayCompletions(
Stream.of(mInfo.suggestedFolderNames.getLabels())
.filter(Objects::nonNull)
@@ -644,6 +645,11 @@
* is played.
*/
private void animateOpen(List<WorkspaceItemInfo> items, int pageNo) {
+ if (items == null || items.size() <= 1) {
+ Log.d(TAG, "Couldn't animate folder open because items is: " + items);
+ return;
+ }
+
Folder openFolder = getOpen(mActivityContext);
if (openFolder != null && openFolder != this) {
// Close any open folder before opening a folder.
@@ -692,7 +698,8 @@
public void onAnimationEnd(Animator animation) {
setState(STATE_OPEN);
announceAccessibilityChanges();
- AccessibilityManagerCompat.sendFolderOpenedEventToTest(getContext());
+ AccessibilityManagerCompat.sendTestProtocolEventToTest(getContext(),
+ FOLDER_OPENED_MESSAGE);
mContent.setFocusOnFirstChild();
}
@@ -881,7 +888,6 @@
final ItemInfo item = d.dragInfo;
final int itemType = item.itemType;
return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
- itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT ||
itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT));
}
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index dd82ecf..9e2e2bf 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -105,11 +105,11 @@
mDelay = res.getInteger(R.integer.config_folderDelay);
mFolderInterpolator = AnimationUtils.loadInterpolator(mContext,
- R.interpolator.folder_interpolator);
+ R.interpolator.standard_interpolator);
mLargeFolderPreviewItemOpenInterpolator = AnimationUtils.loadInterpolator(mContext,
R.interpolator.large_folder_preview_item_open_interpolator);
mLargeFolderPreviewItemCloseInterpolator = AnimationUtils.loadInterpolator(mContext,
- R.interpolator.large_folder_preview_item_close_interpolator);
+ R.interpolator.standard_accelerate_interpolator);
}
/**
@@ -236,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
+ int width = mDeviceProfile.folderCellLayoutBorderSpacePx.x
+ mDeviceProfile.folderCellWidthPx * 2;
- int height = mDeviceProfile.folderCellLayoutBorderSpacePx
+ int height = mDeviceProfile.folderCellLayoutBorderSpacePx.y
+ mDeviceProfile.folderCellHeightPx * 2;
int page = mIsOpening ? mContent.getCurrentPage() : mContent.getDestinationPage();
int left = mContent.getPaddingLeft() + page * lp.width;
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 2c1100f..d00d901 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -16,6 +16,7 @@
package com.android.launcher3.folder;
+import static com.android.launcher3.config.FeatureFlags.enableCursorHoverStates;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ICON_OVERLAP_FACTOR;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
import static com.android.launcher3.folder.PreviewItemManager.INITIAL_ITEM_ANIMATION_DURATION;
@@ -42,6 +43,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.Alarm;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.CellLayout;
@@ -56,7 +58,6 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
import com.android.launcher3.dot.FolderDotInfo;
import com.android.launcher3.dragndrop.BaseItemDragListener;
@@ -260,7 +261,6 @@
private boolean willAcceptItem(ItemInfo item) {
final int itemType = item.itemType;
return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
- itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT ||
itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) &&
item != mInfo && !mFolder.isOpen());
}
@@ -407,7 +407,7 @@
final int finalIndex = index;
dragLayer.animateView(animateView, to, finalAlpha,
finalScale, finalScale, DROP_IN_ANIMATION_DURATION,
- Interpolators.DEACCEL_2,
+ Interpolators.DECELERATE_2,
() -> {
mPreviewItemManager.hidePreviewItem(finalIndex, false);
mFolder.showItem(item);
@@ -628,7 +628,7 @@
Utilities.scaleRectAboutCenter(iconBounds, iconScale);
// If we are animating to the accepting state, animate the dot out.
- mDotParams.scale = Math.max(0, mDotScale - mBackground.getScaleProgress());
+ mDotParams.scale = Math.max(0, mDotScale - mBackground.getAcceptScaleProgress());
mDotParams.dotColor = mBackground.getDotColor();
mDotRenderer.draw(canvas, mDotParams);
}
@@ -802,6 +802,14 @@
}
}
+ @Override
+ public void onHoverChanged(boolean hovered) {
+ super.onHoverChanged(hovered);
+ if (enableCursorHoverStates()) {
+ mBackground.setHovered(hovered);
+ }
+ }
+
/**
* Interface that provides callbacks to a parent ViewGroup that hosts this FolderIcon.
*/
diff --git a/src/com/android/launcher3/folder/LauncherDelegate.java b/src/com/android/launcher3/folder/LauncherDelegate.java
index 7ac2472..c06a0f3 100644
--- a/src/com/android/launcher3/folder/LauncherDelegate.java
+++ b/src/com/android/launcher3/folder/LauncherDelegate.java
@@ -94,9 +94,6 @@
// folder
CellLayout cellLayout = mLauncher.getCellLayout(info.container,
mLauncher.getCellPosMapper().mapModelToPresenter(info).screenId);
- if (cellLayout == null) {
- return;
- }
finalItem = info.contents.remove(0);
newIcon = mLauncher.createShortcut(cellLayout, finalItem);
mLauncher.getModelWriter().addOrMoveItemInDatabase(finalItem,
diff --git a/src/com/android/launcher3/folder/PreviewBackground.java b/src/com/android/launcher3/folder/PreviewBackground.java
index 406955c..b320ceb 100644
--- a/src/com/android/launcher3/folder/PreviewBackground.java
+++ b/src/com/android/launcher3/folder/PreviewBackground.java
@@ -16,6 +16,8 @@
package com.android.launcher3.folder;
+import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
+import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ICON_OVERLAP_FACTOR;
import static com.android.launcher3.graphics.IconShape.getShape;
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
@@ -39,6 +41,9 @@
import android.graphics.Shader;
import android.util.Property;
import android.view.View;
+import android.view.animation.Interpolator;
+
+import androidx.annotation.VisibleForTesting;
import com.android.launcher3.CellLayout;
import com.android.launcher3.DeviceProfile;
@@ -55,7 +60,10 @@
private static final boolean DRAW_SHADOW = false;
private static final boolean DRAW_STROKE = false;
- private static final int CONSUMPTION_ANIMATION_DURATION = 100;
+ @VisibleForTesting protected static final int CONSUMPTION_ANIMATION_DURATION = 100;
+
+ @VisibleForTesting protected static final float HOVER_SCALE = 1.1f;
+ @VisibleForTesting protected static final int HOVER_ANIMATION_DURATION = 300;
private final PorterDuffXfermode mShadowPorterDuffXfermode
= new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
@@ -86,17 +94,21 @@
public boolean isClipping = true;
// Drawing / animation configurations
- private static final float ACCEPT_SCALE_FACTOR = 1.20f;
+ @VisibleForTesting protected static final float ACCEPT_SCALE_FACTOR = 1.20f;
// Expressed on a scale from 0 to 255.
private static final int BG_OPACITY = 255;
private static final int MAX_BG_OPACITY = 255;
private static final int SHADOW_OPACITY = 40;
- private ValueAnimator mScaleAnimator;
+ @VisibleForTesting protected ValueAnimator mScaleAnimator;
private ObjectAnimator mStrokeAlphaAnimator;
private ObjectAnimator mShadowAnimator;
+ @VisibleForTesting protected boolean mIsAccepting;
+ @VisibleForTesting protected boolean mIsHovered;
+ @VisibleForTesting protected boolean mIsHoveredOrAnimating;
+
private static final Property<PreviewBackground, Integer> STROKE_ALPHA =
new Property<PreviewBackground, Integer>(Integer.class, "strokeAlpha") {
@Override
@@ -203,11 +215,11 @@
}
/**
- * Returns the progress of the scale animation, where 0 means the scale is at 1f
- * and 1 means the scale is at ACCEPT_SCALE_FACTOR.
+ * Returns the progress of the scale animation to accept state, where 0 means the scale is at
+ * 1f and 1 means the scale is at ACCEPT_SCALE_FACTOR. Returns 0 when scaled due to hover.
*/
- float getScaleProgress() {
- return (mScale - 1f) / (ACCEPT_SCALE_FACTOR - 1f);
+ float getAcceptScaleProgress() {
+ return mIsHoveredOrAnimating ? 0 : (mScale - 1f) / (ACCEPT_SCALE_FACTOR - 1f);
}
void invalidate() {
@@ -385,60 +397,70 @@
return mDrawingDelegate != null;
}
- private void animateScale(float finalScale, final Runnable onStart, final Runnable onEnd) {
- final float scale0 = mScale;
- final float scale1 = finalScale;
-
+ protected void animateScale(boolean isAccepting, boolean isHovered) {
if (mScaleAnimator != null) {
mScaleAnimator.cancel();
}
- mScaleAnimator = ValueAnimator.ofFloat(0f, 1.0f);
-
- mScaleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float prog = animation.getAnimatedFraction();
- mScale = prog * scale1 + (1 - prog) * scale0;
- invalidate();
+ final float startScale = mScale;
+ final float endScale = isAccepting ? ACCEPT_SCALE_FACTOR : (isHovered ? HOVER_SCALE : 1f);
+ Interpolator interpolator =
+ isAccepting != mIsAccepting ? ACCELERATE_DECELERATE : EMPHASIZED_DECELERATE;
+ int duration = isAccepting != mIsAccepting ? CONSUMPTION_ANIMATION_DURATION
+ : HOVER_ANIMATION_DURATION;
+ mIsAccepting = isAccepting;
+ mIsHovered = isHovered;
+ if (startScale == endScale) {
+ if (!mIsAccepting) {
+ clearDrawingDelegate();
}
+ mIsHoveredOrAnimating = mIsHovered;
+ return;
+ }
+
+
+ mScaleAnimator = ValueAnimator.ofFloat(0f, 1.0f);
+ mScaleAnimator.addUpdateListener(animation -> {
+ float prog = animation.getAnimatedFraction();
+ mScale = prog * endScale + (1 - prog) * startScale;
+ invalidate();
});
mScaleAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
- if (onStart != null) {
- onStart.run();
+ if (mIsHovered) {
+ mIsHoveredOrAnimating = true;
}
}
@Override
public void onAnimationEnd(Animator animation) {
- if (onEnd != null) {
- onEnd.run();
+ if (!mIsAccepting) {
+ clearDrawingDelegate();
}
+ mIsHoveredOrAnimating = mIsHovered;
mScaleAnimator = null;
}
});
-
- mScaleAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION);
+ mScaleAnimator.setInterpolator(interpolator);
+ mScaleAnimator.setDuration(duration);
mScaleAnimator.start();
}
public void animateToAccept(CellLayout cl, int cellX, int cellY) {
- animateScale(ACCEPT_SCALE_FACTOR, () -> delegateDrawing(cl, cellX, cellY), null);
+ delegateDrawing(cl, cellX, cellY);
+ animateScale(/* isAccepting= */ true, mIsHovered);
}
public void animateToRest() {
- // This can be called multiple times -- we need to make sure the drawing delegate
- // is saved and restored at the beginning of the animation, since cancelling the
- // existing animation can clear the delgate.
- CellLayout cl = mDrawingDelegate;
- int cellX = mDelegateCellX;
- int cellY = mDelegateCellY;
- animateScale(1f, () -> delegateDrawing(cl, cellX, cellY), this::clearDrawingDelegate);
+ animateScale(/* isAccepting= */ false, mIsHovered);
}
public float getStrokeWidth() {
return mStrokeWidth;
}
+
+ protected void setHovered(boolean hovered) {
+ animateScale(mIsAccepting, /* isHovered= */ hovered);
+ }
}
diff --git a/src/com/android/launcher3/graphics/DragPreviewProvider.java b/src/com/android/launcher3/graphics/DragPreviewProvider.java
index 7457f30..4208343 100644
--- a/src/com/android/launcher3/graphics/DragPreviewProvider.java
+++ b/src/com/android/launcher3/graphics/DragPreviewProvider.java
@@ -16,15 +16,19 @@
package com.android.launcher3.graphics;
+import static com.android.launcher3.BubbleTextView.DISPLAY_SEARCH_RESULT_APP_ROW;
+
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
import android.view.View;
import androidx.annotation.Nullable;
+import com.android.launcher3.BubbleTextView;
import com.android.launcher3.R;
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.icons.BitmapRenderer;
@@ -37,7 +41,6 @@
* A utility class to generate preview bitmap for dragging.
*/
public class DragPreviewProvider {
-
private final Rect mTempRect = new Rect();
protected final View mView;
@@ -99,6 +102,15 @@
height = mView.getHeight();
}
+ if (mView instanceof BubbleTextView btv
+ && btv.getIconDisplay() == DISPLAY_SEARCH_RESULT_APP_ROW) {
+ FastBitmapDrawable icon = ((BubbleTextView) mView).getIcon();
+ Drawable drawable = icon.getConstantState().newDrawable();
+ float xInset = (float) blurSizeOutline / (float) (width + blurSizeOutline);
+ float yInset = (float) blurSizeOutline / (float) (height + blurSizeOutline);
+ return new InsetDrawable(drawable, xInset / 2, yInset / 2, xInset / 2, yInset / 2);
+ }
+
return new FastBitmapDrawable(
BitmapRenderer.createHardwareBitmap(width + blurSizeOutline,
height + blurSizeOutline, (c) -> drawDragView(c, scale)));
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 47677ea..ae44f0a 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -34,13 +34,9 @@
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.content.ContextWrapper;
-import android.content.Intent;
import android.content.res.TypedArray;
-import android.graphics.Color;
import android.graphics.PointF;
import android.graphics.Rect;
-import android.graphics.drawable.AdaptiveIconDrawable;
-import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
@@ -49,12 +45,12 @@
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.ContextThemeWrapper;
+import android.view.Display;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.view.WindowInsets;
-import android.view.WindowManager;
+import android.widget.FrameLayout;
import android.widget.TextClock;
import androidx.annotation.NonNull;
@@ -74,12 +70,11 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.WorkspaceLayoutManager;
+import com.android.launcher3.apppairs.AppPairIcon;
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
import com.android.launcher3.celllayout.CellPosMapper;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.FolderIcon;
-import com.android.launcher3.icons.BaseIconFactory;
-import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
@@ -98,6 +93,7 @@
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
+import com.android.launcher3.util.WindowBounds;
import com.android.launcher3.util.window.WindowManagerProxy;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
@@ -183,7 +179,6 @@
private final DeviceProfile mDp;
private final DeviceProfile mDpOrig;
private final Rect mInsets;
- private final WorkspaceItemInfo mWorkspaceItemInfo;
private final LayoutInflater mHomeElementInflater;
private final InsettableFrameLayout mRootView;
private final Hotseat mHotseat;
@@ -211,29 +206,9 @@
} else {
mDpOrig = mDp;
}
-
- WindowInsets currentWindowInsets = context.getSystemService(WindowManager.class)
- .getCurrentWindowMetrics().getWindowInsets();
- mInsets = new Rect(
- currentWindowInsets.getSystemWindowInsetLeft(),
- currentWindowInsets.getSystemWindowInsetTop(),
- currentWindowInsets.getSystemWindowInsetRight(),
- mDp.isTaskbarPresent ? 0 : currentWindowInsets.getSystemWindowInsetBottom());
+ mInsets = getInsets(context);
mDp.updateInsets(mInsets);
- BaseIconFactory iconFactory =
- new BaseIconFactory(context, mIdp.fillResIconDpi, mIdp.iconBitmapSize) { };
- BitmapInfo iconInfo = iconFactory.createBadgedIconBitmap(
- new AdaptiveIconDrawable(
- new ColorDrawable(Color.WHITE),
- new ColorDrawable(Color.WHITE)));
-
- mWorkspaceItemInfo = new WorkspaceItemInfo();
- mWorkspaceItemInfo.bitmap = iconInfo;
- mWorkspaceItemInfo.intent = new Intent();
- mWorkspaceItemInfo.contentDescription = mWorkspaceItemInfo.title =
- context.getString(R.string.label_application);
-
mHomeElementInflater = LayoutInflater.from(
new ContextThemeWrapper(this, R.style.HomeScreenElementTheme));
mHomeElementInflater.setFactory2(this);
@@ -283,6 +258,26 @@
mAppWidgetHost = new LauncherPreviewAppWidgetHost(context);
}
+ /**
+ * Returns the insets of the screen closest to the display given by the context
+ */
+ private Rect getInsets(Context context) {
+ DisplayController.Info info = DisplayController.INSTANCE.get(context).getInfo();
+ float maxDiff = Float.MAX_VALUE;
+ Display display = context.getDisplay();
+ Rect insets = new Rect();
+ for (WindowBounds supportedBound : info.supportedBounds) {
+ double diff = Math.pow(display.getWidth() - supportedBound.availableSize.x, 2)
+ + Math.pow(display.getHeight() - supportedBound.availableSize.y, 2);
+ if (supportedBound.rotationHint == context.getDisplay().getRotation()
+ && diff < maxDiff) {
+ maxDiff = (float) diff;
+ insets = supportedBound.insets;
+ }
+ }
+ return new Rect(insets);
+ }
+
/** Populate preview and render it. */
public View getRenderedView(BgDataModel dataModel,
Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap) {
@@ -378,12 +373,13 @@
addInScreenFromBind(icon, info);
}
- private void inflateAndAddFolder(FolderInfo info) {
+ private void inflateAndAddCollectionIcon(FolderInfo info) {
CellLayout screen = info.container == Favorites.CONTAINER_DESKTOP
? mWorkspaceScreens.get(info.screenId)
: mHotseat;
- FolderIcon folderIcon = FolderIcon.inflateIcon(R.layout.folder_icon, this, screen,
- info);
+ FrameLayout folderIcon = info.itemType == Favorites.ITEM_TYPE_FOLDER
+ ? FolderIcon.inflateIcon(R.layout.folder_icon, this, screen, info)
+ : AppPairIcon.inflateIcon(R.layout.app_pair_icon, this, screen, info);
addInScreenFromBind(folderIcon, info);
}
@@ -483,12 +479,12 @@
for (ItemInfo itemInfo : currentWorkspaceItems) {
switch (itemInfo.itemType) {
case Favorites.ITEM_TYPE_APPLICATION:
- case Favorites.ITEM_TYPE_SHORTCUT:
case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
inflateAndAddIcon((WorkspaceItemInfo) itemInfo);
break;
case Favorites.ITEM_TYPE_FOLDER:
- inflateAndAddFolder((FolderInfo) itemInfo);
+ case Favorites.ITEM_TYPE_APP_PAIR:
+ inflateAndAddCollectionIcon((FolderInfo) itemInfo);
break;
default:
break;
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index d366c4a..307052a 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -17,8 +17,8 @@
package com.android.launcher3.graphics;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_DOWNLOAD_APP_UX_V2;
import static com.android.launcher3.config.FeatureFlags.ENABLE_DOWNLOAD_APP_UX_V3;
@@ -155,19 +155,19 @@
// Progress color
float[] m3HCT = new float[3];
ColorUtils.colorToM3HCT(primaryIconColor, m3HCT);
- mProgressColor = ColorUtils.M3HCTtoColor(
+ mProgressColor = ColorUtils.M3HCTToColor(
m3HCT[0],
m3HCT[1],
isDarkMode ? Math.max(m3HCT[2], 55) : Math.min(m3HCT[2], 40));
// Track color
- mTrackColor = ColorUtils.M3HCTtoColor(
+ mTrackColor = ColorUtils.M3HCTToColor(
m3HCT[0],
16,
isDarkMode ? 30 : 90
);
// Plate color
- mPlateColor = ColorUtils.M3HCTtoColor(
+ mPlateColor = ColorUtils.M3HCTToColor(
m3HCT[0],
isDarkMode ? 36 : 24,
isDarkMode ? (isThemed() ? 10 : 20) : 80
diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
index e89c0c5..aebcdd4 100644
--- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
+++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
@@ -16,6 +16,8 @@
package com.android.launcher3.graphics;
+import static android.view.Display.DEFAULT_DISPLAY;
+
import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -80,11 +82,12 @@
private static final String KEY_DISPLAY_ID = "display_id";
private static final String KEY_COLORS = "wallpaper_colors";
- private final Context mContext;
- private final InvariantDeviceProfile mIdp;
+ private Context mContext;
private final IBinder mHostToken;
private final int mWidth;
private final int mHeight;
+ private String mGridName;
+
private final Display mDisplay;
private final WallpaperColors mWallpaperColors;
private final RunnableList mOnDestroyCallbacks = new RunnableList();
@@ -97,15 +100,13 @@
public PreviewSurfaceRenderer(Context context, Bundle bundle) throws Exception {
mContext = context;
-
- String gridName = bundle.getString("name");
+ mGridName = bundle.getString("name");
bundle.remove("name");
- if (gridName == null) {
- gridName = InvariantDeviceProfile.getCurrentGridName(context);
+ if (mGridName == null) {
+ mGridName = InvariantDeviceProfile.getCurrentGridName(context);
}
mWallpaperColors = bundle.getParcelable(KEY_COLORS);
mHideQsb = bundle.getBoolean(GridCustomizationsProvider.KEY_HIDE_BOTTOM_ROW);
- mIdp = new InvariantDeviceProfile(context, gridName);
mHostToken = bundle.getBinder(KEY_HOST_TOKEN);
mWidth = bundle.getInt(KEY_VIEW_WIDTH);
@@ -113,9 +114,9 @@
mDisplay = context.getSystemService(DisplayManager.class)
.getDisplay(bundle.getInt(KEY_DISPLAY_ID));
- mSurfaceControlViewHost = MAIN_EXECUTOR
- .submit(() -> new SurfaceControlViewHost(mContext, mDisplay, mHostToken))
- .get(5, TimeUnit.SECONDS);
+ mSurfaceControlViewHost = MAIN_EXECUTOR.submit(() -> new SurfaceControlViewHost(mContext,
+ context.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY),
+ mHostToken)).get(5, TimeUnit.SECONDS);
mOnDestroyCallbacks.add(mSurfaceControlViewHost::release);
}
@@ -195,28 +196,33 @@
}
}
+ /***
+ * Generates a new context overriding the theme color and the display size without affecting the
+ * main application context
+ */
+ private Context getPreviewContext() {
+ Context context = mContext.createDisplayContext(mDisplay);
+ if (mWallpaperColors == null) {
+ return new ContextThemeWrapper(context,
+ Themes.getActivityThemeRes(context));
+ }
+ if (Utilities.ATLEAST_R) {
+ context = context.createWindowContext(
+ LayoutParams.TYPE_APPLICATION_OVERLAY, null);
+ }
+ LocalColorExtractor.newInstance(context)
+ .applyColorsOverride(context, mWallpaperColors);
+ return new ContextThemeWrapper(context,
+ Themes.getActivityThemeRes(context, mWallpaperColors.getColorHints()));
+ }
+
@WorkerThread
private void loadModelData() {
- final Context inflationContext;
- if (mWallpaperColors != null) {
- // Create a themed context, without affecting the main application context
- Context context = mContext.createDisplayContext(mDisplay);
- if (Utilities.ATLEAST_R) {
- context = context.createWindowContext(
- LayoutParams.TYPE_APPLICATION_OVERLAY, null);
- }
- LocalColorExtractor.newInstance(mContext)
- .applyColorsOverride(context, mWallpaperColors);
- inflationContext = new ContextThemeWrapper(context,
- Themes.getActivityThemeRes(context, mWallpaperColors.getColorHints()));
- } else {
- inflationContext = new ContextThemeWrapper(mContext,
- Themes.getActivityThemeRes(mContext));
- }
-
- if (GridSizeMigrationUtil.needsToMigrate(inflationContext, mIdp)) {
+ final Context inflationContext = getPreviewContext();
+ final InvariantDeviceProfile idp = new InvariantDeviceProfile(inflationContext, mGridName);
+ if (GridSizeMigrationUtil.needsToMigrate(inflationContext, idp)) {
// Start the migration
- PreviewContext previewContext = new PreviewContext(inflationContext, mIdp);
+ PreviewContext previewContext = new PreviewContext(inflationContext, idp);
// Copy existing data to preview DB
LauncherDbUtils.copyTable(LauncherAppState.getInstance(mContext)
.getModel().getModelDbController().getDb(),
@@ -239,7 +245,7 @@
@Override
public void run() {
- DeviceProfile deviceProfile = mIdp.getDeviceProfile(previewContext);
+ DeviceProfile deviceProfile = idp.getDeviceProfile(previewContext);
String query =
LauncherSettings.Favorites.SCREEN + " = " + Workspace.FIRST_SCREEN_ID
+ " or " + LauncherSettings.Favorites.CONTAINER + " = "
@@ -254,7 +260,8 @@
getLoadedLauncherWidgetInfo(previewContext.getBaseContext());
MAIN_EXECUTOR.execute(() -> {
- renderView(previewContext, mBgDataModel, mWidgetProvidersMap, spanInfo);
+ renderView(previewContext, mBgDataModel, mWidgetProvidersMap, spanInfo,
+ idp);
mOnDestroyCallbacks.add(previewContext::onDestroy);
});
}
@@ -263,7 +270,7 @@
LauncherAppState.getInstance(inflationContext).getModel().loadAsync(dataModel -> {
if (dataModel != null) {
MAIN_EXECUTOR.execute(() -> renderView(inflationContext, dataModel, null,
- null));
+ null, idp));
} else {
Log.e(TAG, "Model loading failed");
}
@@ -274,11 +281,11 @@
@UiThread
private void renderView(Context inflationContext, BgDataModel dataModel,
Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap,
- @Nullable final SparseArray<Size> launcherWidgetSpanInfo) {
+ @Nullable final SparseArray<Size> launcherWidgetSpanInfo, InvariantDeviceProfile idp) {
if (mDestroyed) {
return;
}
- mRenderer = new LauncherPreviewRenderer(inflationContext, mIdp,
+ mRenderer = new LauncherPreviewRenderer(inflationContext, idp,
mWallpaperColors, launcherWidgetSpanInfo);
mRenderer.hideBottomRow(mHideQsb);
View view = mRenderer.getRenderedView(dataModel, widgetProviderInfoMap);
diff --git a/src/com/android/launcher3/graphics/SysUiScrim.java b/src/com/android/launcher3/graphics/SysUiScrim.java
index 21ebc98..66001d8 100644
--- a/src/com/android/launcher3/graphics/SysUiScrim.java
+++ b/src/com/android/launcher3/graphics/SysUiScrim.java
@@ -13,29 +13,31 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.launcher3.graphics;
+import static android.graphics.Paint.DITHER_FLAG;
+import static android.graphics.Paint.FILTER_BITMAP_FLAG;
+
import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION;
-import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import android.animation.ObjectAnimator;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
-import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
-import android.util.FloatProperty;
import android.view.View;
+import androidx.annotation.ColorInt;
+import androidx.annotation.VisibleForTesting;
+
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
+import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.util.ScreenOnTracker;
import com.android.launcher3.util.ScreenOnTracker.ScreenOnListener;
@@ -46,33 +48,6 @@
*/
public class SysUiScrim implements View.OnAttachStateChangeListener {
- public static final FloatProperty<SysUiScrim> SYSUI_PROGRESS =
- new FloatProperty<SysUiScrim>("sysUiProgress") {
- @Override
- public Float get(SysUiScrim scrim) {
- return scrim.mSysUiProgress;
- }
-
- @Override
- public void setValue(SysUiScrim scrim, float value) {
- scrim.setSysUiProgress(value);
- }
- };
-
- private static final FloatProperty<SysUiScrim> SYSUI_ANIM_MULTIPLIER =
- new FloatProperty<SysUiScrim>("sysUiAnimMultiplier") {
- @Override
- public Float get(SysUiScrim scrim) {
- return scrim.mSysUiAnimMultiplier;
- }
-
- @Override
- public void setValue(SysUiScrim scrim, float value) {
- scrim.mSysUiAnimMultiplier = value;
- scrim.reapplySysUiAlpha();
- }
- };
-
/**
* Receiver used to get a signal that the user unlocked their device.
*/
@@ -92,44 +67,53 @@
}
};
- private static final int MAX_HOTSEAT_SCRIM_ALPHA = 100;
- private static final int ALPHA_MASK_HEIGHT_DP = 500;
- private static final int ALPHA_MASK_BITMAP_DP = 200;
- private static final int ALPHA_MASK_WIDTH_DP = 2;
+ private static final int MAX_SYSUI_SCRIM_ALPHA = 255;
+ private static final int ALPHA_MASK_BITMAP_WIDTH_DP = 2;
+
+ private static final int BOTTOM_MASK_HEIGHT_DP = 200;
+ private static final int TOP_MASK_HEIGHT_DP = 100;
private boolean mDrawTopScrim, mDrawBottomScrim;
- private final RectF mFinalMaskRect = new RectF();
- private final Paint mBottomMaskPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
- private final Bitmap mBottomMask;
- private final int mMaskHeight;
+ private final RectF mTopMaskRect = new RectF();
+ private final Paint mTopMaskPaint = new Paint(FILTER_BITMAP_FLAG | DITHER_FLAG);
+ private final Bitmap mTopMaskBitmap;
+ private final int mTopMaskHeight;
+
+ private final RectF mBottomMaskRect = new RectF();
+ private final Paint mBottomMaskPaint = new Paint(FILTER_BITMAP_FLAG | DITHER_FLAG);
+ private final Bitmap mBottomMaskBitmap;
+ private final int mBottomMaskHeight;
private final View mRoot;
private final BaseDraggingActivity mActivity;
- private final Drawable mTopScrim;
-
- private float mSysUiProgress = 1;
- private boolean mHideSysUiScrim;
+ private final boolean mHideSysUiScrim;
+ private boolean mSkipScrimAnimationForTest = false;
private boolean mAnimateScrimOnNextDraw = false;
- private float mSysUiAnimMultiplier = 1;
+ private final AnimatedFloat mSysUiAnimMultiplier = new AnimatedFloat(this::reapplySysUiAlpha);
+ private final AnimatedFloat mSysUiProgress = new AnimatedFloat(this::reapplySysUiAlpha);
public SysUiScrim(View view) {
mRoot = view;
mActivity = BaseDraggingActivity.fromContext(view.getContext());
- mMaskHeight = ResourceUtils.pxFromDp(ALPHA_MASK_BITMAP_DP,
- view.getResources().getDisplayMetrics());
- mTopScrim = Themes.getAttrDrawable(view.getContext(), R.attr.workspaceStatusBarScrim);
- if (mTopScrim != null) {
- mTopScrim.setDither(true);
- mBottomMask = createDitheredAlphaMask();
- mHideSysUiScrim = false;
- } else {
- mBottomMask = null;
- mHideSysUiScrim = true;
- }
+ DisplayMetrics dm = mActivity.getResources().getDisplayMetrics();
- view.addOnAttachStateChangeListener(this);
+ mTopMaskHeight = ResourceUtils.pxFromDp(TOP_MASK_HEIGHT_DP, dm);
+ mBottomMaskHeight = ResourceUtils.pxFromDp(BOTTOM_MASK_HEIGHT_DP, dm);
+ mHideSysUiScrim = Themes.getAttrBoolean(view.getContext(), R.attr.isWorkspaceDarkText);
+
+ mTopMaskBitmap = mHideSysUiScrim ? null : createDitheredAlphaMask(mTopMaskHeight,
+ new int[]{0x50FFFFFF, 0x0AFFFFFF, 0x00FFFFFF},
+ new float[]{0f, 0.7f, 1f});
+ mTopMaskPaint.setColor(0xFF222222);
+ mBottomMaskBitmap = mHideSysUiScrim ? null : createDitheredAlphaMask(mBottomMaskHeight,
+ new int[]{0x00FFFFFF, 0x2FFFFFFF},
+ new float[]{0f, 1f});
+
+ if (!KEYGUARD_ANIMATION.get() && !mHideSysUiScrim) {
+ view.addOnAttachStateChangeListener(this);
+ }
}
/**
@@ -137,16 +121,16 @@
*/
public void draw(Canvas canvas) {
if (!mHideSysUiScrim) {
- if (mSysUiProgress <= 0) {
+ if (mSysUiProgress.value <= 0) {
mAnimateScrimOnNextDraw = false;
return;
}
if (mAnimateScrimOnNextDraw) {
- mSysUiAnimMultiplier = 0;
+ mSysUiAnimMultiplier.value = 0;
reapplySysUiAlphaNoInvalidate();
- ObjectAnimator oa = createSysuiMultiplierAnim(1);
+ ObjectAnimator oa = mSysUiAnimMultiplier.animateToValue(1);
oa.setDuration(600);
oa.setStartDelay(mActivity.getWindow().getTransitionBackgroundFadeDuration());
oa.start();
@@ -154,21 +138,26 @@
}
if (mDrawTopScrim) {
- mTopScrim.draw(canvas);
+ canvas.drawBitmap(mTopMaskBitmap, null, mTopMaskRect, mTopMaskPaint);
}
if (mDrawBottomScrim) {
- canvas.drawBitmap(mBottomMask, null, mFinalMaskRect, mBottomMaskPaint);
+ canvas.drawBitmap(mBottomMaskBitmap, null, mBottomMaskRect, mBottomMaskPaint);
}
}
}
/**
- * @return an ObjectAnimator that controls the fade in/out of the sys ui scrim.
+ * Returns the sysui multiplier property for controlling fade in/out of the scrim
*/
- public ObjectAnimator createSysuiMultiplierAnim(float... values) {
- ObjectAnimator anim = ObjectAnimator.ofFloat(this, SYSUI_ANIM_MULTIPLIER, values);
- anim.setAutoCancel(true);
- return anim;
+ public AnimatedFloat getSysUIMultiplier() {
+ return mSysUiAnimMultiplier;
+ }
+
+ /**
+ * Returns the sysui progress property for controlling fade in/out of the scrim
+ */
+ public AnimatedFloat getSysUIProgress() {
+ return mSysUiProgress;
}
/**
@@ -180,44 +169,35 @@
*/
public void onInsetsChanged(Rect insets) {
DeviceProfile dp = mActivity.getDeviceProfile();
- mDrawTopScrim = mTopScrim != null && insets.top > 0;
- mDrawBottomScrim = mBottomMask != null
- && !dp.isVerticalBarLayout()
- && !dp.isGestureMode
- && !dp.isTaskbarPresent;
+ mDrawTopScrim = insets.top > 0;
+ mDrawBottomScrim = !dp.isVerticalBarLayout() && !dp.isGestureMode && !dp.isTaskbarPresent;
}
@Override
public void onViewAttachedToWindow(View view) {
- if (!KEYGUARD_ANIMATION.get() && mTopScrim != null) {
- ScreenOnTracker.INSTANCE.get(mActivity).addListener(mScreenOnListener);
- }
+ ScreenOnTracker.INSTANCE.get(mActivity).addListener(mScreenOnListener);
}
@Override
public void onViewDetachedFromWindow(View view) {
- if (!KEYGUARD_ANIMATION.get() && mTopScrim != null) {
- ScreenOnTracker.INSTANCE.get(mActivity).removeListener(mScreenOnListener);
- }
+ ScreenOnTracker.INSTANCE.get(mActivity).removeListener(mScreenOnListener);
}
/**
* Set the width and height of the view being scrimmed
- * @param w
- * @param h
*/
public void setSize(int w, int h) {
- if (mTopScrim != null) {
- mTopScrim.setBounds(0, 0, w, h);
- mFinalMaskRect.set(0, h - mMaskHeight, w, h);
- }
+ mTopMaskRect.set(0, 0, w, mTopMaskHeight);
+ mBottomMaskRect.set(0, h - mBottomMaskHeight, w, h);
}
- private void setSysUiProgress(float progress) {
- if (progress != mSysUiProgress) {
- mSysUiProgress = progress;
- reapplySysUiAlpha();
- }
+ /**
+ * Sets whether the SysUiScrim should hide for testing.
+ */
+ @VisibleForTesting
+ public void skipScrimAnimation() {
+ mSkipScrimAnimationForTest = true;
+ reapplySysUiAlpha();
}
private void reapplySysUiAlpha() {
@@ -228,29 +208,22 @@
}
private void reapplySysUiAlphaNoInvalidate() {
- float factor = mSysUiProgress * mSysUiAnimMultiplier;
- mBottomMaskPaint.setAlpha(Math.round(MAX_HOTSEAT_SCRIM_ALPHA * factor));
- if (mTopScrim != null) {
- mTopScrim.setAlpha(Math.round(255 * factor));
- }
+ float factor = mSysUiProgress.value * mSysUiAnimMultiplier.value;
+ if (mSkipScrimAnimationForTest) factor = 1f;
+ mBottomMaskPaint.setAlpha(Math.round(MAX_SYSUI_SCRIM_ALPHA * factor));
+ mTopMaskPaint.setAlpha(Math.round(MAX_SYSUI_SCRIM_ALPHA * factor));
}
- private Bitmap createDitheredAlphaMask() {
+ private Bitmap createDitheredAlphaMask(int height, @ColorInt int[] colors, float[] positions) {
DisplayMetrics dm = mActivity.getResources().getDisplayMetrics();
- int width = ResourceUtils.pxFromDp(ALPHA_MASK_WIDTH_DP, dm);
- int gradientHeight = ResourceUtils.pxFromDp(ALPHA_MASK_HEIGHT_DP, dm);
- Bitmap dst = Bitmap.createBitmap(width, mMaskHeight, Bitmap.Config.ALPHA_8);
+ int width = ResourceUtils.pxFromDp(ALPHA_MASK_BITMAP_WIDTH_DP, dm);
+ Bitmap dst = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
Canvas c = new Canvas(dst);
- Paint paint = new Paint(Paint.DITHER_FLAG);
- LinearGradient lg = new LinearGradient(0, 0, 0, gradientHeight,
- new int[]{
- 0x00FFFFFF,
- setColorAlphaBound(Color.WHITE, (int) (0xFF * 0.95)),
- 0xFFFFFFFF},
- new float[]{0f, 0.8f, 1f},
- Shader.TileMode.CLAMP);
+ Paint paint = new Paint(DITHER_FLAG);
+ LinearGradient lg = new LinearGradient(0, 0, 0, height,
+ colors, positions, Shader.TileMode.CLAMP);
paint.setShader(lg);
- c.drawRect(0, 0, width, gradientHeight, paint);
+ c.drawPaint(paint);
return dst;
}
}
diff --git a/src/com/android/launcher3/logging/KeyboardStateManager.java b/src/com/android/launcher3/logging/KeyboardStateManager.java
index 6dc0a0b..d0f9c74 100644
--- a/src/com/android/launcher3/logging/KeyboardStateManager.java
+++ b/src/com/android/launcher3/logging/KeyboardStateManager.java
@@ -24,7 +24,10 @@
*/
public class KeyboardStateManager {
private long mUpdatedTime;
- private int mImeHeight;
+ private int mImeHeightPx;
+ // Height of the keyboard when it's shown.
+ // mImeShownHeightPx>=mImeHeightPx always.
+ private int mImeShownHeightPx;
public enum KeyboardState {
NO_IME_ACTION,
@@ -34,8 +37,9 @@
private KeyboardState mKeyboardState;
- public KeyboardStateManager() {
+ public KeyboardStateManager(int defaultImeShownHeightPx) {
mKeyboardState = NO_IME_ACTION;
+ mImeShownHeightPx = defaultImeShownHeightPx;
}
/**
@@ -64,13 +68,25 @@
* Returns keyboard's current height.
*/
public int getImeHeight() {
- return mImeHeight;
+ return mImeHeightPx;
}
/**
- * Setter method to set keyboard height.
+ * Returns keyboard's height in pixels when shown.
*/
- public void setImeHeight(int imeHeight) {
- mImeHeight = imeHeight;
+ public int getImeShownHeight() {
+ return mImeShownHeightPx;
+ }
+
+ /**
+ * Setter method to set keyboard height in pixels.
+ */
+ public void setImeHeight(int imeHeightPx) {
+ mImeHeightPx = imeHeightPx;
+ if (mImeHeightPx > 0) {
+ // Update the mImeShownHeightPx with the actual ime height when shown and store it
+ // for future sessions.
+ mImeShownHeightPx = mImeHeightPx;
+ }
}
}
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 66ed779..4307566 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -32,12 +32,9 @@
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+.
*
@@ -59,6 +56,7 @@
private InstanceId mInstanceId;
protected @Nullable ActivityContext mActivityContext = null;
+ protected @Nullable Context mContext = null;
private KeyboardStateManager mKeyboardStateManager;
/**
@@ -623,6 +621,12 @@
@UiEvent(doc = "User has invoked split to left half with a keyboard shortcut.")
LAUNCHER_KEYBOARD_SHORTCUT_SPLIT_LEFT_TOP(1233),
+ @UiEvent(doc = "User has invoked split to right half from desktop mode.")
+ LAUNCHER_DESKTOP_MODE_SPLIT_RIGHT_BOTTOM(1412),
+
+ @UiEvent(doc = "User has invoked split to left half from desktop mode.")
+ LAUNCHER_DESKTOP_MODE_SPLIT_LEFT_TOP(1464),
+
@UiEvent(doc = "User has collapsed the work FAB button by scrolling down in the all apps"
+ " work A-Z list.")
LAUNCHER_WORK_FAB_BUTTON_COLLAPSE(1276),
@@ -643,11 +647,29 @@
@UiEvent(doc = "User has swiped upwards from the gesture handle to show transient taskbar.")
LAUNCHER_TRANSIENT_TASKBAR_SHOW(1331),
+ @UiEvent(doc = "User has clicked an app pair and launched directly into split screen.")
+ LAUNCHER_APP_PAIR_LAUNCH(1374),
+
+ @UiEvent(doc = "User saved an app pair.")
+ LAUNCHER_APP_PAIR_SAVE(1456),
+
@UiEvent(doc = "App launched through pending intent")
LAUNCHER_APP_LAUNCH_PENDING_INTENT(1394),
- ;
+
+ @UiEvent(doc = "User long pressed on taskbar divider icon to open popup menu")
+ LAUNCHER_TASKBAR_DIVIDER_MENU_OPEN(1488),
+
+ @UiEvent(doc = "User long pressed on taskbar divider icon to close popup menu")
+ LAUNCHER_TASKBAR_DIVIDER_MENU_CLOSE(1489),
+
+ @UiEvent(doc = "User has pinned taskbar using taskbar divider menu")
+ LAUNCHER_TASKBAR_PINNED(1490),
+
+ @UiEvent(doc = "User has unpinned taskbar using taskbar divider menu")
+ LAUNCHER_TASKBAR_UNPINNED(1491)
// ADD MORE
+ ;
private final int mId;
@@ -831,6 +853,10 @@
*/
public interface StatsLatencyLogger {
+ /**
+ * Should be in sync with:
+ * google3/wireless/android/sysui/aster/asterstats/launcher_event_processed.proto
+ */
enum LatencyType {
UNKNOWN(0),
// example: launcher restart that happens via daily backup and restore
@@ -956,33 +982,32 @@
}
/**
- * Sets list of {@link com.android.app.search.ResultType} for the impression event.
+ * Sets {@link com.android.app.search.ResultType} for the impression event.
*/
- default StatsImpressionLogger withResultType(IntArray resultType) {
+ default StatsImpressionLogger withResultType(int 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
+ * Sets 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) {
+ default StatsImpressionLogger withAboveKeyboard(boolean aboveKeyboard) {
return this;
}
/**
- * Sets list of uid for each of {@link com.android.app.search.ResultType} that indicates
+ * Sets uid for each of {@link com.android.app.search.ResultType} that indicates
* package name for the impression event.
*/
- default StatsImpressionLogger withUids(IntArray uid) {
+ default StatsImpressionLogger withUid(int uid) {
+ return this;
+ }
+
+ /**
+ * Sets result source that indicates the origin of the result for the impression event.
+ */
+ default StatsImpressionLogger withResultSource(int resultSource) {
return this;
}
@@ -1031,7 +1056,9 @@
*/
public KeyboardStateManager keyboardStateManager() {
if (mKeyboardStateManager == null) {
- mKeyboardStateManager = new KeyboardStateManager();
+ mKeyboardStateManager = new KeyboardStateManager(
+ mContext != null ? mContext.getResources().getDimensionPixelSize(
+ R.dimen.default_ime_height) : 0);
}
return mKeyboardStateManager;
}
@@ -1067,6 +1094,7 @@
StatsLogManager manager = Overrides.getObject(StatsLogManager.class,
context.getApplicationContext(), R.string.stats_log_manager_class);
manager.mActivityContext = ActivityContext.lookupContextNoThrow(context);
+ manager.mContext = context;
return manager;
}
}
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index 27d1f78..5e86bd6 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -91,8 +91,7 @@
List<ItemInfo> filteredItems = new ArrayList<>();
for (Pair<ItemInfo, Object> entry : mItemList) {
ItemInfo item = entry.first;
- if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
- item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
+ if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
// Short-circuit this logic if the icon exists somewhere on the workspace
if (shortcutExists(dataModel, item.getIntent(), item.user)) {
continue;
diff --git a/src/com/android/launcher3/model/BaseLauncherBinder.java b/src/com/android/launcher3/model/BaseLauncherBinder.java
index 5d85b1c..68544cf 100644
--- a/src/com/android/launcher3/model/BaseLauncherBinder.java
+++ b/src/com/android/launcher3/model/BaseLauncherBinder.java
@@ -21,6 +21,7 @@
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.os.Process;
+import android.os.Trace;
import android.util.Log;
import com.android.launcher3.InvariantDeviceProfile;
@@ -83,13 +84,18 @@
* Binds all loaded data to actual views on the main thread.
*/
public void bindWorkspace(boolean incrementBindId, boolean isBindSync) {
- if (FeatureFlags.ENABLE_WORKSPACE_LOADING_OPTIMIZATION.get()) {
- DisjointWorkspaceBinder workspaceBinder =
+ Trace.beginSection("BaseLauncherBinder#bindWorkspace");
+ try {
+ if (FeatureFlags.ENABLE_WORKSPACE_LOADING_OPTIMIZATION.get()) {
+ DisjointWorkspaceBinder workspaceBinder =
initWorkspaceBinder(incrementBindId, mBgDataModel.collectWorkspaceScreens());
- workspaceBinder.bindCurrentWorkspacePages(isBindSync);
- workspaceBinder.bindOtherWorkspacePages();
- } else {
- bindWorkspaceAllAtOnce(incrementBindId, isBindSync);
+ workspaceBinder.bindCurrentWorkspacePages(isBindSync);
+ workspaceBinder.bindOtherWorkspacePages();
+ } else {
+ bindWorkspaceAllAtOnce(incrementBindId, isBindSync);
+ }
+ } finally {
+ Trace.endSection();
}
}
@@ -106,6 +112,7 @@
synchronized (mBgDataModel) {
if (incrementBindId) {
mBgDataModel.lastBindId++;
+ mBgDataModel.lastLoadId = mApp.getModel().getLastLoadId();
}
mMyBindingId = mBgDataModel.lastBindId;
return new DisjointWorkspaceBinder(workspacePages);
@@ -126,6 +133,7 @@
mBgDataModel.extraItems.forEach(extraItems::add);
if (incrementBindId) {
mBgDataModel.lastBindId++;
+ mBgDataModel.lastLoadId = mApp.getModel().getLastLoadId();
}
mMyBindingId = mBgDataModel.lastBindId;
workspaceItemCount = mBgDataModel.itemsIdMap.size();
@@ -297,6 +305,10 @@
Executor pendingExecutor = pendingTasks::add;
bindWorkspaceItems(otherWorkspaceItems, pendingExecutor);
bindAppWidgets(otherAppWidgets, pendingExecutor);
+
+ StringCache cacheClone = mBgDataModel.stringCache.clone();
+ executeCallbacksTask(c -> c.bindStringCache(cacheClone), pendingExecutor);
+
executeCallbacksTask(c -> c.finishBindingItems(currentScreenIds), pendingExecutor);
pendingExecutor.execute(
() -> {
@@ -311,8 +323,6 @@
c.onInitialBindComplete(
currentScreenIds, pendingTasks, workspaceItemCount, isBindSync);
}, mUiExecutor);
-
- mCallbacks.bindStringCache(mBgDataModel.stringCache.clone());
}
private void bindWorkspaceItems(
@@ -440,9 +450,8 @@
.resumeModelPush(FLAG_LOADER_RUNNING);
});
- for (Callbacks cb : mCallbacksList) {
- cb.bindStringCache(mBgDataModel.stringCache.clone());
- }
+ StringCache cacheClone = mBgDataModel.stringCache.clone();
+ executeCallbacksTask(c -> c.bindStringCache(cacheClone), mUiExecutor);
}
private void bindWorkspaceItems(final ArrayList<ItemInfo> workspaceItems) {
diff --git a/src/com/android/launcher3/model/BaseModelUpdateTask.java b/src/com/android/launcher3/model/BaseModelUpdateTask.java
index 866e222..97f540e 100644
--- a/src/com/android/launcher3/model/BaseModelUpdateTask.java
+++ b/src/com/android/launcher3/model/BaseModelUpdateTask.java
@@ -15,9 +15,6 @@
*/
package com.android.launcher3.model;
-import static com.android.launcher3.testing.shared.TestProtocol.WORK_TAB_MISSING;
-import static com.android.launcher3.testing.shared.TestProtocol.testLogD;
-
import android.util.Log;
import androidx.annotation.NonNull;
@@ -33,7 +30,6 @@
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
@@ -77,7 +73,6 @@
@Override
public final void run() {
boolean isModelLoaded = Objects.requireNonNull(mModel).isModelLoaded();
- testLogD(WORK_TAB_MISSING, "modelLoaded: " + isModelLoaded + " forTask: " + this);
if (!isModelLoaded) {
if (DEBUG_TASKS) {
Log.d(TAG, "Ignoring model task since loader is pending=" + this);
@@ -115,10 +110,6 @@
List<WorkspaceItemInfo> workspaceUpdates = allUpdates.stream()
.filter(info -> info.id != ItemInfo.NO_ID)
.collect(Collectors.toList());
- if (TestProtocol.sDebugTracing) {
- Log.d(WORK_TAB_MISSING, "allUpdates: " + allUpdates.size() + ", workspaceUpdates "
- + workspaceUpdates.size());
- }
if (!workspaceUpdates.isEmpty()) {
scheduleCallbackTask(c -> c.bindWorkspaceItemsChanged(workspaceUpdates));
}
@@ -157,12 +148,7 @@
}
public void bindApplicationsIfNeeded() {
- boolean changeFlag = mAllAppsList.getAndResetChangeFlag();
- if (TestProtocol.sDebugTracing) {
- Log.d(WORK_TAB_MISSING, "bindApplicationsIfNeeded changeFlag? " +
- changeFlag);
- }
- if (changeFlag) {
+ if (mAllAppsList.getAndResetChangeFlag()) {
AppInfo[] apps = mAllAppsList.copyData();
int flags = mAllAppsList.getFlags();
Map<PackageUserKey, Integer> packageUserKeytoUidMap = Arrays.stream(apps).collect(
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index d94df51..5e88b9b 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -126,6 +126,11 @@
public int lastBindId = 0;
/**
+ * Load id for which the callbacks were successfully bound
+ */
+ public int lastLoadId = -1;
+
+ /**
* Clears all the data
*/
public synchronized void clear() {
@@ -165,11 +170,15 @@
writer.println(prefix + '\t' + appWidgets.get(i).toString());
}
writer.println(prefix + " ---- folder items ");
- for (int i = 0; i< folders.size(); i++) {
+ for (int i = 0; i < folders.size(); i++) {
writer.println(prefix + '\t' + folders.valueAt(i).toString());
}
+ writer.println(prefix + " ---- extra items ");
+ for (int i = 0; i < extraItems.size(); i++) {
+ writer.println(prefix + '\t' + extraItems.valueAt(i).toString());
+ }
writer.println(prefix + " ---- items id map ");
- for (int i = 0; i< itemsIdMap.size(); i++) {
+ for (int i = 0; i < itemsIdMap.size(); i++) {
writer.println(prefix + '\t' + itemsIdMap.valueAt(i).toString());
}
@@ -211,7 +220,6 @@
// Fall through.
}
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
workspaceItems.remove(item);
break;
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
@@ -246,7 +254,6 @@
break;
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
workspaceItems.add(item);
@@ -439,6 +446,20 @@
this.containerId = containerId;
this.items = Collections.unmodifiableList(items);
}
+
+ @Override
+ @NonNull
+ public final String toString() {
+ StringBuilder s = new StringBuilder();
+ s.append("FixedContainerItems:");
+ s.append(" id=").append(containerId);
+ s.append(" itemCount=").append(items.size());
+ for (int i = 0; i < items.size(); i++) {
+ s.append(" item #").append(i).append(": ").append(items.get(i).toString());
+ }
+ return s.toString();
+ }
+
}
diff --git a/src/com/android/launcher3/model/DeviceGridState.java b/src/com/android/launcher3/model/DeviceGridState.java
index edc8c1b..f24d1d2 100644
--- a/src/com/android/launcher3/model/DeviceGridState.java
+++ b/src/com/android/launcher3/model/DeviceGridState.java
@@ -33,6 +33,7 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
+import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
import java.util.Locale;
import java.util.Objects;
@@ -92,6 +93,9 @@
* Stores the device state to shared preferences
*/
public void writeToPrefs(Context context) {
+ if (context instanceof SandboxContext) {
+ return;
+ }
LauncherPrefs.get(context).put(
WORKSPACE_SIZE.to(mGridSizeString),
HOTSEAT_COUNT.to(mNumHotseat),
diff --git a/src/com/android/launcher3/model/GridSizeMigrationUtil.java b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
index 9a6cde6..78875a3 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationUtil.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
@@ -45,7 +45,6 @@
import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.IntArray;
-import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
@@ -133,10 +132,8 @@
Log.v(TAG, "Workspace migration completed in "
+ (System.currentTimeMillis() - migrationStartTime));
- if (!(context instanceof SandboxContext)) {
- // Save current configuration, so that the migration does not run again.
- destDeviceState.writeToPrefs(context);
- }
+ // Save current configuration, so that the migration does not run again.
+ destDeviceState.writeToPrefs(context);
}
}
@@ -455,7 +452,6 @@
try {
// calculate weight
switch (entry.itemType) {
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: {
entry.mIntent = c.getString(indexIntent);
@@ -531,7 +527,6 @@
try {
// calculate weight
switch (entry.itemType) {
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: {
entry.mIntent = c.getString(indexIntent);
@@ -544,8 +539,8 @@
verifyPackage(cn.getPackageName());
int widgetId = c.getInt(indexAppWidgetId);
- LauncherAppWidgetProviderInfo pInfo =
- widgetManagerHelper.getLauncherAppWidgetInfo(widgetId);
+ LauncherAppWidgetProviderInfo pInfo = widgetManagerHelper
+ .getLauncherAppWidgetInfo(widgetId, cn);
Point spans = null;
if (pInfo != null) {
spans = pInfo.getMinSpans();
diff --git a/src/com/android/launcher3/model/ItemInstallQueue.java b/src/com/android/launcher3/model/ItemInstallQueue.java
index fa0511c..9a3abd4 100644
--- a/src/com/android/launcher3/model/ItemInstallQueue.java
+++ b/src/com/android/launcher3/model/ItemInstallQueue.java
@@ -286,7 +286,6 @@
final WorkspaceItemInfo si = new WorkspaceItemInfo();
si.user = user;
- si.itemType = ITEM_TYPE_APPLICATION;
LauncherActivityInfo lai;
boolean usePackageIcon = laiList.isEmpty();
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index 2054d93..33332f0 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -193,9 +193,7 @@
public IconRequestInfo<WorkspaceItemInfo> createIconRequestInfo(
WorkspaceItemInfo wai, boolean useLowResIcon) {
- byte[] iconBlob = itemType == Favorites.ITEM_TYPE_SHORTCUT
- || itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT
- || restoreFlag != 0
+ byte[] iconBlob = itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT || restoreFlag != 0
? getIconBlob() : null;
return new IconRequestInfo<>(wai, mActivityInfo, iconBlob, useLowResIcon);
@@ -347,7 +345,6 @@
}
final WorkspaceItemInfo info = new WorkspaceItemInfo();
- info.itemType = Favorites.ITEM_TYPE_APPLICATION;
info.user = user;
info.intent = newIntent;
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index ca356b0..08a6cf0 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -24,8 +24,6 @@
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER;
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_SAFEMODE;
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED;
-import static com.android.launcher3.testing.shared.TestProtocol.WORK_TAB_MISSING;
-import static com.android.launcher3.testing.shared.TestProtocol.testLogD;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.util.PackageManagerHelper.hasShortcutsPermission;
import static com.android.launcher3.util.PackageManagerHelper.isSystemApp;
@@ -33,7 +31,6 @@
import android.annotation.SuppressLint;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -61,7 +58,6 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.LauncherSettings.Settings;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.Folder;
@@ -99,6 +95,7 @@
import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
+import com.android.launcher3.widget.custom.CustomWidgetManager;
import java.util.ArrayList;
import java.util.Collections;
@@ -203,7 +200,7 @@
}
}
- Object traceToken = TraceHelper.INSTANCE.beginSection(TAG);
+ TraceHelper.INSTANCE.beginSection(TAG);
LoaderMemoryLogger memoryLogger = new LoaderMemoryLogger();
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
List<ShortcutInfo> allShortcuts = new ArrayList<>();
@@ -327,7 +324,7 @@
memoryLogger.printLogs();
throw e;
}
- TraceHelper.INSTANCE.endSection(traceToken);
+ TraceHelper.INSTANCE.endSection();
}
public synchronized void stopLocked() {
@@ -361,25 +358,15 @@
String selection,
@Nullable LoaderMemoryLogger memoryLogger) {
final Context context = mApp.getContext();
- final ContentResolver contentResolver = context.getContentResolver();
final PackageManagerHelper pmHelper = new PackageManagerHelper(context);
final boolean isSafeMode = pmHelper.isSafeMode();
final boolean isSdCardReady = Utilities.isBootCompleted();
final WidgetManagerHelper widgetHelper = new WidgetManagerHelper(context);
- boolean clearDb = false;
- if (!mApp.getModel().getModelDbController().migrateGridIfNeeded()) {
- // Migration failed. Clear workspace.
- clearDb = true;
- }
-
- if (clearDb) {
- Log.d(TAG, "loadWorkspace: resetting launcher database");
- Settings.call(contentResolver, Settings.METHOD_CREATE_EMPTY_DB);
- }
-
+ ModelDbController dbController = mApp.getModel().getModelDbController();
+ dbController.tryMigrateDB();
Log.d(TAG, "loadWorkspace: loading default favorites");
- Settings.call(contentResolver, Settings.METHOD_LOAD_DEFAULT_FAVORITES);
+ dbController.loadDefaultFavoritesIfNecessary();
synchronized (mBgDataModel) {
mBgDataModel.clear();
@@ -388,17 +375,18 @@
final HashMap<PackageUserKey, SessionInfo> installingPkgs =
mSessionHelper.getActiveSessions();
installingPkgs.forEach(mApp.getIconCache()::updateSessionCache);
+ FileLog.d(TAG, "loadWorkspace: Packages with active install sessions: "
+ + installingPkgs.values());
final PackageUserKey tempPackageKey = new PackageUserKey(null, null);
mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs);
mShortcutKeyToPinnedShortcuts = new HashMap<>();
- ModelDbController dbController = mApp.getModel().getModelDbController();
final LoaderCursor c = new LoaderCursor(
dbController.query(TABLE_NAME, null, selection, null, null),
mApp, mUserManagerState);
final Bundle extras = c.getExtras();
- mDbName = extras == null ? null : extras.getString(Settings.EXTRA_DB_NAME);
+ mDbName = extras == null ? null : extras.getString(ModelDbController.EXTRA_DB_NAME);
try {
final LongSparseArray<Boolean> unlockedUsers = new LongSparseArray<>();
@@ -505,7 +493,6 @@
boolean allowMissingTarget = false;
switch (c.itemType) {
- case Favorites.ITEM_TYPE_SHORTCUT:
case Favorites.ITEM_TYPE_APPLICATION:
case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
Intent intent = c.parseIntent();
@@ -519,9 +506,8 @@
ComponentName cn = intent.getComponent();
String targetPkg = cn == null ? intent.getPackage() : cn.getPackageName();
- if (TextUtils.isEmpty(targetPkg)
- && c.itemType != Favorites.ITEM_TYPE_SHORTCUT) {
- c.markDeleted("Only legacy shortcuts can have null package");
+ if (TextUtils.isEmpty(targetPkg)) {
+ c.markDeleted("Shortcuts can't have null package");
return;
}
@@ -707,9 +693,11 @@
break;
case Favorites.ITEM_TYPE_FOLDER:
+ case Favorites.ITEM_TYPE_APP_PAIR:
FolderInfo folderInfo = mBgDataModel.findOrMakeFolder(c.id);
c.applyCommonProperties(folderInfo);
+ folderInfo.itemType = c.itemType;
// Do not trim the folder label, as is was set by the user.
folderInfo.title = c.getString(c.mTitleIndex);
folderInfo.spanX = 1;
@@ -753,8 +741,13 @@
ComponentKey providerKey = new ComponentKey(component, c.user);
if (!mWidgetProvidersMap.containsKey(providerKey)) {
- mWidgetProvidersMap.put(providerKey,
- widgetHelper.findProvider(component, c.user));
+ if (customWidget) {
+ mWidgetProvidersMap.put(providerKey, CustomWidgetManager.INSTANCE
+ .get(mApp.getContext()).getWidgetProvider(component));
+ } else {
+ mWidgetProvidersMap.put(providerKey,
+ widgetHelper.findProvider(component, c.user));
+ }
}
final AppWidgetProviderInfo provider = mWidgetProvidersMap.get(providerKey);
@@ -827,7 +820,8 @@
return;
}
LauncherAppWidgetProviderInfo widgetProviderInfo =
- widgetHelper.getLauncherAppWidgetInfo(appWidgetId);
+ widgetHelper.getLauncherAppWidgetInfo(appWidgetId,
+ appWidgetInfo.getTargetComponent());
if (widgetProviderInfo != null
&& (appWidgetInfo.spanX < widgetProviderInfo.minSpanX
|| appWidgetInfo.spanY < widgetProviderInfo.minSpanY)) {
@@ -917,9 +911,7 @@
private void sanitizeFolders(boolean itemsDeleted) {
if (itemsDeleted) {
// Remove any empty folder
- int[] deletedFolderIds = Settings.call(mApp.getContext().getContentResolver(),
- Settings.METHOD_DELETE_EMPTY_FOLDERS)
- .getIntArray(Settings.EXTRA_VALUE);
+ IntArray deletedFolderIds = mApp.getModel().getModelDbController().deleteEmptyFolders();
synchronized (mBgDataModel) {
for (int folderId : deletedFolderIds) {
mBgDataModel.workspaceItems.remove(mBgDataModel.folders.get(folderId));
@@ -932,11 +924,9 @@
private void sanitizeWidgetsShortcutsAndPackages() {
Context context = mApp.getContext();
- ContentResolver contentResolver = context.getContentResolver();
// Remove any ghost widgets
- Settings.call(contentResolver,
- Settings.METHOD_REMOVE_GHOST_WIDGETS);
+ mApp.getModel().getModelDbController().removeGhostWidgets();
// Update pinned state of model shortcuts
mBgDataModel.updateShortcutPinnedState(context);
@@ -951,7 +941,6 @@
}
private List<LauncherActivityInfo> loadAllApps() {
- testLogD(WORK_TAB_MISSING, "loadingAllApps");
final List<UserHandle> profiles = mUserCache.getUserProfiles();
List<LauncherActivityInfo> allActivityList = new ArrayList<>();
// Clear the list of apps
diff --git a/src/com/android/launcher3/model/ModelDbController.java b/src/com/android/launcher3/model/ModelDbController.java
index f0e5ef6..e10e72d 100644
--- a/src/com/android/launcher3/model/ModelDbController.java
+++ b/src/com/android/launcher3/model/ModelDbController.java
@@ -37,7 +37,6 @@
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
-import android.os.Binder;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.Process;
@@ -85,6 +84,7 @@
private static final String TAG = "LauncherProvider";
private static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
+ public static final String EXTRA_DB_NAME = "db_name";
protected DatabaseHelper mOpenHelper;
@@ -140,7 +140,7 @@
table, projection, selection, selectionArgs, null, null, sortOrder);
final Bundle extra = new Bundle();
- extra.putString(LauncherSettings.Settings.EXTRA_DB_NAME, mOpenHelper.getDatabaseName());
+ extra.putString(EXTRA_DB_NAME, mOpenHelper.getDatabaseName());
result.setExtras(extra);
return result;
}
@@ -162,28 +162,6 @@
}
/**
- * Similar to insert but for adding multiple values in a transaction.
- */
- @WorkerThread
- public int bulkInsert(String table, ContentValues[] values) {
- createDbIfNotExists();
-
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- try (SQLiteTransaction t = new SQLiteTransaction(db)) {
- int numValues = values.length;
- for (int i = 0; i < numValues; i++) {
- addModifiedTime(values[i]);
- if (mOpenHelper.dbInsertAndCheck(db, table, values[i]) < 0) {
- return 0;
- }
- }
- onAddOrDeleteOp(db);
- t.commit();
- }
- return values.length;
- }
-
- /**
* Refer {@link SQLiteDatabase#delete(String, String, String[])}
*/
@WorkerThread
@@ -191,10 +169,6 @@
createDbIfNotExists();
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- if (Binder.getCallingPid() != Process.myPid()
- && Favorites.TABLE_NAME.equalsIgnoreCase(table)) {
- mOpenHelper.removeGhostWidgets(mOpenHelper.getWritableDatabase());
- }
int count = db.delete(table, selection, selectionArgs);
if (count > 0) {
onAddOrDeleteOp(db);
@@ -250,6 +224,7 @@
public void createEmptyDB() {
createDbIfNotExists();
mOpenHelper.createEmptyDB(mOpenHelper.getWritableDatabase());
+ LauncherPrefs.get(mContext).putSync(getEmptyDbCreatedKey().to(true));
}
/**
@@ -280,14 +255,34 @@
mOpenHelper.getReadableDatabase(), Favorites.HYBRID_HOTSEAT_BACKUP_TABLE);
}
+
+ /**
+ * Migrates the DB if needed. If the migration failed, it clears the DB.
+ */
+ public void tryMigrateDB() {
+ if (!migrateGridIfNeeded()) {
+ Log.d(TAG, "Migration failed: resetting launcher database");
+ createEmptyDB();
+ LauncherPrefs.get(mContext).putSync(
+ getEmptyDbCreatedKey(mOpenHelper.getDatabaseName()).to(true));
+
+ // Write the grid state to avoid another migration
+ new DeviceGridState(LauncherAppState.getIDP(mContext)).writeToPrefs(mContext);
+ }
+ }
+
/**
* Migrates the DB if needed, and returns false if the migration failed
* and DB needs to be cleared.
* @return true if migration was success or ignored, false if migration failed
* and the DB should be reset.
*/
- public boolean migrateGridIfNeeded() {
+ private boolean migrateGridIfNeeded() {
createDbIfNotExists();
+ if (LauncherPrefs.get(mContext).get(getEmptyDbCreatedKey())) {
+ // If we have already create a new DB, ignore migration
+ return false;
+ }
InvariantDeviceProfile idp = LauncherAppState.getIDP(mContext);
if (!GridSizeMigrationUtil.needsToMigrate(mContext, idp)) {
return true;
@@ -358,7 +353,7 @@
}
private void clearFlagEmptyDbCreated() {
- LauncherPrefs.get(mContext).removeSync(getEmptyDbCreatedKey(mOpenHelper.getDatabaseName()));
+ LauncherPrefs.get(mContext).removeSync(getEmptyDbCreatedKey());
}
/**
@@ -372,7 +367,7 @@
public synchronized void loadDefaultFavoritesIfNecessary() {
createDbIfNotExists();
- if (LauncherPrefs.get(mContext).get(getEmptyDbCreatedKey(mOpenHelper.getDatabaseName()))) {
+ if (LauncherPrefs.get(mContext).get(getEmptyDbCreatedKey())) {
Log.d(TAG, "loading default workspace");
LauncherWidgetHolder widgetHolder = mOpenHelper.newLauncherWidgetHolder();
@@ -471,7 +466,7 @@
() -> parser, AutoInstallsLayout.TAG_WORKSPACE);
}
- private static Uri getLayoutUri(String authority, Context ctx) {
+ public static Uri getLayoutUri(String authority, Context ctx) {
InvariantDeviceProfile grid = LauncherAppState.getIDP(ctx);
return new Uri.Builder().scheme("content").authority(authority).path("launcher_layout")
.appendQueryParameter("version", "1")
@@ -491,6 +486,10 @@
mOpenHelper, mContext.getResources(), defaultLayout);
}
+ private ConstantItem<Boolean> getEmptyDbCreatedKey() {
+ return getEmptyDbCreatedKey(mOpenHelper.getDatabaseName());
+ }
+
/**
* Re-composite given key in respect to database. If the current db is
* {@link LauncherFiles#LAUNCHER_DB}, return the key as-is. Otherwise append the db name to
diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java
index ddb8b05..2358a9f 100644
--- a/src/com/android/launcher3/model/ModelWriter.java
+++ b/src/com/android/launcher3/model/ModelWriter.java
@@ -16,13 +16,12 @@
package com.android.launcher3.model;
+import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
+import static com.android.launcher3.provider.LauncherDbUtils.itemIdMatch;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
-import android.content.ContentProviderOperation;
-import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
-import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
@@ -32,9 +31,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherModel.CallbackTask;
-import com.android.launcher3.LauncherProvider;
import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.LauncherSettings.Settings;
import com.android.launcher3.Utilities;
import com.android.launcher3.celllayout.CellPosMapper;
import com.android.launcher3.celllayout.CellPosMapper.CellPos;
@@ -45,6 +42,7 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
import com.android.launcher3.util.ContentWriter;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.ItemInfoMatcher;
@@ -80,7 +78,7 @@
private final boolean mVerifyChanges;
// Keep track of delete operations that occur when an Undo option is present; we may not commit.
- private final List<Runnable> mDeleteRunnables = new ArrayList<>();
+ private final List<ModelTask> mDeleteRunnables = new ArrayList<>();
private boolean mPreparingToUndo;
private final CellPosMapper mCellPosMapper;
@@ -217,8 +215,7 @@
item.spanX = spanX;
item.spanY = spanY;
notifyItemModified(item);
-
- MODEL_EXECUTOR.execute(new UpdateItemRunnable(item, () ->
+ new UpdateItemRunnable(item, () ->
new ContentWriter(mContext)
.put(Favorites.CONTAINER, item.container)
.put(Favorites.CELLX, item.cellX)
@@ -226,7 +223,8 @@
.put(Favorites.RANK, item.rank)
.put(Favorites.SPANX, item.spanX)
.put(Favorites.SPANY, item.spanY)
- .put(Favorites.SCREEN, item.screenId)));
+ .put(Favorites.SCREEN, item.screenId))
+ .executeOnModelThread();
}
/**
@@ -234,11 +232,11 @@
*/
public void updateItemInDatabase(ItemInfo item) {
notifyItemModified(item);
- MODEL_EXECUTOR.execute(new UpdateItemRunnable(item, () -> {
+ new UpdateItemRunnable(item, () -> {
ContentWriter writer = new ContentWriter(mContext);
item.onAddToDatabase(writer);
return writer;
- }));
+ }).executeOnModelThread();
}
private void notifyItemModified(ItemInfo item) {
@@ -253,13 +251,12 @@
int container, int screenId, int cellX, int cellY) {
updateItemInfoProps(item, container, screenId, cellX, cellY);
- final ContentResolver cr = mContext.getContentResolver();
- item.id = Settings.call(cr, Settings.METHOD_NEW_ITEM_ID).getInt(Settings.EXTRA_VALUE);
+ item.id = mModel.getModelDbController().generateNewItemId();
notifyOtherCallbacks(c -> c.bindItems(Collections.singletonList(item), false));
ModelVerifier verifier = new ModelVerifier();
final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
- MODEL_EXECUTOR.execute(() -> {
+ newModelTask(() -> {
// Write the item on background thread, as some properties might have been updated in
// the background.
final ContentWriter writer = new ContentWriter(mContext);
@@ -272,7 +269,7 @@
mBgDataModel.addItem(mContext, item, true);
verifier.verifyModel();
}
- });
+ }).executeOnModelThread();
}
/**
@@ -303,15 +300,13 @@
Collectors.joining(","))
+ ". Reason: [" + (TextUtils.isEmpty(reason) ? "unknown" : reason) + "]");
notifyDelete(items);
- enqueueDeleteRunnable(() -> {
+ enqueueDeleteRunnable(newModelTask(() -> {
for (ItemInfo item : items) {
- final Uri uri = Favorites.getContentUri(item.id);
- mContext.getContentResolver().delete(uri, null, null);
-
+ mModel.getModelDbController().delete(TABLE_NAME, itemIdMatch(item.id), null);
mBgDataModel.removeItem(mContext, item);
verifier.verifyModel();
}
- });
+ }));
}
/**
@@ -321,7 +316,7 @@
ModelVerifier verifier = new ModelVerifier();
notifyDelete(Collections.singleton(info));
- enqueueDeleteRunnable(() -> {
+ enqueueDeleteRunnable(newModelTask(() -> {
mModel.getModelDbController().delete(Favorites.TABLE_NAME,
Favorites.CONTAINER + "=" + info.id, null);
mBgDataModel.removeItem(mContext, info.contents);
@@ -331,7 +326,7 @@
Favorites._ID + "=" + info.id, null);
mBgDataModel.removeItem(mContext, info);
verifier.verifyModel();
- });
+ }));
}
/**
@@ -343,7 +338,7 @@
if (holder != null && !info.isCustomWidget() && info.isWidgetIdAllocated()) {
// Deleting an app widget ID is a void call but writes to disk before returning
// to the caller...
- enqueueDeleteRunnable(() -> holder.deleteAppWidgetId(info.appWidgetId));
+ enqueueDeleteRunnable(newModelTask(() -> holder.deleteAppWidgetId(info.appWidgetId)));
}
deleteItemFromDatabase(info, reason);
}
@@ -373,19 +368,17 @@
* {@link #commitDelete()} is called (or abandoned if {@link #abortDelete} is called).
* Otherwise, we run the Runnable immediately.
*/
- private void enqueueDeleteRunnable(Runnable r) {
+ private void enqueueDeleteRunnable(ModelTask r) {
if (mPreparingToUndo) {
mDeleteRunnables.add(r);
} else {
- MODEL_EXECUTOR.execute(r);
+ r.executeOnModelThread();
}
}
public void commitDelete() {
mPreparingToUndo = false;
- for (Runnable runnable : mDeleteRunnables) {
- MODEL_EXECUTOR.execute(runnable);
- }
+ mDeleteRunnables.forEach(ModelTask::executeOnModelThread);
mDeleteRunnables.clear();
}
@@ -426,10 +419,9 @@
}
@Override
- public void run() {
- Uri uri = Favorites.getContentUri(mItemId);
- mContext.getContentResolver().update(uri, mWriter.get().getValues(mContext),
- null, null);
+ public void runImpl() {
+ mModel.getModelDbController().update(
+ TABLE_NAME, mWriter.get().getValues(mContext), itemIdMatch(mItemId), null);
updateItemArrays(mItem, mItemId);
}
}
@@ -444,27 +436,24 @@
}
@Override
- public void run() {
- ArrayList<ContentProviderOperation> ops = new ArrayList<>();
- int count = mItems.size();
- for (int i = 0; i < count; i++) {
- ItemInfo item = mItems.get(i);
- final int itemId = item.id;
- final Uri uri = Favorites.getContentUri(itemId);
- ContentValues values = mValues.get(i);
-
- ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());
- updateItemArrays(item, itemId);
- }
- try {
- mContext.getContentResolver().applyBatch(LauncherProvider.AUTHORITY, ops);
+ public void runImpl() {
+ try (SQLiteTransaction t = mModel.getModelDbController().newTransaction()) {
+ int count = mItems.size();
+ for (int i = 0; i < count; i++) {
+ ItemInfo item = mItems.get(i);
+ final int itemId = item.id;
+ mModel.getModelDbController().update(
+ TABLE_NAME, mValues.get(i), itemIdMatch(itemId), null);
+ updateItemArrays(item, itemId);
+ }
+ t.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
}
- private abstract class UpdateItemBaseRunnable implements Runnable {
+ private abstract class UpdateItemBaseRunnable extends ModelTask {
private final StackTraceElement[] mStackTrace;
private final ModelVerifier mVerifier = new ModelVerifier();
@@ -498,9 +487,9 @@
modelItem.container == Favorites.CONTAINER_HOTSEAT)) {
switch (modelItem.itemType) {
case Favorites.ITEM_TYPE_APPLICATION:
- case Favorites.ITEM_TYPE_SHORTCUT:
case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
case Favorites.ITEM_TYPE_FOLDER:
+ case Favorites.ITEM_TYPE_APP_PAIR:
if (!mBgDataModel.workspaceItems.contains(modelItem)) {
mBgDataModel.workspaceItems.add(modelItem);
}
@@ -516,6 +505,35 @@
}
}
+ private abstract class ModelTask implements Runnable {
+
+ private final int mLoadId = mBgDataModel.lastLoadId;
+
+ @Override
+ public final void run() {
+ if (mLoadId != mModel.getLastLoadId()) {
+ Log.d(TAG, "Model changed before the task could execute");
+ return;
+ }
+ runImpl();
+ }
+
+ public final void executeOnModelThread() {
+ MODEL_EXECUTOR.execute(this);
+ }
+
+ public abstract void runImpl();
+ }
+
+ private ModelTask newModelTask(Runnable r) {
+ return new ModelTask() {
+ @Override
+ public void runImpl() {
+ r.run();
+ }
+ };
+ }
+
/**
* Utility class to verify model updates are propagated properly to the callback.
*/
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 8c938f4..1917ba2 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -93,11 +93,6 @@
mOp = op;
mUser = user;
mPackages = packages;
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.WORK_TAB_MISSING, "PackageUpdatedTask mOp: " + mOp +
- " packageCount: " + mPackages.length + " user: " + user);
- DEBUG = true;
- }
}
@Override
@@ -142,9 +137,6 @@
// The update may have changed which shortcuts/widgets are available.
// Refresh the widgets for the package if we have an activity running.
Launcher launcher = Launcher.ACTIVITY_TRACKER.getCreatedActivity();
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.WORK_TAB_MISSING, "launcher: " + launcher);
- }
if (launcher != null) {
launcher.refreshAndBindWidgetsForPackageUser(
new PackageUserKey(packages[i], mUser));
@@ -156,7 +148,7 @@
break;
case OP_REMOVE: {
for (int i = 0; i < N; i++) {
- FileLog.d(TAG, "Removing app icon" + packages[i]);
+ FileLog.d(TAG, "Removing app icon: " + packages[i]);
iconCache.removeIconsForPkg(packages[i], mUser);
}
// Fall through
diff --git a/src/com/android/launcher3/model/UserLockStateChangedTask.java b/src/com/android/launcher3/model/UserLockStateChangedTask.java
index cb78138..63ca35b 100644
--- a/src/com/android/launcher3/model/UserLockStateChangedTask.java
+++ b/src/com/android/launcher3/model/UserLockStateChangedTask.java
@@ -16,12 +16,10 @@
package com.android.launcher3.model;
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER;
-import static com.android.launcher3.testing.shared.TestProtocol.WORK_TAB_MISSING;
import android.content.Context;
import android.content.pm.ShortcutInfo;
import android.os.UserHandle;
-import android.util.Log;
import androidx.annotation.NonNull;
@@ -31,7 +29,6 @@
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.shortcuts.ShortcutRequest;
import com.android.launcher3.shortcuts.ShortcutRequest.QueryResult;
-import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ItemInfoMatcher;
@@ -63,10 +60,6 @@
if (mIsUserUnlocked) {
QueryResult shortcuts = new ShortcutRequest(context, mUser)
.query(ShortcutRequest.PINNED);
- if (TestProtocol.sDebugTracing) {
- Log.d(WORK_TAB_MISSING, "shortcutQuery success? "
- + shortcuts.wasSuccess());
- }
if (shortcuts.wasSuccess()) {
for (ShortcutInfo shortcut : shortcuts) {
pinnedShortcuts.put(ShortcutKey.fromInfo(shortcut), shortcut);
@@ -89,9 +82,6 @@
if (mIsUserUnlocked) {
ShortcutKey key = ShortcutKey.fromItemInfo(si);
ShortcutInfo shortcut = pinnedShortcuts.get(key);
- if (TestProtocol.sDebugTracing) {
- Log.d(WORK_TAB_MISSING, "shortcutInfo: " + shortcut);
- }
// We couldn't verify the shortcut during loader. If its no longer available
// (probably due to clear data), delete the workspace item as well
if (shortcut == null) {
diff --git a/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java b/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java
index 93fc6a5..1fc8a03 100644
--- a/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java
+++ b/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java
@@ -82,9 +82,7 @@
if (!found) {
// Still no position found. Add a new screen to the end.
- screenId = LauncherSettings.Settings.call(app.getContext().getContentResolver(),
- LauncherSettings.Settings.METHOD_NEW_SCREEN_ID)
- .getInt(LauncherSettings.Settings.EXTRA_VALUE);
+ screenId = app.getModel().getModelDbController().getNewScreenId();
// Save the screen id for binding in the workspace
workspaceScreens.add(screenId);
diff --git a/src/com/android/launcher3/model/data/AppInfo.java b/src/com/android/launcher3/model/data/AppInfo.java
index 7e6cbef..6c2f589 100644
--- a/src/com/android/launcher3/model/data/AppInfo.java
+++ b/src/com/android/launcher3/model/data/AppInfo.java
@@ -23,8 +23,6 @@
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
-import android.os.Build;
-import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
@@ -177,12 +175,6 @@
info.runtimeStatusFlags |= (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
? FLAG_SYSTEM_NO : FLAG_SYSTEM_YES;
- if (appInfo.targetSdkVersion >= Build.VERSION_CODES.O
- && Process.myUserHandle().equals(lai.getUser())) {
- // The icon for a non-primary user is badged, hence it's not exactly an adaptive icon.
- info.runtimeStatusFlags |= FLAG_ADAPTIVE_ICON;
- }
-
// Sets the progress level, installation and incremental download flags.
info.setProgressLevel(
PackageManagerHelper.getLoadingProgress(lai),
diff --git a/src/com/android/launcher3/model/data/FolderInfo.java b/src/com/android/launcher3/model/data/FolderInfo.java
index e5a0eb1..9bf6d43 100644
--- a/src/com/android/launcher3/model/data/FolderInfo.java
+++ b/src/com/android/launcher3/model/data/FolderInfo.java
@@ -119,8 +119,8 @@
public static FolderInfo createAppPair(WorkspaceItemInfo app1, WorkspaceItemInfo app2) {
FolderInfo newAppPair = new FolderInfo();
newAppPair.itemType = LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR;
- newAppPair.contents.add(app1);
- newAppPair.contents.add(app2);
+ newAppPair.add(app1, /* animate */ false);
+ newAppPair.add(app2, /* animate */ false);
return newAppPair;
}
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index 660929c..9afa459 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -30,7 +30,6 @@
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_TASK;
import static com.android.launcher3.logger.LauncherAtom.ContainerInfo.ContainerCase.CONTAINER_NOT_SET;
import static com.android.launcher3.shortcuts.ShortcutKey.EXTRA_SHORTCUT_ID;
@@ -50,7 +49,6 @@
import com.android.launcher3.LauncherSettings.Animation;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Workspace;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logger.LauncherAtom.AllAppsContainer;
import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
@@ -88,7 +86,6 @@
/**
* One of {@link Favorites#ITEM_TYPE_APPLICATION},
- * {@link Favorites#ITEM_TYPE_SHORTCUT},
* {@link Favorites#ITEM_TYPE_DEEP_SHORTCUT}
* {@link Favorites#ITEM_TYPE_FOLDER},
* {@link Favorites#ITEM_TYPE_APP_PAIR},
@@ -325,9 +322,7 @@
* Returns whether this item should use the background animation.
*/
public boolean shouldUseBackgroundAnimation() {
- return animationType == LauncherSettings.Animation.VIEW_BACKGROUND
- && FeatureFlags.ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES.get()
- && FeatureFlags.ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION.get();
+ return animationType == LauncherSettings.Animation.VIEW_BACKGROUND;
}
/**
@@ -368,13 +363,6 @@
})
.orElse(LauncherAtom.Shortcut.newBuilder()));
break;
- case ITEM_TYPE_SHORTCUT:
- itemBuilder
- .setShortcut(nullableComponent
- .map(component -> LauncherAtom.Shortcut.newBuilder()
- .setShortcutName(component.flattenToShortString()))
- .orElse(LauncherAtom.Shortcut.newBuilder()));
- break;
case ITEM_TYPE_APPWIDGET:
itemBuilder
.setWidget(nullableComponent
diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
index e5fb015..dc180d8 100644
--- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
@@ -83,17 +83,6 @@
public static final int FLAG_SYSTEM_MASK = FLAG_SYSTEM_YES | FLAG_SYSTEM_NO;
/**
- * Flag indicating that the icon is an {@link android.graphics.drawable.AdaptiveIconDrawable}
- * that can be optimized in various way.
- */
- public static final int FLAG_ADAPTIVE_ICON = 1 << 8;
-
- /**
- * Flag indicating that the icon is badged.
- */
- public static final int FLAG_ICON_BADGED = 1 << 9;
-
- /**
* The icon is being installed. If {@link WorkspaceItemInfo#FLAG_RESTORED_ICON} or
* {@link WorkspaceItemInfo#FLAG_AUTOINSTALL_ICON} is set, then the icon is either being
* installed or is in a broken state.
@@ -119,6 +108,11 @@
| FLAG_DISABLED_VERSION_LOWER;
/**
+ * Flag indicating this item can't be pinned to home screen.
+ */
+ public static final int FLAG_NOT_PINNABLE = 1 << 13;
+
+ /**
* Status associated with the system state of the underlying item. This is calculated every
* time a new info is created and not persisted on the disk.
*/
diff --git a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
index 01606d4..3ce194d 100644
--- a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
+++ b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
@@ -96,7 +96,7 @@
public WorkspaceItemInfo() {
- itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+ itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
}
public WorkspaceItemInfo(WorkspaceItemInfo info) {
@@ -205,8 +205,8 @@
@Override
public ComponentName getTargetComponent() {
ComponentName cn = super.getTargetComponent();
- if (cn == null && (itemType == Favorites.ITEM_TYPE_SHORTCUT || hasStatusFlag(
- FLAG_SUPPORTS_WEB_UI | FLAG_AUTOINSTALL_ICON | FLAG_RESTORED_ICON))) {
+ if (cn == null && hasStatusFlag(
+ FLAG_SUPPORTS_WEB_UI | FLAG_AUTOINSTALL_ICON | FLAG_RESTORED_ICON)) {
// Legacy shortcuts and promise icons with web UI may not have a componentName but just
// a packageName. In that case create a empty componentName instead of adding additional
// check everywhere.
diff --git a/src/com/android/launcher3/notification/NotificationContainer.java b/src/com/android/launcher3/notification/NotificationContainer.java
index 9eb05cd..7cc9ad3 100644
--- a/src/com/android/launcher3/notification/NotificationContainer.java
+++ b/src/com/android/launcher3/notification/NotificationContainer.java
@@ -15,7 +15,7 @@
*/
package com.android.launcher3.notification;
-import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
+import static com.android.app.animation.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL;
import android.animation.Animator;
diff --git a/src/com/android/launcher3/notification/NotificationInfo.java b/src/com/android/launcher3/notification/NotificationInfo.java
index bb2c37f..f4468fd 100644
--- a/src/com/android/launcher3/notification/NotificationInfo.java
+++ b/src/com/android/launcher3/notification/NotificationInfo.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_ACTION_POPUP;
import static com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_ALL_APPS;
+import static com.android.launcher3.Utilities.allowBGLaunch;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NOTIFICATION_LAUNCH_TAP;
import android.app.ActivityOptions;
@@ -26,7 +27,6 @@
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
-import android.os.Bundle;
import android.service.notification.StatusBarNotification;
import android.view.View;
@@ -103,10 +103,10 @@
return;
}
final ActivityContext context = ActivityContext.lookupContext(view.getContext());
- Bundle activityOptions = ActivityOptions.makeClipRevealAnimation(
- view, 0, 0, view.getWidth(), view.getHeight()).toBundle();
+ ActivityOptions options = allowBGLaunch(ActivityOptions.makeClipRevealAnimation(
+ view, 0, 0, view.getWidth(), view.getHeight()));
try {
- intent.send(null, 0, null, null, null, null, activityOptions);
+ intent.send(null, 0, null, null, null, null, options.toBundle());
context.getStatsLogManager().logger().withItemInfo(mItemInfo)
.log(LAUNCHER_NOTIFICATION_LAUNCH_TAP);
} catch (PendingIntent.CanceledException e) {
diff --git a/src/com/android/launcher3/notification/NotificationMainView.java b/src/com/android/launcher3/notification/NotificationMainView.java
index 16a4057..ecd018b 100644
--- a/src/com/android/launcher3/notification/NotificationMainView.java
+++ b/src/com/android/launcher3/notification/NotificationMainView.java
@@ -16,8 +16,8 @@
package com.android.launcher3.notification;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.Utilities.mapToRange;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NOTIFICATION_DISMISSED;
import android.animation.AnimatorSet;
diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java
index 570d6ff..4ab2037 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicator.java
@@ -27,6 +27,14 @@
void setMarkersCount(int numMarkers);
/**
+ * Sets flag to indicate when the screens are in the process of binding so that we don't animate
+ * during that period.
+ */
+ default void setAreScreensBinding(boolean areScreensBinding) {
+ // No-op by default
+ }
+
+ /**
* Sets the flag if the Page Indicator should autohide.
*/
default void setShouldAutoHide(boolean shouldAutoHide) {
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
index b2c64b3..ce71275 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
@@ -130,6 +130,7 @@
*/
private float mCurrentPosition;
private float mFinalPosition;
+ private boolean mAreScreensBinding;
private ObjectAnimator mAnimator;
private @Nullable ObjectAnimator mAlphaAnimator;
@@ -163,7 +164,7 @@
@Override
public void setScroll(int currentScroll, int totalScroll) {
- if (SHOW_DOT_PAGINATION.get() && mActivePage != 0 && currentScroll == 0) {
+ if (SHOW_DOT_PAGINATION.get() && currentScroll == 0 && totalScroll == 0) {
CURRENT_POSITION.set(this, (float) mActivePage);
return;
}
@@ -172,6 +173,11 @@
return;
}
+ // Skip scroll update during binding. We will update it when binding completes.
+ if (mAreScreensBinding) {
+ return;
+ }
+
if (mShouldAutoHide) {
animatePaginationToAlpha(VISIBLE_ALPHA);
}
@@ -359,6 +365,16 @@
}
@Override
+ public void setAreScreensBinding(boolean areScreensBinding) {
+ // Reapply correct current position which was skipped during setScroll.
+ if (mAreScreensBinding && !areScreensBinding) {
+ CURRENT_POSITION.set(this, (float) mActivePage);
+ }
+
+ mAreScreensBinding = areScreensBinding;
+ }
+
+ @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Add extra spacing of mDotRadius on all sides so than entry animation could be run.
int width = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY ?
@@ -381,7 +397,9 @@
// Draw all page indicators;
float circleGap = mCircleGap;
- float startX = (getWidth() - (mNumPages * circleGap) + mDotRadius) / 2;
+ float startX = ((float) getWidth() / 2)
+ - (mCircleGap * (((float) mNumPages - 1) / 2))
+ - mDotRadius;
float x = startX + mDotRadius;
float y = getHeight() / 2;
@@ -420,9 +438,9 @@
float startCircle = (int) mCurrentPosition;
float delta = mCurrentPosition - startCircle;
float diameter = 2 * mDotRadius;
- float startX;
-
- startX = ((getWidth() - (mNumPages * mCircleGap) + mDotRadius) / 2);
+ float startX = ((float) getWidth() / 2)
+ - (mCircleGap * (((float) mNumPages - 1) / 2))
+ - mDotRadius;
sTempRect.top = (getHeight() * 0.5f) - mDotRadius;
sTempRect.bottom = (getHeight() * 0.5f) + mDotRadius;
sTempRect.left = startX + (startCircle * mCircleGap);
diff --git a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
index b24ee34..351ebce 100644
--- a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
+++ b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
@@ -16,8 +16,11 @@
package com.android.launcher3.pm;
+import static com.android.launcher3.Utilities.allowBGLaunch;
+
import android.annotation.TargetApi;
import android.app.Activity;
+import android.app.ActivityOptions;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
@@ -72,7 +75,7 @@
}
public int getItemType() {
- return LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+ return LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
}
@Override
@@ -138,8 +141,10 @@
}
IntentSender is = activity.getSystemService(LauncherApps.class)
.getShortcutConfigActivityIntent(mInfo);
+ ActivityOptions options = allowBGLaunch(ActivityOptions.makeBasic());
try {
- activity.startIntentSenderForResult(is, requestCode, null, 0, 0, 0);
+ activity.startIntentSenderForResult(is, requestCode, null, 0, 0, 0,
+ options.toBundle());
return true;
} catch (IntentSender.SendIntentException e) {
Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
diff --git a/src/com/android/launcher3/pm/UserCache.java b/src/com/android/launcher3/pm/UserCache.java
index 24a9609..92822ab 100644
--- a/src/com/android/launcher3/pm/UserCache.java
+++ b/src/com/android/launcher3/pm/UserCache.java
@@ -16,16 +16,19 @@
package com.android.launcher3.pm;
-import static com.android.launcher3.testing.shared.TestProtocol.WORK_TAB_MISSING;
-import static com.android.launcher3.testing.shared.TestProtocol.sDebugTracing;
-import static com.android.launcher3.testing.shared.TestProtocol.testLogD;
+import static com.android.launcher3.Utilities.ATLEAST_U;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.content.Context;
import android.content.Intent;
+import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArrayMap;
-import android.util.LongSparseArray;
+
+import androidx.annotation.AnyThread;
+import androidx.annotation.NonNull;
+import androidx.annotation.WorkerThread;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.SafeCloseable;
@@ -34,136 +37,121 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
+import java.util.function.BiConsumer;
/**
* Class which manages a local cache of user handles to avoid system rpc
*/
-public class UserCache {
+public class UserCache implements SafeCloseable {
+
+ public static final String ACTION_PROFILE_ADDED = ATLEAST_U
+ ? Intent.ACTION_PROFILE_ADDED : Intent.ACTION_MANAGED_PROFILE_ADDED;
+ public static final String ACTION_PROFILE_REMOVED = ATLEAST_U
+ ? Intent.ACTION_PROFILE_REMOVED : Intent.ACTION_MANAGED_PROFILE_REMOVED;
+
+ public static final String ACTION_PROFILE_UNLOCKED = ATLEAST_U
+ ? Intent.ACTION_PROFILE_ACCESSIBLE : Intent.ACTION_MANAGED_PROFILE_UNLOCKED;
+ public static final String ACTION_PROFILE_LOCKED = ATLEAST_U
+ ? Intent.ACTION_PROFILE_INACCESSIBLE : Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE;
public static final MainThreadInitializedObject<UserCache> INSTANCE =
new MainThreadInitializedObject<>(UserCache::new);
- private final Context mContext;
- private final UserManager mUserManager;
- private final ArrayList<Runnable> mUserChangeListeners = new ArrayList<>();
+ private final List<BiConsumer<UserHandle, String>> mUserEventListeners = new ArrayList<>();
private final SimpleBroadcastReceiver mUserChangeReceiver =
new SimpleBroadcastReceiver(this::onUsersChanged);
- private LongSparseArray<UserHandle> mUsers;
- // Create a separate reverse map as LongSparseArray.indexOfValue checks if objects are same
- // and not {@link Object#equals}
- private ArrayMap<UserHandle, Long> mUserToSerialMap;
+ private final Context mContext;
+
+ @NonNull
+ private Map<UserHandle, Long> mUserToSerialMap;
private UserCache(Context context) {
mContext = context;
- mUserManager = context.getSystemService(UserManager.class);
+ mUserToSerialMap = Collections.emptyMap();
+ MODEL_EXECUTOR.execute(this::initAsync);
}
+ @Override
+ public void close() {
+ MODEL_EXECUTOR.execute(() -> mUserChangeReceiver.unregisterReceiverSafely(mContext));
+ }
+
+ @WorkerThread
+ private void initAsync() {
+ mUserChangeReceiver.register(mContext,
+ Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
+ Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
+ ACTION_PROFILE_ADDED,
+ ACTION_PROFILE_REMOVED,
+ ACTION_PROFILE_UNLOCKED,
+ ACTION_PROFILE_LOCKED);
+ updateCache();
+ }
+
+ @AnyThread
private void onUsersChanged(Intent intent) {
- testLogD(WORK_TAB_MISSING, "onUsersChanged intent: " + intent);
- enableAndResetCache();
- mUserChangeListeners.forEach(Runnable::run);
+ MODEL_EXECUTOR.execute(this::updateCache);
+ UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
+ if (user == null) {
+ return;
+ }
+ String action = intent.getAction();
+ mUserEventListeners.forEach(l -> l.accept(user, action));
+ }
+
+ @WorkerThread
+ private void updateCache() {
+ mUserToSerialMap = queryAllUsers(mContext.getSystemService(UserManager.class));
}
/**
* Adds a listener for user additions and removals
*/
- public SafeCloseable addUserChangeListener(Runnable command) {
- synchronized (this) {
- if (mUserChangeListeners.isEmpty()) {
- // Enable caching and start listening for user broadcast
- mUserChangeReceiver.register(mContext,
- Intent.ACTION_MANAGED_PROFILE_ADDED,
- Intent.ACTION_MANAGED_PROFILE_REMOVED);
- enableAndResetCache();
- }
- mUserChangeListeners.add(command);
- return () -> removeUserChangeListener(command);
- }
- }
-
- private void enableAndResetCache() {
- synchronized (this) {
- mUsers = new LongSparseArray<>();
- mUserToSerialMap = new ArrayMap<>();
- List<UserHandle> users = mUserManager.getUserProfiles();
- if (users != null) {
- for (UserHandle user : users) {
- testLogD(WORK_TAB_MISSING, "caching user: " + user);
- long serial = mUserManager.getSerialNumberForUser(user);
- mUsers.put(serial, user);
- mUserToSerialMap.put(user, serial);
- }
- }
- }
- }
-
- private void removeUserChangeListener(Runnable command) {
- synchronized (this) {
- mUserChangeListeners.remove(command);
- if (mUserChangeListeners.isEmpty()) {
- // Disable cache and stop listening
- mContext.unregisterReceiver(mUserChangeReceiver);
-
- mUsers = null;
- mUserToSerialMap = null;
- }
- }
+ public SafeCloseable addUserEventListener(BiConsumer<UserHandle, String> listener) {
+ mUserEventListeners.add(listener);
+ return () -> mUserEventListeners.remove(listener);
}
/**
* @see UserManager#getSerialNumberForUser(UserHandle)
*/
public long getSerialNumberForUser(UserHandle user) {
- synchronized (this) {
- if (mUserToSerialMap != null) {
- Long serial = mUserToSerialMap.get(user);
- return serial == null ? 0 : serial;
- }
- }
- return mUserManager.getSerialNumberForUser(user);
+ Long serial = mUserToSerialMap.get(user);
+ return serial == null ? 0 : serial;
}
/**
* @see UserManager#getUserForSerialNumber(long)
*/
public UserHandle getUserForSerialNumber(long serialNumber) {
- synchronized (this) {
- if (mUsers != null) {
- return mUsers.get(serialNumber);
- }
- }
- return mUserManager.getUserForSerialNumber(serialNumber);
+ Long value = serialNumber;
+ return mUserToSerialMap
+ .entrySet()
+ .stream()
+ .filter(entry -> value.equals(entry.getValue()))
+ .findFirst()
+ .map(Map.Entry::getKey)
+ .orElse(Process.myUserHandle());
}
/**
* @see UserManager#getUserProfiles()
*/
public List<UserHandle> getUserProfiles() {
- StringBuilder usersToReturn = new StringBuilder();
- List<UserHandle> users;
- if (sDebugTracing) {
- users = mUserManager.getUserProfiles();
- for (UserHandle u : users) {
- usersToReturn.append(u).append(" && ");
- }
- testLogD(WORK_TAB_MISSING, "users from userManager: " + usersToReturn);
- }
+ return List.copyOf(mUserToSerialMap.keySet());
+ }
- synchronized (this) {
- if (mUsers != null) {
- usersToReturn = new StringBuilder();
- for (UserHandle u : mUserToSerialMap.keySet()) {
- usersToReturn.append(u).append(" && ");
- }
- testLogD(WORK_TAB_MISSING, "users from cache: " + usersToReturn);
- return new ArrayList<>(mUserToSerialMap.keySet());
- } else {
- testLogD(WORK_TAB_MISSING, "users from cache null");
+ private static Map<UserHandle, Long> queryAllUsers(UserManager userManager) {
+ Map<UserHandle, Long> users = new ArrayMap<>();
+ List<UserHandle> usersActual = userManager.getUserProfiles();
+ if (usersActual != null) {
+ for (UserHandle user : usersActual) {
+ long serial = userManager.getSerialNumberForUser(user);
+ users.put(user, serial);
}
}
-
- users = mUserManager.getUserProfiles();
- return users == null ? Collections.emptyList() : users;
+ return users;
}
}
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 72f99cb..6b08153 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -18,12 +18,9 @@
import static androidx.core.content.ContextCompat.getColorStateList;
-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.EMPHASIZED_ACCELERATE;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP;
+import static com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE;
+import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
+import static com.android.app.animation.Interpolators.LINEAR;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -170,7 +167,7 @@
mIterateChildrenTag = getContext().getString(R.string.popup_container_iterate_children);
- if (!ENABLE_MATERIAL_U_POPUP.get() && mActivityContext.canUseMultipleShadesForPopup()) {
+ if (mActivityContext.canUseMultipleShadesForPopup()) {
mColorIds = new int[]{R.color.popup_shade_first, R.color.popup_shade_second,
R.color.popup_shade_third};
} else {
@@ -241,7 +238,6 @@
}
}
- int numVisibleChild = 0;
int numVisibleShortcut = 0;
View lastView = null;
AnimatorSet colorAnimator = new AnimatorSet();
@@ -256,26 +252,13 @@
MarginLayoutParams mlp = (MarginLayoutParams) lastView.getLayoutParams();
mlp.bottomMargin = 0;
- if (colors != null) {
- if (!ENABLE_MATERIAL_U_POPUP.get()) {
- backgroundColor = colors[numVisibleChild % colors.length];
- }
-
- if (ENABLE_MATERIAL_U_POPUP.get() && isShortcutContainer(view)) {
- setChildColor(view, colors[0], colorAnimator);
- mArrowColor = colors[0];
- }
- }
-
- // Arrow color matches the first child or the last child.
- if (!ENABLE_MATERIAL_U_POPUP.get()
- && (mIsAboveIcon || (numVisibleChild == 0 && viewGroup == this))) {
- mArrowColor = backgroundColor;
+ if (colors != null && isShortcutContainer(view)) {
+ setChildColor(view, colors[0], colorAnimator);
+ mArrowColor = colors[0];
}
if (view instanceof ViewGroup && isShortcutContainer(view)) {
assignMarginsAndBackgrounds((ViewGroup) view, backgroundColor);
- numVisibleChild++;
continue;
}
@@ -295,7 +278,6 @@
}
setChildColor(view, backgroundColor, colorAnimator);
- numVisibleChild++;
}
}
@@ -573,23 +555,14 @@
protected void animateOpen() {
setVisibility(View.VISIBLE);
- mOpenCloseAnimator = ENABLE_MATERIAL_U_POPUP.get()
- ? getMaterialUOpenCloseAnimator(
+ mOpenCloseAnimator = getOpenCloseAnimator(
true,
OPEN_DURATION_U,
OPEN_FADE_START_DELAY_U,
OPEN_FADE_DURATION_U,
OPEN_CHILD_FADE_START_DELAY_U,
OPEN_CHILD_FADE_DURATION_U,
- EMPHASIZED_DECELERATE)
- : getOpenCloseAnimator(
- true,
- mOpenDuration,
- mOpenFadeStartDelay,
- mOpenFadeDuration,
- mOpenChildFadeStartDelay,
- mOpenChildFadeDuration,
- DECELERATED_EASE);
+ EMPHASIZED_DECELERATE);
onCreateOpenAnimation(mOpenCloseAnimator);
mOpenCloseAnimator.addListener(new AnimatorListenerAdapter() {
@@ -603,44 +576,6 @@
mOpenCloseAnimator.start();
}
- private AnimatorSet getOpenCloseAnimator(boolean isOpening, int totalDuration,
- int fadeStartDelay, int fadeDuration, int childFadeStartDelay,
- int childFadeDuration, Interpolator interpolator) {
- final AnimatorSet animatorSet = new AnimatorSet();
- float[] alphaValues = isOpening ? new float[] {0, 1} : new float[] {1, 0};
- float[] scaleValues = isOpening ? new float[] {0.5f, 1} : new float[] {1, 0.5f};
-
- ValueAnimator fade = ValueAnimator.ofFloat(alphaValues);
- fade.setStartDelay(fadeStartDelay);
- fade.setDuration(fadeDuration);
- fade.setInterpolator(LINEAR);
- fade.addUpdateListener(anim -> {
- float alpha = (float) anim.getAnimatedValue();
- mArrow.setAlpha(alpha);
- setAlpha(alpha);
- });
- animatorSet.play(fade);
-
- setPivotX(mIsLeftAligned ? 0 : getMeasuredWidth());
- setPivotY(mIsAboveIcon ? getMeasuredHeight() : 0);
- Animator scale = ObjectAnimator.ofFloat(this, View.SCALE_Y, scaleValues);
- scale.setDuration(totalDuration);
- scale.setInterpolator(interpolator);
- animatorSet.play(scale);
-
- if (shouldScaleArrow) {
- Animator arrowScaleAnimator = ObjectAnimator.ofFloat(mArrow, View.SCALE_Y,
- scaleValues);
- arrowScaleAnimator.setDuration(totalDuration);
- arrowScaleAnimator.setInterpolator(interpolator);
- animatorSet.play(arrowScaleAnimator);
- }
-
- fadeInChildViews(this, alphaValues, childFadeStartDelay, childFadeDuration, animatorSet);
-
- return animatorSet;
- }
-
private void fadeInChildViews(ViewGroup group, float[] alphaValues, long startDelay,
long duration, AnimatorSet out) {
for (int i = group.getChildCount() - 1; i >= 0; --i) {
@@ -673,26 +608,14 @@
}
mIsOpen = false;
- mOpenCloseAnimator = getOpenCloseAnimator(false, mCloseDuration, mCloseFadeStartDelay,
- mCloseFadeDuration, mCloseChildFadeStartDelay, mCloseChildFadeDuration,
- ACCELERATED_EASE);
-
- mOpenCloseAnimator = ENABLE_MATERIAL_U_POPUP.get()
- ? getMaterialUOpenCloseAnimator(
+ mOpenCloseAnimator = getOpenCloseAnimator(
false,
CLOSE_DURATION_U,
CLOSE_FADE_START_DELAY_U,
CLOSE_FADE_DURATION_U,
CLOSE_CHILD_FADE_START_DELAY_U,
CLOSE_CHILD_FADE_DURATION_U,
- EMPHASIZED_ACCELERATE)
- : getOpenCloseAnimator(false,
- mCloseDuration,
- mCloseFadeStartDelay,
- mCloseFadeDuration,
- mCloseChildFadeStartDelay,
- mCloseChildFadeDuration,
- ACCELERATED_EASE);
+ EMPHASIZED_ACCELERATE);
onCreateCloseAnimation(mOpenCloseAnimator);
mOpenCloseAnimator.addListener(new AnimatorListenerAdapter() {
@@ -709,7 +632,7 @@
mOpenCloseAnimator.start();
}
- protected AnimatorSet getMaterialUOpenCloseAnimator(boolean isOpening, int scaleDuration,
+ protected AnimatorSet getOpenCloseAnimator(boolean isOpening, int scaleDuration,
int fadeStartDelay, int fadeDuration, int childFadeStartDelay, int childFadeDuration,
Interpolator interpolator) {
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 1f26bab..934d43b 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -20,21 +20,15 @@
import static com.android.launcher3.Utilities.ATLEAST_P;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.Utilities.squaredTouchSlop;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP;
import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS;
-import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS_IF_NOTIFICATIONS;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
-import static java.util.Collections.emptyList;
-
import android.animation.AnimatorSet;
import android.animation.LayoutTransition;
-import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
-import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
@@ -55,17 +49,12 @@
import com.android.launcher3.R;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.accessibility.ShortcutMenuAccessibilityDelegate;
-import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.notification.NotificationContainer;
-import com.android.launcher3.notification.NotificationInfo;
-import com.android.launcher3.notification.NotificationKeyData;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
import com.android.launcher3.touch.ItemLongClickListener;
@@ -81,7 +70,7 @@
import java.util.stream.Collectors;
/**
- * A container for shortcuts to deep links and notifications associated with an app.
+ * A container for shortcuts to deep links associated with an app.
*
* @param <T> The activity on with the popup shows
*/
@@ -98,8 +87,6 @@
private final float mShortcutHeight;
private BubbleTextView mOriginalIcon;
- private int mNumNotifications;
- private NotificationContainer mNotificationContainer;
private int mContainerWidth;
private ViewGroup mWidgetContainer;
@@ -142,24 +129,12 @@
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
mInterceptTouchDown.set(ev.getX(), ev.getY());
}
- if (mNotificationContainer != null
- && mNotificationContainer.onInterceptSwipeEvent(ev)) {
- return true;
- }
// Stop sending touch events to deep shortcut views if user moved beyond touch slop.
return squaredHypot(mInterceptTouchDown.x - ev.getX(), mInterceptTouchDown.y - ev.getY())
> squaredTouchSlop(getContext());
}
@Override
- public boolean onTouchEvent(MotionEvent ev) {
- if (mNotificationContainer != null) {
- return mNotificationContainer.onSwipeEvent(ev) || super.onTouchEvent(ev);
- }
- return super.onTouchEvent(ev);
- }
-
- @Override
protected boolean isOfType(int type) {
return (type & TYPE_ACTION_POPUP) != 0;
}
@@ -194,14 +169,6 @@
return false;
}
- @Override
- protected void setChildColor(View view, int color, AnimatorSet animatorSetOut) {
- super.setChildColor(view, color, animatorSetOut);
- if (view.getId() == R.id.notification_container && mNotificationContainer != null) {
- mNotificationContainer.updateBackgroundColor(color, animatorSetOut);
- }
- }
-
/**
* Returns true if we can show the container.
*
@@ -213,7 +180,8 @@
}
/**
- * Shows the notifications and deep shortcuts associated with a Launcher {@param icon}.
+ * Shows a popup with shortcuts associated with a Launcher icon
+ * @param icon the app icon to show the popup for
* @return the container if shown or null.
*/
public static PopupContainerWithArrow<Launcher> showForIcon(BubbleTextView icon) {
@@ -235,21 +203,10 @@
.map(s -> s.getShortcut(launcher, item, icon))
.filter(Objects::nonNull)
.collect(Collectors.toList());
- if (ENABLE_MATERIAL_U_POPUP.get()) {
- container = (PopupContainerWithArrow) launcher.getLayoutInflater().inflate(
- R.layout.popup_container_material_u, launcher.getDragLayer(), false);
- container.configureForLauncher(launcher);
- container.populateAndShowRowsMaterialU(icon, deepShortcutCount, systemShortcuts);
- } else {
- container = (PopupContainerWithArrow) launcher.getLayoutInflater().inflate(
- R.layout.popup_container, launcher.getDragLayer(), false);
- container.configureForLauncher(launcher);
- container.populateAndShow(
- icon,
- deepShortcutCount,
- popupDataProvider.getNotificationKeysForItem(item),
- systemShortcuts);
- }
+ container = (PopupContainerWithArrow) launcher.getLayoutInflater().inflate(
+ R.layout.popup_container, launcher.getDragLayer(), false);
+ container.configureForLauncher(launcher);
+ container.populateAndShowRows(icon, deepShortcutCount, systemShortcuts);
launcher.refreshAndBindWidgetsForPackageUser(PackageUserKey.fromItemInfo(item));
container.requestFocus();
return container;
@@ -263,91 +220,6 @@
launcher.getDragController().addDragListener(this);
}
- private void initializeSystemShortcuts(List<SystemShortcut> shortcuts) {
- if (shortcuts.isEmpty()) {
- return;
- }
- // If there is only 1 shortcut, add it to its own container so it can show text and icon
- if (shortcuts.size() == 1) {
- mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_rows_container,
- this, 0);
- initializeSystemShortcut(R.layout.system_shortcut, mSystemShortcutContainer,
- shortcuts.get(0), false);
- return;
- }
- addSystemShortcutsIconsOnly(shortcuts);
- }
-
- @TargetApi(Build.VERSION_CODES.P)
- public void populateAndShow(final BubbleTextView originalIcon, int shortcutCount,
- final List<NotificationKeyData> notificationKeys, List<SystemShortcut> shortcuts) {
- mNumNotifications = notificationKeys.size();
- mOriginalIcon = originalIcon;
-
- boolean hasDeepShortcuts = shortcutCount > 0;
- mContainerWidth = getResources().getDimensionPixelSize(R.dimen.bg_popup_item_width);
-
- // Add views
- if (mNumNotifications > 0) {
- // Add notification entries
- if (mNotificationContainer == null) {
- mNotificationContainer = findViewById(R.id.notification_container);
- mNotificationContainer.setVisibility(VISIBLE);
- mNotificationContainer.setPopupView(this);
- } else {
- mNotificationContainer.setVisibility(GONE);
- }
- updateNotificationHeader();
- }
- mSystemShortcutContainer = this;
- if (mDeepShortcutContainer == null) {
- mDeepShortcutContainer = findViewById(R.id.deep_shortcuts_container);
- }
- if (hasDeepShortcuts) {
- List<SystemShortcut> systemShortcuts = getNonWidgetSystemShortcuts(shortcuts);
- // if there are deep shortcuts, we might want to increase the width of shortcuts to fit
- // horizontally laid out system shortcuts.
- mContainerWidth = Math.max(mContainerWidth,
- systemShortcuts.size() * getResources()
- .getDimensionPixelSize(R.dimen.system_shortcut_header_icon_touch_size)
- );
-
- mDeepShortcutContainer.setVisibility(View.VISIBLE);
-
- for (int i = shortcutCount; i > 0; i--) {
- DeepShortcutView v = inflateAndAdd(R.layout.deep_shortcut, mDeepShortcutContainer);
- v.getLayoutParams().width = mContainerWidth;
- mDeepShortcuts.add(v);
- }
- updateHiddenShortcuts();
- Optional<SystemShortcut.Widgets> widgetShortcutOpt = getWidgetShortcut(shortcuts);
- if (widgetShortcutOpt.isPresent()) {
- if (mWidgetContainer == null) {
- mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container, this, 0);
- }
- initializeWidgetShortcut(mWidgetContainer, widgetShortcutOpt.get());
- }
-
- initializeSystemShortcuts(systemShortcuts);
- } else {
- mDeepShortcutContainer.setVisibility(View.GONE);
- mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_rows_container,
- this, 0);
- mWidgetContainer = mSystemShortcutContainer;
- if (!shortcuts.isEmpty()) {
- for (int i = 0; i < shortcuts.size(); i++) {
- initializeSystemShortcut(
- R.layout.system_shortcut,
- mSystemShortcutContainer,
- shortcuts.get(i),
- i < shortcuts.size() - 1);
- }
- }
- }
- show();
- loadAppShortcuts((ItemInfo) originalIcon.getTag(), notificationKeys);
- }
-
/**
* Populate and show shortcuts for the Launcher U app shortcut design.
* Will inflate the container and shortcut View instances for the popup container.
@@ -355,28 +227,27 @@
* @param deepShortcutCount Number of DeepShortcutView instances to add to container
* @param systemShortcuts List of SystemShortcuts to add to container
*/
- public void populateAndShowRowsMaterialU(final BubbleTextView originalIcon,
+ public void populateAndShowRows(final BubbleTextView originalIcon,
int deepShortcutCount, List<SystemShortcut> systemShortcuts) {
mOriginalIcon = originalIcon;
mContainerWidth = getResources().getDimensionPixelSize(R.dimen.bg_popup_item_width);
if (deepShortcutCount > 0) {
- addAllShortcutsMaterialU(deepShortcutCount, systemShortcuts);
+ addAllShortcuts(deepShortcutCount, systemShortcuts);
} else if (!systemShortcuts.isEmpty()) {
- addSystemShortcutsMaterialU(systemShortcuts,
- R.layout.system_shortcut_rows_container_material_u,
+ addSystemShortcuts(systemShortcuts,
+ R.layout.system_shortcut_rows_container,
R.layout.system_shortcut);
}
show();
- loadAppShortcuts((ItemInfo) originalIcon.getTag(), /* notificationKeys= */ emptyList());
+ loadAppShortcuts((ItemInfo) originalIcon.getTag());
}
/**
* Animates and loads shortcuts on background thread for this popup container
*/
- private void loadAppShortcuts(ItemInfo originalItemInfo,
- List<NotificationKeyData> notificationKeys) {
+ private void loadAppShortcuts(ItemInfo originalItemInfo) {
if (ATLEAST_P) {
setAccessibilityPaneTitle(getTitleForAccessibility());
@@ -387,7 +258,7 @@
// Load the shortcuts on a background thread and update the container as it animates.
MODEL_EXECUTOR.getHandler().postAtFrontOfQueue(PopupPopulator.createUpdateRunnable(
mActivityContext, originalItemInfo, new Handler(Looper.getMainLooper()),
- this, mDeepShortcuts, notificationKeys));
+ this, mDeepShortcuts));
}
/**
@@ -396,16 +267,16 @@
* @param deepShortcutCount number of DeepShortcutView instances
* @param systemShortcuts List of SystemShortcuts
*/
- private void addAllShortcutsMaterialU(int deepShortcutCount,
+ private void addAllShortcuts(int deepShortcutCount,
List<SystemShortcut> systemShortcuts) {
if (deepShortcutCount + systemShortcuts.size() <= SHORTCUT_COLLAPSE_THRESHOLD) {
// add all system shortcuts including widgets shortcut to same container
- addSystemShortcutsMaterialU(systemShortcuts,
- R.layout.system_shortcut_rows_container_material_u,
+ addSystemShortcuts(systemShortcuts,
+ R.layout.system_shortcut_rows_container,
R.layout.system_shortcut);
float currentHeight = (mShortcutHeight * systemShortcuts.size())
+ mChildContainerMargin;
- addDeepShortcutsMaterialU(deepShortcutCount, currentHeight);
+ addDeepShortcuts(deepShortcutCount, currentHeight);
return;
}
@@ -426,7 +297,7 @@
initializeWidgetShortcut(mWidgetContainer, widgetShortcutOpt.get());
currentHeight += mShortcutHeight + mChildContainerMargin;
}
- addDeepShortcutsMaterialU(deepShortcutCount, currentHeight);
+ addDeepShortcuts(deepShortcutCount, currentHeight);
}
/**
@@ -464,7 +335,7 @@
* @param systemShortcutContainerLayout Layout Resource for the Container of shortcut Views
* @param systemShortcutLayout Layout Resource for the individual shortcut Views
*/
- private void addSystemShortcutsMaterialU(List<SystemShortcut> systemShortcuts,
+ private void addSystemShortcuts(List<SystemShortcut> systemShortcuts,
@LayoutRes int systemShortcutContainerLayout, @LayoutRes int systemShortcutLayout) {
if (systemShortcuts.size() == 0) {
@@ -486,9 +357,7 @@
return;
}
- mSystemShortcutContainer = ENABLE_MATERIAL_U_POPUP.get()
- ? inflateAndAdd(R.layout.system_shortcut_icons_container_material_u, this)
- : inflateAndAdd(R.layout.system_shortcut_icons_container, this, 0);
+ mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_icons_container, this);
for (int i = 0; i < systemShortcuts.size(); i++) {
@LayoutRes int shortcutIconLayout = R.layout.system_shortcut_icon_only;
@@ -513,13 +382,13 @@
* @param deepShortcutCount number of DeepShortcutView instances to add
* @param currentHeight height of popup before adding deep shortcuts
*/
- private void addDeepShortcutsMaterialU(int deepShortcutCount, float currentHeight) {
+ private void addDeepShortcuts(int deepShortcutCount, float currentHeight) {
mDeepShortcutContainer = inflateAndAdd(R.layout.deep_shortcut_container, this);
for (int i = deepShortcutCount; i > 0; i--) {
currentHeight += mShortcutHeight;
// when there is limited vertical screen space, limit total popup rows to fit
if (currentHeight >= mActivityContext.getDeviceProfile().availableHeightPx) break;
- DeepShortcutView v = inflateAndAdd(R.layout.deep_shortcut_material_u,
+ DeepShortcutView v = inflateAndAdd(R.layout.deep_shortcut,
mDeepShortcutContainer);
v.getLayoutParams().width = mContainerWidth;
mDeepShortcuts.add(v);
@@ -527,10 +396,6 @@
updateHiddenShortcuts();
}
- protected NotificationContainer getNotificationContainer() {
- return mNotificationContainer;
- }
-
protected BubbleTextView getOriginalIcon() {
return mOriginalIcon;
}
@@ -548,9 +413,7 @@
}
private String getTitleForAccessibility() {
- return getContext().getString(mNumNotifications == 0 ?
- R.string.action_deep_shortcut :
- R.string.shortcuts_menu_with_notifications_description);
+ return getContext().getString(R.string.action_deep_shortcut);
}
@Override
@@ -564,20 +427,11 @@
: mOriginalIcon.getHeight());
}
- public void applyNotificationInfos(List<NotificationInfo> notificationInfos) {
- if (mNotificationContainer != null) {
- mNotificationContainer.applyNotificationInfos(notificationInfos);
- }
- }
-
protected void updateHiddenShortcuts() {
- int allowedCount = mNotificationContainer != null
- ? MAX_SHORTCUTS_IF_NOTIFICATIONS : MAX_SHORTCUTS;
-
int total = mDeepShortcuts.size();
for (int i = 0; i < total; i++) {
DeepShortcutView view = mDeepShortcuts.get(i);
- view.setVisibility(i >= allowedCount ? GONE : VISIBLE);
+ view.setVisibility(i >= MAX_SHORTCUTS ? GONE : VISIBLE);
}
}
@@ -666,14 +520,6 @@
};
}
- protected void updateNotificationHeader() {
- ItemInfoWithIcon itemInfo = (ItemInfoWithIcon) mOriginalIcon.getTag();
- DotInfo dotInfo = mActivityContext.getDotInfoForItem(itemInfo);
- if (mNotificationContainer != null && dotInfo != null) {
- mNotificationContainer.updateHeader(dotInfo.getNotificationCount());
- }
- }
-
@Override
public void onDropCompleted(View target, DragObject d, boolean success) { }
diff --git a/src/com/android/launcher3/popup/PopupLiveUpdateHandler.java b/src/com/android/launcher3/popup/PopupLiveUpdateHandler.java
index c5d5452..9d6f2a5 100644
--- a/src/com/android/launcher3/popup/PopupLiveUpdateHandler.java
+++ b/src/com/android/launcher3/popup/PopupLiveUpdateHandler.java
@@ -15,22 +15,12 @@
*/
package com.android.launcher3.popup;
-import static android.view.View.GONE;
-
import android.content.Context;
import android.view.View;
import com.android.launcher3.BubbleTextView;
-import com.android.launcher3.dot.DotInfo;
-import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.notification.NotificationContainer;
-import com.android.launcher3.notification.NotificationKeyData;
-import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.views.ActivityContext;
-import java.util.Map;
-import java.util.function.Predicate;
-
/**
* Utility class to handle updates while the popup is visible (like widgets and
* notification changes)
@@ -67,40 +57,6 @@
}
}
- /**
- * Updates the notification header if the original icon's dot updated.
- */
- @Override
- public void onNotificationDotsUpdated(Predicate<PackageUserKey> updatedDots) {
- ItemInfo itemInfo = (ItemInfo) mPopupContainerWithArrow.getOriginalIcon().getTag();
- PackageUserKey packageUser = PackageUserKey.fromItemInfo(itemInfo);
- if (updatedDots.test(packageUser)) {
- mPopupContainerWithArrow.updateNotificationHeader();
- }
- }
-
-
- @Override
- public void trimNotifications(Map<PackageUserKey, DotInfo> updatedDots) {
- NotificationContainer notificationContainer =
- mPopupContainerWithArrow.getNotificationContainer();
- if (notificationContainer == null) {
- return;
- }
- ItemInfo originalInfo = (ItemInfo) mPopupContainerWithArrow.getOriginalIcon().getTag();
- DotInfo dotInfo = updatedDots.get(PackageUserKey.fromItemInfo(originalInfo));
- if (dotInfo == null || dotInfo.getNotificationKeys().size() == 0) {
- // No more notifications, remove the notification views and expand all shortcuts.
- notificationContainer.setVisibility(GONE);
- mPopupContainerWithArrow.updateHiddenShortcuts();
- mPopupContainerWithArrow.assignMarginsAndBackgrounds(mPopupContainerWithArrow);
- mPopupContainerWithArrow.updateArrowColor();
- } else {
- notificationContainer.trimNotifications(
- NotificationKeyData.extractKeysOnly(dotInfo.getNotificationKeys()));
- }
- }
-
@Override
public void onSystemShortcutsUpdated() {
mPopupContainerWithArrow.close(true);
diff --git a/src/com/android/launcher3/popup/PopupPopulator.java b/src/com/android/launcher3/popup/PopupPopulator.java
index 8be4e6c..aa24f60 100644
--- a/src/com/android/launcher3/popup/PopupPopulator.java
+++ b/src/com/android/launcher3/popup/PopupPopulator.java
@@ -24,26 +24,19 @@
import android.os.Handler;
import android.os.UserHandle;
-import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.notification.NotificationInfo;
-import com.android.launcher3.notification.NotificationKeyData;
-import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.shortcuts.ShortcutRequest;
import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Comparator;
-import java.util.Iterator;
import java.util.List;
-import java.util.stream.Collectors;
/**
* Contains logic relevant to populating a {@link PopupContainerWithArrow}. In particular,
@@ -52,24 +45,20 @@
public class PopupPopulator {
public static final int MAX_SHORTCUTS = 4;
- @VisibleForTesting static final int NUM_DYNAMIC = 2;
- public static final int MAX_SHORTCUTS_IF_NOTIFICATIONS = 2;
+ @VisibleForTesting
+ static final int NUM_DYNAMIC = 2;
/**
* Sorts shortcuts in rank order, with manifest shortcuts coming before dynamic shortcuts.
*/
- private static final Comparator<ShortcutInfo> SHORTCUT_RANK_COMPARATOR
- = new Comparator<ShortcutInfo>() {
- @Override
- public int compare(ShortcutInfo a, ShortcutInfo b) {
- if (a.isDeclaredInManifest() && !b.isDeclaredInManifest()) {
- return -1;
- }
- if (!a.isDeclaredInManifest() && b.isDeclaredInManifest()) {
- return 1;
- }
- return Integer.compare(a.getRank(), b.getRank());
+ private static final Comparator<ShortcutInfo> SHORTCUT_RANK_COMPARATOR = (a, b) -> {
+ if (a.isDeclaredInManifest() && !b.isDeclaredInManifest()) {
+ return -1;
}
+ if (!a.isDeclaredInManifest() && b.isDeclaredInManifest()) {
+ return 1;
+ }
+ return Integer.compare(a.getRank(), b.getRank());
};
/**
@@ -77,23 +66,10 @@
* We want the filter to include both static and dynamic shortcuts, so we always
* include NUM_DYNAMIC dynamic shortcuts, if at least that many are present.
*
- * @param shortcutIdToRemoveFirst An id that should be filtered out first, if any.
* @return a subset of shortcuts, in sorted order, with size <= MAX_SHORTCUTS.
*/
- public static List<ShortcutInfo> sortAndFilterShortcuts(
- List<ShortcutInfo> shortcuts, @Nullable String shortcutIdToRemoveFirst) {
- // Remove up to one specific shortcut before sorting and doing somewhat fancy filtering.
- if (shortcutIdToRemoveFirst != null) {
- Iterator<ShortcutInfo> shortcutIterator = shortcuts.iterator();
- while (shortcutIterator.hasNext()) {
- if (shortcutIterator.next().getId().equals(shortcutIdToRemoveFirst)) {
- shortcutIterator.remove();
- break;
- }
- }
- }
-
- Collections.sort(shortcuts, SHORTCUT_RANK_COMPARATOR);
+ public static List<ShortcutInfo> sortAndFilterShortcuts(List<ShortcutInfo> shortcuts) {
+ shortcuts.sort(SHORTCUT_RANK_COMPARATOR);
if (shortcuts.size() <= MAX_SHORTCUTS) {
return shortcuts;
}
@@ -127,37 +103,20 @@
}
/**
- * Returns a runnable to update the provided shortcuts and notifications
+ * Returns a runnable to update the provided shortcuts
*/
public static <T extends Context & ActivityContext> Runnable createUpdateRunnable(
final T context,
final ItemInfo originalInfo,
final Handler uiHandler, final PopupContainerWithArrow container,
- final List<DeepShortcutView> shortcutViews,
- final List<NotificationKeyData> notificationKeys) {
+ final List<DeepShortcutView> shortcutViews) {
final ComponentName activity = originalInfo.getTargetComponent();
final UserHandle user = originalInfo.user;
return () -> {
- if (!notificationKeys.isEmpty()) {
- NotificationListener notificationListener =
- NotificationListener.getInstanceIfConnected();
- final List<NotificationInfo> infos;
- if (notificationListener == null) {
- infos = Collections.emptyList();
- } else {
- infos = notificationListener.getNotificationsForKeys(notificationKeys).stream()
- .map(sbn -> new NotificationInfo(context, sbn, originalInfo))
- .collect(Collectors.toList());
- }
- uiHandler.post(() -> container.applyNotificationInfos(infos));
- }
-
List<ShortcutInfo> shortcuts = new ShortcutRequest(context, user)
.withContainer(activity)
.query(ShortcutRequest.PUBLISHED);
- String shortcutIdToDeDupe = notificationKeys.isEmpty() ? null
- : notificationKeys.get(0).shortcutId;
- shortcuts = PopupPopulator.sortAndFilterShortcuts(shortcuts, shortcutIdToDeDupe);
+ shortcuts = PopupPopulator.sortAndFilterShortcuts(shortcuts);
IconCache cache = LauncherAppState.getInstance(context).getIconCache();
for (int i = 0; i < shortcuts.size() && i < shortcutViews.size(); i++) {
final ShortcutInfo shortcut = shortcuts.get(i);
diff --git a/src/com/android/launcher3/popup/RemoteActionShortcut.java b/src/com/android/launcher3/popup/RemoteActionShortcut.java
index 7c9ab87..eab0969 100644
--- a/src/com/android/launcher3/popup/RemoteActionShortcut.java
+++ b/src/com/android/launcher3/popup/RemoteActionShortcut.java
@@ -16,10 +16,12 @@
package com.android.launcher3.popup;
+import static com.android.launcher3.Utilities.allowBGLaunch;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.annotation.TargetApi;
+import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.app.RemoteAction;
import android.content.Context;
@@ -84,6 +86,8 @@
final WeakReference<BaseDraggingActivity> weakTarget = new WeakReference<>(mTarget);
final String actionIdentity = mAction.getTitle() + ", "
+ mItemInfo.getTargetComponent().getPackageName();
+
+ ActivityOptions options = allowBGLaunch(ActivityOptions.makeBasic());
try {
if (DEBUG) Log.d(TAG, "Sending action: " + actionIdentity);
mAction.getActionIntent().send(
@@ -103,7 +107,9 @@
}
}
},
- MAIN_EXECUTOR.getHandler());
+ MAIN_EXECUTOR.getHandler(),
+ null,
+ options.toBundle());
} catch (PendingIntent.CanceledException e) {
Log.e(TAG, "Remote action canceled: " + actionIdentity, e);
Toast.makeText(mTarget, mTarget.getString(
diff --git a/src/com/android/launcher3/provider/LauncherDbUtils.java b/src/com/android/launcher3/provider/LauncherDbUtils.java
index c718dcc..575551b 100644
--- a/src/com/android/launcher3/provider/LauncherDbUtils.java
+++ b/src/com/android/launcher3/provider/LauncherDbUtils.java
@@ -28,7 +28,6 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Icon;
-import android.os.Binder;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.UserManager;
@@ -50,6 +49,13 @@
*/
public class LauncherDbUtils {
+ /**
+ * Returns a string which can be used as a where clause for DB query to match the given itemId
+ */
+ public static String itemIdMatch(int itemId) {
+ return "_id=" + itemId;
+ }
+
public static IntArray queryIntArray(boolean distinct, SQLiteDatabase db, String tableName,
String columnName, String selection, String groupBy, String orderBy) {
IntArray out = new IntArray();
@@ -114,6 +120,10 @@
deletedShortcuts.add(lc.id);
continue;
}
+ if (TextUtils.isEmpty(lc.getTitle())) {
+ deletedShortcuts.add(lc.id);
+ continue;
+ }
// Make sure the target intent can be launched without any permissions. Otherwise remove
// the shortcut
@@ -166,7 +176,7 @@
/**
* Utility class to simplify managing sqlite transactions
*/
- public static class SQLiteTransaction extends Binder implements AutoCloseable {
+ public static class SQLiteTransaction implements AutoCloseable {
private final SQLiteDatabase mDb;
public SQLiteTransaction(SQLiteDatabase db) {
diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java
index c554def..10005e5 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -28,6 +28,8 @@
import android.app.backup.BackupManager;
import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
@@ -42,20 +44,26 @@
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
+import androidx.annotation.WorkerThread;
-import com.android.launcher3.AppWidgetsRestoredReceiver;
import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherPrefs;
+import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Utilities;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.DeviceGridState;
+import com.android.launcher3.model.LoaderTask;
import com.android.launcher3.model.ModelDbController;
+import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.pm.UserCache;
import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.util.ContentWriter;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.LogConfig;
@@ -82,11 +90,15 @@
public static final String APPWIDGET_OLD_IDS = "appwidget_old_ids";
public static final String APPWIDGET_IDS = "appwidget_ids";
+ private static final String[] DB_COLUMNS_TO_LOG = {"profileId", "title", "itemType", "screen",
+ "container", "cellX", "cellY", "spanX", "spanY", "intent"};
+
/**
* Tries to restore the backup DB if needed
*/
public static void restoreIfNeeded(Context context, ModelDbController dbController) {
if (!isPending(context)) {
+ Log.d(TAG, "No restore task pending, exiting RestoreDbTask");
return;
}
if (!performRestore(context, dbController)) {
@@ -106,6 +118,7 @@
private static boolean performRestore(Context context, ModelDbController controller) {
SQLiteDatabase db = controller.getDb();
+ FileLog.d(TAG, "performRestore: starting restore from db");
try (SQLiteTransaction t = new SQLiteTransaction(db)) {
RestoreDbTask task = new RestoreDbTask();
task.sanitizeDB(context, controller, db, new BackupManager(context));
@@ -133,10 +146,11 @@
@VisibleForTesting
protected int sanitizeDB(Context context, ModelDbController controller, SQLiteDatabase db,
BackupManager backupManager) throws Exception {
+ FileLog.d(TAG, "Old Launcher Database before sanitizing:");
// Primary user ids
long myProfileId = controller.getSerialNumberForUser(myUserHandle());
long oldProfileId = getDefaultProfileId(db);
- Log.d(TAG, "sanitizeDB: myProfileId=" + myProfileId + " oldProfileId=" + oldProfileId);
+ FileLog.d(TAG, "sanitizeDB: myProfileId=" + myProfileId + " oldProfileId=" + oldProfileId);
LongSparseArray<Long> oldManagedProfileIds = getManagedProfileIds(db, oldProfileId);
LongSparseArray<Long> profileMapping = new LongSparseArray<>(oldManagedProfileIds.size()
+ 1);
@@ -149,8 +163,11 @@
if (user != null) {
long newManagedProfileId = controller.getSerialNumberForUser(user);
profileMapping.put(oldManagedProfileId, newManagedProfileId);
- Log.d(TAG, "sanitizeDB: managed profile id=" + oldManagedProfileId
+ FileLog.d(TAG, "sanitizeDB: managed profile id=" + oldManagedProfileId
+ " should be mapped to new id=" + newManagedProfileId);
+ } else {
+ FileLog.e(TAG, "sanitizeDB: No User found for old profileId, Ancestral Serial "
+ + "Number: " + oldManagedProfileId);
}
}
@@ -161,11 +178,13 @@
for (int i = numProfiles - 1; i >= 1; --i) {
profileIds[i] = Long.toString(profileMapping.keyAt(i));
}
+
final String[] args = new String[profileIds.length];
Arrays.fill(args, "?");
final String where = "profileId NOT IN (" + TextUtils.join(", ", Arrays.asList(args)) + ")";
- int itemsDeleted = db.delete(Favorites.TABLE_NAME, where, profileIds);
- FileLog.d(TAG, itemsDeleted + " items from unrestored user(s) were deleted");
+ logUnrestoredItems(db, where, profileIds);
+ int itemsDeletedCount = db.delete(Favorites.TABLE_NAME, where, profileIds);
+ FileLog.d(TAG, itemsDeletedCount + " total items from unrestored user(s) were deleted");
// Mark all items as restored.
boolean keepAllIcons = Utilities.isPropertyEnabled(LogConfig.KEEP_ALL_ICONS);
@@ -219,8 +238,48 @@
// Override shortcuts
maybeOverrideShortcuts(context, controller, db, myProfileId);
+ return itemsDeletedCount;
+ }
- return itemsDeleted;
+ /**
+ * Queries and logs the items we will delete from unrestored profiles in the launcher db.
+ * This is to understand why items might be missing during the restore process for Launcher.
+ * @param database the Launcher db to query from.
+ * @param where the SELECT statement to query items that will be deleted.
+ * @param profileIds the profile ID's the user will be migrating to.
+ */
+ private void logUnrestoredItems(SQLiteDatabase database, String where, String[] profileIds) {
+ try (Cursor itemsToDelete = database.query(
+ /* table */ Favorites.TABLE_NAME,
+ /* columns */ DB_COLUMNS_TO_LOG,
+ /* selection */ where,
+ /* selection args */ profileIds,
+ /* groupBy */ null,
+ /* having */ null,
+ /* orderBy */ null
+ )) {
+ if (itemsToDelete.moveToFirst()) {
+ String[] columnNames = itemsToDelete.getColumnNames();
+ StringBuilder stringBuilder = new StringBuilder(
+ "items to be deleted from the Favorites Table during restore:\n"
+ );
+ do {
+ for (String columnName : columnNames) {
+ stringBuilder.append(columnName)
+ .append("=")
+ .append(itemsToDelete.getString(
+ itemsToDelete.getColumnIndex(columnName)))
+ .append(" ");
+ }
+ stringBuilder.append("\n");
+ } while (itemsToDelete.moveToNext());
+ FileLog.d(TAG, stringBuilder.toString());
+ } else {
+ FileLog.d(TAG, "logDeletedItems: No items found to delete");
+ }
+ } catch (Exception e) {
+ FileLog.e(TAG, "logDeletedItems: Error reading from database", e);
+ }
}
/**
@@ -321,16 +380,18 @@
* Marks the DB state as pending restoration
*/
public static void setPending(Context context) {
- FileLog.d(TAG, "Restore data received through full backup ");
+ FileLog.d(TAG, "Restore data received through full backup");
LauncherPrefs.get(context)
.putSync(RESTORE_DEVICE.to(new DeviceGridState(context).getDeviceType()));
}
- private void restoreAppWidgetIdsIfExists(Context context, ModelDbController controller) {
+ @WorkerThread
+ @VisibleForTesting
+ void restoreAppWidgetIdsIfExists(Context context, ModelDbController controller) {
LauncherPrefs lp = LauncherPrefs.get(context);
if (lp.has(APP_WIDGET_IDS, OLD_APP_WIDGET_IDS)) {
AppWidgetHost host = new AppWidgetHost(context, APPWIDGET_HOST_ID);
- AppWidgetsRestoredReceiver.restoreAppWidgetIds(context, controller,
+ restoreAppWidgetIds(context, controller,
IntArray.fromConcatString(lp.get(OLD_APP_WIDGET_IDS)).toArray(),
IntArray.fromConcatString(lp.get(APP_WIDGET_IDS)).toArray(),
host);
@@ -341,6 +402,133 @@
lp.remove(APP_WIDGET_IDS, OLD_APP_WIDGET_IDS);
}
+ /**
+ * Updates the app widgets whose id has changed during the restore process.
+ */
+ @WorkerThread
+ private void restoreAppWidgetIds(Context context, ModelDbController controller,
+ int[] oldWidgetIds, int[] newWidgetIds, @NonNull AppWidgetHost host) {
+ if (WidgetsModel.GO_DISABLE_WIDGETS) {
+ Log.e(TAG, "Skipping widget ID remap as widgets not supported");
+ host.deleteHost();
+ return;
+ }
+ if (!RestoreDbTask.isPending(context)) {
+ // Someone has already gone through our DB once, probably LoaderTask. Skip any further
+ // modifications of the DB.
+ Log.e(TAG, "Skipping widget ID remap as DB already in use");
+ for (int widgetId : newWidgetIds) {
+ Log.d(TAG, "Deleting widgetId: " + widgetId);
+ host.deleteAppWidgetId(widgetId);
+ }
+ return;
+ }
+
+ final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
+
+ Log.d(TAG, "restoreAppWidgetIds: "
+ + "oldWidgetIds=" + IntArray.wrap(oldWidgetIds).toConcatString()
+ + ", newWidgetIds=" + IntArray.wrap(newWidgetIds).toConcatString());
+
+ // TODO(b/234700507): Remove the logs after the bug is fixed
+ logDatabaseWidgetInfo(controller);
+
+ for (int i = 0; i < oldWidgetIds.length; i++) {
+ Log.i(TAG, "Widget state restore id " + oldWidgetIds[i] + " => " + newWidgetIds[i]);
+
+ final AppWidgetProviderInfo provider = widgets.getAppWidgetInfo(newWidgetIds[i]);
+ final int state;
+ if (LoaderTask.isValidProvider(provider)) {
+ // This will ensure that we show 'Click to setup' UI if required.
+ state = LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
+ } else {
+ state = LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
+ }
+
+ // b/135926478: Work profile widget restore is broken in platform. This forces us to
+ // recreate the widget during loading with the correct host provider.
+ long mainProfileId = UserCache.INSTANCE.get(context)
+ .getSerialNumberForUser(myUserHandle());
+ long controllerProfileId = controller.getSerialNumberForUser(myUserHandle());
+ String oldWidgetId = Integer.toString(oldWidgetIds[i]);
+ final String where = "appWidgetId=? and (restored & 1) = 1 and profileId=?";
+ String profileId = Long.toString(mainProfileId);
+ final String[] args = new String[] { oldWidgetId, profileId };
+ Log.d(TAG, "restoreAppWidgetIds: querying profile id=" + profileId
+ + " with controller profile ID=" + controllerProfileId);
+ int result = new ContentWriter(context,
+ new ContentWriter.CommitParams(controller, where, args))
+ .put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i])
+ .put(LauncherSettings.Favorites.RESTORED, state)
+ .commit();
+ if (result == 0) {
+ // TODO(b/234700507): Remove the logs after the bug is fixed
+ Log.e(TAG, "restoreAppWidgetIds: remapping failed since the widget is not in"
+ + " the database anymore");
+ try (Cursor cursor = controller.getDb().query(
+ Favorites.TABLE_NAME,
+ new String[]{Favorites.APPWIDGET_ID},
+ "appWidgetId=?", new String[]{oldWidgetId}, null, null, null)) {
+ if (!cursor.moveToFirst()) {
+ // The widget no long exists.
+ Log.d(TAG, "Deleting widgetId: " + newWidgetIds[i] + " with old id: "
+ + oldWidgetId);
+ host.deleteAppWidgetId(newWidgetIds[i]);
+ }
+ }
+ }
+ }
+
+ LauncherAppState app = LauncherAppState.getInstanceNoCreate();
+ if (app != null) {
+ app.getModel().forceReload();
+ }
+ }
+
+ private static void logDatabaseWidgetInfo(ModelDbController controller) {
+ try (Cursor cursor = controller.getDb().query(Favorites.TABLE_NAME,
+ new String[]{Favorites.APPWIDGET_ID, Favorites.RESTORED, Favorites.PROFILE_ID},
+ Favorites.APPWIDGET_ID + "!=" + LauncherAppWidgetInfo.NO_ID, null,
+ null, null, null)) {
+ IntArray widgetIdList = new IntArray();
+ IntArray widgetRestoreList = new IntArray();
+ IntArray widgetProfileIdList = new IntArray();
+
+ if (cursor.moveToFirst()) {
+ final int widgetIdColumnIndex = cursor.getColumnIndex(Favorites.APPWIDGET_ID);
+ final int widgetRestoredColumnIndex = cursor.getColumnIndex(Favorites.RESTORED);
+ final int widgetProfileIdIndex = cursor.getColumnIndex(Favorites.PROFILE_ID);
+ while (!cursor.isAfterLast()) {
+ int widgetId = cursor.getInt(widgetIdColumnIndex);
+ int widgetRestoredFlag = cursor.getInt(widgetRestoredColumnIndex);
+ int widgetProfileId = cursor.getInt(widgetProfileIdIndex);
+
+ widgetIdList.add(widgetId);
+ widgetRestoreList.add(widgetRestoredFlag);
+ widgetProfileIdList.add(widgetProfileId);
+ cursor.moveToNext();
+ }
+ }
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("[");
+ for (int i = 0; i < widgetIdList.size(); i++) {
+ builder.append("[")
+ .append(widgetIdList.get(i))
+ .append(", ")
+ .append(widgetRestoreList.get(i))
+ .append(", ")
+ .append(widgetProfileIdList.get(i))
+ .append("]");
+ }
+ builder.append("]");
+ Log.d(TAG, "restoreAppWidgetIds: all widget ids in database: "
+ + builder.toString());
+ } catch (Exception ex) {
+ Log.e(TAG, "Getting widget ids from the database failed", ex);
+ }
+ }
+
public static void setRestoredAppWidgetIds(Context context, @NonNull int[] oldIds,
@NonNull int[] newIds) {
LauncherPrefs.get(context).putSync(
diff --git a/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPool.kt b/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPool.kt
new file mode 100644
index 0000000..3c59c1d
--- /dev/null
+++ b/src/com/android/launcher3/recyclerview/AllAppsRecyclerViewPool.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.recyclerview
+
+import android.content.Context
+import androidx.recyclerview.widget.RecyclerView
+import androidx.recyclerview.widget.RecyclerView.RecycledViewPool
+import androidx.recyclerview.widget.RecyclerView.ViewHolder
+import com.android.launcher3.BubbleTextView
+import com.android.launcher3.allapps.BaseAllAppsAdapter
+import com.android.launcher3.config.FeatureFlags
+import com.android.launcher3.util.Executors.MAIN_EXECUTOR
+import com.android.launcher3.util.Executors.VIEW_PREINFLATION_EXECUTOR
+import com.android.launcher3.views.ActivityContext
+import java.util.concurrent.Future
+
+const val PREINFLATE_ICONS_ROW_COUNT = 4
+const val EXTRA_ICONS_COUNT = 2
+
+/**
+ * An [RecycledViewPool] that preinflates app icons ([ViewHolder] of [BubbleTextView]) of all apps
+ * [RecyclerView]. The view inflation will happen on background thread and inflated [ViewHolder]s
+ * will be added to [RecycledViewPool] on main thread.
+ */
+class AllAppsRecyclerViewPool<T> : RecycledViewPool() {
+
+ private var future: Future<Void>? = null
+
+ /**
+ * Preinflate app icons. If all apps RV cannot be scrolled down, we don't need to preinflate.
+ */
+ fun <T> preInflateAllAppsViewHolders(context: T) where T : Context, T : ActivityContext {
+ val appsView = context.appsView ?: return
+ val activeRv: RecyclerView = appsView.activeRecyclerView ?: return
+ val preInflateCount = getPreinflateCount(context)
+ if (preInflateCount <= 0) {
+ return
+ }
+
+ // Because we perform onCreateViewHolder() on worker thread, we need a separate
+ // adapter/inflator object as they are not thread-safe. Note that the adapter
+ // just need to perform onCreateViewHolder(parent, VIEW_TYPE_ICON) so it doesn't need
+ // data source information.
+ val adapter: RecyclerView.Adapter<BaseAllAppsAdapter.ViewHolder> =
+ object : BaseAllAppsAdapter<T>(context, context.appsView.layoutInflater, null, null) {
+ override fun setAppsPerRow(appsPerRow: Int) = Unit
+ override fun getLayoutManager(): RecyclerView.LayoutManager? = null
+ }
+
+ // Inflate view holders on background thread, and added to view pool on main thread.
+ future?.cancel(true)
+ future =
+ VIEW_PREINFLATION_EXECUTOR.submit<Void> {
+ val viewHolders =
+ Array(preInflateCount) {
+ adapter.createViewHolder(activeRv, BaseAllAppsAdapter.VIEW_TYPE_ICON)
+ }
+ MAIN_EXECUTOR.execute {
+ for (i in 0 until minOf(viewHolders.size, getPreinflateCount(context))) {
+ putRecycledView(viewHolders[i])
+ }
+ }
+ null
+ }
+ }
+
+ /**
+ * After testing on phone, foldable and tablet, we found [PREINFLATE_ICONS_ROW_COUNT] rows of
+ * app icons plus [EXTRA_ICONS_COUNT] is the magic minimal count of app icons to preinflate to
+ * suffice fast scrolling.
+ *
+ * Note that if [FeatureFlags.ALL_APPS_GONE_VISIBILITY] is enabled, we need to preinfate extra
+ * app icons in size of one all apps pages, so that opening all apps don't need to inflate app
+ * icons.
+ */
+ fun <T> getPreinflateCount(context: T): Int where T : Context, T : ActivityContext {
+ var targetPreinflateCount =
+ PREINFLATE_ICONS_ROW_COUNT * context.deviceProfile.numShownAllAppsColumns +
+ EXTRA_ICONS_COUNT
+ if (FeatureFlags.ALL_APPS_GONE_VISIBILITY.get()) {
+ val grid = ActivityContext.lookupContext<T>(context).deviceProfile
+ val approxRows =
+ Math.ceil((grid.availableHeightPx / grid.allAppsIconSizePx).toDouble()).toInt()
+ targetPreinflateCount += (approxRows + 1) * grid.numShownAllAppsColumns
+ }
+ val existingPreinflateCount = getRecycledViewCount(BaseAllAppsAdapter.VIEW_TYPE_ICON)
+ return targetPreinflateCount - existingPreinflateCount
+ }
+}
diff --git a/src/com/android/launcher3/responsive/AllAppsSpecs.kt b/src/com/android/launcher3/responsive/AllAppsSpecs.kt
new file mode 100644
index 0000000..8ed3ffc
--- /dev/null
+++ b/src/com/android/launcher3/responsive/AllAppsSpecs.kt
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.responsive
+
+import android.content.res.TypedArray
+import com.android.launcher3.R
+import com.android.launcher3.responsive.ResponsiveSpec.SpecType
+import com.android.launcher3.util.ResourceHelper
+
+class AllAppsSpecs(widthSpecs: List<AllAppsSpec>, heightSpecs: List<AllAppsSpec>) :
+ ResponsiveSpecs<AllAppsSpec>(widthSpecs, heightSpecs) {
+
+ fun getCalculatedWidthSpec(
+ columns: Int,
+ availableWidth: Int,
+ calculatedWorkspaceSpec: CalculatedWorkspaceSpec
+ ): CalculatedAllAppsSpec {
+ check(calculatedWorkspaceSpec.spec.specType == SpecType.WIDTH) {
+ "Invalid specType for CalculatedWorkspaceSpec. " +
+ "Expected: ${SpecType.WIDTH} - " +
+ "Found: ${calculatedWorkspaceSpec.spec.specType}}"
+ }
+
+ val spec = getWidthSpec(availableWidth)
+ return CalculatedAllAppsSpec(availableWidth, columns, spec, calculatedWorkspaceSpec)
+ }
+
+ fun getCalculatedHeightSpec(
+ rows: Int,
+ availableHeight: Int,
+ calculatedWorkspaceSpec: CalculatedWorkspaceSpec
+ ): CalculatedAllAppsSpec {
+ check(calculatedWorkspaceSpec.spec.specType == SpecType.HEIGHT) {
+ "Invalid specType for CalculatedWorkspaceSpec. " +
+ "Expected: ${SpecType.HEIGHT} - " +
+ "Found: ${calculatedWorkspaceSpec.spec.specType}}"
+ }
+
+ val spec = getHeightSpec(availableHeight)
+ return CalculatedAllAppsSpec(availableHeight, rows, spec, calculatedWorkspaceSpec)
+ }
+
+ companion object {
+ private const val XML_ALL_APPS_SPEC = "allAppsSpec"
+
+ @JvmStatic
+ fun create(resourceHelper: ResourceHelper): AllAppsSpecs {
+ val parser = ResponsiveSpecsParser(resourceHelper)
+ val specs = parser.parseXML(XML_ALL_APPS_SPEC, ::AllAppsSpec)
+ val (widthSpecs, heightSpecs) = specs.partition { it.specType == SpecType.WIDTH }
+ return AllAppsSpecs(widthSpecs, heightSpecs)
+ }
+ }
+}
+
+data class AllAppsSpec(
+ override val maxAvailableSize: Int,
+ override val specType: SpecType,
+ override val startPadding: SizeSpec,
+ override val endPadding: SizeSpec,
+ override val gutter: SizeSpec,
+ override val cellSize: SizeSpec
+) : ResponsiveSpec(maxAvailableSize, specType, startPadding, endPadding, gutter, cellSize) {
+
+ init {
+ check(isValid()) { "Invalid AllAppsSpec found." }
+ }
+
+ constructor(
+ attrs: TypedArray,
+ specs: Map<String, SizeSpec>
+ ) : this(
+ maxAvailableSize =
+ attrs.getDimensionPixelSize(R.styleable.ResponsiveSpec_maxAvailableSize, 0),
+ specType =
+ SpecType.values()[
+ attrs.getInt(R.styleable.ResponsiveSpec_specType, SpecType.HEIGHT.ordinal)],
+ startPadding = specs.getOrError(SizeSpec.XmlTags.START_PADDING),
+ endPadding = specs.getOrError(SizeSpec.XmlTags.END_PADDING),
+ gutter = specs.getOrError(SizeSpec.XmlTags.GUTTER),
+ cellSize = specs.getOrError(SizeSpec.XmlTags.CELL_SIZE)
+ )
+}
+
+class CalculatedAllAppsSpec(
+ availableSpace: Int,
+ cells: Int,
+ spec: AllAppsSpec,
+ calculatedWorkspaceSpec: CalculatedWorkspaceSpec
+) : CalculatedResponsiveSpec(availableSpace, cells, spec, calculatedWorkspaceSpec)
diff --git a/src/com/android/launcher3/responsive/FolderSpecs.kt b/src/com/android/launcher3/responsive/FolderSpecs.kt
new file mode 100644
index 0000000..bc2db28
--- /dev/null
+++ b/src/com/android/launcher3/responsive/FolderSpecs.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.responsive
+
+import android.content.res.TypedArray
+import com.android.launcher3.R
+import com.android.launcher3.responsive.ResponsiveSpec.SpecType
+import com.android.launcher3.util.ResourceHelper
+
+class FolderSpecs(widthSpecs: List<FolderSpec>, heightSpecs: List<FolderSpec>) :
+ ResponsiveSpecs<FolderSpec>(widthSpecs, heightSpecs) {
+
+ fun getCalculatedWidthSpec(
+ columns: Int,
+ availableWidth: Int,
+ calculatedWorkspaceSpec: CalculatedWorkspaceSpec
+ ): CalculatedFolderSpec {
+ check(calculatedWorkspaceSpec.spec.specType == SpecType.WIDTH) {
+ "Invalid specType for CalculatedWorkspaceSpec. " +
+ "Expected: ${SpecType.WIDTH} - " +
+ "Found: ${calculatedWorkspaceSpec.spec.specType}}"
+ }
+
+ val spec = getWidthSpec(availableWidth)
+ return CalculatedFolderSpec(availableWidth, columns, spec, calculatedWorkspaceSpec)
+ }
+
+ fun getCalculatedHeightSpec(
+ rows: Int,
+ availableHeight: Int,
+ calculatedWorkspaceSpec: CalculatedWorkspaceSpec
+ ): CalculatedFolderSpec {
+ check(calculatedWorkspaceSpec.spec.specType == SpecType.HEIGHT) {
+ "Invalid specType for CalculatedWorkspaceSpec. " +
+ "Expected: ${SpecType.HEIGHT} - " +
+ "Found: ${calculatedWorkspaceSpec.spec.specType}}"
+ }
+
+ val spec = getHeightSpec(availableHeight)
+ return CalculatedFolderSpec(availableHeight, rows, spec, calculatedWorkspaceSpec)
+ }
+
+ companion object {
+
+ private const val XML_FOLDER_SPEC = "folderSpec"
+
+ @JvmStatic
+ fun create(resourceHelper: ResourceHelper): FolderSpecs {
+ val parser = ResponsiveSpecsParser(resourceHelper)
+ val specs = parser.parseXML(XML_FOLDER_SPEC, ::FolderSpec)
+ val (widthSpecs, heightSpecs) = specs.partition { it.specType == SpecType.WIDTH }
+ return FolderSpecs(widthSpecs, heightSpecs)
+ }
+ }
+}
+
+data class FolderSpec(
+ override val maxAvailableSize: Int,
+ override val specType: SpecType,
+ override val startPadding: SizeSpec,
+ override val endPadding: SizeSpec,
+ override val gutter: SizeSpec,
+ override val cellSize: SizeSpec
+) : ResponsiveSpec(maxAvailableSize, specType, startPadding, endPadding, gutter, cellSize) {
+
+ init {
+ check(isValid()) { "Invalid FolderSpec found." }
+ }
+
+ constructor(
+ attrs: TypedArray,
+ specs: Map<String, SizeSpec>
+ ) : this(
+ maxAvailableSize =
+ attrs.getDimensionPixelSize(R.styleable.ResponsiveSpec_maxAvailableSize, 0),
+ specType =
+ SpecType.values()[
+ attrs.getInt(R.styleable.ResponsiveSpec_specType, SpecType.HEIGHT.ordinal)],
+ startPadding = specs.getOrError(SizeSpec.XmlTags.START_PADDING),
+ endPadding = specs.getOrError(SizeSpec.XmlTags.END_PADDING),
+ gutter = specs.getOrError(SizeSpec.XmlTags.GUTTER),
+ cellSize = specs.getOrError(SizeSpec.XmlTags.CELL_SIZE)
+ )
+}
+
+class CalculatedFolderSpec(
+ availableSpace: Int,
+ cells: Int,
+ spec: FolderSpec,
+ calculatedWorkspaceSpec: CalculatedWorkspaceSpec
+) : CalculatedResponsiveSpec(availableSpace, cells, spec, calculatedWorkspaceSpec)
diff --git a/src/com/android/launcher3/responsive/HotseatSpecs.kt b/src/com/android/launcher3/responsive/HotseatSpecs.kt
new file mode 100644
index 0000000..37a682f
--- /dev/null
+++ b/src/com/android/launcher3/responsive/HotseatSpecs.kt
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.responsive
+
+import android.content.res.TypedArray
+import android.util.Log
+import com.android.launcher3.R
+import com.android.launcher3.util.ResourceHelper
+
+class HotseatSpecs(widthSpecs: List<HotseatSpec>, heightSpecs: List<HotseatSpec>) {
+
+ val widthSpecs: List<HotseatSpec>
+ val heightSpecs: List<HotseatSpec>
+
+ init {
+ this.widthSpecs = widthSpecs.sortedBy { it.maxAvailableSize }
+ this.heightSpecs = heightSpecs.sortedBy { it.maxAvailableSize }
+ }
+
+ fun getCalculatedHeightSpec(availableHeight: Int): CalculatedHotseatSpec {
+ val spec = heightSpecs.firstOrNull { availableHeight <= it.maxAvailableSize }
+ check(spec != null) { "No available height spec found within $availableHeight." }
+ return CalculatedHotseatSpec(availableHeight, spec)
+ }
+
+ fun getCalculatedWidthSpec(availableWidth: Int): CalculatedHotseatSpec {
+ val spec = widthSpecs.firstOrNull { availableWidth <= it.maxAvailableSize }
+ check(spec != null) { "No available width spec found within $availableWidth." }
+ return CalculatedHotseatSpec(availableWidth, spec)
+ }
+
+ companion object {
+ private const val XML_HOTSEAT_SPEC = "hotseatSpec"
+
+ @JvmStatic
+ fun create(resourceHelper: ResourceHelper): HotseatSpecs {
+ val parser = ResponsiveSpecsParser(resourceHelper)
+ val specs = parser.parseXML(XML_HOTSEAT_SPEC, ::HotseatSpec)
+ val (widthSpecs, heightSpecs) =
+ specs.partition { it.specType == ResponsiveSpec.SpecType.WIDTH }
+ return HotseatSpecs(widthSpecs, heightSpecs)
+ }
+ }
+}
+
+data class HotseatSpec(
+ val maxAvailableSize: Int,
+ val specType: ResponsiveSpec.SpecType,
+ val hotseatQsbSpace: SizeSpec,
+ val edgePadding: SizeSpec
+) {
+
+ init {
+ check(isValid()) { "Invalid HotseatSpec found." }
+ }
+
+ constructor(
+ attrs: TypedArray,
+ specs: Map<String, SizeSpec>
+ ) : this(
+ maxAvailableSize =
+ attrs.getDimensionPixelSize(R.styleable.ResponsiveSpec_maxAvailableSize, 0),
+ specType =
+ ResponsiveSpec.SpecType.values()[
+ attrs.getInt(
+ R.styleable.ResponsiveSpec_specType,
+ ResponsiveSpec.SpecType.HEIGHT.ordinal
+ )],
+ hotseatQsbSpace = specs.getOrError(SizeSpec.XmlTags.HOTSEAT_QSB_SPACE),
+ edgePadding = specs.getOrError(SizeSpec.XmlTags.EDGE_PADDING)
+ )
+
+ fun isValid(): Boolean {
+ if (maxAvailableSize <= 0) {
+ Log.e(LOG_TAG, "${this::class.simpleName}#isValid - maxAvailableSize <= 0")
+ return false
+ }
+
+ // All specs need to be individually valid
+ if (!allSpecsAreValid()) {
+ Log.e(LOG_TAG, "${this::class.simpleName}#isValid - !allSpecsAreValid()")
+ return false
+ }
+
+ return true
+ }
+
+ private fun allSpecsAreValid(): Boolean {
+ return hotseatQsbSpace.isValid() &&
+ hotseatQsbSpace.onlyFixedSize() &&
+ edgePadding.isValid() &&
+ edgePadding.onlyFixedSize()
+ }
+
+ companion object {
+ private const val LOG_TAG = "HotseatSpec"
+ }
+}
+
+class CalculatedHotseatSpec(val availableSpace: Int, val spec: HotseatSpec) {
+
+ var hotseatQsbSpace: Int = 0
+ private set
+
+ var edgePadding: Int = 0
+ private set
+
+ init {
+ hotseatQsbSpace = spec.hotseatQsbSpace.getCalculatedValue(availableSpace)
+ edgePadding = spec.edgePadding.getCalculatedValue(availableSpace)
+ }
+
+ override fun hashCode(): Int {
+ var result = availableSpace.hashCode()
+ result = 31 * result + hotseatQsbSpace.hashCode()
+ result = 31 * result + edgePadding.hashCode()
+ result = 31 * result + spec.hashCode()
+ return result
+ }
+
+ override fun equals(other: Any?): Boolean {
+ return other is CalculatedHotseatSpec &&
+ availableSpace == other.availableSpace &&
+ hotseatQsbSpace == other.hotseatQsbSpace &&
+ edgePadding == other.edgePadding &&
+ spec == other.spec
+ }
+
+ override fun toString(): String {
+ return "${this::class.simpleName}(" +
+ "availableSpace=$availableSpace, hotseatQsbSpace=$hotseatQsbSpace, " +
+ "edgePadding=$edgePadding, " +
+ "${spec::class.simpleName}.maxAvailableSize=${spec.maxAvailableSize}" +
+ ")"
+ }
+}
diff --git a/src/com/android/launcher3/responsive/ResponsiveSpecs.kt b/src/com/android/launcher3/responsive/ResponsiveSpecs.kt
new file mode 100644
index 0000000..a43c44a
--- /dev/null
+++ b/src/com/android/launcher3/responsive/ResponsiveSpecs.kt
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.responsive
+
+import android.util.Log
+
+/**
+ * Base class for responsive specs that holds a list of width and height specs.
+ *
+ * @param widthSpecs List of width responsive specifications
+ * @param heightSpecs List of height responsive specifications
+ */
+abstract class ResponsiveSpecs<T : ResponsiveSpec>(widthSpecs: List<T>, heightSpecs: List<T>) {
+ val widthSpecs: List<T>
+ val heightSpecs: List<T>
+
+ init {
+ check(widthSpecs.isNotEmpty() && heightSpecs.isNotEmpty()) {
+ "${this::class.simpleName} is incomplete - " +
+ "width list size = ${widthSpecs.size}; " +
+ "height list size = ${heightSpecs.size}."
+ }
+
+ this.widthSpecs = widthSpecs.sortedBy { it.maxAvailableSize }
+ this.heightSpecs = heightSpecs.sortedBy { it.maxAvailableSize }
+ }
+
+ /**
+ * Get a [ResponsiveSpec] for width within the breakpoint.
+ *
+ * @param availableWidth The width breakpoint for the spec
+ * @return A [ResponsiveSpec] for width.
+ */
+ fun getWidthSpec(availableWidth: Int): T {
+ val spec = widthSpecs.firstOrNull { availableWidth <= it.maxAvailableSize }
+ check(spec != null) { "No available width spec found within $availableWidth." }
+ return spec
+ }
+
+ /**
+ * Get a [ResponsiveSpec] for height within the breakpoint.
+ *
+ * @param availableHeight The height breakpoint for the spec
+ * @return A [ResponsiveSpec] for height.
+ */
+ fun getHeightSpec(availableHeight: Int): T {
+ val spec = heightSpecs.firstOrNull { availableHeight <= it.maxAvailableSize }
+ check(spec != null) { "No available height spec found within $availableHeight." }
+ return spec
+ }
+}
+
+/**
+ * Base class for a responsive specification that is used to calculate the paddings, gutter and cell
+ * size.
+ *
+ * @param maxAvailableSize indicates the breakpoint to use this specification.
+ * @param specType indicates whether the paddings and gutters will be applied vertically or
+ * horizontally.
+ * @param startPadding padding used at the top or left (right in RTL) in the workspace folder.
+ * @param endPadding padding used at the bottom or right (left in RTL) in the workspace folder.
+ * @param gutter the space between the cells vertically or horizontally depending on the [specType].
+ * @param cellSize height or width of the cell depending on the [specType].
+ */
+abstract class ResponsiveSpec(
+ open val maxAvailableSize: Int,
+ open val specType: SpecType,
+ open val startPadding: SizeSpec,
+ open val endPadding: SizeSpec,
+ open val gutter: SizeSpec,
+ open val cellSize: SizeSpec
+) {
+ open fun isValid(): Boolean {
+ if (maxAvailableSize <= 0) {
+ Log.e(LOG_TAG, "${this::class.simpleName}#isValid - maxAvailableSize <= 0")
+ return false
+ }
+
+ // All specs need to be individually valid
+ if (!allSpecsAreValid()) {
+ Log.e(LOG_TAG, "${this::class.simpleName}#isValid - !allSpecsAreValid()")
+ return false
+ }
+
+ return true
+ }
+
+ private fun allSpecsAreValid(): Boolean {
+ return startPadding.isValid() &&
+ endPadding.isValid() &&
+ gutter.isValid() &&
+ cellSize.isValid()
+ }
+
+ enum class SpecType {
+ HEIGHT,
+ WIDTH
+ }
+
+ companion object {
+ private const val LOG_TAG = "ResponsiveSpec"
+ }
+}
+
+/**
+ * Calculated responsive specs contains the final paddings, gutter and cell size in pixels after
+ * they are calculated from the available space, cells and workspace specs.
+ */
+sealed class CalculatedResponsiveSpec {
+ var availableSpace: Int = 0
+ private set
+
+ var cells: Int = 0
+ private set
+
+ var startPaddingPx: Int = 0
+ private set
+
+ var endPaddingPx: Int = 0
+ private set
+
+ var gutterPx: Int = 0
+ private set
+
+ var cellSizePx: Int = 0
+ private set
+
+ var spec: ResponsiveSpec
+ private set
+
+ constructor(
+ availableSpace: Int,
+ cells: Int,
+ spec: ResponsiveSpec,
+ calculatedWorkspaceSpec: CalculatedWorkspaceSpec
+ ) {
+ this.availableSpace = availableSpace
+ this.cells = cells
+ this.spec = spec
+
+ // Map if is fixedSize, ofAvailableSpace or matchWorkspace
+ startPaddingPx =
+ spec.startPadding.getCalculatedValue(
+ availableSpace,
+ calculatedWorkspaceSpec.startPaddingPx
+ )
+ endPaddingPx =
+ spec.endPadding.getCalculatedValue(availableSpace, calculatedWorkspaceSpec.endPaddingPx)
+ gutterPx = spec.gutter.getCalculatedValue(availableSpace, calculatedWorkspaceSpec.gutterPx)
+ cellSizePx =
+ spec.cellSize.getCalculatedValue(availableSpace, calculatedWorkspaceSpec.cellSizePx)
+
+ updateRemainderSpaces(availableSpace, cells, spec)
+ }
+
+ constructor(availableSpace: Int, cells: Int, spec: ResponsiveSpec) {
+ this.availableSpace = availableSpace
+ this.cells = cells
+ this.spec = spec
+
+ // Map if is fixedSize or ofAvailableSpace
+ startPaddingPx = spec.startPadding.getCalculatedValue(availableSpace)
+ endPaddingPx = spec.endPadding.getCalculatedValue(availableSpace)
+ gutterPx = spec.gutter.getCalculatedValue(availableSpace)
+ cellSizePx = spec.cellSize.getCalculatedValue(availableSpace)
+
+ updateRemainderSpaces(availableSpace, cells, spec)
+ }
+
+ private fun updateRemainderSpaces(availableSpace: Int, cells: Int, spec: ResponsiveSpec) {
+ val gutters = cells - 1
+ val usedSpace = startPaddingPx + endPaddingPx + (gutterPx * gutters) + (cellSizePx * cells)
+ val remainderSpace = availableSpace - usedSpace
+
+ startPaddingPx = spec.startPadding.getRemainderSpaceValue(remainderSpace, startPaddingPx)
+ endPaddingPx = spec.endPadding.getRemainderSpaceValue(remainderSpace, endPaddingPx)
+ gutterPx = spec.gutter.getRemainderSpaceValue(remainderSpace, gutterPx)
+ cellSizePx = spec.cellSize.getRemainderSpaceValue(remainderSpace, cellSizePx)
+ }
+
+ override fun hashCode(): Int {
+ var result = availableSpace.hashCode()
+ result = 31 * result + cells.hashCode()
+ result = 31 * result + startPaddingPx.hashCode()
+ result = 31 * result + endPaddingPx.hashCode()
+ result = 31 * result + gutterPx.hashCode()
+ result = 31 * result + cellSizePx.hashCode()
+ result = 31 * result + spec.hashCode()
+ return result
+ }
+
+ override fun equals(other: Any?): Boolean {
+ return other is CalculatedResponsiveSpec &&
+ availableSpace == other.availableSpace &&
+ cells == other.cells &&
+ startPaddingPx == other.startPaddingPx &&
+ endPaddingPx == other.endPaddingPx &&
+ gutterPx == other.gutterPx &&
+ cellSizePx == other.cellSizePx &&
+ spec == other.spec
+ }
+
+ override fun toString(): String {
+ return "${this::class.simpleName}(" +
+ "availableSpace=$availableSpace, cells=$cells, startPaddingPx=$startPaddingPx, " +
+ "endPaddingPx=$endPaddingPx, gutterPx=$gutterPx, cellSizePx=$cellSizePx, " +
+ "${spec::class.simpleName}.maxAvailableSize=${spec.maxAvailableSize}" +
+ ")"
+ }
+}
diff --git a/src/com/android/launcher3/responsive/ResponsiveSpecsParser.kt b/src/com/android/launcher3/responsive/ResponsiveSpecsParser.kt
new file mode 100644
index 0000000..a89b619
--- /dev/null
+++ b/src/com/android/launcher3/responsive/ResponsiveSpecsParser.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.responsive
+
+import android.content.res.TypedArray
+import android.content.res.XmlResourceParser
+import android.util.Xml
+import com.android.launcher3.R
+import com.android.launcher3.util.ResourceHelper
+import java.io.IOException
+import org.xmlpull.v1.XmlPullParser
+import org.xmlpull.v1.XmlPullParserException
+
+class ResponsiveSpecsParser(private val resourceHelper: ResourceHelper) {
+
+ private fun parseSizeSpecs(parser: XmlResourceParser): Map<String, SizeSpec> {
+ val parentName = parser.name
+ parser.next()
+
+ val result = mutableMapOf<String, SizeSpec>()
+ while (parser.eventType != XmlPullParser.END_DOCUMENT && parser.name != parentName) {
+ if (parser.eventType == XmlResourceParser.START_TAG) {
+ result[parser.name] = SizeSpec.create(resourceHelper, Xml.asAttributeSet(parser))
+ }
+ parser.next()
+ }
+
+ return result
+ }
+
+ fun <T> parseXML(
+ tagName: String,
+ map: (attributes: TypedArray, sizeSpecs: Map<String, SizeSpec>) -> T
+ ): List<T> {
+ val parser: XmlResourceParser = resourceHelper.getXml()
+
+ try {
+ val list = mutableListOf<T>()
+
+ var eventType = parser.eventType
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlResourceParser.START_TAG && parser.name == tagName) {
+ val attrs =
+ resourceHelper.obtainStyledAttributes(
+ Xml.asAttributeSet(parser),
+ R.styleable.ResponsiveSpec
+ )
+
+ val sizeSpecs = parseSizeSpecs(parser)
+ list += map(attrs, sizeSpecs)
+ attrs.recycle()
+ }
+
+ eventType = parser.next()
+ }
+
+ parser.close()
+
+ return list
+ } catch (e: Exception) {
+ when (e) {
+ is NoSuchFieldException,
+ is IOException,
+ is XmlPullParserException ->
+ throw RuntimeException("Failure parsing specs file.", e)
+ else -> throw e
+ }
+ } finally {
+ parser.close()
+ }
+ }
+}
+
+fun Map<String, SizeSpec>.getOrError(key: String): SizeSpec {
+ return this.getOrElse(key) { error("Attr '$key' must be defined.") }
+}
diff --git a/src/com/android/launcher3/responsive/SizeSpec.kt b/src/com/android/launcher3/responsive/SizeSpec.kt
new file mode 100644
index 0000000..2db843b
--- /dev/null
+++ b/src/com/android/launcher3/responsive/SizeSpec.kt
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.responsive
+
+import android.content.res.TypedArray
+import android.util.AttributeSet
+import android.util.Log
+import android.util.TypedValue
+import com.android.launcher3.R
+import com.android.launcher3.util.ResourceHelper
+import kotlin.math.roundToInt
+
+/**
+ * [SizeSpec] is an attribute used to represent a property in the responsive grid specs.
+ *
+ * @param fixedSize a fixed size in dp to be used
+ * @param ofAvailableSpace a percentage of the available space
+ * @param ofRemainderSpace a percentage of the remaining space (available space minus used space)
+ * @param matchWorkspace indicates whether the workspace value will be used or not.
+ * @param maxSize restricts the maximum value allowed for the [SizeSpec].
+ */
+data class SizeSpec(
+ val fixedSize: Float = 0f,
+ val ofAvailableSpace: Float = 0f,
+ val ofRemainderSpace: Float = 0f,
+ val matchWorkspace: Boolean = false,
+ val maxSize: Int = Int.MAX_VALUE
+) {
+
+ /** Retrieves the correct value for [SizeSpec]. */
+ fun getCalculatedValue(availableSpace: Int, workspaceValue: Int = 0): Int {
+ val calculatedValue =
+ when {
+ fixedSize > 0 -> fixedSize.roundToInt()
+ matchWorkspace -> workspaceValue
+ ofAvailableSpace > 0 -> (ofAvailableSpace * availableSpace).roundToInt()
+ else -> 0
+ }
+
+ return calculatedValue.coerceAtMost(maxSize)
+ }
+
+ /**
+ * Calculates the [SizeSpec] value when remainder space value is defined. If no remainderSpace
+ * is 0, returns a default value.
+ */
+ fun getRemainderSpaceValue(remainderSpace: Int, defaultValue: Int): Int {
+ val remainderSpaceValue =
+ if (ofRemainderSpace > 0) {
+ (ofRemainderSpace * remainderSpace).roundToInt()
+ } else {
+ defaultValue
+ }
+
+ return remainderSpaceValue.coerceAtMost(maxSize)
+ }
+
+ fun isValid(): Boolean {
+ // All attributes are empty
+ if (fixedSize < 0f && ofAvailableSpace <= 0f && ofRemainderSpace <= 0f && !matchWorkspace) {
+ Log.e(TAG, "SizeSpec#isValid - all attributes are empty")
+ return false
+ }
+
+ // More than one attribute is filled
+ val attrCount =
+ (if (fixedSize > 0) 1 else 0) +
+ (if (ofAvailableSpace > 0) 1 else 0) +
+ (if (ofRemainderSpace > 0) 1 else 0) +
+ (if (matchWorkspace) 1 else 0)
+ if (attrCount > 1) {
+ Log.e(TAG, "SizeSpec#isValid - more than one attribute is filled")
+ return false
+ }
+
+ // Values should be between 0 and 1
+ if (ofAvailableSpace !in 0f..1f || ofRemainderSpace !in 0f..1f) {
+ Log.e(TAG, "SizeSpec#isValid - values should be between 0 and 1")
+ return false
+ }
+
+ // Invalid fixed or max size
+ if (fixedSize < 0f || maxSize < 0f) {
+ Log.e(TAG, "SizeSpec#isValid - values should be bigger or equal to zero.")
+ return false
+ }
+
+ if (fixedSize > 0f && fixedSize > maxSize) {
+ Log.e(TAG, "SizeSpec#isValid - fixed size should be smaller than the max size.")
+ return false
+ }
+
+ return true
+ }
+
+ fun onlyFixedSize(): Boolean {
+ if (ofAvailableSpace > 0 || ofRemainderSpace > 0 || matchWorkspace) {
+ Log.e(TAG, "SizeSpec#onlyFixedSize - only fixed size allowed for this tag")
+ return false
+ }
+ return true
+ }
+
+ object XmlTags {
+ const val START_PADDING = "startPadding"
+ const val END_PADDING = "endPadding"
+ const val GUTTER = "gutter"
+ const val CELL_SIZE = "cellSize"
+ const val HOTSEAT_QSB_SPACE = "hotseatQsbSpace"
+ const val EDGE_PADDING = "edgePadding"
+ }
+
+ companion object {
+ private const val TAG = "SizeSpec"
+
+ private fun getValue(a: TypedArray, index: Int): Float {
+ return when (a.getType(index)) {
+ TypedValue.TYPE_DIMENSION -> a.getDimensionPixelSize(index, 0).toFloat()
+ TypedValue.TYPE_FLOAT -> a.getFloat(index, 0f)
+ else -> 0f
+ }
+ }
+
+ fun create(resourceHelper: ResourceHelper, attrs: AttributeSet): SizeSpec {
+ val styledAttrs = resourceHelper.obtainStyledAttributes(attrs, R.styleable.SizeSpec)
+
+ val fixedSize = getValue(styledAttrs, R.styleable.SizeSpec_fixedSize)
+ val ofAvailableSpace = getValue(styledAttrs, R.styleable.SizeSpec_ofAvailableSpace)
+ val ofRemainderSpace = getValue(styledAttrs, R.styleable.SizeSpec_ofRemainderSpace)
+ val matchWorkspace = styledAttrs.getBoolean(R.styleable.SizeSpec_matchWorkspace, false)
+ val maxSize =
+ styledAttrs.getDimensionPixelSize(R.styleable.SizeSpec_maxSize, Int.MAX_VALUE)
+
+ styledAttrs.recycle()
+
+ return SizeSpec(fixedSize, ofAvailableSpace, ofRemainderSpace, matchWorkspace, maxSize)
+ }
+ }
+}
diff --git a/src/com/android/launcher3/responsive/WorkspaceSpecs.kt b/src/com/android/launcher3/responsive/WorkspaceSpecs.kt
new file mode 100644
index 0000000..0da7026
--- /dev/null
+++ b/src/com/android/launcher3/responsive/WorkspaceSpecs.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.responsive
+
+import android.content.res.TypedArray
+import android.util.Log
+import com.android.launcher3.R
+import com.android.launcher3.responsive.ResponsiveSpec.SpecType
+import com.android.launcher3.util.ResourceHelper
+
+private const val TAG = "WorkspaceSpecs"
+
+class WorkspaceSpecs(widthSpecs: List<WorkspaceSpec>, heightSpecs: List<WorkspaceSpec>) :
+ ResponsiveSpecs<WorkspaceSpec>(widthSpecs, heightSpecs) {
+
+ fun getCalculatedWidthSpec(columns: Int, availableWidth: Int): CalculatedWorkspaceSpec {
+ val spec = getWidthSpec(availableWidth)
+ return CalculatedWorkspaceSpec(availableWidth, columns, spec)
+ }
+
+ fun getCalculatedHeightSpec(rows: Int, availableHeight: Int): CalculatedWorkspaceSpec {
+ val spec = getHeightSpec(availableHeight)
+ return CalculatedWorkspaceSpec(availableHeight, rows, spec)
+ }
+
+ companion object {
+ private const val XML_WORKSPACE_SPEC = "workspaceSpec"
+
+ @JvmStatic
+ fun create(resourceHelper: ResourceHelper): WorkspaceSpecs {
+ val parser = ResponsiveSpecsParser(resourceHelper)
+ val specs = parser.parseXML(XML_WORKSPACE_SPEC, ::WorkspaceSpec)
+ val (widthSpecs, heightSpecs) = specs.partition { it.specType == SpecType.WIDTH }
+ return WorkspaceSpecs(widthSpecs, heightSpecs)
+ }
+ }
+}
+
+data class WorkspaceSpec(
+ override val maxAvailableSize: Int,
+ override val specType: SpecType,
+ override val startPadding: SizeSpec,
+ override val endPadding: SizeSpec,
+ override val gutter: SizeSpec,
+ override val cellSize: SizeSpec
+) : ResponsiveSpec(maxAvailableSize, specType, startPadding, endPadding, gutter, cellSize) {
+
+ init {
+ check(isValid()) { "Invalid WorkspaceSpec found." }
+ }
+
+ constructor(
+ attrs: TypedArray,
+ specs: Map<String, SizeSpec>
+ ) : this(
+ maxAvailableSize =
+ attrs.getDimensionPixelSize(R.styleable.ResponsiveSpec_maxAvailableSize, 0),
+ specType =
+ SpecType.values()[
+ attrs.getInt(R.styleable.ResponsiveSpec_specType, SpecType.HEIGHT.ordinal)],
+ startPadding = specs.getOrError(SizeSpec.XmlTags.START_PADDING),
+ endPadding = specs.getOrError(SizeSpec.XmlTags.END_PADDING),
+ gutter = specs.getOrError(SizeSpec.XmlTags.GUTTER),
+ cellSize = specs.getOrError(SizeSpec.XmlTags.CELL_SIZE)
+ )
+
+ override fun isValid(): Boolean {
+ // Workspace spec should not match workspace
+ if (
+ startPadding.matchWorkspace ||
+ endPadding.matchWorkspace ||
+ gutter.matchWorkspace ||
+ cellSize.matchWorkspace
+ ) {
+ Log.e(TAG, "WorkspaceSpec#isValid - workspace shouldn't contain matchWorkspace!")
+ return false
+ }
+
+ return super.isValid()
+ }
+}
+
+class CalculatedWorkspaceSpec(availableSpace: Int, cells: Int, spec: WorkspaceSpec) :
+ CalculatedResponsiveSpec(availableSpace, cells, spec)
diff --git a/src/com/android/launcher3/secondarydisplay/PinnedAppsAdapter.java b/src/com/android/launcher3/secondarydisplay/PinnedAppsAdapter.java
index f03c62a..2d69bfa 100644
--- a/src/com/android/launcher3/secondarydisplay/PinnedAppsAdapter.java
+++ b/src/com/android/launcher3/secondarydisplay/PinnedAppsAdapter.java
@@ -60,13 +60,15 @@
private final OnClickListener mOnClickListener;
private final OnLongClickListener mOnLongClickListener;
private final SharedPreferences mPrefs;
- private final AllAppsStore mAllAppsList;
+ private final AllAppsStore<SecondaryDisplayLauncher> mAllAppsList;
private final AppInfoComparator mAppNameComparator;
private final Set<ComponentKey> mPinnedApps = new HashSet<>();
private final ArrayList<AppInfo> mItems = new ArrayList<>();
- public PinnedAppsAdapter(SecondaryDisplayLauncher launcher, AllAppsStore allAppsStore,
+ public PinnedAppsAdapter(
+ SecondaryDisplayLauncher launcher,
+ AllAppsStore<SecondaryDisplayLauncher> allAppsStore,
OnLongClickListener onLongClickListener) {
mLauncher = launcher;
mOnClickListener = launcher.getItemOnClickListener();
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
index 458f137..a10c0ad 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
@@ -72,7 +72,7 @@
implements BgDataModel.Callbacks, DragController.DragListener {
private LauncherModel mModel;
- private BaseDragLayer mDragLayer;
+ private SecondaryDragLayer mDragLayer;
private SecondaryDragController mDragController;
private ActivityAllAppsContainerView<SecondaryDisplayLauncher> mAppsView;
private View mAppsButton;
@@ -302,7 +302,7 @@
public void bindAllApplications(AppInfo[] apps, int flags,
Map<PackageUserKey, Integer> packageUserKeytoUidMap) {
Preconditions.assertUIThread();
- AllAppsStore appsStore = mAppsView.getAppsStore();
+ AllAppsStore<SecondaryDisplayLauncher> appsStore = mAppsView.getAppsStore();
appsStore.setApps(apps, flags, packageUserKeytoUidMap);
PopupContainerWithArrow.dismissInvalidPopup(this);
}
@@ -314,10 +314,6 @@
}
}
- public SecondaryDisplayPredictions getSecondaryDisplayPredictions() {
- return mSecondaryDisplayPredictions;
- }
-
@Override
public StringCache getStringCache() {
return mStringCache;
@@ -337,6 +333,11 @@
return this::onIconClicked;
}
+ @Override
+ public View.OnLongClickListener getAllAppsItemLongClickListener() {
+ return v -> mDragLayer.onIconLongClicked(v);
+ }
+
private void onIconClicked(View v) {
// Make sure that rogue clicks don't get through while allapps is launching, or after the
// view has detached (it's possible for this to happen if the view is removed mid touch).
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayPredictions.java b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayPredictions.java
index 21c50d3..a58916a 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayPredictions.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayPredictions.java
@@ -16,10 +16,8 @@
package com.android.launcher3.secondarydisplay;
import android.content.Context;
-import android.view.View;
import com.android.launcher3.R;
-import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.util.ResourceBasedOverride;
@@ -47,12 +45,4 @@
*/
public void setPredictedApps(BgDataModel.FixedContainerItems item) {
}
-
- /**
- * Set long click listener for predicted apps in top of app drawer.
- */
- public void setLongClickListener(
- ActivityAllAppsContainerView<?> appsView,
- View.OnLongClickListener onIconLongClickListener) {
- }
}
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
index 87afcab..6e697d9 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
@@ -18,7 +18,6 @@
import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.makeMeasureSpec;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP;
import static com.android.launcher3.popup.SystemShortcut.APP_INFO;
import android.content.Context;
@@ -45,7 +44,6 @@
import com.android.launcher3.views.BaseDragLayer;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
/**
@@ -79,9 +77,6 @@
mAllAppsButton = findViewById(R.id.all_apps_button);
mAppsView = findViewById(R.id.apps_view);
- mAppsView.setOnIconLongClickListener(this::onIconLongClicked);
- mActivity.getSecondaryDisplayPredictions()
- .setLongClickListener(mAppsView, this::onIconLongClicked);
// Setup workspace
mWorkspace = findViewById(R.id.workspace_grid);
mPinnedAppsAdapter = new PinnedAppsAdapter(mActivity, mAppsView.getAppsStore(),
@@ -179,7 +174,7 @@
return mPinnedAppsAdapter;
}
- private boolean onIconLongClicked(View v) {
+ boolean onIconLongClicked(View v) {
if (!(v instanceof BubbleTextView)) {
return false;
}
@@ -206,20 +201,10 @@
}
int deepShortcutCount = popupDataProvider.getShortcutCountForItem(item);
final PopupContainerWithArrow<SecondaryDisplayLauncher> container;
- if (ENABLE_MATERIAL_U_POPUP.get()) {
- container = (PopupContainerWithArrow) mActivity.getLayoutInflater().inflate(
- R.layout.popup_container_material_u, mActivity.getDragLayer(), false);
- container.populateAndShowRowsMaterialU((BubbleTextView) v, deepShortcutCount,
- systemShortcuts);
- } else {
- container = (PopupContainerWithArrow) mActivity.getLayoutInflater().inflate(
- R.layout.popup_container, mActivity.getDragLayer(), false);
- container.populateAndShow(
- (BubbleTextView) v,
- deepShortcutCount,
- Collections.emptyList(),
- systemShortcuts);
- }
+ container = (PopupContainerWithArrow) mActivity.getLayoutInflater().inflate(
+ R.layout.popup_container, mActivity.getDragLayer(), false);
+ container.populateAndShowRows((BubbleTextView) v, deepShortcutCount,
+ systemShortcuts);
container.requestFocus();
if (!FeatureFlags.SECONDARY_DRAG_N_DROP_TO_PIN.get() || !mActivity.isAppDrawerShown()) {
@@ -243,9 +228,8 @@
public void onPreDragStart(DropTarget.DragObject dragObject) {
mDragView = dragObject.dragView;
if (!shouldStartDrag(0)) {
- mDragView.setOnAnimationEndCallback(() -> {
- mActivity.beginDragShared(v, mActivity.getAppsView(), options);
- });
+ mDragView.setOnScaleAnimEndCallback(() ->
+ mActivity.beginDragShared(v, mActivity.getAppsView(), options));
}
}
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index 198dad3..9ac8f6b 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -76,6 +76,10 @@
return mState;
}
+ public STATE_TYPE getTargetState() {
+ return (STATE_TYPE) mConfig.targetState;
+ }
+
public STATE_TYPE getCurrentStableState() {
return mCurrentStableState;
}
@@ -221,6 +225,7 @@
private void goToState(
STATE_TYPE state, boolean animated, long delay, AnimatorListener listener) {
+
animated &= areAnimatorsEnabled();
if (mActivity.isInState(state)) {
if (mConfig.currentAnimation == null) {
diff --git a/src/com/android/launcher3/states/StateAnimationConfig.java b/src/com/android/launcher3/states/StateAnimationConfig.java
index d1e816b..0d9e010 100644
--- a/src/com/android/launcher3/states/StateAnimationConfig.java
+++ b/src/com/android/launcher3/states/StateAnimationConfig.java
@@ -66,7 +66,8 @@
ANIM_WORKSPACE_PAGE_TRANSLATE_X,
ANIM_OVERVIEW_SPLIT_SELECT_FLOATING_TASK_TRANSLATE_OFFSCREEN,
ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE,
- ANIM_ALL_APPS_BOTTOM_SHEET_FADE
+ ANIM_ALL_APPS_BOTTOM_SHEET_FADE,
+ ANIM_ALL_APPS_KEYBOARD_FADE
})
@Retention(RetentionPolicy.SOURCE)
public @interface AnimType {}
@@ -90,8 +91,9 @@
public static final int ANIM_OVERVIEW_SPLIT_SELECT_FLOATING_TASK_TRANSLATE_OFFSCREEN = 17;
public static final int ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE = 18;
public static final int ANIM_ALL_APPS_BOTTOM_SHEET_FADE = 19;
+ public static final int ANIM_ALL_APPS_KEYBOARD_FADE = 20;
- private static final int ANIM_TYPES_COUNT = 20;
+ private static final int ANIM_TYPES_COUNT = 21;
protected final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT];
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
index e62ccbc..a75f326 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -16,6 +16,7 @@
package com.android.launcher3.testing;
import static com.android.launcher3.allapps.AllAppsStore.DEFER_UPDATES_TEST;
+import static com.android.launcher3.config.FeatureFlags.enableGridOnlyOverview;
import static com.android.launcher3.config.FeatureFlags.FOLDABLE_SINGLE_PAGE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -31,6 +32,7 @@
import android.view.WindowInsets;
import androidx.annotation.Nullable;
+import androidx.core.view.WindowInsetsCompat;
import com.android.launcher3.CellLayout;
import com.android.launcher3.DeviceProfile;
@@ -141,6 +143,14 @@
}, this::getCurrentActivity);
}
+ case TestProtocol.REQUEST_IME_INSETS: {
+ return getUIProperty(Bundle::putParcelable, activity -> {
+ WindowInsetsCompat insets = WindowInsetsCompat.toWindowInsetsCompat(
+ activity.getWindow().getDecorView().getRootWindowInsets());
+ return insets.getInsets(WindowInsetsCompat.Type.ime()).toPlatformInsets();
+ }, this::getCurrentActivity);
+ }
+
case TestProtocol.REQUEST_ICON_HEIGHT: {
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD,
mDeviceProfile.allAppsCellHeightPx);
@@ -203,10 +213,11 @@
}
case TestProtocol.REQUEST_WORKSPACE_COLUMNS_ROWS: {
+ InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(mContext);
return getLauncherUIProperty(Bundle::putParcelable, launcher -> new Point(
- InvariantDeviceProfile.INSTANCE.get(mContext).numColumns,
- InvariantDeviceProfile.INSTANCE.get(mContext).numRows)
- );
+ idp.getDeviceProfile(mContext).getPanelCount() * idp.numColumns,
+ idp.numRows
+ ));
}
case TestProtocol.REQUEST_WORKSPACE_CURRENT_PAGE_INDEX: {
@@ -229,7 +240,7 @@
}
case TestProtocol.REQUEST_HAS_TIS: {
- response.putBoolean(TestProtocol.REQUEST_HAS_TIS, false);
+ response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD, false);
return response;
}
@@ -245,6 +256,12 @@
+ l.getAppsView().getActiveRecyclerView().getPaddingBottom());
}
+ case TestProtocol.REQUEST_FLAG_ENABLE_GRID_ONLY_OVERVIEW: {
+ response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
+ enableGridOnlyOverview());
+ return response;
+ }
+
default:
return null;
}
diff --git a/src/com/android/launcher3/testing/TestLogging.java b/src/com/android/launcher3/testing/TestLogging.java
index f95548d..70691f8 100644
--- a/src/com/android/launcher3/testing/TestLogging.java
+++ b/src/com/android/launcher3/testing/TestLogging.java
@@ -27,26 +27,29 @@
import java.util.function.BiConsumer;
public final class TestLogging {
+ private static final String TAPL_EVENTS_TAG = "TaplEvents";
+ private static final String LAUNCHER_EVENTS_TAG = "LauncherEvents";
private static BiConsumer<String, String> sEventConsumer;
public static boolean sHadEventsNotFromTest;
- private static void recordEventSlow(String sequence, String event) {
- Log.d(TestProtocol.TAPL_EVENTS_TAG, sequence + " / " + event);
+ private static void recordEventSlow(String sequence, String event, boolean reportToTapl) {
+ Log.d(reportToTapl ? TAPL_EVENTS_TAG : LAUNCHER_EVENTS_TAG,
+ sequence + " / " + event);
final BiConsumer<String, String> eventConsumer = sEventConsumer;
- if (eventConsumer != null) {
+ if (reportToTapl && eventConsumer != null) {
eventConsumer.accept(sequence, event);
}
}
public static void recordEvent(String sequence, String event) {
if (Utilities.isRunningInTestHarness()) {
- recordEventSlow(sequence, event);
+ recordEventSlow(sequence, event, true);
}
}
public static void recordEvent(String sequence, String message, Object parameter) {
if (Utilities.isRunningInTestHarness()) {
- recordEventSlow(sequence, message + ": " + parameter);
+ recordEventSlow(sequence, message + ": " + parameter, true);
}
}
@@ -59,14 +62,20 @@
public static void recordKeyEvent(String sequence, String message, KeyEvent event) {
if (Utilities.isRunningInTestHarness()) {
- recordEventSlow(sequence, message + ": " + event);
+ recordEventSlow(sequence, message + ": " + event, true);
registerEventNotFromTest(event);
}
}
public static void recordMotionEvent(String sequence, String message, MotionEvent event) {
- if (Utilities.isRunningInTestHarness() && event.getAction() != MotionEvent.ACTION_MOVE) {
- recordEventSlow(sequence, message + ": " + event);
+ final int action = event.getAction();
+ if (Utilities.isRunningInTestHarness() && action != MotionEvent.ACTION_MOVE) {
+ // "Expecting" in TAPL motion events was thought to be producing considerable noise in
+ // tests due to failed checks for expected events. So we are not sending them to TAPL.
+ // Other events, such as EVENT_PILFER_POINTERS produce less noise and are thought to
+ // be more useful.
+ // That's why we pass false as the value for the 'reportToTapl' parameter.
+ recordEventSlow(sequence, message + ": " + event, false);
registerEventNotFromTest(event);
}
}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index c499e35..cec4574 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.touch;
+import static com.android.app.animation.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.LauncherAnimUtils.TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
@@ -22,7 +23,6 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
@@ -384,8 +384,8 @@
} else {
logReachedState(targetState);
}
- mLauncher.getRootView().getSysUiScrim().createSysuiMultiplierAnim(
- 1f).setDuration(0).start();
+ mLauncher.getRootView().getSysUiScrim().getSysUIMultiplier().animateToValue(1f)
+ .setDuration(0).start();
}
private void logReachedState(LauncherState targetState) {
diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java
index d028f24..447d22b 100644
--- a/src/com/android/launcher3/touch/AllAppsSwipeController.java
+++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java
@@ -15,17 +15,20 @@
*/
package com.android.launcher3.touch;
+import static com.android.app.animation.Interpolators.DECELERATED_EASE;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE;
+import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
+import static com.android.app.animation.Interpolators.FINAL_FRAME;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.clampToProgress;
+import static com.android.app.animation.Interpolators.mapToProgress;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED_ACCELERATE;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE;
-import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_BOTTOM_SHEET_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_KEYBOARD_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_DEPTH;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
@@ -40,11 +43,11 @@
import android.view.MotionEvent;
import android.view.animation.Interpolator;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.states.StateAnimationConfig;
/**
@@ -209,8 +212,8 @@
if (!config.userControlled) {
config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED);
}
- config.setInterpolator(ANIM_WORKSPACE_SCALE, EMPHASIZED);
- config.setInterpolator(ANIM_DEPTH, EMPHASIZED);
+ config.setInterpolator(ANIM_WORKSPACE_SCALE, DECELERATED_EASE);
+ config.setInterpolator(ANIM_DEPTH, DECELERATED_EASE);
} else {
if (config.userControlled) {
config.setInterpolator(ANIM_DEPTH, Interpolators.reverse(BLUR_MANUAL));
@@ -250,8 +253,8 @@
if (!config.userControlled) {
config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED);
}
- config.setInterpolator(ANIM_WORKSPACE_SCALE, EMPHASIZED);
- config.setInterpolator(ANIM_DEPTH, EMPHASIZED);
+ config.setInterpolator(ANIM_WORKSPACE_SCALE, DECELERATED_EASE);
+ config.setInterpolator(ANIM_DEPTH, DECELERATED_EASE);
} else {
config.setInterpolator(ANIM_DEPTH, config.userControlled ? BLUR_MANUAL : BLUR_ATOMIC);
config.setInterpolator(ANIM_WORKSPACE_FADE,
@@ -293,20 +296,15 @@
config.setInterpolator(ANIM_WORKSPACE_SCALE, INSTANT);
config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, INSTANT);
} else {
- // Remove scrim for this transition.
- config.setInterpolator(ANIM_SCRIM_FADE, progress -> 0);
-
- // For now, pop the background panel in at full opacity at the threshold.
+ // Pop the background panel, keyboard, and content in at full opacity at the threshold.
config.setInterpolator(ANIM_ALL_APPS_BOTTOM_SHEET_FADE,
thresholdInterpolator(threshold, INSTANT));
-
- // Fade the apps in when the scrim normally does, so it's apparent sooner what is
- // happening (in this case we are fading them on top of the background panel).
- config.setInterpolator(ANIM_ALL_APPS_FADE,
- thresholdInterpolator(threshold, SCRIM_FADE_MANUAL));
+ config.setInterpolator(ANIM_ALL_APPS_KEYBOARD_FADE,
+ thresholdInterpolator(threshold, INSTANT));
+ config.setInterpolator(ANIM_ALL_APPS_FADE, thresholdInterpolator(threshold, INSTANT));
config.setInterpolator(ANIM_VERTICAL_PROGRESS,
- thresholdInterpolator(threshold, ALL_APPS_VERTICAL_PROGRESS_MANUAL));
+ thresholdInterpolator(threshold, mapToProgress(LINEAR, threshold, 1f)));
}
}
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 790c226..8c12547 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -42,6 +42,7 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.apppairs.AppPairIcon;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.logging.InstanceId;
@@ -95,6 +96,8 @@
} else if (tag instanceof FolderInfo) {
if (v instanceof FolderIcon) {
onClickFolderIcon(v);
+ } else if (v instanceof AppPairIcon) {
+ onClickAppPairIcon(v);
}
} else if (tag instanceof AppInfo) {
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher);
@@ -123,6 +126,17 @@
}
/**
+ * Event handler for an app pair icon click.
+ *
+ * @param v The view that was clicked. Must be an instance of {@link AppPairIcon}.
+ */
+ private static void onClickAppPairIcon(View v) {
+ Launcher launcher = Launcher.getLauncher(v.getContext());
+ FolderInfo folderInfo = ((AppPairIcon) v).getInfo();
+ launcher.launchAppPair(folderInfo.contents.get(0), folderInfo.contents.get(1));
+ }
+
+ /**
* Event handler for the app widget view which has not fully restored.
*/
private static void onClickPendingWidget(PendingAppWidgetHostView v, Launcher launcher) {
diff --git a/src/com/android/launcher3/touch/ItemLongClickListener.java b/src/com/android/launcher3/touch/ItemLongClickListener.java
index 9cba19d..122b1e0 100644
--- a/src/com/android/launcher3/touch/ItemLongClickListener.java
+++ b/src/com/android/launcher3/touch/ItemLongClickListener.java
@@ -67,7 +67,7 @@
if (!(v.getTag() instanceof ItemInfo)) return false;
launcher.setWaitingForResult(null);
- beginDrag(v, launcher, (ItemInfo) v.getTag(), launcher.getDefaultWorkspaceDragOptions());
+ beginDrag(v, launcher, (ItemInfo) v.getTag(), new DragOptions());
return true;
}
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 6a972eb..dc4621e 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -582,7 +582,8 @@
? splitInfo.dividerHeightPercent
: splitInfo.dividerWidthPercent;
- float scale = (float) outRect.height() / dp.availableHeightPx;
+ int taskbarHeight = dp.isTransientTaskbar ? 0 : dp.taskbarHeight;
+ float scale = (float) outRect.height() / (dp.availableHeightPx - taskbarHeight);
float topTaskHeight = dp.availableHeightPx * topLeftTaskPercent;
float scaledTopTaskHeight = topTaskHeight * scale;
float dividerHeight = dp.availableHeightPx * dividerBarPercent;
@@ -639,7 +640,8 @@
// Reset unused translations
primarySnapshot.setTranslationY(0);
} else {
- float scale = (float) totalThumbnailHeight / dp.availableHeightPx;
+ int taskbarHeight = dp.isTransientTaskbar ? 0 : dp.taskbarHeight;
+ float scale = (float) totalThumbnailHeight / (dp.availableHeightPx - taskbarHeight);
float topTaskHeight = dp.availableHeightPx * taskPercent;
float finalDividerHeight = Math.round(totalThumbnailHeight * dividerScale);
float scaledTopTaskHeight = topTaskHeight * scale;
diff --git a/src/com/android/launcher3/util/BackPressHandler.java b/src/com/android/launcher3/util/BackPressHandler.java
new file mode 100644
index 0000000..b63f648
--- /dev/null
+++ b/src/com/android/launcher3/util/BackPressHandler.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util;
+
+import android.os.Build;
+import android.window.OnBackAnimationCallback;
+
+import androidx.annotation.RequiresApi;
+
+/**
+ * Extension of {@link OnBackAnimationCallback} that allows a check to determine
+ * if this callback supports handling back or not
+ */
+@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+public interface BackPressHandler extends OnBackAnimationCallback {
+ boolean canHandleBack();
+}
diff --git a/src/com/android/launcher3/util/CannedAnimationCoordinator.kt b/src/com/android/launcher3/util/CannedAnimationCoordinator.kt
new file mode 100644
index 0000000..18f8339
--- /dev/null
+++ b/src/com/android/launcher3/util/CannedAnimationCoordinator.kt
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.launcher3.util
+
+import android.animation.AnimatorSet
+import android.animation.ValueAnimator
+import android.util.Log
+import android.view.ViewTreeObserver.OnGlobalLayoutListener
+import androidx.core.view.OneShotPreDrawListener
+import com.android.app.animation.Interpolators.LINEAR
+import com.android.launcher3.anim.AnimatorListeners
+import com.android.launcher3.anim.AnimatorPlaybackController
+import com.android.launcher3.anim.PendingAnimation
+import com.android.launcher3.statemanager.StatefulActivity
+import java.util.function.Consumer
+
+private const val TAG = "CannedAnimCoordinator"
+
+/**
+ * Utility class to run a canned animation on Launcher.
+ *
+ * This class takes care to registering animations with stateManager and ensures that only one
+ * animation is playing at a time.
+ */
+class CannedAnimationCoordinator(private val activity: StatefulActivity<*>) {
+
+ private val launcherLayoutListener = OnGlobalLayoutListener { scheduleRecreateAnimOnPreDraw() }
+ private var recreatePending = false
+
+ private var animationProvider: Any? = null
+
+ private var animationDuration: Long = 0L
+ private var animationFactory: Consumer<PendingAnimation>? = null
+ private var animationController: AnimatorPlaybackController? = null
+
+ private var currentAnim: AnimatorPlaybackController? = null
+
+ /**
+ * Sets the current animation cancelling any previously set animation.
+ *
+ * Callers can control the animation using {@link #getPlaybackController}. The state is
+ * automatically cleared when the playback controller ends. The animation is automatically
+ * recreated when any layout change happens. Callers can also ask for recreation by calling
+ * {@link #recreateAnimation}
+ */
+ fun setAnimation(provider: Any, factory: Consumer<PendingAnimation>, duration: Long) {
+ if (provider != animationProvider) {
+ Log.e(TAG, "Trying to play two animations together, $provider and $animationProvider")
+ }
+
+ // Cancel any previously running animation
+ endCurrentAnimation(false)
+ animationController?.dispatchOnCancel()?.dispatchOnEnd()
+
+ animationProvider = provider
+ animationFactory = factory
+ animationDuration = duration
+
+ // Setup a new controller and link it with launcher state animation
+ val anim = AnimatorSet()
+ anim.play(
+ ValueAnimator.ofFloat(0f, 1f).apply {
+ interpolator = LINEAR
+ this.duration = duration
+ addUpdateListener { anim -> currentAnim?.setPlayFraction(anim.animatedFraction) }
+ }
+ )
+ val controller = AnimatorPlaybackController.wrap(anim, duration)
+ anim.addListener(
+ AnimatorListeners.forEndCallback { success ->
+ if (animationController != controller) {
+ return@forEndCallback
+ }
+
+ endCurrentAnimation(success)
+ animationController = null
+ animationFactory = null
+ animationProvider = null
+
+ activity.rootView.viewTreeObserver.apply {
+ if (isAlive) {
+ removeOnGlobalLayoutListener(launcherLayoutListener)
+ }
+ }
+ }
+ )
+
+ // Recreate animation whenever layout happens in case transforms change during layout
+ activity.rootView.viewTreeObserver.apply {
+ if (isAlive) {
+ addOnGlobalLayoutListener(launcherLayoutListener)
+ }
+ }
+ // Link this to the state manager so that it auto-cancels when state changes
+ recreatePending = false
+ animationController =
+ controller.apply { activity.stateManager.setCurrentUserControlledAnimation(this) }
+ recreateAnimation(provider)
+ }
+
+ private fun endCurrentAnimation(success: Boolean) {
+ currentAnim?.apply {
+ // When cancelling an animation, apply final progress so that all transformations
+ // are restored
+ setPlayFraction(1f)
+ if (!success) dispatchOnCancel()
+ dispatchOnEnd()
+ }
+ currentAnim = null
+ }
+
+ /** Returns the current animation controller to control the animation */
+ fun getPlaybackController(provider: Any): AnimatorPlaybackController? {
+ return if (provider == animationProvider) animationController
+ else {
+ Log.d(TAG, "Wrong controller access from $provider, actual provider $animationProvider")
+ null
+ }
+ }
+
+ private fun scheduleRecreateAnimOnPreDraw() {
+ if (!recreatePending) {
+ recreatePending = true
+ OneShotPreDrawListener.add(activity.rootView) {
+ if (recreatePending) {
+ recreatePending = false
+ animationProvider?.apply { recreateAnimation(this) }
+ }
+ }
+ }
+ }
+
+ /** Notify the controller to recreate the animation. The animation progress is preserved */
+ fun recreateAnimation(provider: Any) {
+ if (provider != animationProvider) {
+ Log.e(TAG, "Ignore recreate request from $provider, actual provider $animationProvider")
+ return
+ }
+ endCurrentAnimation(false /* success */)
+
+ if (animationFactory == null || animationController == null) {
+ return
+ }
+ currentAnim =
+ PendingAnimation(animationDuration)
+ .apply { animationFactory?.accept(this) }
+ .createPlaybackController()
+ .apply { setPlayFraction(animationController!!.progressFraction) }
+ }
+}
diff --git a/src/com/android/launcher3/util/DimensionUtils.kt b/src/com/android/launcher3/util/DimensionUtils.kt
index 9188c2e..0eb0e08 100644
--- a/src/com/android/launcher3/util/DimensionUtils.kt
+++ b/src/com/android/launcher3/util/DimensionUtils.kt
@@ -29,9 +29,9 @@
*/
@JvmStatic
fun getTaskbarPhoneDimensions(
- deviceProfile: DeviceProfile,
- res: Resources,
- isPhoneMode: Boolean
+ deviceProfile: DeviceProfile,
+ res: Resources,
+ isPhoneMode: Boolean
): Point {
val p = Point()
// Taskbar for large screen
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 6647d0d..a7c94bb 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -54,8 +54,8 @@
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -106,7 +106,8 @@
private final LauncherPrefs mPrefs;
- private DisplayController(Context context) {
+ @VisibleForTesting
+ protected DisplayController(Context context) {
mContext = context;
mDM = context.getSystemService(DisplayManager.class);
mPrefs = LauncherPrefs.get(context);
@@ -127,8 +128,7 @@
Context displayInfoContext = getDisplayInfoContext(display);
mInfo = new Info(displayInfoContext, wmProxy,
wmProxy.estimateInternalDisplayBounds(displayInfoContext));
- mInfo.mPerDisplayBounds.forEach((key, value) -> FileLog.i(TAG,
- "(CTOR) perDisplayBounds - " + key + ": " + Arrays.deepToString(value)));
+ FileLog.i(TAG, "(CTOR) perDisplayBounds: " + mInfo.mPerDisplayBounds);
}
/**
@@ -286,9 +286,8 @@
if (!newInfo.supportedBounds.equals(oldInfo.supportedBounds)
|| !newInfo.mPerDisplayBounds.equals(oldInfo.mPerDisplayBounds)) {
change |= CHANGE_SUPPORTED_BOUNDS;
- newInfo.mPerDisplayBounds.forEach((key, value) -> FileLog.w(TAG,
- "(CHANGE_SUPPORTED_BOUNDS) perDisplayBounds - " + key + ": "
- + Arrays.deepToString(value)));
+ FileLog.w(TAG,
+ "(CHANGE_SUPPORTED_BOUNDS) perDisplayBounds: " + newInfo.mPerDisplayBounds);
}
if (DEBUG) {
Log.d(TAG, "handleInfoChange - change: " + getChangeFlagsString(change));
@@ -329,7 +328,7 @@
// WindowBounds
public final WindowBounds realBounds;
public final Set<WindowBounds> supportedBounds = new ArraySet<>();
- private final ArrayMap<CachedDisplayInfo, WindowBounds[]> mPerDisplayBounds =
+ private final ArrayMap<CachedDisplayInfo, List<WindowBounds>> mPerDisplayBounds =
new ArrayMap<>();
public Info(Context displayInfoContext) {
@@ -340,7 +339,7 @@
// Used for testing
public Info(Context displayInfoContext,
WindowManagerProxy wmProxy,
- Map<CachedDisplayInfo, WindowBounds[]> perDisplayBoundsCache) {
+ Map<CachedDisplayInfo, List<WindowBounds>> perDisplayBoundsCache) {
CachedDisplayInfo displayInfo = wmProxy.getDisplayInfo(displayInfoContext);
normalizedDisplayInfo = displayInfo.normalize();
rotation = displayInfo.rotation;
@@ -354,16 +353,14 @@
navigationMode = wmProxy.getNavigationMode(displayInfoContext);
mPerDisplayBounds.putAll(perDisplayBoundsCache);
- WindowBounds[] cachedValue = mPerDisplayBounds.get(normalizedDisplayInfo);
+ List<WindowBounds> cachedValue = mPerDisplayBounds.get(normalizedDisplayInfo);
realBounds = wmProxy.getRealBounds(displayInfoContext, displayInfo);
if (cachedValue == null) {
// Unexpected normalizedDisplayInfo is found, recreate the cache
FileLog.e(TAG, "Unexpected normalizedDisplayInfo found, invalidating cache: "
+ normalizedDisplayInfo);
- mPerDisplayBounds.forEach((key, value) -> FileLog.e(TAG,
- "(Invalid Cache) perDisplayBounds - " + key + ": " + Arrays.deepToString(
- value)));
+ FileLog.e(TAG, "(Invalid Cache) perDisplayBounds : " + mPerDisplayBounds);
mPerDisplayBounds.clear();
mPerDisplayBounds.putAll(wmProxy.estimateInternalDisplayBounds(displayInfoContext));
cachedValue = mPerDisplayBounds.get(normalizedDisplayInfo);
@@ -376,22 +373,19 @@
if (cachedValue != null) {
// Verify that the real bounds are a match
- WindowBounds expectedBounds = cachedValue[displayInfo.rotation];
+ WindowBounds expectedBounds = cachedValue.get(displayInfo.rotation);
if (!realBounds.equals(expectedBounds)) {
- WindowBounds[] clone = new WindowBounds[4];
- System.arraycopy(cachedValue, 0, clone, 0, 4);
- clone[displayInfo.rotation] = realBounds;
+ List<WindowBounds> clone = new ArrayList<>(cachedValue);
+ clone.set(displayInfo.rotation, realBounds);
mPerDisplayBounds.put(normalizedDisplayInfo, clone);
}
}
- mPerDisplayBounds.values().forEach(
- windowBounds -> Collections.addAll(supportedBounds, windowBounds));
+ mPerDisplayBounds.values().forEach(supportedBounds::addAll);
if (DEBUG) {
Log.d(TAG, "displayInfo: " + displayInfo);
Log.d(TAG, "realBounds: " + realBounds);
Log.d(TAG, "normalizedDisplayInfo: " + normalizedDisplayInfo);
- mPerDisplayBounds.forEach((key, value) -> Log.d(TAG,
- "perDisplayBounds - " + key + ": " + Arrays.deepToString(value)));
+ Log.d(TAG, "perDisplayBounds: " + mPerDisplayBounds);
}
}
@@ -448,7 +442,7 @@
pw.println(" navigationMode=" + info.navigationMode.name());
pw.println(" currentSize=" + info.currentSize);
info.mPerDisplayBounds.forEach((key, value) -> pw.println(
- " perDisplayBounds - " + key + ": " + Arrays.deepToString(value)));
+ " perDisplayBounds - " + key + ": " + value));
}
/**
diff --git a/src/com/android/launcher3/util/Executors.java b/src/com/android/launcher3/util/Executors.java
index 6978e0c..dec4b5c 100644
--- a/src/com/android/launcher3/util/Executors.java
+++ b/src/com/android/launcher3/util/Executors.java
@@ -21,6 +21,7 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
@@ -58,6 +59,11 @@
new LooperExecutor(
createAndStartNewLooper("UiThreadHelper", Process.THREAD_PRIORITY_FOREGROUND));
+
+ /** A background executor to preinflate views. */
+ public static final ExecutorService VIEW_PREINFLATION_EXECUTOR =
+ java.util.concurrent.Executors.newSingleThreadExecutor();
+
/**
* Utility method to get a started handler thread statically
*/
diff --git a/src/com/android/launcher3/util/IconSizeSteps.kt b/src/com/android/launcher3/util/IconSizeSteps.kt
new file mode 100644
index 0000000..2a5afe0
--- /dev/null
+++ b/src/com/android/launcher3/util/IconSizeSteps.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util
+
+import android.content.res.Resources
+import androidx.core.content.res.getDimensionOrThrow
+import androidx.core.content.res.use
+import com.android.launcher3.R
+import kotlin.math.max
+
+class IconSizeSteps(res: Resources) {
+ private val steps: List<Int>
+
+ init {
+ steps =
+ res.obtainTypedArray(R.array.icon_size_steps).use {
+ (0 until it.length()).map { step -> it.getDimensionOrThrow(step).toInt() }.sorted()
+ }
+ }
+
+ fun minimumIconSize(): Int = steps[0]
+
+ fun getNextLowerIconSize(iconSizePx: Int): Int {
+ return steps[max(0, getIndexForIconSize(iconSizePx) - 1)]
+ }
+
+ fun getIconSmallerThan(cellWidth: Int): Int {
+ return steps.lastOrNull { it <= cellWidth } ?: steps[0]
+ }
+
+ private fun getIndexForIconSize(iconSizePx: Int): Int {
+ return max(0, steps.indexOfFirst { iconSizePx <= it })
+ }
+}
diff --git a/src/com/android/launcher3/util/InstantAppResolver.java b/src/com/android/launcher3/util/InstantAppResolver.java
index 6f706d2..bdb5e77 100644
--- a/src/com/android/launcher3/util/InstantAppResolver.java
+++ b/src/com/android/launcher3/util/InstantAppResolver.java
@@ -42,14 +42,7 @@
return false;
}
- public boolean isInstantApp(Context context, String packageName) {
- PackageManager packageManager = context.getPackageManager();
- try {
- return isInstantApp(packageManager.getPackageInfo(packageName, 0).applicationInfo);
- } catch (PackageManager.NameNotFoundException e) {
- Log.e("InstantAppResolver", "Failed to determine whether package is instant app "
- + packageName, e);
- }
+ public boolean isInstantApp(String packageName, int userId) {
return false;
}
}
diff --git a/src/com/android/launcher3/util/IntArray.java b/src/com/android/launcher3/util/IntArray.java
index 1c78795..2498242 100644
--- a/src/com/android/launcher3/util/IntArray.java
+++ b/src/com/android/launcher3/util/IntArray.java
@@ -250,6 +250,11 @@
return b.toString();
}
+ @Override
+ public String toString() {
+ return "IntArray [" + toConcatString() + "]";
+ }
+
public static IntArray fromConcatString(String concatString) {
StringTokenizer tokenizer = new StringTokenizer(concatString, ",");
int[] array = new int[tokenizer.countTokens()];
diff --git a/src/com/android/launcher3/util/LockedUserState.kt b/src/com/android/launcher3/util/LockedUserState.kt
index 1231604..0a87594 100644
--- a/src/com/android/launcher3/util/LockedUserState.kt
+++ b/src/com/android/launcher3/util/LockedUserState.kt
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.android.launcher3.util
import android.content.Context
diff --git a/src/com/android/launcher3/util/MainThreadInitializedObject.java b/src/com/android/launcher3/util/MainThreadInitializedObject.java
index 6a4e528..1cb9994 100644
--- a/src/com/android/launcher3/util/MainThreadInitializedObject.java
+++ b/src/com/android/launcher3/util/MainThreadInitializedObject.java
@@ -48,8 +48,8 @@
}
public T get(Context context) {
- if (context instanceof SandboxContext) {
- return ((SandboxContext) context).getObject(this, mProvider);
+ if (context instanceof SandboxContext sc) {
+ return sc.getObject(this);
}
if (mValue == null) {
@@ -131,23 +131,22 @@
* Find a cached object from mObjectMap if we have already created one. If not, generate
* an object using the provider.
*/
- private <T> T getObject(MainThreadInitializedObject<T> object, ObjectProvider<T> provider) {
+ protected <T> T getObject(MainThreadInitializedObject<T> object) {
synchronized (mDestroyLock) {
if (mDestroyed) {
Log.e(TAG, "Static object access with a destroyed context");
}
-
T t = (T) mObjectMap.get(object);
if (t != null) {
return t;
}
if (Looper.myLooper() == Looper.getMainLooper()) {
- t = createObject(provider);
+ t = createObject(object);
// Check if we've explicitly allowed the object or if it's a SafeCloseable,
// it will get destroyed in onDestroy()
if (!mAllowedObjects.contains(object) && !(t instanceof SafeCloseable)) {
- throw new IllegalStateException(
- "Leaking unknown objects " + object + " " + provider + " " + t);
+ throw new IllegalStateException("Leaking unknown objects "
+ + object + " " + object.mProvider + " " + t);
}
mObjectMap.put(object, t);
mOrderedObjects.add(t);
@@ -156,15 +155,15 @@
}
try {
- return MAIN_EXECUTOR.submit(() -> getObject(object, provider)).get();
+ return MAIN_EXECUTOR.submit(() -> getObject(object)).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
@UiThread
- protected <T> T createObject(ObjectProvider<T> provider) {
- return provider.get(this);
+ protected <T> T createObject(MainThreadInitializedObject<T> object) {
+ return object.mProvider.get(this);
}
}
}
diff --git a/src/com/android/launcher3/util/MultiScalePropertyFactory.java b/src/com/android/launcher3/util/MultiScalePropertyFactory.java
index a7e6cc8..cf8d6cc 100644
--- a/src/com/android/launcher3/util/MultiScalePropertyFactory.java
+++ b/src/com/android/launcher3/util/MultiScalePropertyFactory.java
@@ -40,8 +40,7 @@
private static final boolean DEBUG = false;
private static final String TAG = "MultiScaleProperty";
private final String mName;
- private final ArrayMap<Integer, MultiScaleProperty> mProperties =
- new ArrayMap<Integer, MultiScaleProperty>();
+ private final ArrayMap<Integer, MultiScaleProperty> mProperties = new ArrayMap<>();
// This is an optimization for cases when set is called repeatedly with the same setterIndex.
private float mMinOfOthers = 0;
@@ -55,7 +54,7 @@
}
/** Returns the [MultiFloatProperty] associated with [inx], creating it if not present. */
- public MultiScaleProperty get(Integer index) {
+ public FloatProperty<T> get(Integer index) {
return mProperties.computeIfAbsent(index,
(k) -> new MultiScaleProperty(index, mName + "_" + index));
}
diff --git a/src/com/android/launcher3/util/MultiTranslateDelegate.java b/src/com/android/launcher3/util/MultiTranslateDelegate.java
index 1cb7a45..0e32ba7 100644
--- a/src/com/android/launcher3/util/MultiTranslateDelegate.java
+++ b/src/com/android/launcher3/util/MultiTranslateDelegate.java
@@ -40,6 +40,9 @@
// Specific for widgets
public static final int INDEX_WIDGET_CENTERING = 3;
+ // Specific for hotseat items when adjusting for bubbles
+ public static final int INDEX_BUBBLE_ADJUSTMENT_ANIM = 3;
+
public static final int COUNT = 5;
private final MultiPropertyFactory<View> mTranslationX;
diff --git a/src/com/android/launcher3/util/MultiValueAlpha.java b/src/com/android/launcher3/util/MultiValueAlpha.java
index ac016a8..a66a9d2 100644
--- a/src/com/android/launcher3/util/MultiValueAlpha.java
+++ b/src/com/android/launcher3/util/MultiValueAlpha.java
@@ -32,8 +32,15 @@
// Whether we should change from INVISIBLE to VISIBLE and vice versa at low alpha values.
private boolean mUpdateVisibility;
+ private final int mHiddenVisibility;
+
public MultiValueAlpha(View view, int size) {
+ this(view, size, View.INVISIBLE);
+ }
+
+ public MultiValueAlpha(View view, int size, int hiddenVisibility) {
super(view, VIEW_ALPHA, size, ALPHA_AGGREGATOR, 1f);
+ this.mHiddenVisibility = hiddenVisibility;
}
/** Sets whether we should update between INVISIBLE and VISIBLE based on alpha. */
@@ -45,7 +52,7 @@
protected void apply(float value) {
super.apply(value);
if (mUpdateVisibility) {
- AlphaUpdateListener.updateVisibility(mTarget);
+ AlphaUpdateListener.updateVisibility(mTarget, mHiddenVisibility);
}
}
}
diff --git a/src/com/android/launcher3/util/OnboardingPrefs.java b/src/com/android/launcher3/util/OnboardingPrefs.java
index 6573691..f8f4b5f 100644
--- a/src/com/android/launcher3/util/OnboardingPrefs.java
+++ b/src/com/android/launcher3/util/OnboardingPrefs.java
@@ -38,19 +38,13 @@
public static final String HOME_BOUNCE_COUNT = "launcher.home_bounce_count";
public static final String HOTSEAT_DISCOVERY_TIP_COUNT = "launcher.hotseat_discovery_tip_count";
public static final String HOTSEAT_LONGPRESS_TIP_SEEN = "launcher.hotseat_longpress_tip_seen";
- public static final String SEARCH_KEYBOARD_EDU_SEEN = "launcher.search_edu_seen";
- public static final String SEARCH_SNACKBAR_COUNT = "launcher.keyboard_snackbar_count";
- public static final String SEARCH_ONBOARDING_COUNT = "launcher.search_onboarding_count";
public static final String ALL_APPS_VISITED_COUNT = "launcher.all_apps_visited_count";
- public static final String QSB_SEARCH_ONBOARDING_CARD_DISMISSED = "launcher.qsb_edu_dismiss";
public static final String TASKBAR_EDU_TOOLTIP_STEP = "launcher.taskbar_edu_tooltip_step";
// When adding a new key, add it here as well, to be able to reset it from Developer Options.
public static final Map<String, String[]> ALL_PREF_KEYS = Map.of(
"All Apps Bounce", new String[] { HOME_BOUNCE_SEEN, HOME_BOUNCE_COUNT },
"Hybrid Hotseat Education", new String[] { HOTSEAT_DISCOVERY_TIP_COUNT,
HOTSEAT_LONGPRESS_TIP_SEEN },
- "Search Education", new String[] { SEARCH_KEYBOARD_EDU_SEEN, SEARCH_SNACKBAR_COUNT,
- SEARCH_ONBOARDING_COUNT, QSB_SEARCH_ONBOARDING_CARD_DISMISSED},
"Taskbar Education", new String[] { TASKBAR_EDU_TOOLTIP_STEP },
"All Apps Visited Count", new String[] {ALL_APPS_VISITED_COUNT}
);
@@ -61,8 +55,6 @@
@StringDef(value = {
HOME_BOUNCE_SEEN,
HOTSEAT_LONGPRESS_TIP_SEEN,
- SEARCH_KEYBOARD_EDU_SEEN,
- QSB_SEARCH_ONBOARDING_CARD_DISMISSED
})
@Retention(RetentionPolicy.SOURCE)
public @interface EventBoolKey {}
@@ -73,8 +65,6 @@
@StringDef(value = {
HOME_BOUNCE_COUNT,
HOTSEAT_DISCOVERY_TIP_COUNT,
- SEARCH_SNACKBAR_COUNT,
- SEARCH_ONBOARDING_COUNT,
ALL_APPS_VISITED_COUNT,
TASKBAR_EDU_TOOLTIP_STEP,
})
@@ -87,9 +77,6 @@
Map<String, Integer> maxCounts = new ArrayMap<>(5);
maxCounts.put(HOME_BOUNCE_COUNT, 3);
maxCounts.put(HOTSEAT_DISCOVERY_TIP_COUNT, 5);
- maxCounts.put(SEARCH_SNACKBAR_COUNT, 3);
- // This is the sum of all onboarding cards. Currently there is only 1 card shown 3 times.
- maxCounts.put(SEARCH_ONBOARDING_COUNT, 3);
maxCounts.put(ALL_APPS_VISITED_COUNT, 20);
maxCounts.put(TASKBAR_EDU_TOOLTIP_STEP, 2);
MAX_COUNTS = Collections.unmodifiableMap(maxCounts);
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index 1d6bc25..91203a7 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -164,13 +164,6 @@
}
}
- public static Intent getStyleWallpapersIntent(Context context) {
- return new Intent(Intent.ACTION_SET_WALLPAPER).setComponent(
- new ComponentName(context.getString(R.string.wallpaper_picker_package),
- context.getString(R.string.custom_activity_picker)
- ));
- }
-
/**
* Starts the details activity for {@code info}
*/
diff --git a/src/com/android/launcher3/util/SettingsCache.java b/src/com/android/launcher3/util/SettingsCache.java
index 0c5b722..06cb00e 100644
--- a/src/com/android/launcher3/util/SettingsCache.java
+++ b/src/com/android/launcher3/util/SettingsCache.java
@@ -154,7 +154,7 @@
*/
public void unregister(Uri uri, OnChangeListener listener) {
List<OnChangeListener> listenersToRemoveFrom = mListenerMap.get(uri);
- if (!listenersToRemoveFrom.contains(listener)) {
+ if (listenersToRemoveFrom == null) {
return;
}
diff --git a/src/com/android/launcher3/util/SplitConfigurationOptions.java b/src/com/android/launcher3/util/SplitConfigurationOptions.java
index 1ae43d0..f4a0225 100644
--- a/src/com/android/launcher3/util/SplitConfigurationOptions.java
+++ b/src/com/android/launcher3/util/SplitConfigurationOptions.java
@@ -77,11 +77,6 @@
public @interface StageType {}
///////////////////////////////////
- /**
- * Default split ratio for launching app pair from overview.
- */
- public static final float DEFAULT_SPLIT_RATIO = 0.5f;
-
public static class SplitPositionOption {
public final int iconResId;
public final int textResId;
@@ -116,6 +111,8 @@
public final float leftTaskPercent;
public final float dividerWidthPercent;
public final float dividerHeightPercent;
+ public final int snapPosition;
+
/**
* If {@code true}, that means at the time of creation of this object, the
* split-screened apps were vertically stacked. This is useful in scenarios like
@@ -135,11 +132,12 @@
public final int rightBottomTaskId;
public SplitBounds(Rect leftTopBounds, Rect rightBottomBounds, int leftTopTaskId,
- int rightBottomTaskId) {
+ int rightBottomTaskId, int snapPosition) {
this.leftTopBounds = leftTopBounds;
this.rightBottomBounds = rightBottomBounds;
this.leftTopTaskId = leftTopTaskId;
this.rightBottomTaskId = rightBottomTaskId;
+ this.snapPosition = snapPosition;
if (rightBottomBounds.top > leftTopBounds.top) {
// vertical apps, horizontal divider
diff --git a/quickstep/src/com/android/launcher3/proxy/StartActivityParams.java b/src/com/android/launcher3/util/StartActivityParams.java
similarity index 88%
rename from quickstep/src/com/android/launcher3/proxy/StartActivityParams.java
rename to src/com/android/launcher3/util/StartActivityParams.java
index b47ef47..b48562f 100644
--- a/quickstep/src/com/android/launcher3/proxy/StartActivityParams.java
+++ b/src/com/android/launcher3/util/StartActivityParams.java
@@ -14,13 +14,16 @@
* limitations under the License.
*/
-package com.android.launcher3.proxy;
+package com.android.launcher3.util;
import static android.app.PendingIntent.FLAG_MUTABLE;
import static android.app.PendingIntent.FLAG_ONE_SHOT;
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
+import static com.android.launcher3.Utilities.allowBGLaunch;
+
import android.app.Activity;
+import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.content.Context;
@@ -31,6 +34,9 @@
import android.os.Parcelable;
import android.util.Log;
+/**
+ * Wrapper class for parameters to start an activity.
+ */
public class StartActivityParams implements Parcelable {
private static final String TAG = "StartActivityParams";
@@ -90,10 +96,12 @@
parcel.writeBundle(options);
}
+ /** Perform the operation on the pendingIntent. */
public void deliverResult(Context context, int resultCode, Intent data) {
+ ActivityOptions options = allowBGLaunch(ActivityOptions.makeBasic());
try {
if (mPICallback != null) {
- mPICallback.send(context, resultCode, data);
+ mPICallback.send(context, resultCode, data, null, null, null, options.toBundle());
}
} catch (CanceledException e) {
Log.e(TAG, "Unable to send back result", e);
@@ -101,7 +109,7 @@
}
public static final Parcelable.Creator<StartActivityParams> CREATOR =
- new Parcelable.Creator<StartActivityParams>() {
+ new Parcelable.Creator<>() {
public StartActivityParams createFromParcel(Parcel source) {
return new StartActivityParams(source);
}
diff --git a/src/com/android/launcher3/util/Themes.java b/src/com/android/launcher3/util/Themes.java
index a5c663f..60951ba 100644
--- a/src/com/android/launcher3/util/Themes.java
+++ b/src/com/android/launcher3/util/Themes.java
@@ -21,8 +21,6 @@
import static com.android.launcher3.LauncherPrefs.THEMED_ICONS;
-import android.app.WallpaperColors;
-import android.app.WallpaperManager;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
@@ -48,16 +46,9 @@
public static final String KEY_THEMED_ICONS = "themed_icons";
+ /** Gets the WallpaperColorHints and then uses those to get the correct activity theme res. */
public static int getActivityThemeRes(Context context) {
- final int colorHints;
- if (Utilities.ATLEAST_P) {
- WallpaperColors colors = context.getSystemService(WallpaperManager.class)
- .getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
- colorHints = colors == null ? 0 : colors.getColorHints();
- } else {
- colorHints = 0;
- }
- return getActivityThemeRes(context, colorHints);
+ return getActivityThemeRes(context, WallpaperColorHints.get(context).getHints());
}
public static int getActivityThemeRes(Context context, int wallpaperColorHints) {
diff --git a/src/com/android/launcher3/util/TraceHelper.java b/src/com/android/launcher3/util/TraceHelper.java
index c23df77..138cc4a 100644
--- a/src/com/android/launcher3/util/TraceHelper.java
+++ b/src/com/android/launcher3/util/TraceHelper.java
@@ -15,12 +15,17 @@
*/
package com.android.launcher3.util;
+import android.annotation.SuppressLint;
import android.os.Trace;
import androidx.annotation.MainThread;
+import com.android.launcher3.Utilities;
+
import java.util.function.Supplier;
+import kotlin.random.Random;
+
/**
* A wrapper around {@link Trace} to allow better testing.
*
@@ -36,54 +41,63 @@
// Temporarily ignore blocking binder calls for this trace.
public static final int FLAG_IGNORE_BINDERS = 1 << 1;
- public static final int FLAG_CHECK_FOR_RACE_CONDITIONS = 1 << 2;
-
- public static final int FLAG_UI_EVENT =
- FLAG_ALLOW_BINDER_TRACKING | FLAG_CHECK_FOR_RACE_CONDITIONS;
-
/**
* Static instance of Trace helper, overridden in tests.
*/
public static TraceHelper INSTANCE = new TraceHelper();
/**
- * @return a token to pass into {@link #endSection(Object)}.
+ * @see Trace#beginSection(String)
*/
- public Object beginSection(String sectionName) {
- return beginSection(sectionName, 0);
- }
-
- public Object beginSection(String sectionName, int flags) {
+ public void beginSection(String sectionName) {
Trace.beginSection(sectionName);
- return null;
}
/**
- * @param token the token returned from {@link #beginSection(String, int)}
+ * @see Trace#endSection()
*/
- public void endSection(Object token) {
+ public void endSection() {
Trace.endSection();
}
/**
- * Similar to {@link #beginSection} but doesn't add a trace section.
+ * @see Trace#beginAsyncSection(String, int)
+ * @return a SafeCloseable that can be used to end the session
*/
- public Object beginFlagsOverride(int flags) {
- return null;
+ @SuppressWarnings("NewApi")
+ @SuppressLint("NewApi")
+ public SafeCloseable beginAsyncSection(String sectionName) {
+ if (!Utilities.ATLEAST_Q) {
+ return () -> { };
+ }
+ int cookie = Random.Default.nextInt();
+ Trace.beginAsyncSection(sectionName, cookie);
+ return () -> Trace.endAsyncSection(sectionName, cookie);
}
- public void endFlagsOverride(Object token) { }
+ /**
+ * Returns a SafeCloseable to temporarily ignore blocking binder calls.
+ */
+ @SuppressWarnings("NewApi")
+ @SuppressLint("NewApi")
+ public SafeCloseable allowIpcs(String rpcName) {
+ if (!Utilities.ATLEAST_Q) {
+ return () -> { };
+ }
+ int cookie = Random.Default.nextInt();
+ Trace.beginAsyncSection(rpcName, cookie);
+ return () -> Trace.endAsyncSection(rpcName, cookie);
+ }
/**
* Temporarily ignore blocking binder calls for the duration of this {@link Supplier}.
+ *
+ * Note, new features should be designed to not rely on mainThread RPCs.
*/
@MainThread
public static <T> T allowIpcs(String rpcName, Supplier<T> supplier) {
- Object traceToken = INSTANCE.beginSection(rpcName, FLAG_IGNORE_BINDERS);
- try {
+ try (SafeCloseable c = INSTANCE.allowIpcs(rpcName)) {
return supplier.get();
- } finally {
- INSTANCE.endSection(traceToken);
}
}
}
diff --git a/src/com/android/launcher3/util/VibratorWrapper.java b/src/com/android/launcher3/util/VibratorWrapper.java
index ceba0db..91945ca 100644
--- a/src/com/android/launcher3/util/VibratorWrapper.java
+++ b/src/com/android/launcher3/util/VibratorWrapper.java
@@ -17,6 +17,7 @@
import static android.os.VibrationEffect.createPredefined;
import static android.provider.Settings.System.HAPTIC_FEEDBACK_ENABLED;
+
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
@@ -68,6 +69,9 @@
@Nullable
private final VibrationEffect mBumpEffect;
+ @Nullable
+ private final VibrationEffect mAssistEffect;
+
private long mLastDragTime;
private final int mThresholdUntilNextDragCallMillis;
@@ -125,12 +129,25 @@
mBumpEffect = null;
mThresholdUntilNextDragCallMillis = 0;
}
+
+ if (Utilities.ATLEAST_R && mVibrator.areAllPrimitivesSupported(
+ VibrationEffect.Composition.PRIMITIVE_QUICK_RISE,
+ VibrationEffect.Composition.PRIMITIVE_TICK)) {
+ // quiet ramp, short pause, then sharp tick
+ mAssistEffect = VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, 0.25f)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1f, 50)
+ .compose();
+ } else {
+ // fallback for devices without composition support
+ mAssistEffect = VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK);
+ }
}
/**
- * This is called when the user swipes to/from all apps. This is meant to be used in between
- * long animation progresses so that it gives a dragging texture effect. For a better
- * experience, this should be used in combination with vibrateForDragCommit().
+ * This is called when the user swipes to/from all apps. This is meant to be used in between
+ * long animation progresses so that it gives a dragging texture effect. For a better
+ * experience, this should be used in combination with vibrateForDragCommit().
*/
public void vibrateForDragTexture() {
if (mDragEffect == null) {
@@ -145,7 +162,7 @@
}
/**
- * This is used when user reaches the commit threshold when swiping to/from from all apps.
+ * This is used when user reaches the commit threshold when swiping to/from from all apps.
*/
public void vibrateForDragCommit() {
if (mCommitEffect != null) {
@@ -156,9 +173,9 @@
}
/**
- * The bump haptic is used to be called at the end of a swipe and only if it the gesture is a
- * FLING going to/from all apps. Client can just call this method elsewhere just for the
- * effect.
+ * The bump haptic is used to be called at the end of a swipe and only if it the gesture is a
+ * FLING going to/from all apps. Client can just call this method elsewhere just for the
+ * effect.
*/
public void vibrateForDragBump() {
if (mBumpEffect != null) {
@@ -167,6 +184,15 @@
}
/**
+ * The assist haptic is used to be called when an assistant is invoked
+ */
+ public void vibrateForAssist() {
+ if (mAssistEffect != null) {
+ vibrate(mAssistEffect);
+ }
+ }
+
+ /**
* This should be used to cancel a haptic in case where the haptic shouldn't be vibrating. For
* example, when no animation is happening but a vibrator happens to be vibrating still. Need
* boolean parameter for {@link PendingAnimation#addEndListener(Consumer)}.
@@ -176,6 +202,7 @@
// reset dragTexture timestamp to be able to play dragTexture again whenever cancelled
mLastDragTime = 0;
}
+
private boolean isHapticFeedbackEnabled(ContentResolver resolver) {
return Settings.System.getInt(resolver, HAPTIC_FEEDBACK_ENABLED, 0) == 1;
}
diff --git a/src/com/android/launcher3/util/WallpaperColorHints.kt b/src/com/android/launcher3/util/WallpaperColorHints.kt
new file mode 100644
index 0000000..1361c1e
--- /dev/null
+++ b/src/com/android/launcher3/util/WallpaperColorHints.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.util
+
+import android.app.WallpaperColors
+import android.app.WallpaperManager
+import android.app.WallpaperManager.FLAG_SYSTEM
+import android.app.WallpaperManager.OnColorsChangedListener
+import android.content.Context
+import androidx.annotation.MainThread
+import androidx.annotation.VisibleForTesting
+import com.android.launcher3.Utilities
+import com.android.launcher3.util.Executors.MAIN_EXECUTOR
+import com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR
+
+/**
+ * This class caches the system's wallpaper color hints for use by other classes as a performance
+ * enhancer. It also centralizes all the WallpaperManager color hint code in one location.
+ */
+class WallpaperColorHints(private val context: Context) : SafeCloseable {
+ var hints: Int = 0
+ private set
+ private val wallpaperManager
+ get() = context.getSystemService(WallpaperManager::class.java)!!
+ private val onColorHintsChangedListeners = mutableListOf<OnColorHintListener>()
+ private val onClose: SafeCloseable
+
+ init {
+ if (Utilities.ATLEAST_S) {
+ hints = wallpaperManager.getWallpaperColors(FLAG_SYSTEM)?.colorHints ?: 0
+ val onColorsChangedListener = OnColorsChangedListener { colors, which ->
+ onColorsChanged(colors, which)
+ }
+ UI_HELPER_EXECUTOR.execute {
+ wallpaperManager.addOnColorsChangedListener(
+ onColorsChangedListener,
+ MAIN_EXECUTOR.handler
+ )
+ }
+ onClose = SafeCloseable {
+ UI_HELPER_EXECUTOR.execute {
+ wallpaperManager.removeOnColorsChangedListener(onColorsChangedListener)
+ }
+ }
+ } else {
+ onClose = SafeCloseable {}
+ }
+ }
+
+ @MainThread
+ private fun onColorsChanged(colors: WallpaperColors?, which: Int) {
+ if ((which and FLAG_SYSTEM) != 0 && Utilities.ATLEAST_S) {
+ val newHints = colors?.colorHints ?: 0
+ if (newHints != hints) {
+ hints = newHints
+ onColorHintsChangedListeners.forEach { it.onColorHintsChanged(newHints) }
+ }
+ }
+ }
+
+ override fun close() = onClose.close()
+
+ fun registerOnColorHintsChangedListener(listener: OnColorHintListener) {
+ onColorHintsChangedListeners.add(listener)
+ }
+
+ fun unregisterOnColorsChangedListener(listener: OnColorHintListener) {
+ onColorHintsChangedListeners.remove(listener)
+ }
+
+ companion object {
+ @VisibleForTesting
+ @JvmField
+ val INSTANCE = MainThreadInitializedObject { WallpaperColorHints(it) }
+ @JvmStatic fun get(context: Context): WallpaperColorHints = INSTANCE.get(context)
+ }
+}
+
+interface OnColorHintListener {
+ fun onColorHintsChanged(colorHints: Int)
+}
diff --git a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
index 4ac6bc4..b97b889 100644
--- a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
+++ b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
@@ -15,9 +15,9 @@
import androidx.annotation.AnyThread;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
-import com.android.launcher3.anim.Interpolators;
/**
* Utility class to handle wallpaper scrolling along with workspace.
@@ -237,7 +237,7 @@
public OffsetHandler(Context context) {
super(UI_HELPER_EXECUTOR.getLooper());
- mInterpolator = Interpolators.DEACCEL_1_5;
+ mInterpolator = Interpolators.DECELERATE_1_5;
mWM = WallpaperManager.getInstance(context);
}
diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java
index 4093bc9..278a37e 100644
--- a/src/com/android/launcher3/util/window/WindowManagerProxy.java
+++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java
@@ -57,6 +57,9 @@
import com.android.launcher3.util.ResourceBasedOverride;
import com.android.launcher3.util.WindowBounds;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Utility class for mocking some window manager behaviours
*/
@@ -90,11 +93,11 @@
* Returns a map of normalized info of internal displays to estimated window bounds
* for that display
*/
- public ArrayMap<CachedDisplayInfo, WindowBounds[]> estimateInternalDisplayBounds(
+ public ArrayMap<CachedDisplayInfo, List<WindowBounds>> estimateInternalDisplayBounds(
Context displayInfoContext) {
CachedDisplayInfo info = getDisplayInfo(displayInfoContext).normalize();
- WindowBounds[] bounds = estimateWindowBounds(displayInfoContext, info);
- ArrayMap<CachedDisplayInfo, WindowBounds[]> result = new ArrayMap<>();
+ List<WindowBounds> bounds = estimateWindowBounds(displayInfoContext, info);
+ ArrayMap<CachedDisplayInfo, List<WindowBounds>> result = new ArrayMap<>();
result.put(info, bounds);
return result;
}
@@ -200,7 +203,8 @@
/**
* Returns a list of possible WindowBounds for the display keyed on the 4 surface rotations
*/
- protected WindowBounds[] estimateWindowBounds(Context context, CachedDisplayInfo displayInfo) {
+ protected List<WindowBounds> estimateWindowBounds(Context context,
+ CachedDisplayInfo displayInfo) {
int densityDpi = context.getResources().getConfiguration().densityDpi;
int rotation = displayInfo.rotation;
Rect safeCutout = displayInfo.cutout;
@@ -243,7 +247,7 @@
? 0
: getDimenByName(systemRes, NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE);
- WindowBounds[] result = new WindowBounds[4];
+ List<WindowBounds> result = new ArrayList<>(4);
Point tempSize = new Point();
for (int i = 0; i < 4; i++) {
int rotationChange = deltaRotation(rotation, i);
@@ -274,7 +278,7 @@
} else {
insets.right = Math.max(insets.right, navbarWidth);
}
- result[i] = new WindowBounds(bounds, insets, i);
+ result.add(new WindowBounds(bounds, insets, i));
}
return result;
}
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index ec7ec0b..30e0971 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -17,24 +17,22 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.LauncherAnimUtils.TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.allapps.AllAppsTransitionController.REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS;
-import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.util.ScrollableLayoutManager.PREDICTIVE_BACK_MIN_SCALE;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Outline;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
-import android.util.Property;
+import android.util.FloatProperty;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -47,10 +45,13 @@
import androidx.annotation.Px;
import androidx.annotation.RequiresApi;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatedFloat;
-import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.anim.AnimatorListeners;
+import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.touch.BaseSwipeDetector;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
@@ -66,8 +67,8 @@
public abstract class AbstractSlideInView<T extends Context & ActivityContext>
extends AbstractFloatingView implements SingleAxisSwipeDetector.Listener {
- protected static final Property<AbstractSlideInView, Float> TRANSLATION_SHIFT =
- new Property<AbstractSlideInView, Float>(Float.class, "translationShift") {
+ protected static final FloatProperty<AbstractSlideInView<?>> TRANSLATION_SHIFT =
+ new FloatProperty<>("translationShift") {
@Override
public Float get(AbstractSlideInView view) {
@@ -75,25 +76,54 @@
}
@Override
- public void set(AbstractSlideInView view, Float value) {
+ public void setValue(AbstractSlideInView view, float value) {
view.setTranslationShift(value);
}
};
protected static final float TRANSLATION_SHIFT_CLOSED = 1f;
protected static final float TRANSLATION_SHIFT_OPENED = 0f;
private static final float VIEW_NO_SCALE = 1f;
+ private static final int DEFAULT_DURATION = 300;
protected final T mActivityContext;
protected final SingleAxisSwipeDetector mSwipeDetector;
- protected final ObjectAnimator mOpenCloseAnimator;
+ protected @NonNull AnimatorPlaybackController mOpenCloseAnimation;
protected ViewGroup mContent;
protected final View mColorScrim;
- protected Interpolator mScrollInterpolator;
+
+ /**
+ * Interpolator for {@link #mOpenCloseAnimation} when we are closing due to dragging downwards.
+ */
+ private Interpolator mScrollInterpolator;
+ private long mScrollDuration;
+ /**
+ * End progress for {@link #mOpenCloseAnimation} when we are closing due to dragging downloads.
+ * <p>
+ * There are two cases that determine this value:
+ * <ol>
+ * <li>
+ * If the drag interrupts the opening transition (i.e. {@link #mToTranslationShift}
+ * is {@link #TRANSLATION_SHIFT_OPENED}), we need to animate back to {@code 0} to
+ * reverse the animation that was paused at {@link #onDragStart(boolean, float)}.
+ * </li>
+ * <li>
+ * If the drag started after the view is fully opened (i.e.
+ * {@link #mToTranslationShift} is {@link #TRANSLATION_SHIFT_CLOSED}), the animation
+ * that was set up at {@link #onDragStart(boolean, float)} for closing the view
+ * should go forward to {@code 1}.
+ * </li>
+ * </ol>
+ */
+ private float mScrollEndProgress;
// range [0, 1], 0=> completely open, 1=> completely closed
protected float mTranslationShift = TRANSLATION_SHIFT_CLOSED;
+ protected float mFromTranslationShift;
+ protected float mToTranslationShift;
+ /** {@link #mOpenCloseAnimation} progress at {@link #onDragStart(boolean, float)}. */
+ private float mDragStartProgress;
protected boolean mNoIntercept;
protected @Nullable OnCloseListener mOnCloseBeginListener;
@@ -102,8 +132,8 @@
protected final AnimatedFloat mSlideInViewScale =
new AnimatedFloat(this::onScaleProgressChanged, VIEW_NO_SCALE);
protected boolean mIsBackProgressing;
- @Nullable private Drawable mContentBackground;
- @Nullable private View mContentBackgroundParentView;
+ private @Nullable Drawable mContentBackground;
+ private @Nullable View mContentBackgroundParentView;
protected final ViewOutlineProvider mViewOutlineProvider = new ViewOutlineProvider() {
@Override
@@ -122,21 +152,78 @@
mActivityContext = ActivityContext.lookupContext(context);
mScrollInterpolator = Interpolators.SCROLL_CUBIC;
+ mScrollDuration = DEFAULT_DURATION;
mSwipeDetector = new SingleAxisSwipeDetector(context, this,
SingleAxisSwipeDetector.VERTICAL);
- mOpenCloseAnimator = ObjectAnimator.ofPropertyValuesHolder(this);
- mOpenCloseAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mSwipeDetector.finishedScrolling();
- announceAccessibilityChanges();
- }
- });
+ mOpenCloseAnimation = new PendingAnimation(0).createPlaybackController();
+
int scrimColor = getScrimColor(context);
mColorScrim = scrimColor != -1 ? createColorScrim(context, scrimColor) : null;
}
+ /**
+ * Sets up a {@link #mOpenCloseAnimation} for opening with default parameters.
+ *
+ * @see #setUpOpenCloseAnimation(float, float, long)
+ */
+ protected final AnimatorPlaybackController setUpDefaultOpenAnimation() {
+ AnimatorPlaybackController animation = setUpOpenCloseAnimation(
+ TRANSLATION_SHIFT_CLOSED, TRANSLATION_SHIFT_OPENED, DEFAULT_DURATION);
+ animation.getAnimationPlayer().setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ return animation;
+ }
+
+ /**
+ * Sets up a {@link #mOpenCloseAnimation} for opening with a given duration.
+ *
+ * @see #setUpOpenCloseAnimation(float, float, long)
+ */
+ protected final AnimatorPlaybackController setUpOpenAnimation(long duration) {
+ return setUpOpenCloseAnimation(
+ TRANSLATION_SHIFT_CLOSED, TRANSLATION_SHIFT_OPENED, duration);
+ }
+
+ private AnimatorPlaybackController setUpCloseAnimation(long duration) {
+ return setUpOpenCloseAnimation(
+ TRANSLATION_SHIFT_OPENED, TRANSLATION_SHIFT_CLOSED, duration);
+ }
+
+ /**
+ * Initializes a new {@link #mOpenCloseAnimation}.
+ *
+ * @param fromTranslationShift translation shift to animate from.
+ * @param toTranslationShift translation shift to animate to.
+ * @param duration animation duration.
+ * @return {@link #mOpenCloseAnimation}
+ */
+ private AnimatorPlaybackController setUpOpenCloseAnimation(
+ float fromTranslationShift, float toTranslationShift, long duration) {
+ mFromTranslationShift = fromTranslationShift;
+ mToTranslationShift = toTranslationShift;
+
+ PendingAnimation animation = new PendingAnimation(duration);
+ animation.addEndListener(b -> {
+ mSwipeDetector.finishedScrolling();
+ announceAccessibilityChanges();
+ });
+
+ animation.addFloat(
+ this, TRANSLATION_SHIFT, fromTranslationShift, toTranslationShift, LINEAR);
+ onOpenCloseAnimationPending(animation);
+
+ mOpenCloseAnimation = animation.createPlaybackController();
+ return mOpenCloseAnimation;
+ }
+
+ /**
+ * Invoked when a {@link #mOpenCloseAnimation} is being set up.
+ * <p>
+ * Subclasses can override this method to modify the animation before it's used to create a
+ * {@link AnimatorPlaybackController}.
+ */
+ protected void onOpenCloseAnimationPending(PendingAnimation animation) {}
+
protected void attachToContainer() {
if (mColorScrim != null) {
getPopupContainer().addView(mColorScrim);
@@ -279,19 +366,28 @@
}
private boolean isOpeningAnimationRunning() {
- return mIsOpen && mOpenCloseAnimator.isRunning();
+ return mIsOpen && mOpenCloseAnimation.getAnimationPlayer().isRunning();
}
/* SingleAxisSwipeDetector.Listener */
@Override
- public void onDragStart(boolean start, float startDisplacement) { }
+ public void onDragStart(boolean start, float startDisplacement) {
+ if (mOpenCloseAnimation.getAnimationPlayer().isRunning()) {
+ mOpenCloseAnimation.pause();
+ mDragStartProgress = mOpenCloseAnimation.getProgressFraction();
+ } else {
+ setUpCloseAnimation(DEFAULT_DURATION);
+ mDragStartProgress = 0;
+ }
+ }
@Override
public boolean onDrag(float displacement) {
- float range = getShiftRange();
- displacement = Utilities.boundToRange(displacement, 0, range);
- setTranslationShift(displacement / range);
+ float progress = mDragStartProgress
+ + Math.signum(mToTranslationShift - mFromTranslationShift)
+ * (displacement / getShiftRange());
+ mOpenCloseAnimation.setPlayFraction(Utilities.boundToRange(progress, 0, 1));
return true;
}
@@ -302,16 +398,18 @@
if ((mSwipeDetector.isFling(velocity) && velocity > 0)
|| mTranslationShift > successfulShiftThreshold) {
mScrollInterpolator = scrollInterpolatorForVelocity(velocity);
- mOpenCloseAnimator.setDuration(BaseSwipeDetector.calculateDuration(
- velocity, TRANSLATION_SHIFT_CLOSED - mTranslationShift));
+ mScrollDuration = BaseSwipeDetector.calculateDuration(
+ velocity, TRANSLATION_SHIFT_CLOSED - mTranslationShift);
+ mScrollEndProgress = mToTranslationShift == TRANSLATION_SHIFT_OPENED ? 0 : 1;
close(true);
} else {
- mOpenCloseAnimator.setValues(PropertyValuesHolder.ofFloat(
- TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
- mOpenCloseAnimator.setDuration(
- BaseSwipeDetector.calculateDuration(velocity, mTranslationShift))
- .setInterpolator(Interpolators.DEACCEL);
- mOpenCloseAnimator.start();
+ ValueAnimator animator = mOpenCloseAnimation.getAnimationPlayer();
+ animator.setInterpolator(Interpolators.DECELERATE);
+ animator.setFloatValues(
+ mOpenCloseAnimation.getProgressFraction(),
+ mToTranslationShift == TRANSLATION_SHIFT_OPENED ? 1 : 0);
+ animator.setDuration(BaseSwipeDetector.calculateDuration(velocity, mTranslationShift))
+ .start();
}
}
@@ -332,32 +430,31 @@
Optional.ofNullable(mOnCloseBeginListener).ifPresent(OnCloseListener::onSlideInViewClosed);
if (!animate) {
- mOpenCloseAnimator.cancel();
+ mOpenCloseAnimation.pause();
setTranslationShift(TRANSLATION_SHIFT_CLOSED);
onCloseComplete();
return;
}
- mOpenCloseAnimator.setValues(
- PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_CLOSED));
- mOpenCloseAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mOpenCloseAnimator.removeListener(this);
- onCloseComplete();
- }
- });
+
+ final ValueAnimator animator;
if (mSwipeDetector.isIdleState()) {
- mOpenCloseAnimator
- .setDuration(defaultDuration)
- .setInterpolator(getIdleInterpolator());
+ setUpCloseAnimation(defaultDuration);
+ animator = mOpenCloseAnimation.getAnimationPlayer();
+ animator.setInterpolator(getIdleInterpolator());
} else {
- mOpenCloseAnimator.setInterpolator(mScrollInterpolator);
+ animator = mOpenCloseAnimation.getAnimationPlayer();
+ animator.setInterpolator(mScrollInterpolator);
+ animator.setDuration(mScrollDuration);
+ mOpenCloseAnimation.getAnimationPlayer().setFloatValues(
+ mOpenCloseAnimation.getProgressFraction(), mScrollEndProgress);
}
- mOpenCloseAnimator.start();
+
+ animator.addListener(AnimatorListeners.forEndCallback(this::onCloseComplete));
+ animator.start();
}
protected Interpolator getIdleInterpolator() {
- return Interpolators.ACCEL;
+ return Interpolators.ACCELERATE;
}
protected void onCloseComplete() {
diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java
index 4b319e5..04f2ffa 100644
--- a/src/com/android/launcher3/views/ActivityContext.java
+++ b/src/com/android/launcher3/views/ActivityContext.java
@@ -18,6 +18,7 @@
import static android.window.SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR;
import static com.android.launcher3.LauncherSettings.Animation.DEFAULT_NO_ICON;
+import static com.android.launcher3.Utilities.allowBGLaunch;
import static com.android.launcher3.logging.KeyboardStateManager.KeyboardState.HIDE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_KEYBOARD_CLOSED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_PENDING_INTENT;
@@ -38,7 +39,6 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
-import android.os.StrictMode;
import android.os.UserHandle;
import android.util.Log;
import android.view.Display;
@@ -239,6 +239,11 @@
};
}
+ /** Long-click callback used for All Apps items. */
+ default View.OnLongClickListener getAllAppsItemLongClickListener() {
+ return v -> false;
+ }
+
@Nullable
default PopupDataProvider getPopupDataProvider() {
return null;
@@ -268,13 +273,19 @@
final WindowInsetsController wic = root.getWindowInsetsController();
WindowInsets insets = root.getRootWindowInsets();
boolean isImeShown = insets != null && insets.isVisible(WindowInsets.Type.ime());
- if (wic != null && isImeShown) {
- StatsLogManager slm = getStatsLogManager();
- slm.keyboardStateManager().setKeyboardState(HIDE);
+ if (wic != null) {
+ // Only hide the keyboard if it is actually showing.
+ if (isImeShown) {
+ StatsLogManager slm = getStatsLogManager();
+ slm.keyboardStateManager().setKeyboardState(HIDE);
- // this method cannot be called cross threads
- wic.hide(WindowInsets.Type.ime());
- slm.logger().log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED);
+ // this method cannot be called cross threads
+ wic.hide(WindowInsets.Type.ime());
+ slm.logger().log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED);
+ }
+
+ // If the WindowInsetsController is not null, we end here regardless of whether we
+ // hid the keyboard or not.
return;
}
}
@@ -338,6 +349,12 @@
return null;
}
+ boolean isShortcut = (item instanceof WorkspaceItemInfo)
+ && item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
+ && !((WorkspaceItemInfo) item).isPromise();
+ if (isShortcut && GO_DISABLE_WIDGETS) {
+ return null;
+ }
ActivityOptionsWrapper options = v != null ? getActivityLaunchOptions(v, item)
: makeDefaultActivityOptions(item != null && item.animationType == DEFAULT_NO_ICON
? SPLASH_SCREEN_STYLE_SOLID_COLOR : -1 /* SPLASH_SCREEN_STYLE_UNDEFINED */);
@@ -349,13 +366,11 @@
intent.setSourceBounds(Utilities.getViewBounds(v));
}
try {
- boolean isShortcut = (item instanceof WorkspaceItemInfo)
- && (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
- || item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)
- && !((WorkspaceItemInfo) item).isPromise();
if (isShortcut) {
- // Shortcuts need some special checks due to legacy reasons.
- startShortcutIntentSafely(intent, optsBundle, item);
+ String id = ((WorkspaceItemInfo) item).getDeepShortcutId();
+ String packageName = intent.getPackage();
+ ((Context) this).getSystemService(LauncherApps.class).startShortcut(
+ packageName, id, intent.getSourceBounds(), optsBundle, user);
} else if (user == null || user.equals(Process.myUserHandle())) {
// Could be launching some bookkeeping activity
context.startActivity(intent, optsBundle);
@@ -410,8 +425,7 @@
}
}
ActivityOptions options =
- ActivityOptions.makeClipRevealAnimation(v, left, top, width, height);
-
+ allowBGLaunch(ActivityOptions.makeClipRevealAnimation(v, left, top, width, height));
options.setLaunchDisplayId(
(v != null && v.getDisplay() != null) ? v.getDisplay().getDisplayId()
: Display.DEFAULT_DISPLAY);
@@ -423,66 +437,27 @@
* Creates a default activity option and we do not want association with any launcher element.
*/
default ActivityOptionsWrapper makeDefaultActivityOptions(int splashScreenStyle) {
- ActivityOptions options = ActivityOptions.makeBasic();
+ ActivityOptions options = allowBGLaunch(ActivityOptions.makeBasic());
if (Utilities.ATLEAST_T) {
options.setSplashScreenStyle(splashScreenStyle);
}
return new ActivityOptionsWrapper(options, new RunnableList());
}
- /**
- * Safely launches an intent for a shortcut.
- *
- * @param intent Intent to start.
- * @param optsBundle Optional launch arguments.
- * @param info Shortcut information.
- */
- default void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info) {
- try {
- StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
- try {
- // Temporarily disable deathPenalty on all default checks. For eg, shortcuts
- // containing file Uri's would cause a crash as penaltyDeathOnFileUriExposure
- // is enabled by default on NYC.
- StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll()
- .penaltyLog().build());
-
- if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
- String id = ((WorkspaceItemInfo) info).getDeepShortcutId();
- String packageName = intent.getPackage();
- startShortcut(packageName, id, intent.getSourceBounds(), optsBundle, info.user);
- } else {
- // Could be launching some bookkeeping activity
- ((Context) this).startActivity(intent, optsBundle);
- }
- } finally {
- StrictMode.setVmPolicy(oldPolicy);
- }
- } catch (SecurityException e) {
- throw e;
- }
- }
-
- /**
- * A wrapper around the platform method with Launcher specific checks.
- */
- default void startShortcut(String packageName, String id, Rect sourceBounds,
- Bundle startActivityOptions, UserHandle user) {
- if (GO_DISABLE_WIDGETS) {
- return;
- }
- try {
- ((Context) this).getSystemService(LauncherApps.class).startShortcut(packageName, id,
- sourceBounds, startActivityOptions, user);
- } catch (SecurityException | IllegalStateException e) {
- Log.e(TAG, "Failed to start shortcut", e);
- }
- }
-
default CellPosMapper getCellPosMapper() {
return CellPosMapper.DEFAULT;
}
+ /** Whether bubbles are enabled. */
+ default boolean isBubbleBarEnabled() {
+ return false;
+ }
+
+ /** Whether the bubble bar has bubbles. */
+ default boolean hasBubbles() {
+ return false;
+ }
+
/**
* Returns the ActivityContext associated with the given Context, or throws an exception if
* the Context is not associated with any ActivityContext.
diff --git a/src/com/android/launcher3/views/ArrowTipView.java b/src/com/android/launcher3/views/ArrowTipView.java
index 73c5ad4..2f0da03 100644
--- a/src/com/android/launcher3/views/ArrowTipView.java
+++ b/src/com/android/launcher3/views/ArrowTipView.java
@@ -16,14 +16,21 @@
package com.android.launcher3.views;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Configuration;
+import android.content.res.TypedArray;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.ShapeDrawable;
import android.os.Handler;
+import android.util.IntProperty;
import android.util.Log;
+import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
@@ -33,18 +40,17 @@
import androidx.annotation.Nullable;
import androidx.annotation.Px;
-import androidx.core.content.ContextCompat;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
-import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.graphics.TriangleShape;
/**
- * A base class for arrow tip view in launcher
+ * A base class for arrow tip view in launcher.
*/
public class ArrowTipView extends AbstractFloatingView {
@@ -54,33 +60,66 @@
private static final long SHOW_DURATION_MS = 300;
private static final long HIDE_DURATION_MS = 100;
- protected final BaseDraggingActivity mActivity;
+ public static final IntProperty<ArrowTipView> TEXT_ALPHA =
+ new IntProperty<>("textAlpha") {
+ @Override
+ public void setValue(ArrowTipView view, int v) {
+ view.setTextAlpha(v);
+ }
+
+ @Override
+ public Integer get(ArrowTipView view) {
+ return view.getTextAlpha();
+ }
+ };
+
+ private final ActivityContext mActivityContext;
private final Handler mHandler = new Handler();
- private final int mArrowWidth;
- private final int mArrowMinOffset;
private boolean mIsPointingUp;
private Runnable mOnClosed;
private View mArrowView;
+ private final int mArrowWidth;
+ private final int mArrowMinOffset;
+ private final int mArrowViewPaintColor;
+
+ private AnimatorSet mOpenAnimator = new AnimatorSet();
+ private AnimatorSet mCloseAnimator = new AnimatorSet();
+
+ private int mTextAlpha;
public ArrowTipView(Context context) {
this(context, false);
}
public ArrowTipView(Context context, boolean isPointingUp) {
+ this(context, isPointingUp, R.layout.arrow_toast);
+ }
+
+ public ArrowTipView(Context context, boolean isPointingUp, int layoutId) {
super(context, null, 0);
- mActivity = BaseDraggingActivity.fromContext(context);
+ mActivityContext = ActivityContext.lookupContext(context);
mIsPointingUp = isPointingUp;
- mArrowWidth = context.getResources().getDimensionPixelSize(R.dimen.arrow_toast_arrow_width);
+ mArrowWidth = context.getResources().getDimensionPixelSize(
+ R.dimen.arrow_toast_arrow_width);
mArrowMinOffset = context.getResources().getDimensionPixelSize(
R.dimen.dynamic_grid_cell_border_spacing);
- init(context);
+ TypedArray ta = context.obtainStyledAttributes(R.styleable.ArrowTipView);
+ // Set style to default to avoid inflation issues with missing attributes.
+ if (!ta.hasValue(R.styleable.ArrowTipView_arrowTipBackground)
+ || !ta.hasValue(R.styleable.ArrowTipView_arrowTipTextColor)) {
+ context = new ContextThemeWrapper(context, R.style.ArrowTipStyle);
+ }
+ mArrowViewPaintColor = ta.getColor(R.styleable.ArrowTipView_arrowTipBackground,
+ context.getColor(R.color.arrow_tip_view_bg));
+ ta.recycle();
+ init(context, layoutId);
}
@Override
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
close(true);
- if (mActivity.getDragLayer().isEventOverView(this, ev)) {
+ if (mActivityContext.getDragLayer().isEventOverView(this, ev)) {
return true;
}
}
@@ -89,18 +128,17 @@
@Override
protected void handleClose(boolean animate) {
+ if (mOpenAnimator.isStarted()) {
+ mOpenAnimator.cancel();
+ }
if (mIsOpen) {
if (animate) {
- animate().alpha(0f)
- .withLayer()
- .setStartDelay(0)
- .setDuration(HIDE_DURATION_MS)
- .setInterpolator(Interpolators.ACCEL)
- .withEndAction(() -> mActivity.getDragLayer().removeView(this))
- .start();
+ mCloseAnimator.addListener(AnimatorListeners.forSuccessCallback(
+ () -> mActivityContext.getDragLayer().removeView(this)));
+ mCloseAnimator.start();
} else {
- animate().cancel();
- mActivity.getDragLayer().removeView(this);
+ mCloseAnimator.cancel();
+ mActivityContext.getDragLayer().removeView(this);
}
if (mOnClosed != null) mOnClosed.run();
mIsOpen = false;
@@ -112,12 +150,31 @@
return (type & TYPE_ON_BOARD_POPUP) != 0;
}
- private void init(Context context) {
- inflate(context, R.layout.arrow_toast, this);
+ private void init(Context context, int layoutId) {
+ inflate(context, layoutId, this);
setOrientation(LinearLayout.VERTICAL);
mArrowView = findViewById(R.id.arrow);
- updateArrowTipInView();
+ updateArrowTipInView(mIsPointingUp);
+ setAlpha(0);
+
+ // Create default open animator.
+ mOpenAnimator.play(ObjectAnimator.ofFloat(this, ALPHA, 1f));
+ mOpenAnimator.setStartDelay(SHOW_DELAY_MS);
+ mOpenAnimator.setDuration(SHOW_DURATION_MS);
+ mOpenAnimator.setInterpolator(Interpolators.DECELERATE);
+
+ // Create default close animator.
+ mCloseAnimator.play(ObjectAnimator.ofFloat(this, ALPHA, 0));
+ mCloseAnimator.setStartDelay(0);
+ mCloseAnimator.setDuration(HIDE_DURATION_MS);
+ mCloseAnimator.setInterpolator(Interpolators.ACCELERATE);
+ mCloseAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mActivityContext.getDragLayer().removeView(ArrowTipView.this);
+ }
+ });
}
/**
@@ -153,10 +210,10 @@
public ArrowTipView show(
String text, int gravity, int arrowMarginStart, int top, boolean shouldAutoClose) {
((TextView) findViewById(R.id.text)).setText(text);
- ViewGroup parent = mActivity.getDragLayer();
+ ViewGroup parent = mActivityContext.getDragLayer();
parent.addView(this);
- DeviceProfile grid = mActivity.getDeviceProfile();
+ DeviceProfile grid = mActivityContext.getDeviceProfile();
DragLayer.LayoutParams params = (DragLayer.LayoutParams) getLayoutParams();
params.gravity = gravity;
@@ -185,14 +242,8 @@
if (shouldAutoClose) {
mHandler.postDelayed(() -> handleClose(true), AUTO_CLOSE_TIMEOUT_MILLIS);
}
- setAlpha(0);
- animate()
- .alpha(1f)
- .withLayer()
- .setStartDelay(SHOW_DELAY_MS)
- .setDuration(SHOW_DURATION_MS)
- .setInterpolator(Interpolators.DEACCEL)
- .start();
+
+ mOpenAnimator.start();
return this;
}
@@ -273,7 +324,7 @@
*/
@Nullable private ArrowTipView showAtLocation(String text, @Px int arrowXCoord,
@Px int yCoordDownPointingTip, @Px int yCoordUpPointingTip, boolean shouldAutoClose) {
- ViewGroup parent = mActivity.getDragLayer();
+ ViewGroup parent = mActivityContext.getDragLayer();
@Px int parentViewWidth = parent.getWidth();
@Px int parentViewHeight = parent.getHeight();
@Px int maxTextViewWidth = getContext().getResources()
@@ -288,8 +339,10 @@
TextView textView = findViewById(R.id.text);
textView.setText(text);
textView.setMaxWidth(maxTextViewWidth);
- parent.addView(this);
- requestLayout();
+ if (parent.indexOfChild(this) < 0) {
+ parent.addView(this);
+ requestLayout();
+ }
post(() -> {
// Adjust the tooltip horizontally.
@@ -311,17 +364,18 @@
// Adjust the tooltip vertically.
@Px int viewHeight = getHeight();
+ boolean isPointingUp = mIsPointingUp;
if (mIsPointingUp
? (yCoordUpPointingTip + viewHeight > parentViewHeight)
: (yCoordDownPointingTip - viewHeight < 0)) {
// Flip the view if it exceeds the vertical bounds of screen.
- mIsPointingUp = !mIsPointingUp;
- updateArrowTipInView();
+ isPointingUp = !mIsPointingUp;
}
+ updateArrowTipInView(isPointingUp);
// Place the tooltip such that its top is at yCoordUpPointingTip if arrow is displayed
// pointing upwards, otherwise place it such that its bottom is at
// yCoordDownPointingTip.
- setY(mIsPointingUp ? yCoordUpPointingTip : yCoordDownPointingTip - viewHeight);
+ setY(isPointingUp ? yCoordUpPointingTip : yCoordDownPointingTip - viewHeight);
// Adjust the arrow's relative position on tooltip to make sure the actual position of
// arrow's pointed tip is always at arrowXCoord.
@@ -333,30 +387,24 @@
if (shouldAutoClose) {
mHandler.postDelayed(() -> handleClose(true), AUTO_CLOSE_TIMEOUT_MILLIS);
}
- setAlpha(0);
- animate()
- .alpha(1f)
- .withLayer()
- .setStartDelay(SHOW_DELAY_MS)
- .setDuration(SHOW_DURATION_MS)
- .setInterpolator(Interpolators.DEACCEL)
- .start();
+
+ mOpenAnimator.start();
return this;
}
- private void updateArrowTipInView() {
+ private void updateArrowTipInView(boolean isPointingUp) {
ViewGroup.LayoutParams arrowLp = mArrowView.getLayoutParams();
ShapeDrawable arrowDrawable = new ShapeDrawable(TriangleShape.create(
- arrowLp.width, arrowLp.height, mIsPointingUp));
+ arrowLp.width, arrowLp.height, isPointingUp));
Paint arrowPaint = arrowDrawable.getPaint();
@Px int arrowTipRadius = getContext().getResources()
.getDimensionPixelSize(R.dimen.arrow_toast_corner_radius);
- arrowPaint.setColor(ContextCompat.getColor(getContext(), R.color.arrow_tip_view_bg));
+ arrowPaint.setColor(mArrowViewPaintColor);
arrowPaint.setPathEffect(new CornerPathEffect(arrowTipRadius));
mArrowView.setBackground(arrowDrawable);
// Add negative margin so that the rounded corners on base of arrow are not visible.
removeView(mArrowView);
- if (mIsPointingUp) {
+ if (isPointingUp) {
addView(mArrowView, 0);
((ViewGroup.MarginLayoutParams) arrowLp).setMargins(0, 0, 0, -1 * arrowTipRadius);
} else {
@@ -378,4 +426,30 @@
super.onConfigurationChanged(newConfig);
close(/* animate= */ false);
}
+
+ /**
+ * Sets a custom animation to run on open of the ArrowTipView.
+ */
+ public void setCustomOpenAnimation(AnimatorSet animator) {
+ mOpenAnimator = animator;
+ }
+
+ /**
+ * Sets a custom animation to run on close of the ArrowTipView.
+ */
+ public void setCustomCloseAnimation(AnimatorSet animator) {
+ mCloseAnimator = animator;
+ }
+
+ private void setTextAlpha(int textAlpha) {
+ if (mTextAlpha != textAlpha) {
+ mTextAlpha = textAlpha;
+ TextView textView = findViewById(R.id.text);
+ textView.setTextColor(textView.getTextColors().withAlpha(mTextAlpha));
+ }
+ }
+
+ private int getTextAlpha() {
+ return mTextAlpha;
+ }
}
diff --git a/src/com/android/launcher3/views/ClipIconView.java b/src/com/android/launcher3/views/ClipIconView.java
index 694dead..87e496e 100644
--- a/src/com/android/launcher3/views/ClipIconView.java
+++ b/src/com/android/launcher3/views/ClipIconView.java
@@ -15,9 +15,9 @@
*/
package com.android.launcher3.views;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.Utilities.boundToRange;
import static com.android.launcher3.Utilities.mapToRange;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import static java.lang.Math.max;
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 6b5c8df..32c70a3 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -17,10 +17,9 @@
import static android.view.Gravity.LEFT;
-import static com.android.launcher3.Utilities.getBadge;
+import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.Utilities.getFullDrawable;
import static com.android.launcher3.Utilities.mapToRange;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.views.IconLabelDotView.setIconAndDotVisible;
@@ -36,6 +35,7 @@
import android.os.CancellationSignal;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
@@ -288,26 +288,20 @@
} else {
int width = (int) pos.width();
int height = (int) pos.height();
- Object[] tmpObjArray = new Object[1];
+ Pair<AdaptiveIconDrawable, Drawable> fullIcon = null;
if (supportsAdaptiveIcons) {
- boolean shouldThemeIcon = btvIcon instanceof FastBitmapDrawable
- && ((FastBitmapDrawable) btvIcon).isThemed();
- drawable = getFullDrawable(l, info, width, height, shouldThemeIcon, tmpObjArray);
- if (drawable instanceof AdaptiveIconDrawable) {
- badge = getBadge(l, info, tmpObjArray[0]);
- } else {
- // The drawable we get back is not an adaptive icon, so we need to use the
- // BubbleTextView icon that is already legacy treated.
- drawable = btvIcon;
- }
+ boolean shouldThemeIcon = (btvIcon instanceof FastBitmapDrawable fbd)
+ && fbd.isCreatedForTheme();
+ fullIcon = getFullDrawable(l, info, width, height, shouldThemeIcon);
+ } else if (!(originalView instanceof BubbleTextView)) {
+ fullIcon = getFullDrawable(l, info, width, height, true /* shouldThemeIcon */);
+ }
+
+ if (fullIcon != null) {
+ drawable = fullIcon.first;
+ badge = fullIcon.second;
} else {
- if (originalView instanceof BubbleTextView) {
- // Similar to DragView, we simply use the BubbleTextView icon here.
- drawable = btvIcon;
- } else {
- drawable = getFullDrawable(l, info, width, height, true /* shouldThemeIcon */,
- tmpObjArray);
- }
+ drawable = btvIcon;
}
}
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index 4641e31..cf59085 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -18,7 +18,6 @@
import static androidx.core.content.ContextCompat.getColorStateList;
import static com.android.launcher3.LauncherState.EDIT_MODE;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP;
import static com.android.launcher3.config.FeatureFlags.MULTI_SELECT_EDIT_MODE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SETTINGS_BUTTON_TAP_OR_LONGPRESS;
@@ -26,7 +25,6 @@
import android.content.Context;
import android.content.Intent;
-import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
@@ -55,7 +53,6 @@
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;
@@ -63,8 +60,10 @@
/**
* Popup shown on long pressing an empty space in launcher
+ *
+ * @param <T> The context showing this popup.
*/
-public class OptionsPopupView extends ArrowPopup<Launcher>
+public class OptionsPopupView<T extends Context & ActivityContext> extends ArrowPopup<T>
implements OnClickListener, OnLongClickListener {
// An intent extra to indicate the horizontal scroll of the wallpaper.
@@ -148,29 +147,31 @@
@Override
public void assignMarginsAndBackgrounds(ViewGroup viewGroup) {
- if (ENABLE_MATERIAL_U_POPUP.get()) {
- assignMarginsAndBackgrounds(viewGroup,
- getColorStateList(getContext(), mColorIds[0]).getDefaultColor());
- } else {
- assignMarginsAndBackgrounds(viewGroup, Color.TRANSPARENT);
- }
+ assignMarginsAndBackgrounds(viewGroup,
+ getColorStateList(getContext(), mColorIds[0]).getDefaultColor());
}
- public static OptionsPopupView show(ActivityContext launcher, RectF targetRect,
- List<OptionItem> items, boolean shouldAddArrow) {
- return show(launcher, targetRect, items, shouldAddArrow, 0 /* width */);
+ public static <T extends Context & ActivityContext> OptionsPopupView<T> show(
+ ActivityContext activityContext,
+ RectF targetRect,
+ List<OptionItem> items,
+ boolean shouldAddArrow) {
+ return show(activityContext, targetRect, items, shouldAddArrow, 0 /* width */);
}
- public static OptionsPopupView show(ActivityContext launcher, RectF targetRect,
- List<OptionItem> items, boolean shouldAddArrow, int width) {
- OptionsPopupView popup = (OptionsPopupView) launcher.getLayoutInflater()
- .inflate(R.layout.longpress_options_menu, launcher.getDragLayer(), false);
+ public static <T extends Context & ActivityContext> OptionsPopupView<T> show(
+ ActivityContext activityContext,
+ RectF targetRect,
+ List<OptionItem> items,
+ boolean shouldAddArrow,
+ int width) {
+ OptionsPopupView<T> popup = (OptionsPopupView<T>) activityContext.getLayoutInflater()
+ .inflate(R.layout.longpress_options_menu, activityContext.getDragLayer(), false);
popup.mTargetRect = targetRect;
popup.setShouldAddArrow(shouldAddArrow);
for (OptionItem item : items) {
- DeepShortcutView view =
- (DeepShortcutView) popup.inflateAndAdd(R.layout.system_shortcut, popup);
+ DeepShortcutView view = popup.inflateAndAdd(R.layout.system_shortcut, popup);
if (width > 0) {
view.getLayoutParams().width = width;
}
@@ -190,14 +191,9 @@
*/
public static ArrayList<OptionItem> getOptions(Launcher launcher) {
ArrayList<OptionItem> options = new ArrayList<>();
- 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,
+ R.string.styles_wallpaper_button_text,
+ R.drawable.ic_palette,
IGNORE,
OptionsPopupView::startWallpaperPicker));
if (!WidgetsModel.GO_DISABLE_WIDGETS) {
@@ -274,12 +270,8 @@
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
.putExtra(EXTRA_WALLPAPER_OFFSET,
launcher.getWorkspace().getWallpaperOffsetForCenterPage())
- .putExtra(EXTRA_WALLPAPER_LAUNCH_SOURCE, "app_launched_launcher");
- if (!styleWallpapersExists(launcher)) {
- intent.putExtra(EXTRA_WALLPAPER_FLAVOR, "wallpaper_only");
- } else {
- intent.putExtra(EXTRA_WALLPAPER_FLAVOR, "focus_wallpaper");
- }
+ .putExtra(EXTRA_WALLPAPER_LAUNCH_SOURCE, "app_launched_launcher")
+ .putExtra(EXTRA_WALLPAPER_FLAVOR, "focus_wallpaper");
String pickerPackage = launcher.getString(R.string.wallpaper_picker_package);
if (!TextUtils.isEmpty(pickerPackage)) {
intent.setPackage(pickerPackage);
@@ -290,7 +282,6 @@
static WorkspaceItemInfo placeholderInfo(Intent intent) {
WorkspaceItemInfo placeholderInfo = new WorkspaceItemInfo();
placeholderInfo.intent = intent;
- placeholderInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
placeholderInfo.container = LauncherSettings.Favorites.CONTAINER_SETTINGS;
return placeholderInfo;
}
@@ -323,9 +314,4 @@
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/views/Snackbar.java b/src/com/android/launcher3/views/Snackbar.java
index 2460be1..99040ff 100644
--- a/src/com/android/launcher3/views/Snackbar.java
+++ b/src/com/android/launcher3/views/Snackbar.java
@@ -30,10 +30,10 @@
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.dragndrop.DragLayer;
@@ -175,7 +175,7 @@
.scaleX(1)
.scaleY(1)
.setDuration(SHOW_DURATION_MS)
- .setInterpolator(Interpolators.ACCEL_DEACCEL)
+ .setInterpolator(Interpolators.ACCELERATE_DECELERATE)
.start();
int timeout = AccessibilityManagerCompat.getRecommendedTimeoutMillis(activity,
TIMEOUT_DURATION_MS, FLAG_CONTENT_TEXT | FLAG_CONTENT_CONTROLS);
@@ -190,7 +190,7 @@
.withLayer()
.setStartDelay(0)
.setDuration(HIDE_DURATION_MS)
- .setInterpolator(Interpolators.ACCEL)
+ .setInterpolator(Interpolators.ACCELERATE)
.withEndAction(this::onClosed)
.start();
} else {
diff --git a/src/com/android/launcher3/views/WidgetsEduView.java b/src/com/android/launcher3/views/WidgetsEduView.java
index c2947c7..e70b1cb 100644
--- a/src/com/android/launcher3/views/WidgetsEduView.java
+++ b/src/com/android/launcher3/views/WidgetsEduView.java
@@ -15,9 +15,6 @@
*/
package com.android.launcher3.views;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-
-import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
@@ -119,14 +116,11 @@
}
private void animateOpen() {
- if (mIsOpen || mOpenCloseAnimator.isRunning()) {
+ if (mIsOpen || mOpenCloseAnimation.getAnimationPlayer().isRunning()) {
return;
}
mIsOpen = true;
- mOpenCloseAnimator.setValues(
- PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
- mOpenCloseAnimator.setInterpolator(FAST_OUT_SLOW_IN);
- mOpenCloseAnimator.start();
+ setUpDefaultOpenAnimation().start();
}
/** Shows widget education dialog. */
diff --git a/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java b/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java
index 9442734..80b1cdd 100644
--- a/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java
@@ -17,9 +17,7 @@
package com.android.launcher3.widget;
import static com.android.launcher3.Utilities.ATLEAST_R;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import android.animation.PropertyValuesHolder;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Insets;
@@ -130,14 +128,11 @@
}
private void animateOpen() {
- if (mIsOpen || mOpenCloseAnimator.isRunning()) {
+ if (mIsOpen || mOpenCloseAnimation.getAnimationPlayer().isRunning()) {
return;
}
mIsOpen = true;
- mOpenCloseAnimator.setValues(
- PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
- mOpenCloseAnimator.setInterpolator(FAST_OUT_SLOW_IN);
- mOpenCloseAnimator.start();
+ setUpDefaultOpenAnimation().start();
}
@Override
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 049131e..dcc86a1 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -15,7 +15,7 @@
*/
package com.android.launcher3.widget;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
import static com.android.launcher3.config.FeatureFlags.LARGE_SCREEN_WIDGET_PICKER;
import android.content.Context;
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index bc3889f..1aa49c7 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -23,9 +23,11 @@
import android.graphics.Rect;
import android.os.Build;
import android.os.Handler;
+import android.os.Parcelable;
import android.os.SystemClock;
import android.os.Trace;
import android.util.Log;
+import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.view.MotionEvent;
@@ -37,6 +39,7 @@
import android.widget.Advanceable;
import android.widget.RemoteViews;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.CheckLongPressHelper;
@@ -63,6 +66,8 @@
private static final long ADVANCE_INTERVAL = 20000;
private static final long ADVANCE_STAGGER = 250;
+ private @Nullable CellChildViewPreLayoutListener mCellChildViewPreLayoutListener;
+
// Maintains a list of widget ids which are supposed to be auto advanced.
private static final SparseBooleanArray sAutoAdvanceWidgetIds = new SparseBooleanArray();
// Maximum duration for which updates can be deferred.
@@ -95,6 +100,8 @@
private boolean mTrackingWidgetUpdate = false;
+ private boolean mIsWidgetCachingDisabled = false;
+
public LauncherAppWidgetHostView(Context context) {
super(context);
mLauncher = Launcher.getLauncher(context);
@@ -105,7 +112,7 @@
if (Utilities.ATLEAST_Q && Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText)) {
setOnLightBackground(true);
}
- mColorExtractor = LocalColorExtractor.newInstance(getContext());
+ mColorExtractor = new LocalColorExtractor(); // no-op
}
@Override
@@ -138,6 +145,10 @@
}
}
+ public void setIsWidgetCachingDisabled(boolean isWidgetCachingDisabled) {
+ mIsWidgetCachingDisabled = isWidgetCachingDisabled;
+ }
+
@Override
@TargetApi(Build.VERSION_CODES.Q)
public void updateAppWidget(RemoteViews remoteViews) {
@@ -147,7 +158,8 @@
TRACE_METHOD_NAME + getAppWidgetInfo().provider, getAppWidgetId());
mTrackingWidgetUpdate = false;
}
- if (FeatureFlags.ENABLE_CACHED_WIDGET.get()) {
+ if (FeatureFlags.ENABLE_CACHED_WIDGET.get()
+ && !mIsWidgetCachingDisabled) {
mLastRemoteViews = remoteViews;
if (isDeferringUpdates()) {
return;
@@ -328,6 +340,26 @@
requestLayout();
}
+ /**
+ * Set the pre-layout listener
+ * @param listener The listener to be notified when {@code CellLayout} is to layout this view
+ */
+ public void setCellChildViewPreLayoutListener(
+ @NonNull CellChildViewPreLayoutListener listener) {
+ mCellChildViewPreLayoutListener = listener;
+ }
+
+ /** @return The current cell layout listener */
+ @Nullable
+ public CellChildViewPreLayoutListener getCellChildViewPreLayoutListener() {
+ return mCellChildViewPreLayoutListener;
+ }
+
+ /** Clear the listener for the pre-layout in CellLayout */
+ public void clearCellChildViewPreLayoutListener() {
+ mCellChildViewPreLayoutListener = null;
+ }
+
@Override
public void onColorsChanged(SparseIntArray colors) {
if (isDeferringUpdates()) {
@@ -453,4 +485,28 @@
}
return false;
}
+
+ /**
+ * Listener interface to be called when {@code CellLayout} is about to layout this child view
+ */
+ public interface CellChildViewPreLayoutListener {
+ /**
+ * Notify the bound changes to this view on pre-layout
+ * @param v The view which the listener is set for
+ * @param left The new left coordinate of this view
+ * @param top The new top coordinate of this view
+ * @param right The new right coordinate of this view
+ * @param bottom The new bottom coordinate of this view
+ */
+ void notifyBoundChangeOnPreLayout(View v, int left, int top, int right, int bottom);
+ }
+
+ @Override
+ protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
+ try {
+ super.dispatchRestoreInstanceState(container);
+ } catch (Exception e) {
+ Log.i(TAG, "Exception: " + e);
+ }
+ }
}
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
index 10aef9a..ef51d15 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
@@ -67,7 +67,7 @@
*/
public int maxSpanY;
- private boolean mIsMinSizeFulfilled;
+ protected boolean mIsMinSizeFulfilled;
public static LauncherAppWidgetProviderInfo fromProviderInfo(Context context,
AppWidgetProviderInfo info) {
diff --git a/src/com/android/launcher3/widget/LauncherWidgetHolder.java b/src/com/android/launcher3/widget/LauncherWidgetHolder.java
index 2ca825c..6acc83d 100644
--- a/src/com/android/launcher3/widget/LauncherWidgetHolder.java
+++ b/src/com/android/launcher3/widget/LauncherWidgetHolder.java
@@ -275,9 +275,15 @@
protected Bundle getConfigurationActivityOptions(@NonNull BaseDraggingActivity activity,
int widgetId) {
LauncherAppWidgetHostView view = mViews.get(widgetId);
- if (view == null) return null;
+ if (view == null) {
+ return activity.makeDefaultActivityOptions(
+ -1 /* SPLASH_SCREEN_STYLE_UNDEFINED */).toBundle();
+ }
Object tag = view.getTag();
- if (!(tag instanceof ItemInfo)) return null;
+ if (!(tag instanceof ItemInfo)) {
+ return activity.makeDefaultActivityOptions(
+ -1 /* SPLASH_SCREEN_STYLE_UNDEFINED */).toBundle();
+ }
Bundle bundle = activity.getActivityLaunchOptions(view, (ItemInfo) tag).toBundle();
bundle.putInt(KEY_SPLASH_SCREEN_STYLE, SPLASH_SCREEN_STYLE_EMPTY);
return bundle;
diff --git a/src/com/android/launcher3/widget/WidgetManagerHelper.java b/src/com/android/launcher3/widget/WidgetManagerHelper.java
index 737cdbd..0860e72 100644
--- a/src/com/android/launcher3/widget/WidgetManagerHelper.java
+++ b/src/com/android/launcher3/widget/WidgetManagerHelper.java
@@ -57,10 +57,15 @@
/**
* @see AppWidgetManager#getAppWidgetInfo(int)
*/
- public LauncherAppWidgetProviderInfo getLauncherAppWidgetInfo(int appWidgetId) {
- if (appWidgetId <= LauncherAppWidgetInfo.CUSTOM_WIDGET_ID) {
- return CustomWidgetManager.INSTANCE.get(mContext).getWidgetProvider(appWidgetId);
+ public LauncherAppWidgetProviderInfo getLauncherAppWidgetInfo(
+ int appWidgetId, ComponentName componentName) {
+
+ // For custom widgets.
+ if (appWidgetId <= LauncherAppWidgetInfo.CUSTOM_WIDGET_ID && !CustomWidgetManager
+ .INSTANCE.get(mContext).getWidgetIdForCustomProvider(componentName).equals("")) {
+ return CustomWidgetManager.INSTANCE.get(mContext).getWidgetProvider(componentName);
}
+
AppWidgetProviderInfo info = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
return info == null ? null : LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
}
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 846dafd..c347939 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -17,9 +17,7 @@
package com.android.launcher3.widget;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_BOTTOM_WIDGETS_TRAY;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
@@ -226,15 +224,12 @@
}
private void animateOpen() {
- if (mIsOpen || mOpenCloseAnimator.isRunning()) {
+ if (mIsOpen || mOpenCloseAnimation.getAnimationPlayer().isRunning()) {
return;
}
mIsOpen = true;
setupNavBarColor();
- mOpenCloseAnimator.setValues(
- PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
- mOpenCloseAnimator.setInterpolator(FAST_OUT_SLOW_IN);
- mOpenCloseAnimator.start();
+ setUpDefaultOpenAnimation().start();
}
@Override
diff --git a/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java
index 8b3bbce..44571a6 100644
--- a/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java
@@ -33,14 +33,15 @@
public class CustomAppWidgetProviderInfo extends LauncherAppWidgetProviderInfo
implements Parcelable {
- public final int providerId;
+ public final String providerId;
- protected CustomAppWidgetProviderInfo(Parcel parcel, boolean readSelf, int providerId) {
+ protected CustomAppWidgetProviderInfo(Parcel parcel, boolean readSelf, String providerId) {
super(parcel);
if (readSelf) {
- this.providerId = parcel.readInt();
+ this.providerId = parcel.readString();
- provider = new ComponentName(parcel.readString(), CLS_CUSTOM_WIDGET_PREFIX + providerId);
+ provider = new ComponentName(parcel.readString(),
+ CLS_CUSTOM_WIDGET_PREFIX + parcel.readString());
label = parcel.readString();
initialLayout = parcel.readInt();
@@ -58,7 +59,10 @@
}
@Override
- public void initSpans(Context context, InvariantDeviceProfile idp) { }
+ public void initSpans(Context context, InvariantDeviceProfile idp) {
+ mIsMinSizeFulfilled = Math.min(spanX, minSpanX) <= idp.numColumns
+ && Math.min(spanY, minSpanY) <= idp.numRows;
+ }
@Override
public String getLabel(PackageManager packageManager) {
@@ -73,8 +77,9 @@
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
- out.writeInt(providerId);
+ out.writeString(providerId);
out.writeString(provider.getPackageName());
+ out.writeString(provider.getClassName());
out.writeString(label);
out.writeInt(initialLayout);
@@ -93,7 +98,7 @@
@Override
public CustomAppWidgetProviderInfo createFromParcel(Parcel parcel) {
- return new CustomAppWidgetProviderInfo(parcel, true, 0);
+ return new CustomAppWidgetProviderInfo(parcel, true, "");
}
@Override
diff --git a/src/com/android/launcher3/widget/custom/CustomWidgetManager.java b/src/com/android/launcher3/widget/custom/CustomWidgetManager.java
index 2e2a968..7cf0221 100644
--- a/src/com/android/launcher3/widget/custom/CustomWidgetManager.java
+++ b/src/com/android/launcher3/widget/custom/CustomWidgetManager.java
@@ -16,7 +16,8 @@
package com.android.launcher3.widget.custom;
-import static com.android.launcher3.widget.LauncherAppWidgetProviderInfo.CLS_CUSTOM_WIDGET_PREFIX;
+import static com.android.launcher3.config.FeatureFlags.SMARTSPACE_AS_A_WIDGET;
+import static com.android.launcher3.model.data.LauncherAppWidgetInfo.CUSTOM_WIDGET_ID;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
@@ -24,12 +25,12 @@
import android.content.Context;
import android.os.Parcel;
import android.os.Process;
-import android.util.SparseArray;
+import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.model.data.LauncherAppWidgetInfo;
+import com.android.launcher3.R;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.PackageUserKey;
@@ -39,8 +40,11 @@
import com.android.systemui.plugins.CustomWidgetPlugin;
import com.android.systemui.plugins.PluginListener;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;
@@ -52,24 +56,37 @@
public static final MainThreadInitializedObject<CustomWidgetManager> INSTANCE =
new MainThreadInitializedObject<>(CustomWidgetManager::new);
+ private static final String TAG = "CustomWidgetManager";
private final Context mContext;
- /**
- * auto provider Id is an ever-increasing number that serves as the providerId whenever a new
- * custom widget has been connected.
- */
- private int mAutoProviderId = 0;
- private final SparseArray<CustomWidgetPlugin> mPlugins;
+ private final HashMap<String, CustomWidgetPlugin> mPlugins;
private final List<CustomAppWidgetProviderInfo> mCustomWidgets;
- private final SparseArray<ComponentName> mWidgetsIdMap;
+ private final HashMap<ComponentName, String> mWidgetsIdMap;
private Consumer<PackageUserKey> mWidgetRefreshCallback;
private CustomWidgetManager(Context context) {
mContext = context;
- mPlugins = new SparseArray<>();
+ mPlugins = new HashMap<>();
mCustomWidgets = new ArrayList<>();
- mWidgetsIdMap = new SparseArray<>();
+ mWidgetsIdMap = new HashMap<>();
PluginManagerWrapper.INSTANCE.get(context)
.addPluginListener(this, CustomWidgetPlugin.class, true);
+
+ if (SMARTSPACE_AS_A_WIDGET.get()) {
+ for (String s: context.getResources()
+ .getStringArray(R.array.custom_widget_providers)) {
+ try {
+ Class<?> cls = Class.forName(s);
+ CustomWidgetPlugin plugin = (CustomWidgetPlugin)
+ cls.getDeclaredConstructor(Context.class).newInstance(context);
+ mPlugins.put(plugin.getId(), plugin);
+ onPluginConnected(mPlugins.get(plugin.getId()), context);
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
+ | ClassCastException | NoSuchMethodException
+ | InvocationTargetException e) {
+ Log.e(TAG, "Exception found when trying to add custom widgets: " + e);
+ }
+ }
+ }
}
@Override
@@ -79,28 +96,41 @@
@Override
public void onPluginConnected(CustomWidgetPlugin plugin, Context context) {
- mPlugins.put(mAutoProviderId, plugin);
List<AppWidgetProviderInfo> providers = AppWidgetManager.getInstance(context)
.getInstalledProvidersForProfile(Process.myUserHandle());
if (providers.isEmpty()) return;
Parcel parcel = Parcel.obtain();
providers.get(0).writeToParcel(parcel, 0);
parcel.setDataPosition(0);
- CustomAppWidgetProviderInfo info = newInfo(mAutoProviderId, plugin, parcel, context);
+ CustomAppWidgetProviderInfo info = newInfo(plugin.getId(), plugin, parcel, context);
parcel.recycle();
mCustomWidgets.add(info);
- mWidgetsIdMap.put(mAutoProviderId, info.provider);
- mWidgetRefreshCallback.accept(null);
- mAutoProviderId++;
+ mWidgetsIdMap.put(info.provider, plugin.getId());
}
@Override
public void onPluginDisconnected(CustomWidgetPlugin plugin) {
- int providerId = findProviderId(plugin);
- if (providerId == -1) return;
- mPlugins.remove(providerId);
- mCustomWidgets.remove(getWidgetProvider(providerId));
- mWidgetsIdMap.remove(providerId);
+ String providerId = plugin.getId();
+ if (mPlugins.containsKey(providerId)) {
+ mPlugins.remove(providerId);
+ }
+
+ ComponentName cn = null;
+ for (Map.Entry entry: mWidgetsIdMap.entrySet()) {
+ if (entry.getValue().equals(providerId)) {
+ cn = (ComponentName) entry.getKey();
+ }
+ }
+
+ if (cn != null) {
+ mWidgetsIdMap.remove(cn);
+ for (int i = 0; i < mCustomWidgets.size(); i++) {
+ if (mCustomWidgets.get(i).getComponent().equals(cn)) {
+ mCustomWidgets.remove(i);
+ return;
+ }
+ }
+ }
}
/**
@@ -131,12 +161,11 @@
/**
* Returns the widget id for a specific provider.
*/
- public int getWidgetIdForCustomProvider(@NonNull ComponentName provider) {
- int index = mWidgetsIdMap.indexOfValue(provider);
- if (index >= 0) {
- return LauncherAppWidgetInfo.CUSTOM_WIDGET_ID - mWidgetsIdMap.keyAt(index);
+ public String getWidgetIdForCustomProvider(@NonNull ComponentName provider) {
+ if (mWidgetsIdMap.containsKey(provider)) {
+ return mWidgetsIdMap.get(provider);
} else {
- return AppWidgetManager.INVALID_APPWIDGET_ID;
+ return "";
}
}
@@ -144,38 +173,26 @@
* Returns the widget provider in respect to given widget id.
*/
@Nullable
- public LauncherAppWidgetProviderInfo getWidgetProvider(int widgetId) {
- ComponentName cn = mWidgetsIdMap.get(LauncherAppWidgetInfo.CUSTOM_WIDGET_ID - widgetId);
+ public LauncherAppWidgetProviderInfo getWidgetProvider(ComponentName componentName) {
for (LauncherAppWidgetProviderInfo info : mCustomWidgets) {
- if (info.provider.equals(cn)) return info;
+ if (info.provider.equals(componentName)) return info;
}
return null;
}
- private static CustomAppWidgetProviderInfo newInfo(int providerId, CustomWidgetPlugin plugin,
+ private static CustomAppWidgetProviderInfo newInfo(String providerId, CustomWidgetPlugin plugin,
Parcel parcel, Context context) {
CustomAppWidgetProviderInfo info = new CustomAppWidgetProviderInfo(
parcel, false, providerId);
- info.provider = new ComponentName(
- context.getPackageName(), CLS_CUSTOM_WIDGET_PREFIX + providerId);
-
- info.label = plugin.getLabel();
- info.resizeMode = plugin.getResizeMode();
-
- info.spanX = plugin.getSpanX();
- info.spanY = plugin.getSpanY();
- info.minSpanX = plugin.getMinSpanX();
- info.minSpanY = plugin.getMinSpanY();
+ plugin.updateWidgetInfo(info, context);
return info;
}
- private int findProviderId(CustomWidgetPlugin plugin) {
- for (int i = 0; i < mPlugins.size(); i++) {
- int providerId = mPlugins.keyAt(i);
- if (mPlugins.get(providerId) == plugin) {
- return providerId;
- }
- }
- return -1;
+ /**
+ * Returns an id to set as the appWidgetId for a custom widget.
+ */
+ public int allocateCustomAppWidgetId(ComponentName componentName) {
+ return CUSTOM_WIDGET_ID - mCustomWidgets.indexOf(getWidgetProvider(componentName));
}
+
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 33c4f8d..4105a9a 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -23,8 +23,6 @@
import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.content.pm.LauncherApps;
import android.content.res.Configuration;
@@ -62,6 +60,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.UserManagerState;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.pm.UserCache;
@@ -627,20 +626,13 @@
mContent.setAlpha(0);
setTranslationShift(VERTICAL_START_POSITION);
}
- mOpenCloseAnimator.setValues(
- PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
- mOpenCloseAnimator
- .setDuration(mActivityContext.getDeviceProfile().bottomSheetOpenDuration)
- .setInterpolator(AnimationUtils.loadInterpolator(
- getContext(), android.R.interpolator.linear_out_slow_in));
- mOpenCloseAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mOpenCloseAnimator.removeListener(this);
- }
- });
+ setUpOpenAnimation(mActivityContext.getDeviceProfile().bottomSheetOpenDuration);
+ Animator animator = mOpenCloseAnimation.getAnimationPlayer();
+ animator.setInterpolator(AnimationUtils.loadInterpolator(
+ getContext(), android.R.interpolator.linear_out_slow_in));
post(() -> {
- mOpenCloseAnimator.start();
+ animator.setDuration(mActivityContext.getDeviceProfile().bottomSheetOpenDuration)
+ .start();
mContent.animate().alpha(1).setDuration(FADE_IN_DURATION);
});
} else {
@@ -690,7 +682,8 @@
boolean isTwoPane = LARGE_SCREEN_WIDGET_PICKER.get()
&& launcher.getDeviceProfile().isTablet
&& launcher.getDeviceProfile().isLandscape
- && !launcher.getDeviceProfile().isTwoPanels;
+ && (!launcher.getDeviceProfile().isTwoPanels
+ || FeatureFlags.UNFOLDED_WIDGET_PICKER.get());
WidgetsFullSheet sheet;
if (isTwoPane) {
@@ -774,7 +767,7 @@
super.onCloseComplete();
removeCallbacks(mShowEducationTipTask);
if (mLatestEducationalTip != null) {
- mLatestEducationalTip.close(false);
+ mLatestEducationalTip.close(true);
}
AccessibilityManagerCompat.sendStateEventToTest(getContext(), NORMAL_STATE_ORDINAL);
}
@@ -803,13 +796,15 @@
}
// Checks the orientation of the screen
- if (LARGE_SCREEN_WIDGET_PICKER.get()
- && mOrientation != newConfig.orientation
- && mDeviceProfile.isTablet
- && !mDeviceProfile.isTwoPanels) {
+ if (mOrientation != newConfig.orientation) {
mOrientation = newConfig.orientation;
- handleClose(false);
- show(Launcher.getLauncher(getContext()), false);
+ if (LARGE_SCREEN_WIDGET_PICKER.get()
+ && mDeviceProfile.isTablet && !mDeviceProfile.isTwoPanels) {
+ handleClose(false);
+ show(Launcher.getLauncher(getContext()), false);
+ } else {
+ reset();
+ }
}
}
@@ -891,6 +886,19 @@
return false;
}
+ /** Gets the sheet for widget picker, which is used for testing. */
+ @VisibleForTesting
+ public View getSheet() {
+ return mContent;
+ }
+
+ /** Opens the first header in widget picker and scrolls to the top of the RecyclerView. */
+ @VisibleForTesting
+ public void openFirstHeader() {
+ mAdapters.get(AdapterHolder.PRIMARY).mWidgetsListAdapter.selectFirstHeaderEntry();
+ mAdapters.get(AdapterHolder.PRIMARY).mWidgetsRecyclerView.scrollToTop();
+ }
+
/** A holder class for holding adapters & their corresponding recycler view. */
final class AdapterHolder {
static final int PRIMARY = 0;
diff --git a/src/com/android/launcher3/workspace/WorkspaceSpecs.kt b/src/com/android/launcher3/workspace/WorkspaceSpecs.kt
deleted file mode 100644
index ac0a166..0000000
--- a/src/com/android/launcher3/workspace/WorkspaceSpecs.kt
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.workspace
-
-import android.content.res.TypedArray
-import android.content.res.XmlResourceParser
-import android.util.AttributeSet
-import android.util.Log
-import android.util.TypedValue
-import android.util.Xml
-import com.android.launcher3.R
-import com.android.launcher3.util.ResourceHelper
-import java.io.IOException
-import kotlin.math.roundToInt
-import org.xmlpull.v1.XmlPullParser
-import org.xmlpull.v1.XmlPullParserException
-
-private const val TAG = "WorkspaceSpecs"
-
-class WorkspaceSpecs(resourceHelper: ResourceHelper) {
- object XmlTags {
- const val WORKSPACE_SPECS = "workspaceSpecs"
-
- const val WORKSPACE_SPEC = "workspaceSpec"
- const val START_PADDING = "startPadding"
- const val END_PADDING = "endPadding"
- const val GUTTER = "gutter"
- const val CELL_SIZE = "cellSize"
- }
-
- val workspaceHeightSpecList = mutableListOf<WorkspaceSpec>()
- val workspaceWidthSpecList = mutableListOf<WorkspaceSpec>()
-
- init {
- try {
- val parser: XmlResourceParser = resourceHelper.getXml()
- val depth = parser.depth
- var type: Int
- while (
- (parser.next().also { type = it } != XmlPullParser.END_TAG ||
- parser.depth > depth) && type != XmlPullParser.END_DOCUMENT
- ) {
- if (type == XmlPullParser.START_TAG && XmlTags.WORKSPACE_SPECS == parser.name) {
- val displayDepth = parser.depth
- while (
- (parser.next().also { type = it } != XmlPullParser.END_TAG ||
- parser.depth > displayDepth) && type != XmlPullParser.END_DOCUMENT
- ) {
- if (
- type == XmlPullParser.START_TAG && XmlTags.WORKSPACE_SPEC == parser.name
- ) {
- val attrs =
- resourceHelper.obtainStyledAttributes(
- Xml.asAttributeSet(parser),
- R.styleable.WorkspaceSpec
- )
- val maxAvailableSize =
- attrs.getDimensionPixelSize(
- R.styleable.WorkspaceSpec_maxAvailableSize,
- 0
- )
- val specType =
- WorkspaceSpec.SpecType.values()[
- attrs.getInt(
- R.styleable.WorkspaceSpec_specType,
- WorkspaceSpec.SpecType.HEIGHT.ordinal
- )]
- attrs.recycle()
-
- var startPadding: SizeSpec? = null
- var endPadding: SizeSpec? = null
- var gutter: SizeSpec? = null
- var cellSize: SizeSpec? = null
-
- val limitDepth = parser.depth
- while (
- (parser.next().also { type = it } != XmlPullParser.END_TAG ||
- parser.depth > limitDepth) && type != XmlPullParser.END_DOCUMENT
- ) {
- val attr: AttributeSet = Xml.asAttributeSet(parser)
- if (type == XmlPullParser.START_TAG) {
- when (parser.name) {
- XmlTags.START_PADDING -> {
- startPadding = SizeSpec(resourceHelper, attr)
- }
- XmlTags.END_PADDING -> {
- endPadding = SizeSpec(resourceHelper, attr)
- }
- XmlTags.GUTTER -> {
- gutter = SizeSpec(resourceHelper, attr)
- }
- XmlTags.CELL_SIZE -> {
- cellSize = SizeSpec(resourceHelper, attr)
- }
- }
- }
- }
-
- if (
- startPadding == null ||
- endPadding == null ||
- gutter == null ||
- cellSize == null
- ) {
- throw IllegalStateException(
- "All attributes in workspaceSpec must be defined"
- )
- }
-
- val workspaceSpec =
- WorkspaceSpec(
- maxAvailableSize,
- specType,
- startPadding,
- endPadding,
- gutter,
- cellSize
- )
- if (workspaceSpec.isValid()) {
- if (workspaceSpec.specType == WorkspaceSpec.SpecType.HEIGHT)
- workspaceHeightSpecList.add(workspaceSpec)
- else workspaceWidthSpecList.add(workspaceSpec)
- } else {
- throw IllegalStateException("Invalid workspaceSpec found.")
- }
- }
- }
-
- if (workspaceWidthSpecList.isEmpty() || workspaceHeightSpecList.isEmpty()) {
- throw IllegalStateException(
- "WorkspaceSpecs is incomplete - " +
- "height list size = ${workspaceHeightSpecList.size}; " +
- "width list size = ${workspaceWidthSpecList.size}."
- )
- }
- }
- }
- parser.close()
- } catch (e: Exception) {
- when (e) {
- is IOException,
- is XmlPullParserException -> {
- throw RuntimeException("Failure parsing workspaces specs file.", e)
- }
- else -> throw e
- }
- }
- }
-
- /**
- * Returns the CalculatedWorkspaceSpec for width, based on the available width and the
- * WorkspaceSpecs.
- */
- fun getCalculatedWidthSpec(columns: Int, availableWidth: Int): CalculatedWorkspaceSpec {
- val widthSpec = workspaceWidthSpecList.first { availableWidth <= it.maxAvailableSize }
-
- return CalculatedWorkspaceSpec(availableWidth, columns, widthSpec)
- }
-
- /**
- * Returns the CalculatedWorkspaceSpec for height, based on the available height and the
- * WorkspaceSpecs.
- */
- fun getCalculatedHeightSpec(rows: Int, availableHeight: Int): CalculatedWorkspaceSpec {
- val heightSpec = workspaceHeightSpecList.first { availableHeight <= it.maxAvailableSize }
-
- return CalculatedWorkspaceSpec(availableHeight, rows, heightSpec)
- }
-}
-
-class CalculatedWorkspaceSpec(
- val availableSpace: Int,
- val cells: Int,
- val workspaceSpec: WorkspaceSpec
-) {
- var startPaddingPx: Int = 0
- private set
- var endPaddingPx: Int = 0
- private set
- var gutterPx: Int = 0
- private set
- var cellSizePx: Int = 0
- private set
- init {
- // Calculate all fixed size first
- if (workspaceSpec.startPadding.fixedSize > 0)
- startPaddingPx = workspaceSpec.startPadding.fixedSize.roundToInt()
- if (workspaceSpec.endPadding.fixedSize > 0)
- endPaddingPx = workspaceSpec.endPadding.fixedSize.roundToInt()
- if (workspaceSpec.gutter.fixedSize > 0)
- gutterPx = workspaceSpec.gutter.fixedSize.roundToInt()
- if (workspaceSpec.cellSize.fixedSize > 0)
- cellSizePx = workspaceSpec.cellSize.fixedSize.roundToInt()
-
- // Calculate all available space next
- if (workspaceSpec.startPadding.ofAvailableSpace > 0)
- startPaddingPx =
- (workspaceSpec.startPadding.ofAvailableSpace * availableSpace).roundToInt()
- if (workspaceSpec.endPadding.ofAvailableSpace > 0)
- endPaddingPx = (workspaceSpec.endPadding.ofAvailableSpace * availableSpace).roundToInt()
- if (workspaceSpec.gutter.ofAvailableSpace > 0)
- gutterPx = (workspaceSpec.gutter.ofAvailableSpace * availableSpace).roundToInt()
- if (workspaceSpec.cellSize.ofAvailableSpace > 0)
- cellSizePx = (workspaceSpec.cellSize.ofAvailableSpace * availableSpace).roundToInt()
-
- // Calculate remainder space last
- val gutters = cells - 1
- val usedSpace = startPaddingPx + endPaddingPx + (gutterPx * gutters) + (cellSizePx * cells)
- val remainderSpace = availableSpace - usedSpace
- if (workspaceSpec.startPadding.ofRemainderSpace > 0)
- startPaddingPx =
- (workspaceSpec.startPadding.ofRemainderSpace * remainderSpace).roundToInt()
- if (workspaceSpec.endPadding.ofRemainderSpace > 0)
- endPaddingPx = (workspaceSpec.endPadding.ofRemainderSpace * remainderSpace).roundToInt()
- if (workspaceSpec.gutter.ofRemainderSpace > 0)
- gutterPx = (workspaceSpec.gutter.ofRemainderSpace * remainderSpace).roundToInt()
- if (workspaceSpec.cellSize.ofRemainderSpace > 0)
- cellSizePx = (workspaceSpec.cellSize.ofRemainderSpace * remainderSpace).roundToInt()
- }
-}
-
-data class WorkspaceSpec(
- val maxAvailableSize: Int,
- val specType: SpecType,
- val startPadding: SizeSpec,
- val endPadding: SizeSpec,
- val gutter: SizeSpec,
- val cellSize: SizeSpec
-) {
-
- enum class SpecType {
- HEIGHT,
- WIDTH
- }
-
- fun isValid(): Boolean {
- if (maxAvailableSize <= 0) {
- Log.e(TAG, "WorkspaceSpec#isValid - maxAvailableSize <= 0")
- return false
- }
-
- // All specs need to be individually valid
- if (!allSpecsAreValid()) {
- Log.e(TAG, "WorkspaceSpec#isValid - !allSpecsAreValid()")
- return false
- }
-
- return true
- }
-
- private fun allSpecsAreValid(): Boolean =
- startPadding.isValid() && endPadding.isValid() && gutter.isValid() && cellSize.isValid()
-}
-
-class SizeSpec(resourceHelper: ResourceHelper, attrs: AttributeSet) {
- val fixedSize: Float
- val ofAvailableSpace: Float
- val ofRemainderSpace: Float
-
- init {
- val styledAttrs = resourceHelper.obtainStyledAttributes(attrs, R.styleable.SpecSize)
-
- fixedSize = getValue(styledAttrs, R.styleable.SpecSize_fixedSize)
- ofAvailableSpace = getValue(styledAttrs, R.styleable.SpecSize_ofAvailableSpace)
- ofRemainderSpace = getValue(styledAttrs, R.styleable.SpecSize_ofRemainderSpace)
-
- styledAttrs.recycle()
- }
-
- private fun getValue(a: TypedArray, index: Int): Float {
- if (a.getType(index) == TypedValue.TYPE_DIMENSION) {
- return a.getDimensionPixelSize(index, 0).toFloat()
- } else if (a.getType(index) == TypedValue.TYPE_FLOAT) {
- return a.getFloat(index, 0f)
- }
- return 0f
- }
-
- fun isValid(): Boolean {
- // All attributes are empty
- if (fixedSize < 0f && ofAvailableSpace <= 0f && ofRemainderSpace <= 0f) {
- Log.e(TAG, "SizeSpec#isValid - all attributes are empty")
- return false
- }
-
- // More than one attribute is filled
- val attrCount =
- (if (fixedSize > 0) 1 else 0) +
- (if (ofAvailableSpace > 0) 1 else 0) +
- (if (ofRemainderSpace > 0) 1 else 0)
- if (attrCount > 1) {
- Log.e(TAG, "SizeSpec#isValid - more than one attribute is filled")
- return false
- }
-
- // Values should be between 0 and 1
- if (ofAvailableSpace !in 0f..1f || ofRemainderSpace !in 0f..1f) {
- Log.e(TAG, "SizeSpec#isValid - values should be between 0 and 1")
- return false
- }
-
- return true
- }
-
- override fun toString(): String {
- return "SizeSpec(fixedSize=$fixedSize, ofAvailableSpace=$ofAvailableSpace, " +
- "ofRemainderSpace=$ofRemainderSpace)"
- }
-}
diff --git a/src_plugins/com/android/systemui/plugins/CustomWidgetPlugin.java b/src_plugins/com/android/systemui/plugins/CustomWidgetPlugin.java
index 56ebcc5..af4f22c 100644
--- a/src_plugins/com/android/systemui/plugins/CustomWidgetPlugin.java
+++ b/src_plugins/com/android/systemui/plugins/CustomWidgetPlugin.java
@@ -17,6 +17,8 @@
package com.android.systemui.plugins;
import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.Context;
import com.android.systemui.plugins.annotations.ProvidesInterface;
@@ -30,42 +32,20 @@
int VERSION = 1;
/**
- * The label to display to the user in the AppWidget picker.
- */
- String getLabel();
-
- /**
- * The default width of the widget when added to a host, in dp. The widget will get
- * at least this width, and will often be given more, depending on the host.
- */
- int getSpanX();
-
- /**
- * The default height of the widget when added to a host, in dp. The widget will get
- * at least this height, and will often be given more, depending on the host.
- */
- int getSpanY();
-
- /**
- * Minimum width (in dp) which the widget can be resized to. This field has no effect if it
- * is greater than minWidth or if horizontal resizing isn't enabled.
- */
- int getMinSpanX();
-
- /**
- * Minimum height (in dp) which the widget can be resized to. This field has no effect if it
- * is greater than minHeight or if vertical resizing isn't enabled.
- */
- int getMinSpanY();
-
- /**
- * The rules by which a widget can be resized.
- */
- int getResizeMode();
-
- /**
* Notify the plugin that container of the widget has been rendered, where the custom widget
* can be attached to.
*/
void onViewCreated(AppWidgetHostView parent);
+
+ /**
+ * Get the UUID for the custom widget.
+ */
+ String getId();
+
+ /**
+ * Used to modify a widgets' info.
+ */
+ default void updateWidgetInfo(AppWidgetProviderInfo info, Context context) {
+
+ }
}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java b/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
index d6b41c9..599a591 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
@@ -16,6 +16,7 @@
package com.android.launcher3.uioverrides;
+import android.app.ActivityOptions;
import android.app.Person;
import android.content.Context;
import android.content.pm.LauncherActivityInfo;
@@ -40,4 +41,11 @@
public static Map<String, LauncherActivityInfo> getActivityOverrides(Context context) {
return Collections.emptyMap();
}
+
+ /**
+ * Creates an ActivityOptions to play fade-out animation on closing targets
+ */
+ public static ActivityOptions createFadeOutAnimOptions(Context context) {
+ return ActivityOptions.makeCustomAnimation(context, 0, android.R.anim.fade_out);
+ }
}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
index 772a995..b62dbd1 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -15,7 +15,7 @@
*/
package com.android.launcher3.uioverrides.states;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.app.animation.Interpolators.DECELERATE;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
import android.content.Context;
@@ -80,7 +80,7 @@
@Override
public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
PageAlphaProvider superPageAlphaProvider = super.getWorkspacePageAlphaProvider(launcher);
- return new PageAlphaProvider(DEACCEL_2) {
+ return new PageAlphaProvider(DECELERATE) {
@Override
public float getPageAlpha(int pageIndex) {
return launcher.getDeviceProfile().isTablet
diff --git a/tests/Android.bp b/tests/Android.bp
index e7f4084..1471c08 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -42,6 +42,9 @@
filegroup {
name: "launcher-oop-tests-src",
srcs: [
+ "src/com/android/launcher3/allapps/OopTaplOpenCloseAllApps.java",
+ "src/com/android/launcher3/dragging/TaplDragTest.java",
+ "src/com/android/launcher3/dragging/TaplUninstallRemove.java",
"src/com/android/launcher3/ui/AbstractLauncherUiTest.java",
"src/com/android/launcher3/ui/PortraitLandscapeRunner.java",
"src/com/android/launcher3/ui/TaplTestsLauncher3.java",
@@ -50,14 +53,14 @@
"src/com/android/launcher3/util/Wait.java",
"src/com/android/launcher3/util/WidgetUtils.java",
"src/com/android/launcher3/util/rule/FailureWatcher.java",
- "src/com/android/launcher3/util/rule/LauncherActivityRule.java",
"src/com/android/launcher3/util/rule/ViewCaptureRule.kt",
"src/com/android/launcher3/util/rule/SamplerRule.java",
"src/com/android/launcher3/util/rule/ScreenRecordRule.java",
"src/com/android/launcher3/util/rule/ShellCommandRule.java",
- "src/com/android/launcher3/util/rule/SimpleActivityRule.java",
+ "src/com/android/launcher3/util/rule/TestIsolationRule.java",
"src/com/android/launcher3/util/rule/TestStabilityRule.java",
"src/com/android/launcher3/util/rule/TISBindRule.java",
+ "src/com/android/launcher3/util/viewcapture_analysis/*.java",
"src/com/android/launcher3/testcomponent/BaseTestingActivity.java",
"src/com/android/launcher3/testcomponent/OtherBaseTestingActivity.java",
"src/com/android/launcher3/testcomponent/CustomShortcutConfigActivity.java",
@@ -74,6 +77,7 @@
asset_dirs: ["assets"],
resource_dirs: ["res"],
static_libs: [
+ "flag-junit-base",
"launcher-aosp-tapl",
"androidx.test.core",
"androidx.test.runner",
@@ -83,10 +87,12 @@
"androidx.test.espresso.contrib",
"androidx.test.espresso.intents",
"androidx.test.uiautomator_uiautomator",
- "mockito-target-inline-minus-junit4",
+ "mockito-target-extended-minus-junit4",
"launcher_log_protos_lite",
"truth-prebuilt",
"platform-test-rules",
+ "testables",
+ "com_android_launcher3_flags_lib",
],
manifest: "AndroidManifest-common.xml",
platform_apis: true,
@@ -103,12 +109,16 @@
":launcher-tests-src",
":launcher-non-quickstep-tests-src",
],
- static_libs: ["Launcher3TestLib"],
+ static_libs: [
+ "Launcher3TestLib",
+ "com_android_launcher3_flags_lib",
+ ],
libs: [
"android.test.base",
"android.test.runner",
"android.test.mock",
],
+ // Libraries used by mockito inline extended
jni_libs: [
"libdexmakerjvmtiagent",
"libstaticjvmtiagent",
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index b170061..ee151bb 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -32,6 +32,7 @@
<receiver
android:name="com.android.launcher3.testcomponent.AppWidgetNoConfig"
android:exported="true"
+ android:icon="@drawable/test_widget_no_config_icon"
android:label="No Config">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
@@ -41,6 +42,17 @@
</receiver>
<receiver
+ android:name="com.android.launcher3.testcomponent.AppWidgetNoConfigLarge"
+ android:exported="true"
+ android:label="No Config Large">
+ <intent-filter>
+ <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
+ </intent-filter>
+ <meta-data android:name="android.appwidget.provider"
+ android:resource="@xml/appwidget_no_config_large"/>
+ </receiver>
+
+ <receiver
android:name="com.android.launcher3.testcomponent.AppWdigetHidden"
android:exported="true"
android:label="Hidden widget">
@@ -54,6 +66,7 @@
<receiver
android:name="com.android.launcher3.testcomponent.AppWidgetWithConfig"
android:exported="true"
+ android:icon="@drawable/test_widget_with_config_icon"
android:label="With Config">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
@@ -65,6 +78,7 @@
<receiver
android:name="com.android.launcher3.testcomponent.AppWidgetWithDialog"
android:exported="true"
+ android:icon="@drawable/test_widget_with_dialog_icon"
android:label="With Dialog">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
@@ -76,6 +90,7 @@
<receiver
android:name="com.android.launcher3.testcomponent.AppWidgetDynamicColors"
android:exported="true"
+ android:icon="@drawable/test_widget_dynamic_colors_icon"
android:label="Dynamic Colors">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
@@ -288,6 +303,28 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
+ <activity-alias android:name="MaxShortcutsActivity"
+ android:label="TestActivityMaxShortcuts"
+ android:exported="true"
+ android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ <meta-data android:name="android.app.shortcuts"
+ android:resource="@xml/max_shortcuts"/>
+ </activity-alias>
+ <activity-alias android:name="SingleShortcutActivity"
+ android:label="TestActivitySingleShortcut"
+ android:exported="true"
+ android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ <meta-data android:name="android.app.shortcuts"
+ android:resource="@xml/single_shortcut"/>
+ </activity-alias>
<activity
android:name="com.android.launcher3.testcomponent.DialogTestActivity"
android:label="Dialog Activity"
@@ -308,6 +345,15 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <activity-alias android:name="WebSearchActivity"
+ android:label="WebSearchActivity"
+ android:exported="true"
+ android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.WEB_SEARCH" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity-alias>
<!-- [b/197780098] Disable eager initialization of Jetpack libraries. -->
<provider
diff --git a/tests/assets/ReorderWidgets/multiple_cell_layouts_no_space_reorder b/tests/assets/ReorderWidgets/multiple_cell_layouts_no_space_reorder
new file mode 100644
index 0000000..c6d65f8
--- /dev/null
+++ b/tests/assets/ReorderWidgets/multiple_cell_layouts_no_space_reorder
@@ -0,0 +1,56 @@
+###################################################################################################
+# This file contains test case composed of the following tags:
+# * # (coments): Lines starting with this character would be ignored.
+# * arguments: is set of words separated by spaces that can later be parsed
+# * board: represent a workspace, the first line is the dimensions of the board width x height (wxh)
+# There are different characters on the board that represent different things:
+# * x: The x character represents spaces that would be ignored, for example it can be used in
+# the first row if we don't know how wide the smartspace is.
+# * i: Represents an icon on the workspace, none in particular just an icon
+# * [a-z]: Represents a widget and it can be any number or character
+# except any other already in use. The whole continuos are of the same character is the
+# area of the widget.
+# * [A-Z]: Represents a folder and number of icons in the folder is represented by the order of
+# letter in the alphabet, A=2, B=3, C=4 ... etc.
+# Test are parsed by CellLayoutTestCaseReader.java and boards are parsed by CellLayoutBoard.java
+###################################################################################################
+# 5x5 Test
+board: 5x5
+xxxxx|aeeee
+--mm-|acccc
+--mm-|acccc
+ggggg|acccc
+ggggg|adddd
+arguments: 7 1
+board: 10x5
+xxxxx|aeeee
+---mm|acccc
+---mm|acccc
+ggggg|acccc
+ggggg|adddd
+# 4x4 Test
+board: 4x4
+xxxx|aeee
+--mm|accc
+--mm|accc
+gggg|accc
+arguments: 5 1
+board: 8x4
+xxxx|aeee
+--mm|accc
+--mm|accc
+gggg|accc
+# 6x5 Test
+board: 6x5
+xxxxxx|aeeeee
+--mm--|accccc
+--mm--|accccc
+gggggg|accccc
+gggggg|addddd
+arguments: 8 1
+board: 12x5
+xxxxxx|aeeeee
+----mm|accccc
+----mm|accccc
+gggggg|accccc
+gggggg|addddd
diff --git a/tests/assets/ReorderWidgets/multiple_cell_layouts_reorder_other_side b/tests/assets/ReorderWidgets/multiple_cell_layouts_reorder_other_side
new file mode 100644
index 0000000..376638e
--- /dev/null
+++ b/tests/assets/ReorderWidgets/multiple_cell_layouts_reorder_other_side
@@ -0,0 +1,56 @@
+###################################################################################################
+# This file contains test case composed of the following tags:
+# * # (coments): Lines starting with this character would be ignored.
+# * arguments: is set of words separated by spaces that can later be parsed
+# * board: represent a workspace, the first line is the dimensions of the board width x height (wxh)
+# There are different characters on the board that represent different things:
+# * x: The x character represents spaces that would be ignored, for example it can be used in
+# the first row if we don't know how wide the smartspace is.
+# * i: Represents an icon on the workspace, none in particular just an icon
+# * [a-z]: Represents a widget and it can be any number or character
+# except any other already in use. The whole continuos are of the same character is the
+# area of the widget.
+# * [A-Z]: Represents a folder and number of icons in the folder is represented by the order of
+# letter in the alphabet, A=2, B=3, C=4 ... etc.
+# Test are parsed by CellLayoutTestCaseReader.java and boards are parsed by CellLayoutBoard.java
+###################################################################################################
+# 5x5 Test
+board: 5x5
+xxxxx|aaaaa
+--mm-|plllh
+--mm-|piiih
+ggggg|piiih
+ggggg|fffff
+arguments: 7 1
+board: 10x5
+xxxxx|aaaaa
+--lll|p-mmh
+---ii|pimmh
+ggggg|piiih
+ggggg|fffff
+# 4x4 Test
+board: 4x4
+xxxx|aaaa
+--mm|pllh
+--mm|piih
+gggg|ffff
+arguments: 5 1
+board: 8x4
+xxxx|aaaa
+--ll|pmmh
+--ii|pmmh
+gggg|ffff
+# 6x5 Test
+board: 6x5
+xxxxxx|aaaaaa
+--mmm-|pllllh
+--mmm-|piiiih
+--mmm-|piiiih
+gggggg|ffffff
+arguments: 8 1
+board: 12x5
+xxxxxx|aaaaaa
+--llll|p-mmmh
+---iii|pimmmh
+---iii|pimmmh
+gggggg|ffffff
\ No newline at end of file
diff --git a/tests/assets/ReorderWidgets/multiple_cell_layouts_simple_reorder b/tests/assets/ReorderWidgets/multiple_cell_layouts_simple_reorder
new file mode 100644
index 0000000..44301d2
--- /dev/null
+++ b/tests/assets/ReorderWidgets/multiple_cell_layouts_simple_reorder
@@ -0,0 +1,56 @@
+###################################################################################################
+# This file contains test case composed of the following tags:
+# * # (coments): Lines starting with this character would be ignored.
+# * arguments: is set of words separated by spaces that can later be parsed
+# * board: represent a workspace, the first line is the dimensions of the board width x height (wxh)
+# There are different characters on the board that represent different things:
+# * x: The x character represents spaces that would be ignored, for example it can be used in
+# the first row if we don't know how wide the smartspace is.
+# * i: Represents an icon on the workspace, none in particular just an icon
+# * [a-z]: Represents a widget and it can be any number or character
+# except any other already in use. The whole continuos are of the same character is the
+# area of the widget.
+# * [A-Z]: Represents a folder and number of icons in the folder is represented by the order of
+# letter in the alphabet, A=2, B=3, C=4 ... etc.
+# Test are parsed by CellLayoutTestCaseReader.java and boards are parsed by CellLayoutBoard.java
+###################################################################################################
+# 5x5 Test
+board: 5x5
+xxxxx|-----
+--mm-|-----
+--mm-|-----
+-----|-----
+-----|-----
+arguments: 8 3
+board: 10x5
+xxxxx|-----
+-----|-----
+-----|-----
+-----|---mm
+-----|---mm
+# 4x4 Test
+board: 4x4
+xxxx|----
+--mm|----
+--mm|----
+----|----
+arguments: 5 3
+board: 8x4
+xxxx|----
+----|----
+----|-mm-
+----|-mm-
+# 6x5 Test
+board: 6x5
+xxxxxx|------
+--m---|------
+------|------
+------|------
+------|------
+arguments: 10 4
+board: 12x5
+xxxxxx|------
+------|------
+------|------
+------|------
+------|----m-
\ No newline at end of file
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt
new file mode 100644
index 0000000..b8f4c0b
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt
@@ -0,0 +1,127 @@
+DeviceProfile:
+ 1 dp = 2.625 px
+ isTablet:false
+ isPhone:true
+ transposeLayoutWithOrientation:true
+ isGestureMode:true
+ isLandscape:false
+ isMultiWindowMode:false
+ isTwoPanels:false
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 1080.0px (411.42856dp)
+ heightPx: 2400.0px (914.2857dp)
+ availableWidthPx: 1080.0px (411.42856dp)
+ availableHeightPx: 2219.0px (845.3333dp)
+ mInsets.left: 0.0px (0.0dp)
+ mInsets.top: 118.0px (44.95238dp)
+ mInsets.right: 0.0px (0.0dp)
+ mInsets.bottom: 63.0px (24.0dp)
+ aspectRatio:2.2222223
+ isResponsiveGrid:false
+ isScalableGrid:false
+ inv.numRows: 5
+ inv.numColumns: 5
+ inv.numSearchContainerColumns: 5
+ minCellSize: PointF(0.0, 0.0)dp
+ cellWidthPx: 159.0px (60.57143dp)
+ cellHeightPx: 229.0px (87.2381dp)
+ getCellSize().x: 207.0px (78.85714dp)
+ getCellSize().y: 383.0px (145.90475dp)
+ cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+ cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+ cellLayoutPaddingPx.left: 21.0px (8.0dp)
+ cellLayoutPaddingPx.top: 28.0px (10.666667dp)
+ cellLayoutPaddingPx.right: 21.0px (8.0dp)
+ cellLayoutPaddingPx.bottom: 28.0px (10.666667dp)
+ iconSizePx: 147.0px (56.0dp)
+ iconTextSizePx: 38.0px (14.476191dp)
+ iconDrawablePaddingPx: 12.0px (4.571429dp)
+ inv.numFolderRows: 4
+ inv.numFolderColumns: 4
+ folderCellWidthPx: 195.0px (74.28571dp)
+ folderCellHeightPx: 230.0px (87.61905dp)
+ folderChildIconSizePx: 147.0px (56.0dp)
+ folderChildTextSizePx: 38.0px (14.476191dp)
+ folderChildDrawablePaddingPx: 4.0px (1.5238096dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 21.0px (8.0dp)
+ folderTopPadding: 63.0px (24.0dp)
+ folderFooterHeight: 147.0px (56.0dp)
+ bottomSheetTopPadding: 146.0px (55.61905dp)
+ bottomSheetOpenDuration: 267
+ bottomSheetCloseDuration: 267
+ bottomSheetWorkspaceScale: 1.0
+ bottomSheetDepth: 0.0
+ allAppsShiftRange: 788.0px (300.1905dp)
+ allAppsTopPadding: 0.0px (0.0dp)
+ allAppsOpenDuration: 600
+ allAppsCloseDuration: 300
+ allAppsIconSizePx: 147.0px (56.0dp)
+ allAppsIconTextSizePx: 38.0px (14.476191dp)
+ allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+ allAppsCellHeightPx: 315.0px (120.0dp)
+ allAppsCellWidthPx: 189.0px (72.0dp)
+ allAppsBorderSpacePxX: 42.0px (16.0dp)
+ allAppsBorderSpacePxY: 42.0px (16.0dp)
+ numShownAllAppsColumns: 5
+ allAppsLeftRightPadding: 0.0px (0.0dp)
+ allAppsLeftRightMargin: 0.0px (0.0dp)
+ hotseatBarSizePx: 273.0px (104.0dp)
+ inv.hotseatColumnSpan: 5
+ hotseatCellHeightPx: 166.0px (63.238094dp)
+ hotseatBarBottomSpacePx: 126.0px (48.0dp)
+ mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+ mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 200.0px (76.190475dp)
+ getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+ getHotseatLayoutPadding(context).bottom: 107.0px (40.761906dp)
+ getHotseatLayoutPadding(context).left: 21.0px (8.0dp)
+ getHotseatLayoutPadding(context).right: 21.0px (8.0dp)
+ numShownHotseatIcons: 5
+ hotseatBorderSpace: 0.0px (0.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 0.0px (0.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:false
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)
+ workspacePadding.left: 0.0px (0.0dp)
+ workspacePadding.top: 0.0px (0.0dp)
+ workspacePadding.right: 0.0px (0.0dp)
+ workspacePadding.bottom: 245.0px (93.333336dp)
+ iconScale: 1.0px (0.3809524dp)
+ cellScaleToFit : 1.0px (0.3809524dp)
+ extraSpace: 773.0px (294.4762dp)
+ unscaled extraSpace: 773.0px (294.4762dp)
+ maxEmptySpace: 0.0px (0.0dp)
+ workspaceTopPadding: 0.0px (0.0dp)
+ workspaceBottomPadding: 0.0px (0.0dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 63.0px (24.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 84.0px (32.0dp)
+ dropTargetBarSizePx: 147.0px (56.0dp)
+ dropTargetBarBottomMarginPx: 42.0px (16.0dp)
+ getCellLayoutSpringLoadShrunkTop(): 391.0px (148.95238dp)
+ getCellLayoutSpringLoadShrunkBottom(): 1927.0px (734.0952dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
+ getWorkspaceSpringLoadScale(): 0.7781155px (0.29642496dp)
+ getCellLayoutHeight(): 1974.0px (752.0dp)
+ getCellLayoutWidth(): 1080.0px (411.42856dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt
new file mode 100644
index 0000000..a512277
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt
@@ -0,0 +1,127 @@
+DeviceProfile:
+ 1 dp = 2.625 px
+ isTablet:false
+ isPhone:true
+ transposeLayoutWithOrientation:true
+ isGestureMode:false
+ isLandscape:false
+ isMultiWindowMode:false
+ isTwoPanels:false
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 1080.0px (411.42856dp)
+ heightPx: 2400.0px (914.2857dp)
+ availableWidthPx: 1080.0px (411.42856dp)
+ availableHeightPx: 2156.0px (821.3333dp)
+ mInsets.left: 0.0px (0.0dp)
+ mInsets.top: 118.0px (44.95238dp)
+ mInsets.right: 0.0px (0.0dp)
+ mInsets.bottom: 126.0px (48.0dp)
+ aspectRatio:2.2222223
+ isResponsiveGrid:false
+ isScalableGrid:false
+ inv.numRows: 5
+ inv.numColumns: 5
+ inv.numSearchContainerColumns: 5
+ minCellSize: PointF(0.0, 0.0)dp
+ cellWidthPx: 159.0px (60.57143dp)
+ cellHeightPx: 229.0px (87.2381dp)
+ getCellSize().x: 207.0px (78.85714dp)
+ getCellSize().y: 379.0px (144.38095dp)
+ cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+ cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+ cellLayoutPaddingPx.left: 21.0px (8.0dp)
+ cellLayoutPaddingPx.top: 28.0px (10.666667dp)
+ cellLayoutPaddingPx.right: 21.0px (8.0dp)
+ cellLayoutPaddingPx.bottom: 28.0px (10.666667dp)
+ iconSizePx: 147.0px (56.0dp)
+ iconTextSizePx: 38.0px (14.476191dp)
+ iconDrawablePaddingPx: 12.0px (4.571429dp)
+ inv.numFolderRows: 4
+ inv.numFolderColumns: 4
+ folderCellWidthPx: 195.0px (74.28571dp)
+ folderCellHeightPx: 230.0px (87.61905dp)
+ folderChildIconSizePx: 147.0px (56.0dp)
+ folderChildTextSizePx: 38.0px (14.476191dp)
+ folderChildDrawablePaddingPx: 4.0px (1.5238096dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 21.0px (8.0dp)
+ folderTopPadding: 63.0px (24.0dp)
+ folderFooterHeight: 147.0px (56.0dp)
+ bottomSheetTopPadding: 146.0px (55.61905dp)
+ bottomSheetOpenDuration: 267
+ bottomSheetCloseDuration: 267
+ bottomSheetWorkspaceScale: 1.0
+ bottomSheetDepth: 0.0
+ allAppsShiftRange: 788.0px (300.1905dp)
+ allAppsTopPadding: 0.0px (0.0dp)
+ allAppsOpenDuration: 600
+ allAppsCloseDuration: 300
+ allAppsIconSizePx: 147.0px (56.0dp)
+ allAppsIconTextSizePx: 38.0px (14.476191dp)
+ allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+ allAppsCellHeightPx: 315.0px (120.0dp)
+ allAppsCellWidthPx: 189.0px (72.0dp)
+ allAppsBorderSpacePxX: 42.0px (16.0dp)
+ allAppsBorderSpacePxY: 42.0px (16.0dp)
+ numShownAllAppsColumns: 5
+ allAppsLeftRightPadding: 0.0px (0.0dp)
+ allAppsLeftRightMargin: 0.0px (0.0dp)
+ hotseatBarSizePx: 294.0px (112.0dp)
+ inv.hotseatColumnSpan: 5
+ hotseatCellHeightPx: 166.0px (63.238094dp)
+ hotseatBarBottomSpacePx: 147.0px (56.0dp)
+ mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+ mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 200.0px (76.190475dp)
+ getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+ getHotseatLayoutPadding(context).bottom: 128.0px (48.761906dp)
+ getHotseatLayoutPadding(context).left: 21.0px (8.0dp)
+ getHotseatLayoutPadding(context).right: 21.0px (8.0dp)
+ numShownHotseatIcons: 5
+ hotseatBorderSpace: 0.0px (0.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 0.0px (0.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:false
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)
+ workspacePadding.left: 0.0px (0.0dp)
+ workspacePadding.top: 0.0px (0.0dp)
+ workspacePadding.right: 0.0px (0.0dp)
+ workspacePadding.bottom: 203.0px (77.333336dp)
+ iconScale: 1.0px (0.3809524dp)
+ cellScaleToFit : 1.0px (0.3809524dp)
+ extraSpace: 752.0px (286.4762dp)
+ unscaled extraSpace: 752.0px (286.4762dp)
+ maxEmptySpace: 0.0px (0.0dp)
+ workspaceTopPadding: 0.0px (0.0dp)
+ workspaceBottomPadding: 0.0px (0.0dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 126.0px (48.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 84.0px (32.0dp)
+ dropTargetBarSizePx: 147.0px (56.0dp)
+ dropTargetBarBottomMarginPx: 42.0px (16.0dp)
+ getCellLayoutSpringLoadShrunkTop(): 391.0px (148.95238dp)
+ getCellLayoutSpringLoadShrunkBottom(): 1906.0px (726.0952dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
+ getWorkspaceSpringLoadScale(): 0.77572966px (0.29551607dp)
+ getCellLayoutHeight(): 1953.0px (744.0dp)
+ getCellLayoutWidth(): 1080.0px (411.42856dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
new file mode 100644
index 0000000..a3a8dc5
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
@@ -0,0 +1,127 @@
+DeviceProfile:
+ 1 dp = 2.625 px
+ isTablet:false
+ isPhone:true
+ transposeLayoutWithOrientation:true
+ isGestureMode:true
+ isLandscape:true
+ isMultiWindowMode:false
+ isTwoPanels:false
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 2400.0px (914.2857dp)
+ heightPx: 1080.0px (411.42856dp)
+ availableWidthPx: 2282.0px (869.3333dp)
+ availableHeightPx: 943.0px (359.2381dp)
+ mInsets.left: 118.0px (44.95238dp)
+ mInsets.top: 74.0px (28.190475dp)
+ mInsets.right: 0.0px (0.0dp)
+ mInsets.bottom: 63.0px (24.0dp)
+ aspectRatio:2.2222223
+ isResponsiveGrid:false
+ isScalableGrid:false
+ inv.numRows: 5
+ inv.numColumns: 5
+ inv.numSearchContainerColumns: 5
+ minCellSize: PointF(0.0, 0.0)dp
+ cellWidthPx: 152.0px (57.904762dp)
+ cellHeightPx: 166.0px (63.238094dp)
+ getCellSize().x: 393.0px (149.71428dp)
+ getCellSize().y: 180.0px (68.57143dp)
+ cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+ cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+ cellLayoutPaddingPx.left: 53.0px (20.190475dp)
+ cellLayoutPaddingPx.top: 0.0px (0.0dp)
+ cellLayoutPaddingPx.right: 53.0px (20.190475dp)
+ cellLayoutPaddingPx.bottom: 40.0px (15.238095dp)
+ iconSizePx: 147.0px (56.0dp)
+ iconTextSizePx: 0.0px (0.0dp)
+ iconDrawablePaddingPx: 0.0px (0.0dp)
+ inv.numFolderRows: 4
+ inv.numFolderColumns: 4
+ folderCellWidthPx: 163.0px (62.095238dp)
+ folderCellHeightPx: 192.0px (73.14286dp)
+ folderChildIconSizePx: 123.0px (46.857143dp)
+ folderChildTextSizePx: 32.0px (12.190476dp)
+ folderChildDrawablePaddingPx: 3.0px (1.1428572dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 21.0px (8.0dp)
+ folderTopPadding: 53.0px (20.190475dp)
+ folderFooterHeight: 123.0px (46.857143dp)
+ bottomSheetTopPadding: 114.0px (43.42857dp)
+ bottomSheetOpenDuration: 267
+ bottomSheetCloseDuration: 267
+ bottomSheetWorkspaceScale: 1.0
+ bottomSheetDepth: 0.0
+ allAppsShiftRange: 788.0px (300.1905dp)
+ allAppsTopPadding: 0.0px (0.0dp)
+ allAppsOpenDuration: 600
+ allAppsCloseDuration: 300
+ allAppsIconSizePx: 147.0px (56.0dp)
+ allAppsIconTextSizePx: 38.0px (14.476191dp)
+ allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+ allAppsCellHeightPx: 321.0px (122.28571dp)
+ allAppsCellWidthPx: 189.0px (72.0dp)
+ allAppsBorderSpacePxX: 42.0px (16.0dp)
+ allAppsBorderSpacePxY: 42.0px (16.0dp)
+ numShownAllAppsColumns: 5
+ allAppsLeftRightPadding: 0.0px (0.0dp)
+ allAppsLeftRightMargin: 0.0px (0.0dp)
+ hotseatBarSizePx: 252.0px (96.0dp)
+ inv.hotseatColumnSpan: 5
+ hotseatCellHeightPx: 166.0px (63.238094dp)
+ hotseatBarBottomSpacePx: 0.0px (0.0dp)
+ mHotseatBarEdgePaddingPx: 63.0px (24.0dp)
+ mHotseatBarWorkspaceSpacePx: 42.0px (16.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 118.0px (44.95238dp)
+ getHotseatLayoutPadding(context).top: 64.0px (24.380953dp)
+ getHotseatLayoutPadding(context).bottom: 112.0px (42.666668dp)
+ getHotseatLayoutPadding(context).left: 42.0px (16.0dp)
+ getHotseatLayoutPadding(context).right: 63.0px (24.0dp)
+ numShownHotseatIcons: 5
+ hotseatBorderSpace: 0.0px (0.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 0.0px (0.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:false
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 0.0px (0.0dp)
+ workspacePadding.left: 10.0px (3.8095238dp)
+ workspacePadding.top: 0.0px (0.0dp)
+ workspacePadding.right: 199.0px (75.809525dp)
+ workspacePadding.bottom: 0.0px (0.0dp)
+ iconScale: 1.0px (0.3809524dp)
+ cellScaleToFit : 1.0px (0.3809524dp)
+ extraSpace: 73.0px (27.809525dp)
+ unscaled extraSpace: 73.0px (27.809525dp)
+ maxEmptySpace: 0.0px (0.0dp)
+ workspaceTopPadding: 0.0px (0.0dp)
+ workspaceBottomPadding: 0.0px (0.0dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 63.0px (24.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 16.0px (6.095238dp)
+ dropTargetBarSizePx: 95.0px (36.190475dp)
+ dropTargetBarBottomMarginPx: 16.0px (6.095238dp)
+ getCellLayoutSpringLoadShrunkTop(): 201.0px (76.57143dp)
+ getCellLayoutSpringLoadShrunkBottom(): 952.0px (362.66666dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
+ getWorkspaceSpringLoadScale(): 0.79639447px (0.30338836dp)
+ getCellLayoutHeight(): 943.0px (359.2381dp)
+ getCellLayoutWidth(): 2073.0px (789.7143dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
new file mode 100644
index 0000000..55066cb
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
@@ -0,0 +1,127 @@
+DeviceProfile:
+ 1 dp = 2.625 px
+ isTablet:false
+ isPhone:true
+ transposeLayoutWithOrientation:true
+ isGestureMode:false
+ isLandscape:true
+ isMultiWindowMode:false
+ isTwoPanels:false
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 2400.0px (914.2857dp)
+ heightPx: 1080.0px (411.42856dp)
+ availableWidthPx: 2156.0px (821.3333dp)
+ availableHeightPx: 1006.0px (383.2381dp)
+ mInsets.left: 118.0px (44.95238dp)
+ mInsets.top: 74.0px (28.190475dp)
+ mInsets.right: 126.0px (48.0dp)
+ mInsets.bottom: 0.0px (0.0dp)
+ aspectRatio:2.2222223
+ isResponsiveGrid:false
+ isScalableGrid:false
+ inv.numRows: 5
+ inv.numColumns: 5
+ inv.numSearchContainerColumns: 5
+ minCellSize: PointF(0.0, 0.0)dp
+ cellWidthPx: 152.0px (57.904762dp)
+ cellHeightPx: 166.0px (63.238094dp)
+ getCellSize().x: 368.0px (140.19048dp)
+ getCellSize().y: 193.0px (73.52381dp)
+ cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+ cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+ cellLayoutPaddingPx.left: 53.0px (20.190475dp)
+ cellLayoutPaddingPx.top: 0.0px (0.0dp)
+ cellLayoutPaddingPx.right: 53.0px (20.190475dp)
+ cellLayoutPaddingPx.bottom: 40.0px (15.238095dp)
+ iconSizePx: 147.0px (56.0dp)
+ iconTextSizePx: 0.0px (0.0dp)
+ iconDrawablePaddingPx: 0.0px (0.0dp)
+ inv.numFolderRows: 4
+ inv.numFolderColumns: 4
+ folderCellWidthPx: 173.0px (65.90476dp)
+ folderCellHeightPx: 205.0px (78.09524dp)
+ folderChildIconSizePx: 131.0px (49.904762dp)
+ folderChildTextSizePx: 34.0px (12.952381dp)
+ folderChildDrawablePaddingPx: 4.0px (1.5238096dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 21.0px (8.0dp)
+ folderTopPadding: 56.0px (21.333334dp)
+ folderFooterHeight: 131.0px (49.904762dp)
+ bottomSheetTopPadding: 114.0px (43.42857dp)
+ bottomSheetOpenDuration: 267
+ bottomSheetCloseDuration: 267
+ bottomSheetWorkspaceScale: 1.0
+ bottomSheetDepth: 0.0
+ allAppsShiftRange: 788.0px (300.1905dp)
+ allAppsTopPadding: 0.0px (0.0dp)
+ allAppsOpenDuration: 600
+ allAppsCloseDuration: 300
+ allAppsIconSizePx: 147.0px (56.0dp)
+ allAppsIconTextSizePx: 38.0px (14.476191dp)
+ allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+ allAppsCellHeightPx: 321.0px (122.28571dp)
+ allAppsCellWidthPx: 189.0px (72.0dp)
+ allAppsBorderSpacePxX: 42.0px (16.0dp)
+ allAppsBorderSpacePxY: 42.0px (16.0dp)
+ numShownAllAppsColumns: 5
+ allAppsLeftRightPadding: 0.0px (0.0dp)
+ allAppsLeftRightMargin: 0.0px (0.0dp)
+ hotseatBarSizePx: 252.0px (96.0dp)
+ inv.hotseatColumnSpan: 5
+ hotseatCellHeightPx: 166.0px (63.238094dp)
+ hotseatBarBottomSpacePx: 0.0px (0.0dp)
+ mHotseatBarEdgePaddingPx: 63.0px (24.0dp)
+ mHotseatBarWorkspaceSpacePx: 42.0px (16.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 118.0px (44.95238dp)
+ getHotseatLayoutPadding(context).top: 64.0px (24.380953dp)
+ getHotseatLayoutPadding(context).bottom: 49.0px (18.666666dp)
+ getHotseatLayoutPadding(context).left: 42.0px (16.0dp)
+ getHotseatLayoutPadding(context).right: 189.0px (72.0dp)
+ numShownHotseatIcons: 5
+ hotseatBorderSpace: 0.0px (0.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 0.0px (0.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:false
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 0.0px (0.0dp)
+ workspacePadding.left: 10.0px (3.8095238dp)
+ workspacePadding.top: 0.0px (0.0dp)
+ workspacePadding.right: 199.0px (75.809525dp)
+ workspacePadding.bottom: 0.0px (0.0dp)
+ iconScale: 1.0px (0.3809524dp)
+ cellScaleToFit : 1.0px (0.3809524dp)
+ extraSpace: 136.0px (51.809525dp)
+ unscaled extraSpace: 136.0px (51.809525dp)
+ maxEmptySpace: 0.0px (0.0dp)
+ workspaceTopPadding: 0.0px (0.0dp)
+ workspaceBottomPadding: 0.0px (0.0dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 16.0px (6.095238dp)
+ dropTargetBarSizePx: 95.0px (36.190475dp)
+ dropTargetBarBottomMarginPx: 16.0px (6.095238dp)
+ getCellLayoutSpringLoadShrunkTop(): 201.0px (76.57143dp)
+ getCellLayoutSpringLoadShrunkBottom(): 1008.0px (384.0dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
+ getWorkspaceSpringLoadScale(): 0.8021869px (0.305595dp)
+ getCellLayoutHeight(): 1006.0px (383.2381dp)
+ getCellLayoutWidth(): 1947.0px (741.7143dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt
new file mode 100644
index 0000000..6e764c2
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt
@@ -0,0 +1,127 @@
+DeviceProfile:
+ 1 dp = 2.0 px
+ isTablet:true
+ isPhone:false
+ transposeLayoutWithOrientation:false
+ isGestureMode:true
+ isLandscape:true
+ isMultiWindowMode:false
+ isTwoPanels:false
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 2560.0px (1280.0dp)
+ heightPx: 1600.0px (800.0dp)
+ availableWidthPx: 2560.0px (1280.0dp)
+ availableHeightPx: 1496.0px (748.0dp)
+ mInsets.left: 0.0px (0.0dp)
+ mInsets.top: 104.0px (52.0dp)
+ mInsets.right: 0.0px (0.0dp)
+ mInsets.bottom: 0.0px (0.0dp)
+ aspectRatio:1.6
+ isResponsiveGrid:false
+ isScalableGrid:true
+ inv.numRows: 5
+ inv.numColumns: 6
+ inv.numSearchContainerColumns: 3
+ minCellSize: PointF(120.0, 104.0)dp
+ cellWidthPx: 240.0px (120.0dp)
+ cellHeightPx: 208.0px (104.0dp)
+ getCellSize().x: 240.0px (120.0dp)
+ getCellSize().y: 208.0px (104.0dp)
+ cellLayoutBorderSpacePx Horizontal: 128.0px (64.0dp)
+ cellLayoutBorderSpacePx Vertical: 32.0px (16.0dp)
+ cellLayoutPaddingPx.left: 59.0px (29.5dp)
+ cellLayoutPaddingPx.top: 25.0px (12.5dp)
+ cellLayoutPaddingPx.right: 59.0px (29.5dp)
+ cellLayoutPaddingPx.bottom: 59.0px (29.5dp)
+ iconSizePx: 120.0px (60.0dp)
+ iconTextSizePx: 28.0px (14.0dp)
+ iconDrawablePaddingPx: 9.0px (4.5dp)
+ inv.numFolderRows: 3
+ inv.numFolderColumns: 3
+ folderCellWidthPx: 240.0px (120.0dp)
+ folderCellHeightPx: 208.0px (104.0dp)
+ folderChildIconSizePx: 120.0px (60.0dp)
+ folderChildTextSizePx: 28.0px (14.0dp)
+ folderChildDrawablePaddingPx: 11.0px (5.5dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 0.0px (0.0dp)
+ folderTopPadding: 48.0px (24.0dp)
+ folderFooterHeight: 112.0px (56.0dp)
+ bottomSheetTopPadding: 104.0px (52.0dp)
+ bottomSheetOpenDuration: 500
+ bottomSheetCloseDuration: 500
+ bottomSheetWorkspaceScale: 0.97
+ bottomSheetDepth: 0.0
+ allAppsShiftRange: 1496.0px (748.0dp)
+ allAppsTopPadding: 104.0px (52.0dp)
+ allAppsOpenDuration: 500
+ allAppsCloseDuration: 500
+ allAppsIconSizePx: 120.0px (60.0dp)
+ allAppsIconTextSizePx: 28.0px (14.0dp)
+ allAppsIconDrawablePaddingPx: 9.0px (4.5dp)
+ allAppsCellHeightPx: 284.0px (142.0dp)
+ allAppsCellWidthPx: 252.0px (126.0dp)
+ allAppsBorderSpacePxX: 32.0px (16.0dp)
+ allAppsBorderSpacePxY: 32.0px (16.0dp)
+ numShownAllAppsColumns: 6
+ allAppsLeftRightPadding: 32.0px (16.0dp)
+ allAppsLeftRightMargin: 412.0px (206.0dp)
+ hotseatBarSizePx: 200.0px (100.0dp)
+ inv.hotseatColumnSpan: 4
+ hotseatCellHeightPx: 135.0px (67.5dp)
+ hotseatBarBottomSpacePx: 80.0px (40.0dp)
+ mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+ mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 128.0px (64.0dp)
+ getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+ getHotseatLayoutPadding(context).bottom: 65.0px (32.5dp)
+ getHotseatLayoutPadding(context).left: 668.0px (334.0dp)
+ getHotseatLayoutPadding(context).right: 668.0px (334.0dp)
+ numShownHotseatIcons: 6
+ hotseatBorderSpace: 100.0px (50.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 1224.0px (612.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:true
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 240.0px (120.0dp)
+ workspacePadding.left: 181.0px (90.5dp)
+ workspacePadding.top: 0.0px (0.0dp)
+ workspacePadding.right: 181.0px (90.5dp)
+ workspacePadding.bottom: 244.0px (122.0dp)
+ iconScale: 1.0px (0.5dp)
+ cellScaleToFit : 1.0px (0.5dp)
+ extraSpace: 80.0px (40.0dp)
+ unscaled extraSpace: 80.0px (40.0dp)
+ maxEmptySpace: 200.0px (100.0dp)
+ workspaceTopPadding: 25.0px (12.5dp)
+ workspaceBottomPadding: 55.0px (27.5dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 0.0px (0.0dp)
+ dropTargetBarSizePx: 144.0px (72.0dp)
+ dropTargetBarBottomMarginPx: 64.0px (32.0dp)
+ getCellLayoutSpringLoadShrunkTop(): 312.0px (156.0dp)
+ getCellLayoutSpringLoadShrunkBottom(): 1272.0px (636.0dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)
+ getWorkspaceSpringLoadScale(): 0.76677316px (0.38338658dp)
+ getCellLayoutHeight(): 1252.0px (626.0dp)
+ getCellLayoutWidth(): 2198.0px (1099.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt
new file mode 100644
index 0000000..7650082
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt
@@ -0,0 +1,127 @@
+DeviceProfile:
+ 1 dp = 2.0 px
+ isTablet:true
+ isPhone:false
+ transposeLayoutWithOrientation:false
+ isGestureMode:false
+ isLandscape:true
+ isMultiWindowMode:false
+ isTwoPanels:false
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 2560.0px (1280.0dp)
+ heightPx: 1600.0px (800.0dp)
+ availableWidthPx: 2560.0px (1280.0dp)
+ availableHeightPx: 1496.0px (748.0dp)
+ mInsets.left: 0.0px (0.0dp)
+ mInsets.top: 104.0px (52.0dp)
+ mInsets.right: 0.0px (0.0dp)
+ mInsets.bottom: 0.0px (0.0dp)
+ aspectRatio:1.6
+ isResponsiveGrid:false
+ isScalableGrid:true
+ inv.numRows: 5
+ inv.numColumns: 6
+ inv.numSearchContainerColumns: 3
+ minCellSize: PointF(120.0, 104.0)dp
+ cellWidthPx: 240.0px (120.0dp)
+ cellHeightPx: 208.0px (104.0dp)
+ getCellSize().x: 240.0px (120.0dp)
+ getCellSize().y: 208.0px (104.0dp)
+ cellLayoutBorderSpacePx Horizontal: 128.0px (64.0dp)
+ cellLayoutBorderSpacePx Vertical: 32.0px (16.0dp)
+ cellLayoutPaddingPx.left: 59.0px (29.5dp)
+ cellLayoutPaddingPx.top: 25.0px (12.5dp)
+ cellLayoutPaddingPx.right: 59.0px (29.5dp)
+ cellLayoutPaddingPx.bottom: 59.0px (29.5dp)
+ iconSizePx: 120.0px (60.0dp)
+ iconTextSizePx: 28.0px (14.0dp)
+ iconDrawablePaddingPx: 9.0px (4.5dp)
+ inv.numFolderRows: 3
+ inv.numFolderColumns: 3
+ folderCellWidthPx: 240.0px (120.0dp)
+ folderCellHeightPx: 208.0px (104.0dp)
+ folderChildIconSizePx: 120.0px (60.0dp)
+ folderChildTextSizePx: 28.0px (14.0dp)
+ folderChildDrawablePaddingPx: 11.0px (5.5dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 0.0px (0.0dp)
+ folderTopPadding: 48.0px (24.0dp)
+ folderFooterHeight: 112.0px (56.0dp)
+ bottomSheetTopPadding: 104.0px (52.0dp)
+ bottomSheetOpenDuration: 500
+ bottomSheetCloseDuration: 500
+ bottomSheetWorkspaceScale: 0.97
+ bottomSheetDepth: 0.0
+ allAppsShiftRange: 1496.0px (748.0dp)
+ allAppsTopPadding: 104.0px (52.0dp)
+ allAppsOpenDuration: 500
+ allAppsCloseDuration: 500
+ allAppsIconSizePx: 120.0px (60.0dp)
+ allAppsIconTextSizePx: 28.0px (14.0dp)
+ allAppsIconDrawablePaddingPx: 9.0px (4.5dp)
+ allAppsCellHeightPx: 284.0px (142.0dp)
+ allAppsCellWidthPx: 252.0px (126.0dp)
+ allAppsBorderSpacePxX: 32.0px (16.0dp)
+ allAppsBorderSpacePxY: 32.0px (16.0dp)
+ numShownAllAppsColumns: 6
+ allAppsLeftRightPadding: 32.0px (16.0dp)
+ allAppsLeftRightMargin: 412.0px (206.0dp)
+ hotseatBarSizePx: 200.0px (100.0dp)
+ inv.hotseatColumnSpan: 4
+ hotseatCellHeightPx: 135.0px (67.5dp)
+ hotseatBarBottomSpacePx: 80.0px (40.0dp)
+ mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+ mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 128.0px (64.0dp)
+ getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+ getHotseatLayoutPadding(context).bottom: 65.0px (32.5dp)
+ getHotseatLayoutPadding(context).left: 668.0px (334.0dp)
+ getHotseatLayoutPadding(context).right: 668.0px (334.0dp)
+ numShownHotseatIcons: 6
+ hotseatBorderSpace: 100.0px (50.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 1224.0px (612.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:true
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 240.0px (120.0dp)
+ workspacePadding.left: 181.0px (90.5dp)
+ workspacePadding.top: 0.0px (0.0dp)
+ workspacePadding.right: 181.0px (90.5dp)
+ workspacePadding.bottom: 244.0px (122.0dp)
+ iconScale: 1.0px (0.5dp)
+ cellScaleToFit : 1.0px (0.5dp)
+ extraSpace: 80.0px (40.0dp)
+ unscaled extraSpace: 80.0px (40.0dp)
+ maxEmptySpace: 200.0px (100.0dp)
+ workspaceTopPadding: 25.0px (12.5dp)
+ workspaceBottomPadding: 55.0px (27.5dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 0.0px (0.0dp)
+ dropTargetBarSizePx: 144.0px (72.0dp)
+ dropTargetBarBottomMarginPx: 64.0px (32.0dp)
+ getCellLayoutSpringLoadShrunkTop(): 312.0px (156.0dp)
+ getCellLayoutSpringLoadShrunkBottom(): 1272.0px (636.0dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)
+ getWorkspaceSpringLoadScale(): 0.76677316px (0.38338658dp)
+ getCellLayoutHeight(): 1252.0px (626.0dp)
+ getCellLayoutWidth(): 2198.0px (1099.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt
new file mode 100644
index 0000000..2b241a1
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt
@@ -0,0 +1,127 @@
+DeviceProfile:
+ 1 dp = 2.0 px
+ isTablet:true
+ isPhone:false
+ transposeLayoutWithOrientation:false
+ isGestureMode:true
+ isLandscape:false
+ isMultiWindowMode:false
+ isTwoPanels:false
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 1600.0px (800.0dp)
+ heightPx: 2560.0px (1280.0dp)
+ availableWidthPx: 1600.0px (800.0dp)
+ availableHeightPx: 2456.0px (1228.0dp)
+ mInsets.left: 0.0px (0.0dp)
+ mInsets.top: 104.0px (52.0dp)
+ mInsets.right: 0.0px (0.0dp)
+ mInsets.bottom: 0.0px (0.0dp)
+ aspectRatio:1.6
+ isResponsiveGrid:false
+ isScalableGrid:true
+ inv.numRows: 5
+ inv.numColumns: 6
+ inv.numSearchContainerColumns: 3
+ minCellSize: PointF(102.0, 120.0)dp
+ cellWidthPx: 204.0px (102.0dp)
+ cellHeightPx: 240.0px (120.0dp)
+ getCellSize().x: 204.0px (102.0dp)
+ getCellSize().y: 240.0px (120.0dp)
+ cellLayoutBorderSpacePx Horizontal: 32.0px (16.0dp)
+ cellLayoutBorderSpacePx Vertical: 128.0px (64.0dp)
+ cellLayoutPaddingPx.left: 72.0px (36.0dp)
+ cellLayoutPaddingPx.top: 72.0px (36.0dp)
+ cellLayoutPaddingPx.right: 72.0px (36.0dp)
+ cellLayoutPaddingPx.bottom: 72.0px (36.0dp)
+ iconSizePx: 120.0px (60.0dp)
+ iconTextSizePx: 28.0px (14.0dp)
+ iconDrawablePaddingPx: 9.0px (4.5dp)
+ inv.numFolderRows: 3
+ inv.numFolderColumns: 3
+ folderCellWidthPx: 204.0px (102.0dp)
+ folderCellHeightPx: 240.0px (120.0dp)
+ folderChildIconSizePx: 120.0px (60.0dp)
+ folderChildTextSizePx: 28.0px (14.0dp)
+ folderChildDrawablePaddingPx: 22.0px (11.0dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 0.0px (0.0dp)
+ folderTopPadding: 48.0px (24.0dp)
+ folderFooterHeight: 112.0px (56.0dp)
+ bottomSheetTopPadding: 704.0px (352.0dp)
+ bottomSheetOpenDuration: 500
+ bottomSheetCloseDuration: 500
+ bottomSheetWorkspaceScale: 0.97
+ bottomSheetDepth: 0.0
+ allAppsShiftRange: 1810.0px (905.0dp)
+ allAppsTopPadding: 750.0px (375.0dp)
+ allAppsOpenDuration: 500
+ allAppsCloseDuration: 500
+ allAppsIconSizePx: 120.0px (60.0dp)
+ allAppsIconTextSizePx: 28.0px (14.0dp)
+ allAppsIconDrawablePaddingPx: 9.0px (4.5dp)
+ allAppsCellHeightPx: 316.0px (158.0dp)
+ allAppsCellWidthPx: 192.0px (96.0dp)
+ allAppsBorderSpacePxX: 16.0px (8.0dp)
+ allAppsBorderSpacePxY: 32.0px (16.0dp)
+ numShownAllAppsColumns: 6
+ allAppsLeftRightPadding: 32.0px (16.0dp)
+ allAppsLeftRightMargin: 152.0px (76.0dp)
+ hotseatBarSizePx: 272.0px (136.0dp)
+ inv.hotseatColumnSpan: 6
+ hotseatCellHeightPx: 135.0px (67.5dp)
+ hotseatBarBottomSpacePx: 152.0px (76.0dp)
+ mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+ mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 216.0px (108.0dp)
+ getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+ getHotseatLayoutPadding(context).bottom: 137.0px (68.5dp)
+ getHotseatLayoutPadding(context).left: 150.0px (75.0dp)
+ getHotseatLayoutPadding(context).right: 150.0px (75.0dp)
+ numShownHotseatIcons: 6
+ hotseatBorderSpace: 116.0px (58.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 1300.0px (650.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:true
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 108.0px (54.0dp)
+ workspacePadding.left: 36.0px (18.0dp)
+ workspacePadding.top: 132.0px (66.0dp)
+ workspacePadding.right: 36.0px (18.0dp)
+ workspacePadding.bottom: 468.0px (234.0dp)
+ iconScale: 1.0px (0.5dp)
+ cellScaleToFit : 1.0px (0.5dp)
+ extraSpace: 424.0px (212.0dp)
+ unscaled extraSpace: 424.0px (212.0dp)
+ maxEmptySpace: 19998.0px (9999.0dp)
+ workspaceTopPadding: 204.0px (102.0dp)
+ workspaceBottomPadding: 220.0px (110.0dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 220.0px (110.0dp)
+ dropTargetBarSizePx: 144.0px (72.0dp)
+ dropTargetBarBottomMarginPx: 96.0px (48.0dp)
+ getCellLayoutSpringLoadShrunkTop(): 564.0px (282.0dp)
+ getCellLayoutSpringLoadShrunkBottom(): 2072.0px (1036.0dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)
+ getWorkspaceSpringLoadScale(): 0.8125px (0.40625dp)
+ getCellLayoutHeight(): 1856.0px (928.0dp)
+ getCellLayoutWidth(): 1528.0px (764.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt
new file mode 100644
index 0000000..6d38d27
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt
@@ -0,0 +1,127 @@
+DeviceProfile:
+ 1 dp = 2.0 px
+ isTablet:true
+ isPhone:false
+ transposeLayoutWithOrientation:false
+ isGestureMode:false
+ isLandscape:false
+ isMultiWindowMode:false
+ isTwoPanels:false
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 1600.0px (800.0dp)
+ heightPx: 2560.0px (1280.0dp)
+ availableWidthPx: 1600.0px (800.0dp)
+ availableHeightPx: 2456.0px (1228.0dp)
+ mInsets.left: 0.0px (0.0dp)
+ mInsets.top: 104.0px (52.0dp)
+ mInsets.right: 0.0px (0.0dp)
+ mInsets.bottom: 0.0px (0.0dp)
+ aspectRatio:1.6
+ isResponsiveGrid:false
+ isScalableGrid:true
+ inv.numRows: 5
+ inv.numColumns: 6
+ inv.numSearchContainerColumns: 3
+ minCellSize: PointF(102.0, 120.0)dp
+ cellWidthPx: 204.0px (102.0dp)
+ cellHeightPx: 240.0px (120.0dp)
+ getCellSize().x: 204.0px (102.0dp)
+ getCellSize().y: 240.0px (120.0dp)
+ cellLayoutBorderSpacePx Horizontal: 32.0px (16.0dp)
+ cellLayoutBorderSpacePx Vertical: 128.0px (64.0dp)
+ cellLayoutPaddingPx.left: 72.0px (36.0dp)
+ cellLayoutPaddingPx.top: 72.0px (36.0dp)
+ cellLayoutPaddingPx.right: 72.0px (36.0dp)
+ cellLayoutPaddingPx.bottom: 72.0px (36.0dp)
+ iconSizePx: 120.0px (60.0dp)
+ iconTextSizePx: 28.0px (14.0dp)
+ iconDrawablePaddingPx: 9.0px (4.5dp)
+ inv.numFolderRows: 3
+ inv.numFolderColumns: 3
+ folderCellWidthPx: 204.0px (102.0dp)
+ folderCellHeightPx: 240.0px (120.0dp)
+ folderChildIconSizePx: 120.0px (60.0dp)
+ folderChildTextSizePx: 28.0px (14.0dp)
+ folderChildDrawablePaddingPx: 22.0px (11.0dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 0.0px (0.0dp)
+ folderTopPadding: 48.0px (24.0dp)
+ folderFooterHeight: 112.0px (56.0dp)
+ bottomSheetTopPadding: 704.0px (352.0dp)
+ bottomSheetOpenDuration: 500
+ bottomSheetCloseDuration: 500
+ bottomSheetWorkspaceScale: 0.97
+ bottomSheetDepth: 0.0
+ allAppsShiftRange: 1810.0px (905.0dp)
+ allAppsTopPadding: 750.0px (375.0dp)
+ allAppsOpenDuration: 500
+ allAppsCloseDuration: 500
+ allAppsIconSizePx: 120.0px (60.0dp)
+ allAppsIconTextSizePx: 28.0px (14.0dp)
+ allAppsIconDrawablePaddingPx: 9.0px (4.5dp)
+ allAppsCellHeightPx: 316.0px (158.0dp)
+ allAppsCellWidthPx: 192.0px (96.0dp)
+ allAppsBorderSpacePxX: 16.0px (8.0dp)
+ allAppsBorderSpacePxY: 32.0px (16.0dp)
+ numShownAllAppsColumns: 6
+ allAppsLeftRightPadding: 32.0px (16.0dp)
+ allAppsLeftRightMargin: 152.0px (76.0dp)
+ hotseatBarSizePx: 272.0px (136.0dp)
+ inv.hotseatColumnSpan: 6
+ hotseatCellHeightPx: 135.0px (67.5dp)
+ hotseatBarBottomSpacePx: 152.0px (76.0dp)
+ mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+ mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 216.0px (108.0dp)
+ getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+ getHotseatLayoutPadding(context).bottom: 137.0px (68.5dp)
+ getHotseatLayoutPadding(context).left: 150.0px (75.0dp)
+ getHotseatLayoutPadding(context).right: 150.0px (75.0dp)
+ numShownHotseatIcons: 6
+ hotseatBorderSpace: 116.0px (58.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 1300.0px (650.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:true
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 108.0px (54.0dp)
+ workspacePadding.left: 36.0px (18.0dp)
+ workspacePadding.top: 132.0px (66.0dp)
+ workspacePadding.right: 36.0px (18.0dp)
+ workspacePadding.bottom: 468.0px (234.0dp)
+ iconScale: 1.0px (0.5dp)
+ cellScaleToFit : 1.0px (0.5dp)
+ extraSpace: 424.0px (212.0dp)
+ unscaled extraSpace: 424.0px (212.0dp)
+ maxEmptySpace: 19998.0px (9999.0dp)
+ workspaceTopPadding: 204.0px (102.0dp)
+ workspaceBottomPadding: 220.0px (110.0dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 220.0px (110.0dp)
+ dropTargetBarSizePx: 144.0px (72.0dp)
+ dropTargetBarBottomMarginPx: 96.0px (48.0dp)
+ getCellLayoutSpringLoadShrunkTop(): 564.0px (282.0dp)
+ getCellLayoutSpringLoadShrunkBottom(): 2072.0px (1036.0dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)
+ getWorkspaceSpringLoadScale(): 0.8125px (0.40625dp)
+ getCellLayoutHeight(): 1856.0px (928.0dp)
+ getCellLayoutWidth(): 1528.0px (764.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt
new file mode 100644
index 0000000..5799de7
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt
@@ -0,0 +1,127 @@
+DeviceProfile:
+ 1 dp = 2.625 px
+ isTablet:true
+ isPhone:false
+ transposeLayoutWithOrientation:false
+ isGestureMode:true
+ isLandscape:true
+ isMultiWindowMode:false
+ isTwoPanels:true
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 2208.0px (841.1429dp)
+ heightPx: 1840.0px (700.9524dp)
+ availableWidthPx: 2208.0px (841.1429dp)
+ availableHeightPx: 1730.0px (659.0476dp)
+ mInsets.left: 0.0px (0.0dp)
+ mInsets.top: 110.0px (41.904762dp)
+ mInsets.right: 0.0px (0.0dp)
+ mInsets.bottom: 0.0px (0.0dp)
+ aspectRatio:1.2
+ isResponsiveGrid:false
+ isScalableGrid:false
+ inv.numRows: 4
+ inv.numColumns: 4
+ inv.numSearchContainerColumns: 4
+ minCellSize: PointF(0.0, 0.0)dp
+ cellWidthPx: 154.0px (58.666668dp)
+ cellHeightPx: 218.0px (83.04762dp)
+ getCellSize().x: 270.0px (102.85714dp)
+ getCellSize().y: 342.0px (130.28572dp)
+ cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+ cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+ cellLayoutPaddingPx.left: 0.0px (0.0dp)
+ cellLayoutPaddingPx.top: 0.0px (0.0dp)
+ cellLayoutPaddingPx.right: 0.0px (0.0dp)
+ cellLayoutPaddingPx.bottom: 0.0px (0.0dp)
+ iconSizePx: 141.0px (53.714287dp)
+ iconTextSizePx: 34.0px (12.952381dp)
+ iconDrawablePaddingPx: 13.0px (4.952381dp)
+ inv.numFolderRows: 3
+ inv.numFolderColumns: 4
+ folderCellWidthPx: 189.0px (72.0dp)
+ folderCellHeightPx: 219.0px (83.42857dp)
+ folderChildIconSizePx: 141.0px (53.714287dp)
+ folderChildTextSizePx: 34.0px (12.952381dp)
+ folderChildDrawablePaddingPx: 5.0px (1.9047619dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 21.0px (8.0dp)
+ folderTopPadding: 63.0px (24.0dp)
+ folderFooterHeight: 147.0px (56.0dp)
+ bottomSheetTopPadding: 110.0px (41.904762dp)
+ bottomSheetOpenDuration: 500
+ bottomSheetCloseDuration: 500
+ bottomSheetWorkspaceScale: 0.97
+ bottomSheetDepth: 1.0
+ allAppsShiftRange: 1730.0px (659.0476dp)
+ allAppsTopPadding: 110.0px (41.904762dp)
+ allAppsOpenDuration: 500
+ allAppsCloseDuration: 500
+ allAppsIconSizePx: 141.0px (53.714287dp)
+ allAppsIconTextSizePx: 34.0px (12.952381dp)
+ allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+ allAppsCellHeightPx: 315.0px (120.0dp)
+ allAppsCellWidthPx: 183.0px (69.71429dp)
+ allAppsBorderSpacePxX: 42.0px (16.0dp)
+ allAppsBorderSpacePxY: 42.0px (16.0dp)
+ numShownAllAppsColumns: 8
+ allAppsLeftRightPadding: 42.0px (16.0dp)
+ allAppsLeftRightMargin: 183.0px (69.71429dp)
+ hotseatBarSizePx: 267.0px (101.71429dp)
+ inv.hotseatColumnSpan: 4
+ hotseatCellHeightPx: 159.0px (60.57143dp)
+ hotseatBarBottomSpacePx: 126.0px (48.0dp)
+ mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+ mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 116.0px (44.190475dp)
+ getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+ getHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)
+ getHotseatLayoutPadding(context).left: 113.0px (43.04762dp)
+ getHotseatLayoutPadding(context).right: 113.0px (43.04762dp)
+ numShownHotseatIcons: 6
+ hotseatBorderSpace: 0.0px (0.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 0.0px (0.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:true
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)
+ workspacePadding.left: 21.0px (8.0dp)
+ workspacePadding.top: 30.0px (11.428572dp)
+ workspacePadding.right: 21.0px (8.0dp)
+ workspacePadding.bottom: 330.0px (125.71429dp)
+ iconScale: 1.0px (0.3809524dp)
+ cellScaleToFit : 1.0px (0.3809524dp)
+ extraSpace: 498.0px (189.71428dp)
+ unscaled extraSpace: 498.0px (189.71428dp)
+ maxEmptySpace: 0.0px (0.0dp)
+ workspaceTopPadding: 0.0px (0.0dp)
+ workspaceBottomPadding: 0.0px (0.0dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 0.0px (0.0dp)
+ dropTargetBarSizePx: 147.0px (56.0dp)
+ dropTargetBarBottomMarginPx: 42.0px (16.0dp)
+ getCellLayoutSpringLoadShrunkTop(): 299.0px (113.90476dp)
+ getCellLayoutSpringLoadShrunkBottom(): 1457.0px (555.0476dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
+ getWorkspaceSpringLoadScale(): 0.8452555px (0.32200208dp)
+ getCellLayoutHeight(): 1370.0px (521.9048dp)
+ getCellLayoutWidth(): 1083.0px (412.57144dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt
new file mode 100644
index 0000000..b4956ff
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt
@@ -0,0 +1,127 @@
+DeviceProfile:
+ 1 dp = 2.625 px
+ isTablet:true
+ isPhone:false
+ transposeLayoutWithOrientation:false
+ isGestureMode:false
+ isLandscape:true
+ isMultiWindowMode:false
+ isTwoPanels:true
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 2208.0px (841.1429dp)
+ heightPx: 1840.0px (700.9524dp)
+ availableWidthPx: 2208.0px (841.1429dp)
+ availableHeightPx: 1730.0px (659.0476dp)
+ mInsets.left: 0.0px (0.0dp)
+ mInsets.top: 110.0px (41.904762dp)
+ mInsets.right: 0.0px (0.0dp)
+ mInsets.bottom: 0.0px (0.0dp)
+ aspectRatio:1.2
+ isResponsiveGrid:false
+ isScalableGrid:false
+ inv.numRows: 4
+ inv.numColumns: 4
+ inv.numSearchContainerColumns: 4
+ minCellSize: PointF(0.0, 0.0)dp
+ cellWidthPx: 154.0px (58.666668dp)
+ cellHeightPx: 218.0px (83.04762dp)
+ getCellSize().x: 270.0px (102.85714dp)
+ getCellSize().y: 342.0px (130.28572dp)
+ cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+ cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+ cellLayoutPaddingPx.left: 0.0px (0.0dp)
+ cellLayoutPaddingPx.top: 0.0px (0.0dp)
+ cellLayoutPaddingPx.right: 0.0px (0.0dp)
+ cellLayoutPaddingPx.bottom: 0.0px (0.0dp)
+ iconSizePx: 141.0px (53.714287dp)
+ iconTextSizePx: 34.0px (12.952381dp)
+ iconDrawablePaddingPx: 13.0px (4.952381dp)
+ inv.numFolderRows: 3
+ inv.numFolderColumns: 4
+ folderCellWidthPx: 189.0px (72.0dp)
+ folderCellHeightPx: 219.0px (83.42857dp)
+ folderChildIconSizePx: 141.0px (53.714287dp)
+ folderChildTextSizePx: 34.0px (12.952381dp)
+ folderChildDrawablePaddingPx: 5.0px (1.9047619dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 21.0px (8.0dp)
+ folderTopPadding: 63.0px (24.0dp)
+ folderFooterHeight: 147.0px (56.0dp)
+ bottomSheetTopPadding: 110.0px (41.904762dp)
+ bottomSheetOpenDuration: 500
+ bottomSheetCloseDuration: 500
+ bottomSheetWorkspaceScale: 0.97
+ bottomSheetDepth: 1.0
+ allAppsShiftRange: 1730.0px (659.0476dp)
+ allAppsTopPadding: 110.0px (41.904762dp)
+ allAppsOpenDuration: 500
+ allAppsCloseDuration: 500
+ allAppsIconSizePx: 141.0px (53.714287dp)
+ allAppsIconTextSizePx: 34.0px (12.952381dp)
+ allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+ allAppsCellHeightPx: 315.0px (120.0dp)
+ allAppsCellWidthPx: 183.0px (69.71429dp)
+ allAppsBorderSpacePxX: 42.0px (16.0dp)
+ allAppsBorderSpacePxY: 42.0px (16.0dp)
+ numShownAllAppsColumns: 8
+ allAppsLeftRightPadding: 42.0px (16.0dp)
+ allAppsLeftRightMargin: 183.0px (69.71429dp)
+ hotseatBarSizePx: 267.0px (101.71429dp)
+ inv.hotseatColumnSpan: 4
+ hotseatCellHeightPx: 159.0px (60.57143dp)
+ hotseatBarBottomSpacePx: 126.0px (48.0dp)
+ mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+ mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 116.0px (44.190475dp)
+ getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+ getHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)
+ getHotseatLayoutPadding(context).left: 113.0px (43.04762dp)
+ getHotseatLayoutPadding(context).right: 113.0px (43.04762dp)
+ numShownHotseatIcons: 6
+ hotseatBorderSpace: 0.0px (0.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 0.0px (0.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:true
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)
+ workspacePadding.left: 21.0px (8.0dp)
+ workspacePadding.top: 30.0px (11.428572dp)
+ workspacePadding.right: 21.0px (8.0dp)
+ workspacePadding.bottom: 330.0px (125.71429dp)
+ iconScale: 1.0px (0.3809524dp)
+ cellScaleToFit : 1.0px (0.3809524dp)
+ extraSpace: 498.0px (189.71428dp)
+ unscaled extraSpace: 498.0px (189.71428dp)
+ maxEmptySpace: 0.0px (0.0dp)
+ workspaceTopPadding: 0.0px (0.0dp)
+ workspaceBottomPadding: 0.0px (0.0dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 0.0px (0.0dp)
+ dropTargetBarSizePx: 147.0px (56.0dp)
+ dropTargetBarBottomMarginPx: 42.0px (16.0dp)
+ getCellLayoutSpringLoadShrunkTop(): 299.0px (113.90476dp)
+ getCellLayoutSpringLoadShrunkBottom(): 1457.0px (555.0476dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
+ getWorkspaceSpringLoadScale(): 0.8452555px (0.32200208dp)
+ getCellLayoutHeight(): 1370.0px (521.9048dp)
+ getCellLayoutWidth(): 1083.0px (412.57144dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt
new file mode 100644
index 0000000..15afb61
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt
@@ -0,0 +1,127 @@
+DeviceProfile:
+ 1 dp = 2.625 px
+ isTablet:true
+ isPhone:false
+ transposeLayoutWithOrientation:false
+ isGestureMode:true
+ isLandscape:false
+ isMultiWindowMode:false
+ isTwoPanels:true
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 1840.0px (700.9524dp)
+ heightPx: 2208.0px (841.1429dp)
+ availableWidthPx: 1840.0px (700.9524dp)
+ availableHeightPx: 2075.0px (790.4762dp)
+ mInsets.left: 0.0px (0.0dp)
+ mInsets.top: 133.0px (50.666668dp)
+ mInsets.right: 0.0px (0.0dp)
+ mInsets.bottom: 0.0px (0.0dp)
+ aspectRatio:1.2
+ isResponsiveGrid:false
+ isScalableGrid:false
+ inv.numRows: 4
+ inv.numColumns: 4
+ inv.numSearchContainerColumns: 4
+ minCellSize: PointF(0.0, 0.0)dp
+ cellWidthPx: 154.0px (58.666668dp)
+ cellHeightPx: 218.0px (83.04762dp)
+ getCellSize().x: 224.0px (85.333336dp)
+ getCellSize().y: 430.0px (163.80952dp)
+ cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+ cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+ cellLayoutPaddingPx.left: 0.0px (0.0dp)
+ cellLayoutPaddingPx.top: 0.0px (0.0dp)
+ cellLayoutPaddingPx.right: 0.0px (0.0dp)
+ cellLayoutPaddingPx.bottom: 0.0px (0.0dp)
+ iconSizePx: 141.0px (53.714287dp)
+ iconTextSizePx: 34.0px (12.952381dp)
+ iconDrawablePaddingPx: 13.0px (4.952381dp)
+ inv.numFolderRows: 3
+ inv.numFolderColumns: 4
+ folderCellWidthPx: 189.0px (72.0dp)
+ folderCellHeightPx: 219.0px (83.42857dp)
+ folderChildIconSizePx: 141.0px (53.714287dp)
+ folderChildTextSizePx: 34.0px (12.952381dp)
+ folderChildDrawablePaddingPx: 5.0px (1.9047619dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 21.0px (8.0dp)
+ folderTopPadding: 63.0px (24.0dp)
+ folderFooterHeight: 147.0px (56.0dp)
+ bottomSheetTopPadding: 133.0px (50.666668dp)
+ bottomSheetOpenDuration: 500
+ bottomSheetCloseDuration: 500
+ bottomSheetWorkspaceScale: 0.97
+ bottomSheetDepth: 1.0
+ allAppsShiftRange: 1826.0px (695.619dp)
+ allAppsTopPadding: 382.0px (145.5238dp)
+ allAppsOpenDuration: 500
+ allAppsCloseDuration: 500
+ allAppsIconSizePx: 141.0px (53.714287dp)
+ allAppsIconTextSizePx: 34.0px (12.952381dp)
+ allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+ allAppsCellHeightPx: 315.0px (120.0dp)
+ allAppsCellWidthPx: 183.0px (69.71429dp)
+ allAppsBorderSpacePxX: 42.0px (16.0dp)
+ allAppsBorderSpacePxY: 42.0px (16.0dp)
+ numShownAllAppsColumns: 8
+ allAppsLeftRightPadding: 42.0px (16.0dp)
+ allAppsLeftRightMargin: 1.0px (0.3809524dp)
+ hotseatBarSizePx: 267.0px (101.71429dp)
+ inv.hotseatColumnSpan: 4
+ hotseatCellHeightPx: 159.0px (60.57143dp)
+ hotseatBarBottomSpacePx: 126.0px (48.0dp)
+ mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+ mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 171.0px (65.14286dp)
+ getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+ getHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)
+ getHotseatLayoutPadding(context).left: 98.0px (37.333332dp)
+ getHotseatLayoutPadding(context).right: 98.0px (37.333332dp)
+ numShownHotseatIcons: 6
+ hotseatBorderSpace: 0.0px (0.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 0.0px (0.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:true
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)
+ workspacePadding.left: 21.0px (8.0dp)
+ workspacePadding.top: 24.0px (9.142858dp)
+ workspacePadding.right: 21.0px (8.0dp)
+ workspacePadding.bottom: 330.0px (125.71429dp)
+ iconScale: 1.0px (0.3809524dp)
+ cellScaleToFit : 1.0px (0.3809524dp)
+ extraSpace: 849.0px (323.42856dp)
+ unscaled extraSpace: 849.0px (323.42856dp)
+ maxEmptySpace: 0.0px (0.0dp)
+ workspaceTopPadding: 0.0px (0.0dp)
+ workspaceBottomPadding: 0.0px (0.0dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 168.0px (64.0dp)
+ dropTargetBarSizePx: 147.0px (56.0dp)
+ dropTargetBarBottomMarginPx: 42.0px (16.0dp)
+ getCellLayoutSpringLoadShrunkTop(): 490.0px (186.66667dp)
+ getCellLayoutSpringLoadShrunkBottom(): 1770.0px (674.2857dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
+ getWorkspaceSpringLoadScale(): 0.7437536px (0.2833347dp)
+ getCellLayoutHeight(): 1721.0px (655.619dp)
+ getCellLayoutWidth(): 899.0px (342.4762dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt
new file mode 100644
index 0000000..6cbed1f
--- /dev/null
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt
@@ -0,0 +1,127 @@
+DeviceProfile:
+ 1 dp = 2.625 px
+ isTablet:true
+ isPhone:false
+ transposeLayoutWithOrientation:false
+ isGestureMode:false
+ isLandscape:false
+ isMultiWindowMode:false
+ isTwoPanels:true
+ windowX: 0.0px (0.0dp)
+ windowY: 0.0px (0.0dp)
+ widthPx: 1840.0px (700.9524dp)
+ heightPx: 2208.0px (841.1429dp)
+ availableWidthPx: 1840.0px (700.9524dp)
+ availableHeightPx: 2075.0px (790.4762dp)
+ mInsets.left: 0.0px (0.0dp)
+ mInsets.top: 133.0px (50.666668dp)
+ mInsets.right: 0.0px (0.0dp)
+ mInsets.bottom: 0.0px (0.0dp)
+ aspectRatio:1.2
+ isResponsiveGrid:false
+ isScalableGrid:false
+ inv.numRows: 4
+ inv.numColumns: 4
+ inv.numSearchContainerColumns: 4
+ minCellSize: PointF(0.0, 0.0)dp
+ cellWidthPx: 154.0px (58.666668dp)
+ cellHeightPx: 218.0px (83.04762dp)
+ getCellSize().x: 224.0px (85.333336dp)
+ getCellSize().y: 430.0px (163.80952dp)
+ cellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)
+ cellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)
+ cellLayoutPaddingPx.left: 0.0px (0.0dp)
+ cellLayoutPaddingPx.top: 0.0px (0.0dp)
+ cellLayoutPaddingPx.right: 0.0px (0.0dp)
+ cellLayoutPaddingPx.bottom: 0.0px (0.0dp)
+ iconSizePx: 141.0px (53.714287dp)
+ iconTextSizePx: 34.0px (12.952381dp)
+ iconDrawablePaddingPx: 13.0px (4.952381dp)
+ inv.numFolderRows: 3
+ inv.numFolderColumns: 4
+ folderCellWidthPx: 189.0px (72.0dp)
+ folderCellHeightPx: 219.0px (83.42857dp)
+ folderChildIconSizePx: 141.0px (53.714287dp)
+ folderChildTextSizePx: 34.0px (12.952381dp)
+ folderChildDrawablePaddingPx: 5.0px (1.9047619dp)
+ folderCellLayoutBorderSpacePx.x: 0.0px (0.0dp)
+ folderCellLayoutBorderSpacePx.y: 0.0px (0.0dp)
+ folderContentPaddingLeftRight: 21.0px (8.0dp)
+ folderTopPadding: 63.0px (24.0dp)
+ folderFooterHeight: 147.0px (56.0dp)
+ bottomSheetTopPadding: 133.0px (50.666668dp)
+ bottomSheetOpenDuration: 500
+ bottomSheetCloseDuration: 500
+ bottomSheetWorkspaceScale: 0.97
+ bottomSheetDepth: 1.0
+ allAppsShiftRange: 1826.0px (695.619dp)
+ allAppsTopPadding: 382.0px (145.5238dp)
+ allAppsOpenDuration: 500
+ allAppsCloseDuration: 500
+ allAppsIconSizePx: 141.0px (53.714287dp)
+ allAppsIconTextSizePx: 34.0px (12.952381dp)
+ allAppsIconDrawablePaddingPx: 21.0px (8.0dp)
+ allAppsCellHeightPx: 315.0px (120.0dp)
+ allAppsCellWidthPx: 183.0px (69.71429dp)
+ allAppsBorderSpacePxX: 42.0px (16.0dp)
+ allAppsBorderSpacePxY: 42.0px (16.0dp)
+ numShownAllAppsColumns: 8
+ allAppsLeftRightPadding: 42.0px (16.0dp)
+ allAppsLeftRightMargin: 1.0px (0.3809524dp)
+ hotseatBarSizePx: 267.0px (101.71429dp)
+ inv.hotseatColumnSpan: 4
+ hotseatCellHeightPx: 159.0px (60.57143dp)
+ hotseatBarBottomSpacePx: 126.0px (48.0dp)
+ mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
+ mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ hotseatBarEndOffset: 0.0px (0.0dp)
+ hotseatQsbSpace: 0.0px (0.0dp)
+ hotseatQsbHeight: 0.0px (0.0dp)
+ springLoadedHotseatBarTopMarginPx: 171.0px (65.14286dp)
+ getHotseatLayoutPadding(context).top: 0.0px (0.0dp)
+ getHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)
+ getHotseatLayoutPadding(context).left: 98.0px (37.333332dp)
+ getHotseatLayoutPadding(context).right: 98.0px (37.333332dp)
+ numShownHotseatIcons: 6
+ hotseatBorderSpace: 0.0px (0.0dp)
+ isQsbInline: false
+ hotseatQsbWidth: 0.0px (0.0dp)
+ isTaskbarPresent:false
+ isTaskbarPresentInApps:true
+ taskbarHeight: 0.0px (0.0dp)
+ stashedTaskbarHeight: 0.0px (0.0dp)
+ taskbarBottomMargin: 0.0px (0.0dp)
+ taskbarIconSize: 0.0px (0.0dp)
+ desiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)
+ workspacePadding.left: 21.0px (8.0dp)
+ workspacePadding.top: 24.0px (9.142858dp)
+ workspacePadding.right: 21.0px (8.0dp)
+ workspacePadding.bottom: 330.0px (125.71429dp)
+ iconScale: 1.0px (0.3809524dp)
+ cellScaleToFit : 1.0px (0.3809524dp)
+ extraSpace: 849.0px (323.42856dp)
+ unscaled extraSpace: 849.0px (323.42856dp)
+ maxEmptySpace: 0.0px (0.0dp)
+ workspaceTopPadding: 0.0px (0.0dp)
+ workspaceBottomPadding: 0.0px (0.0dp)
+ overviewTaskMarginPx: 0.0px (0.0dp)
+ overviewTaskIconSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizePx: 0.0px (0.0dp)
+ overviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)
+ overviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)
+ overviewActionsTopMarginPx: 0.0px (0.0dp)
+ overviewActionsHeight: 0.0px (0.0dp)
+ overviewActionsClaimedSpaceBelow: 0.0px (0.0dp)
+ overviewActionsButtonSpacing: 0.0px (0.0dp)
+ overviewPageSpacing: 0.0px (0.0dp)
+ overviewRowSpacing: 0.0px (0.0dp)
+ overviewGridSideMargin: 0.0px (0.0dp)
+ dropTargetBarTopMarginPx: 168.0px (64.0dp)
+ dropTargetBarSizePx: 147.0px (56.0dp)
+ dropTargetBarBottomMarginPx: 42.0px (16.0dp)
+ getCellLayoutSpringLoadShrunkTop(): 490.0px (186.66667dp)
+ getCellLayoutSpringLoadShrunkBottom(): 1770.0px (674.2857dp)
+ workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
+ getWorkspaceSpringLoadScale(): 0.7437536px (0.2833347dp)
+ getCellLayoutHeight(): 1721.0px (655.619dp)
+ getCellLayoutWidth(): 899.0px (342.4762dp)
diff --git a/tests/res/drawable/test_widget_dynamic_colors_icon.xml b/tests/res/drawable/test_widget_dynamic_colors_icon.xml
new file mode 100644
index 0000000..69f6675
--- /dev/null
+++ b/tests/res/drawable/test_widget_dynamic_colors_icon.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@android:color/white"/>
+ <foreground>
+ <color android:color="#964B00"/>
+ </foreground>
+ <monochrome>
+ <vector android:width="48dp" android:height="48dp" android:viewportWidth="48.0" android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M0,24L48,24 48,48, 0,48 Z"/>
+ </vector>
+ </monochrome>
+</adaptive-icon>
diff --git a/tests/res/drawable/test_widget_no_config_icon.xml b/tests/res/drawable/test_widget_no_config_icon.xml
new file mode 100644
index 0000000..e3d0125
--- /dev/null
+++ b/tests/res/drawable/test_widget_no_config_icon.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@android:color/white"/>
+ <foreground>
+ <color android:color="#00FFFF"/>
+ </foreground>
+ <monochrome>
+ <vector android:width="48dp" android:height="48dp" android:viewportWidth="48.0" android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M0,24L48,24 48,48, 0,48 Z"/>
+ </vector>
+ </monochrome>
+</adaptive-icon>
diff --git a/tests/res/drawable/test_widget_with_config_icon.xml b/tests/res/drawable/test_widget_with_config_icon.xml
new file mode 100644
index 0000000..98b797b
--- /dev/null
+++ b/tests/res/drawable/test_widget_with_config_icon.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@android:color/white"/>
+ <foreground>
+ <color android:color="#008000" />
+ </foreground>
+ <monochrome>
+ <vector android:width="48dp" android:height="48dp" android:viewportWidth="48.0" android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M0,24L48,24 48,48, 0,48 Z"/>
+ </vector>
+ </monochrome>
+</adaptive-icon>
diff --git a/tests/res/drawable/test_widget_with_dialog_icon.xml b/tests/res/drawable/test_widget_with_dialog_icon.xml
new file mode 100644
index 0000000..d2879d2
--- /dev/null
+++ b/tests/res/drawable/test_widget_with_dialog_icon.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@android:color/white"/>
+ <foreground>
+ <color android:color="#800080"/>
+ </foreground>
+ <monochrome>
+ <vector android:width="48dp" android:height="48dp" android:viewportWidth="48.0" android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M0,24L48,24 48,48, 0,48 Z"/>
+ </vector>
+ </monochrome>
+</adaptive-icon>
diff --git a/tests/res/raw/cache_data_updated_task_data.txt b/tests/res/raw/cache_data_updated_task_data.txt
deleted file mode 100644
index 603dbe3..0000000
--- a/tests/res/raw/cache_data_updated_task_data.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-# Model data used by CacheDataUpdatedTaskTest
-
-classMap s com.android.launcher3.model.data.WorkspaceItemInfo
-
-# Items for the BgDataModel
-
-# App shortcuts
-bgItem s itemType=0 title=app1-class1 intent=component=app1/class1 id=1
-bgItem s itemType=0 title=app1-class2 intent=component=app1/class2 id=2
-bgItem s itemType=0 title=app2-class1 intent=component=app2/class1 id=3
-bgItem s itemType=0 title=app2-class2 intent=component=app2/class2 id=4
-
-# Auto install app shortcut
-bgItem s itemType=0 status=2 title=app3-class1 intent=component=app3/class1 id=5
-bgItem s itemType=0 status=2 title=app3-class2 intent=component=app3/class2 id=6
-
-# Custom shortcuts
-bgItem s itemType=1 title=app1-shrt intent=component=app1/class3 id=7
-bgItem s itemType=1 title=app4-shrt intent=component=app4/class1 id=8
-
-# Restored custom shortcut
-bgItem s itemType=1 status=1 title=app3-shrt intent=component=app3/class3 id=9
-bgItem s itemType=1 status=1 title=app5-shrt intent=component=app5/class1 id=10
-
-allApps componentName=app1/class1 intent=component=app1/class1
-allApps componentName=app1/class2 intent=component=app1/class2
-allApps componentName=app2/class1 intent=component=app2/class1
-allApps componentName=app2/class2 intent=component=app2/class2
\ No newline at end of file
diff --git a/tests/res/raw/package_install_state_change_task_data.txt b/tests/res/raw/package_install_state_change_task_data.txt
deleted file mode 100644
index e82ea9d..0000000
--- a/tests/res/raw/package_install_state_change_task_data.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-# Model data used by PackageInstallStateChangeTaskTest
-
-classMap s com.android.launcher3.model.data.WorkspaceItemInfo
-classMap w com.android.launcher3.model.data.LauncherAppWidgetInfo
-
-# Items for the BgDataModel
-
-# App shortcuts
-bgItem s itemType=0 title=app1-class1 intent=component=app1/class1 id=1
-bgItem s itemType=0 title=app1-class2 intent=component=app1/class2 id=2
-bgItem s itemType=0 title=app2-class1 intent=component=app2/class1 id=3
-bgItem s itemType=0 title=app2-class2 intent=component=app2/class2 id=4
-
-# Promise icons for app3
-bgItem s itemType=0 status=2 title=app3-class1 intent=component=app3/class1 id=5
-bgItem s itemType=0 status=2 title=app3-class2 intent=component=app3/class2 id=6
-bgItem s itemType=1 status=1 title=app3-shrt intent=component=app3/class3 id=7
-
-# Promise icon for app4
-bgItem s itemType=1 status=1 title=app4-shrt intent=component=app4/class1 id=8
-
-# Widget
-bgItem w providerName=app4/provider1 id=9
-bgItem w providerName=app5/provider1 id=10
\ No newline at end of file
diff --git a/tests/res/raw/widgets_predication_update_task_data.txt b/tests/res/raw/widgets_predication_update_task_data.txt
deleted file mode 100644
index 941d195..0000000
--- a/tests/res/raw/widgets_predication_update_task_data.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-# Model data used by WidgetsPredictionUpdateTasksTest
-
-classMap s com.android.launcher3.model.data.WorkspaceItemInfo
-classMap w com.android.launcher3.model.data.LauncherAppWidgetInfo
-
-# Items for the BgDataModel
-
-# App shortcuts
-bgItem s itemType=0 title=app1-class1 intent=component=app1/class1 id=1
-bgItem s itemType=0 title=app1-class2 intent=component=app1/class2 id=2
-bgItem s itemType=0 title=app2-class1 intent=component=app2/class1 id=3
-bgItem s itemType=0 title=app2-class2 intent=component=app2/class2 id=4
-
-# Promise icons for app3
-bgItem s itemType=0 status=2 title=app3-class1 intent=component=app3/class1 id=5
-bgItem s itemType=0 status=2 title=app3-class2 intent=component=app3/class2 id=6
-bgItem s itemType=1 status=1 title=app3-shrt intent=component=app3/class3 id=7
-
-# Promise icon for app4
-bgItem s itemType=1 status=1 title=app4-shrt intent=component=app4/class1 id=8
-
-# Widget
-bgItem w providerName=app4/provider1 id=9
-bgItem w providerName=app5/provider1 id=10
\ No newline at end of file
diff --git a/tests/res/values/attrs.xml b/tests/res/values/attrs.xml
index 2310d9e..e5ee064 100644
--- a/tests/res/values/attrs.xml
+++ b/tests/res/values/attrs.xml
@@ -18,7 +18,7 @@
<!-- Attributes have to be copied to test for correct parsing of files -->
<resources>
<!-- Responsive grids attributes -->
- <declare-styleable name="WorkspaceSpec">
+ <declare-styleable name="ResponsiveSpec">
<attr name="specType" format="integer">
<enum name="height" value="0" />
<enum name="width" value="1" />
@@ -26,10 +26,26 @@
<attr name="maxAvailableSize" format="dimension" />
</declare-styleable>
- <declare-styleable name="SpecSize">
+ <declare-styleable name="WorkspaceSpec">
+ <attr name="specType" />
+ <attr name="maxAvailableSize" />
+ </declare-styleable>
+
+ <declare-styleable name="FolderSpec">
+ <attr name="specType" />
+ <attr name="maxAvailableSize" />
+ </declare-styleable>
+
+ <declare-styleable name="AllAppsSpec">
+ <attr name="specType" />
+ <attr name="maxAvailableSize" />
+ </declare-styleable>
+
+ <declare-styleable name="SizeSpec">
<attr name="fixedSize" format="dimension" />
<attr name="ofAvailableSpace" format="float" />
<attr name="ofRemainderSpace" format="float" />
+ <attr name="matchWorkspace" format="boolean" />
+ <attr name="maxSize" format="dimension" />
</declare-styleable>
-
</resources>
diff --git a/tests/res/values/strings.xml b/tests/res/values/strings.xml
index 0ad87fb..54ade56 100644
--- a/tests/res/values/strings.xml
+++ b/tests/res/values/strings.xml
@@ -3,4 +3,5 @@
<string name="shortcut1" translatable="false">Shortcut 1</string>
<string name="shortcut2" translatable="false">Shortcut 2</string>
<string name="shortcut3" translatable="false">Shortcut 3</string>
+ <string name="shortcut4" translatable="false">Shortcut 4</string>
</resources>
diff --git a/tests/res/xml/appwidget_no_config_large.xml b/tests/res/xml/appwidget_no_config_large.xml
new file mode 100644
index 0000000..b3b69d9
--- /dev/null
+++ b/tests/res/xml/appwidget_no_config_large.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<appwidget-provider
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:minWidth="1dp"
+ android:minHeight="1dp"
+ android:minResizeWidth="1dp"
+ android:maxResizeWidth="3000dp"
+ android:targetCellHeight="1"
+ android:targetCellWidth="5"
+ android:updatePeriodMillis="86400000"
+ android:initialLayout="@layout/test_layout_appwidget_red"
+ android:previewLayout="@layout/test_layout_appwidget_red"
+ android:resizeMode="horizontal|vertical"
+ android:widgetCategory="home_screen">
+</appwidget-provider>
\ No newline at end of file
diff --git a/tests/res/xml/invalid_all_apps_file_case_1.xml b/tests/res/xml/invalid_all_apps_file_case_1.xml
new file mode 100644
index 0000000..6fd35b1
--- /dev/null
+++ b/tests/res/xml/invalid_all_apps_file_case_1.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<allAppsSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <allAppsSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <!-- missing startPadding -->
+ <endPadding launcher:fixedSize="0dp" />
+ <gutter launcher:matchWorkspace="true" />
+ <cellSize launcher:matchWorkspace="true" />
+ </allAppsSpec>
+
+ <allAppsSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:matchWorkspace="true" />
+ <endPadding launcher:matchWorkspace="true" />
+ <gutter launcher:matchWorkspace="true" />
+ <cellSize launcher:matchWorkspace="true" />
+ </allAppsSpec>
+
+</allAppsSpecs>
+
diff --git a/tests/res/xml/invalid_all_apps_file_case_2.xml b/tests/res/xml/invalid_all_apps_file_case_2.xml
new file mode 100644
index 0000000..de9c1ac
--- /dev/null
+++ b/tests/res/xml/invalid_all_apps_file_case_2.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<allAppsSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <allAppsSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="0dp" />
+ <!-- more than 1 value in one tag -->
+ <gutter
+ launcher:matchWorkspace="true"
+ launcher:fixedSize="16dp" />
+ <cellSize launcher:matchWorkspace="true" />
+ </allAppsSpec>
+
+ <allAppsSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:matchWorkspace="true" />
+ <endPadding launcher:matchWorkspace="true" />
+ <gutter launcher:matchWorkspace="true" />
+ <cellSize launcher:matchWorkspace="true" />
+ </allAppsSpec>
+
+</allAppsSpecs>
\ No newline at end of file
diff --git a/tests/res/xml/invalid_all_apps_file_case_3.xml b/tests/res/xml/invalid_all_apps_file_case_3.xml
new file mode 100644
index 0000000..7af0af4
--- /dev/null
+++ b/tests/res/xml/invalid_all_apps_file_case_3.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<allAppsSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <allAppsSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="0dp" />
+ <gutter launcher:matchWorkspace="true" />
+ <!-- value bigger than 1 -->
+ <cellSize launcher:ofRemainderSpace="1.001" />
+ </allAppsSpec>
+
+ <allAppsSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:matchWorkspace="true" />
+ <endPadding launcher:matchWorkspace="true" />
+ <gutter launcher:matchWorkspace="true" />
+ <cellSize launcher:matchWorkspace="true" />
+ </allAppsSpec>
+
+</allAppsSpecs>
+
diff --git a/tests/res/xml/invalid_folders_specs_1.xml b/tests/res/xml/invalid_folders_specs_1.xml
new file mode 100644
index 0000000..0864249
--- /dev/null
+++ b/tests/res/xml/invalid_folders_specs_1.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!-- Tablet - 6x5 portrait -->
+<folderSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
+ <!-- missing startPadding -->
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:matchWorkspace="true" />
+ </folderSpec>
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="102dp" />
+ </folderSpec>
+
+ <!-- Height spec is fixed -->
+ <folderSpec launcher:specType="height" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="24dp" />
+ <!-- mapped to footer height size -->
+ <endPadding launcher:fixedSize="64dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </folderSpec>
+</folderSpecs>
diff --git a/tests/res/xml/invalid_folders_specs_2.xml b/tests/res/xml/invalid_folders_specs_2.xml
new file mode 100644
index 0000000..0b7dd62
--- /dev/null
+++ b/tests/res/xml/invalid_folders_specs_2.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!-- Tablet - 6x5 portrait -->
+<folderSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <!-- more than 1 value in one tag -->
+ <gutter
+ launcher:ofAvailableSpace="0.0125"
+ launcher:fixedSize="16dp" />
+ <cellSize launcher:matchWorkspace="true" />
+ </folderSpec>
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="102dp" />
+ </folderSpec>
+
+ <!-- Height spec is fixed -->
+ <folderSpec launcher:specType="height" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="24dp" />
+ <!-- mapped to footer height size -->
+ <endPadding launcher:fixedSize="64dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </folderSpec>
+</folderSpecs>
diff --git a/tests/res/xml/invalid_folders_specs_3.xml b/tests/res/xml/invalid_folders_specs_3.xml
new file mode 100644
index 0000000..83fd3e1
--- /dev/null
+++ b/tests/res/xml/invalid_folders_specs_3.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!-- Tablet - 6x5 portrait - More the one value first gutter -->
+<folderSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <!-- value bigger than 1 -->
+ <cellSize launcher:ofRemainderSpace="1.001" />
+ </folderSpec>
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="102dp" />
+ </folderSpec>
+
+ <!-- Height spec is fixed -->
+ <folderSpec launcher:specType="height" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="24dp" />
+ <!-- mapped to footer height size -->
+ <endPadding launcher:fixedSize="64dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </folderSpec>
+</folderSpecs>
diff --git a/tests/res/xml/invalid_folders_specs_4.xml b/tests/res/xml/invalid_folders_specs_4.xml
new file mode 100644
index 0000000..2d8c730
--- /dev/null
+++ b/tests/res/xml/invalid_folders_specs_4.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<!-- missing height spec -->
+<folderSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:matchWorkspace="true" />
+ </folderSpec>
+</folderSpecs>
diff --git a/tests/res/xml/invalid_folders_specs_5.xml b/tests/res/xml/invalid_folders_specs_5.xml
new file mode 100644
index 0000000..b4f1f4d
--- /dev/null
+++ b/tests/res/xml/invalid_folders_specs_5.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<!-- missing breakpoints > 800dp -->
+<folderSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:matchWorkspace="true" />
+ </folderSpec>
+
+ <!-- Height spec is fixed -->
+ <folderSpec launcher:specType="height" launcher:maxAvailableSize="800dp">
+ <startPadding launcher:fixedSize="24dp" />
+ <!-- mapped to footer height size -->
+ <endPadding launcher:fixedSize="64dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </folderSpec>
+</folderSpecs>
diff --git a/tests/res/xml/invalid_hotseat_file_case_1.xml b/tests/res/xml/invalid_hotseat_file_case_1.xml
new file mode 100644
index 0000000..aaaf8bb
--- /dev/null
+++ b/tests/res/xml/invalid_hotseat_file_case_1.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<hotseatSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+
+ <hotseatSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="847dp">
+ <hotseatQsbSpace launcher:ofAvailableSpace="1" />
+ <edgePadding launcher:fixedSize="36dp" />
+ </hotseatSpec>
+
+ <hotseatSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <hotseatQsbSpace launcher:fixedSize="36dp" />
+ <edgePadding launcher:fixedSize="36dp" />
+ </hotseatSpec>
+
+</hotseatSpecs>
\ No newline at end of file
diff --git a/tests/res/xml/invalid_workspace_file_case_4.xml b/tests/res/xml/invalid_workspace_file_case_4.xml
new file mode 100644
index 0000000..9e74c85
--- /dev/null
+++ b/tests/res/xml/invalid_workspace_file_case_4.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<workspaceSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="648dp">
+ <startPadding
+ launcher:ofAvailableSpace="0.0125" />
+ <endPadding
+ launcher:ofAvailableSpace="0.05" />
+ <!-- value in workspace spec using matchWorkspace -->
+ <gutter
+ launcher:matchWorkspace="true" />
+ <cellSize
+ launcher:ofRemainderSpace="0.2" />
+ </workspaceSpec>
+
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding
+ launcher:ofAvailableSpace="0.0306" />
+ <endPadding
+ launcher:ofAvailableSpace="0.068" />
+ <gutter
+ launcher:fixedSize="16dp" />
+ <cellSize
+ launcher:ofRemainderSpace="0.2" />
+ </workspaceSpec>
+
+ <!-- Width spec is always the same -->
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding
+ launcher:ofRemainderSpace="0.21436227" />
+ <endPadding
+ launcher:ofRemainderSpace="0.21436227" />
+ <gutter
+ launcher:ofRemainderSpace="0.11425509" />
+ <cellSize
+ launcher:fixedSize="120dp" />
+ </workspaceSpec>
+</workspaceSpecs>
diff --git a/tests/res/xml/max_shortcuts.xml b/tests/res/xml/max_shortcuts.xml
new file mode 100644
index 0000000..312a24c
--- /dev/null
+++ b/tests/res/xml/max_shortcuts.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ <shortcut
+ android:shortcutId="max_shortcut1"
+ android:icon="@drawable/test_theme_icon"
+ android:shortcutShortLabel="@string/shortcut1">
+ <intent android:action="com.android.launcher3.intent.action.test_shortcut_max"/>
+ </shortcut>
+ <shortcut
+ android:shortcutId="max_shortcut2"
+ android:shortcutShortLabel="@string/shortcut2">
+ <intent android:action="com.android.launcher3.intent.action.test_shortcut_max"/>
+ </shortcut>
+ <shortcut
+ android:shortcutId="max_shortcut3"
+ android:shortcutShortLabel="@string/shortcut3">
+ <intent android:action="com.android.launcher3.intent.action.test_shortcut_max"/>
+ </shortcut>
+ <shortcut
+ android:shortcutId="max_shortcut4"
+ android:shortcutShortLabel="@string/shortcut4">
+ <intent android:action="com.android.launcher3.intent.action.test_shortcut_max"/>
+ </shortcut>
+</shortcuts>
diff --git a/tests/res/xml/shortcuts.xml b/tests/res/xml/shortcuts.xml
index 94e8edd..2ba9d7f 100644
--- a/tests/res/xml/shortcuts.xml
+++ b/tests/res/xml/shortcuts.xml
@@ -1,4 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
<shortcut
android:shortcutId="shortcut1_themed"
diff --git a/tests/res/xml/single_shortcut.xml b/tests/res/xml/single_shortcut.xml
new file mode 100644
index 0000000..e8d938f
--- /dev/null
+++ b/tests/res/xml/single_shortcut.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ <shortcut
+ android:shortcutId="single_shortcut_themed"
+ android:icon="@drawable/test_theme_icon"
+ android:shortcutShortLabel="@string/shortcut1">
+ <intent android:action="com.android.launcher3.intent.action.test_shortcut_single"/>
+ </shortcut>
+</shortcuts>
diff --git a/tests/res/xml/valid_all_apps_file.xml b/tests/res/xml/valid_all_apps_file.xml
new file mode 100644
index 0000000..0be55d1
--- /dev/null
+++ b/tests/res/xml/valid_all_apps_file.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<allAppsSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <allAppsSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="0dp" />
+ <gutter launcher:matchWorkspace="true" />
+ <cellSize launcher:matchWorkspace="true" />
+ </allAppsSpec>
+
+ <allAppsSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:matchWorkspace="true" />
+ <endPadding launcher:matchWorkspace="true" />
+ <gutter launcher:matchWorkspace="true" />
+ <cellSize launcher:matchWorkspace="true" />
+ </allAppsSpec>
+
+</allAppsSpecs>
diff --git a/tests/res/xml/valid_folders_specs.xml b/tests/res/xml/valid_folders_specs.xml
new file mode 100644
index 0000000..0c45544
--- /dev/null
+++ b/tests/res/xml/valid_folders_specs.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<folderSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="800dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:matchWorkspace="true" />
+ </folderSpec>
+ <folderSpec launcher:specType="width" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="16dp" />
+ <endPadding launcher:fixedSize="16dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="102dp" />
+ </folderSpec>
+
+ <!-- Height spec is fixed -->
+ <folderSpec launcher:specType="height" launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="24dp" />
+ <!-- mapped to footer height size -->
+ <endPadding launcher:fixedSize="64dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:matchWorkspace="true" />
+ </folderSpec>
+</folderSpecs>
diff --git a/tests/res/xml/valid_hotseat_file.xml b/tests/res/xml/valid_hotseat_file.xml
new file mode 100644
index 0000000..f698bd1
--- /dev/null
+++ b/tests/res/xml/valid_hotseat_file.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<hotseatSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+
+ <hotseatSpec
+ launcher:maxAvailableSize="847dp"
+ launcher:specType="height">
+ <hotseatQsbSpace launcher:fixedSize="24dp" />
+ <edgePadding launcher:fixedSize="48dp" />
+ </hotseatSpec>
+
+ <hotseatSpec
+ launcher:maxAvailableSize="9999dp"
+ launcher:specType="height">
+ <hotseatQsbSpace launcher:fixedSize="36dp" />
+ <edgePadding launcher:fixedSize="48dp" />
+ </hotseatSpec>
+
+</hotseatSpecs>
\ No newline at end of file
diff --git a/tests/res/xml/valid_hotseat_land_file.xml b/tests/res/xml/valid_hotseat_land_file.xml
new file mode 100644
index 0000000..fc4a836
--- /dev/null
+++ b/tests/res/xml/valid_hotseat_land_file.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<hotseatSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+
+ <hotseatSpec
+ launcher:maxAvailableSize="743dp"
+ launcher:specType="width">
+ <hotseatQsbSpace launcher:fixedSize="0dp" />
+ <edgePadding launcher:fixedSize="48dp" />
+ </hotseatSpec>
+
+ <hotseatSpec
+ launcher:maxAvailableSize="9999dp"
+ launcher:specType="width">
+ <hotseatQsbSpace launcher:fixedSize="0dp" />
+ <edgePadding launcher:fixedSize="64dp" />
+ </hotseatSpec>
+
+</hotseatSpecs>
\ No newline at end of file
diff --git a/tests/res/xml/valid_workspace_unsorted_file.xml b/tests/res/xml/valid_workspace_unsorted_file.xml
new file mode 100644
index 0000000..1216c81
--- /dev/null
+++ b/tests/res/xml/valid_workspace_unsorted_file.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<workspaceSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
+
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="8dp" />
+ <endPadding launcher:ofRemainderSpace="1" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </workspaceSpec>
+
+ <!-- 584 grid height -->
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="584dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:fixedSize="32dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:ofAvailableSpace="0.15808" />
+ </workspaceSpec>
+
+ <!-- 584 grid height + 28 remainder space -->
+ <workspaceSpec
+ launcher:specType="height"
+ launcher:maxAvailableSize="612dp">
+ <startPadding launcher:fixedSize="0dp" />
+ <endPadding launcher:ofRemainderSpace="1" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:fixedSize="104dp" />
+ </workspaceSpec>
+
+ <!-- Width spec is always the same -->
+ <workspaceSpec
+ launcher:specType="width"
+ launcher:maxAvailableSize="9999dp">
+ <startPadding launcher:fixedSize="22dp" />
+ <endPadding launcher:fixedSize="22dp" />
+ <gutter launcher:fixedSize="16dp" />
+ <cellSize launcher:ofRemainderSpace="0.25" />
+ </workspaceSpec>
+
+</workspaceSpecs>
diff --git a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index 2ac0dd7..0798e97 100644
--- a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -28,6 +28,7 @@
public static final String PAUSE_DETECTED_MESSAGE = "TAPL_PAUSE_DETECTED";
public static final String DISMISS_ANIMATION_ENDS_MESSAGE = "TAPL_DISMISS_ANIMATION_ENDS";
public static final String FOLDER_OPENED_MESSAGE = "TAPL_FOLDER_OPENED";
+ public static final String SEARCH_RESULT_COMPLETE = "SEARCH_RESULT_COMPLETE";
public static final int NORMAL_STATE_ORDINAL = 0;
public static final int SPRING_LOADED_STATE_ORDINAL = 1;
public static final int OVERVIEW_STATE_ORDINAL = 2;
@@ -39,7 +40,6 @@
public static final int HINT_STATE_TWO_BUTTON_ORDINAL = 8;
public static final int OVERVIEW_SPLIT_SELECT_ORDINAL = 9;
public static final int EDIT_MODE_STATE_ORDINAL = 10;
- public static final String TAPL_EVENTS_TAG = "TaplEvents";
public static final String SEQUENCE_MAIN = "Main";
public static final String SEQUENCE_TIS = "TIS";
public static final String SEQUENCE_PILFER = "Pilfer";
@@ -103,6 +103,7 @@
public static final String REQUEST_WIDGETS_SCROLL_Y = "widgets-scroll-y";
public static final String REQUEST_TARGET_INSETS = "target-insets";
public static final String REQUEST_WINDOW_INSETS = "window-insets";
+ public static final String REQUEST_IME_INSETS = "ime-insets";
public static final String REQUEST_PID = "pid";
public static final String REQUEST_FORCE_GC = "gc";
public static final String REQUEST_RECENT_TASKS_LIST = "recent-tasks-list";
@@ -110,6 +111,7 @@
public static final String REQUEST_GET_TEST_EVENTS = "get-test-events";
public static final String REQUEST_GET_HAD_NONTEST_EVENTS = "get-had-nontest-events";
public static final String REQUEST_STOP_EVENT_LOGGING = "stop-event-logging";
+ public static final String REQUEST_REINITIALIZE_DATA = "reinitialize-data";
public static final String REQUEST_CLEAR_DATA = "clear-data";
public static final String REQUEST_HOTSEAT_ICON_NAMES = "get-hotseat-icon-names";
public static final String REQUEST_IS_TABLET = "is-tablet";
@@ -152,15 +154,18 @@
public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation";
public static final String PERMANENT_DIAG_TAG = "TaplTarget";
- public static final String WORK_TAB_MISSING = "b/243688989";
public static final String TWO_TASKBAR_LONG_CLICKS = "b/262282528";
- public static final String FLAKY_ACTIVITY_COUNT = "b/260260325";
+ public static final String FLAKY_QUICK_SWITCH_TO_PREVIOUS_APP = "b/286084688";
+ public static final String ICON_MISSING = "b/282963545";
+ public static final String INCORRECT_HOME_STATE = "b/293191790";
public static final String REQUEST_EMULATE_DISPLAY = "emulate-display";
public static final String REQUEST_STOP_EMULATE_DISPLAY = "stop-emulate-display";
public static final String REQUEST_IS_EMULATE_DISPLAY_RUNNING = "is-emulate-display-running";
public static final String REQUEST_EMULATE_PRINT_DEVICE = "emulate-print-device";
+ public static final String REQUEST_FLAG_ENABLE_GRID_ONLY_OVERVIEW = "enable-grid-only-overview";
+
/** Logs {@link Log#d(String, String)} if {@link #sDebugTracing} is true. */
public static void testLogD(String tag, String message) {
if (!sDebugTracing) {
diff --git a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
index 3de4d55..ed8e324 100644
--- a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
+++ b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
@@ -22,15 +22,22 @@
import android.util.DisplayMetrics
import android.view.Surface
import androidx.test.core.app.ApplicationProvider
+import com.android.launcher3.testing.shared.ResourceUtils
import com.android.launcher3.util.DisplayController
import com.android.launcher3.util.NavigationMode
import com.android.launcher3.util.WindowBounds
+import com.android.launcher3.util.rule.TestStabilityRule
import com.android.launcher3.util.window.CachedDisplayInfo
import com.android.launcher3.util.window.WindowManagerProxy
+import java.io.BufferedReader
+import java.io.File
+import java.io.PrintWriter
+import java.io.StringWriter
import kotlin.math.max
import kotlin.math.min
import org.junit.After
import org.junit.Before
+import org.junit.Rule
import org.mockito.ArgumentMatchers
import org.mockito.Mockito.mock
import org.mockito.Mockito.`when` as whenever
@@ -49,6 +56,8 @@
private lateinit var originalDisplayController: DisplayController
private lateinit var originalWindowManagerProxy: WindowManagerProxy
+ @Rule @JvmField val testStabilityRule = TestStabilityRule()
+
@Before
open fun setUp() {
val appContext: Context = ApplicationProvider.getApplicationContext()
@@ -154,41 +163,55 @@
}
protected fun initializeVarsForTwoPanel(
- deviceTabletSpec: DeviceSpec,
- deviceSpec: DeviceSpec,
+ deviceSpecUnfolded: DeviceSpec,
+ deviceSpecFolded: DeviceSpec,
isLandscape: Boolean = false,
- isGestureMode: Boolean = true
+ isGestureMode: Boolean = true,
+ isFolded: Boolean = false
) {
- val (tabletNaturalX, tabletNaturalY) = deviceTabletSpec.naturalSize
- val tabletWindowsBounds =
- tabletWindowsBounds(deviceTabletSpec, tabletNaturalX, tabletNaturalY)
- val tabletDisplayInfo =
+ val (unfoldedNaturalX, unfoldedNaturalY) = deviceSpecUnfolded.naturalSize
+ val unfoldedWindowsBounds =
+ tabletWindowsBounds(deviceSpecUnfolded, unfoldedNaturalX, unfoldedNaturalY)
+ val unfoldedDisplayInfo =
CachedDisplayInfo(
- Point(tabletNaturalX, tabletNaturalY),
+ Point(unfoldedNaturalX, unfoldedNaturalY),
Surface.ROTATION_0,
Rect(0, 0, 0, 0)
)
- val (phoneNaturalX, phoneNaturalY) = deviceSpec.naturalSize
- val phoneWindowsBounds =
- phoneWindowsBounds(deviceSpec, isGestureMode, phoneNaturalX, phoneNaturalY)
- val phoneDisplayInfo =
+ val (foldedNaturalX, foldedNaturalY) = deviceSpecFolded.naturalSize
+ val foldedWindowsBounds =
+ phoneWindowsBounds(deviceSpecFolded, isGestureMode, foldedNaturalX, foldedNaturalY)
+ val foldedDisplayInfo =
CachedDisplayInfo(
- Point(phoneNaturalX, phoneNaturalY),
+ Point(foldedNaturalX, foldedNaturalY),
Surface.ROTATION_0,
Rect(0, 0, 0, 0)
)
val perDisplayBoundsCache =
- mapOf(tabletDisplayInfo to tabletWindowsBounds, phoneDisplayInfo to phoneWindowsBounds)
+ mapOf(
+ unfoldedDisplayInfo to unfoldedWindowsBounds,
+ foldedDisplayInfo to foldedWindowsBounds
+ )
- initializeCommonVars(
- perDisplayBoundsCache,
- tabletDisplayInfo,
- rotation = if (isLandscape) Surface.ROTATION_0 else Surface.ROTATION_90,
- isGestureMode,
- densityDpi = deviceTabletSpec.densityDpi
- )
+ if (isFolded) {
+ initializeCommonVars(
+ perDisplayBoundsCache = perDisplayBoundsCache,
+ displayInfo = foldedDisplayInfo,
+ rotation = if (isLandscape) Surface.ROTATION_90 else Surface.ROTATION_0,
+ isGestureMode = isGestureMode,
+ densityDpi = deviceSpecFolded.densityDpi
+ )
+ } else {
+ initializeCommonVars(
+ perDisplayBoundsCache = perDisplayBoundsCache,
+ displayInfo = unfoldedDisplayInfo,
+ rotation = if (isLandscape) Surface.ROTATION_0 else Surface.ROTATION_90,
+ isGestureMode = isGestureMode,
+ densityDpi = deviceSpecUnfolded.densityDpi
+ )
+ }
}
private fun phoneWindowsBounds(
@@ -196,7 +219,7 @@
isGestureMode: Boolean,
naturalX: Int,
naturalY: Int
- ): Array<WindowBounds> {
+ ): List<WindowBounds> {
val buttonsNavHeight = Utilities.dpToPx(48f, deviceSpec.densityDpi)
val rotation0Insets =
@@ -231,7 +254,7 @@
if (isGestureMode) deviceSpec.gesturePx else 0
)
- return arrayOf(
+ return listOf(
WindowBounds(Rect(0, 0, naturalX, naturalY), rotation0Insets, Surface.ROTATION_0),
WindowBounds(Rect(0, 0, naturalY, naturalX), rotation90Insets, Surface.ROTATION_90),
WindowBounds(Rect(0, 0, naturalX, naturalY), rotation180Insets, Surface.ROTATION_180),
@@ -243,11 +266,11 @@
deviceSpec: DeviceSpec,
naturalX: Int,
naturalY: Int
- ): Array<WindowBounds> {
+ ): List<WindowBounds> {
val naturalInsets = Rect(0, deviceSpec.statusBarNaturalPx, 0, 0)
val rotatedInsets = Rect(0, deviceSpec.statusBarRotatedPx, 0, 0)
- return arrayOf(
+ return listOf(
WindowBounds(Rect(0, 0, naturalX, naturalY), naturalInsets, Surface.ROTATION_0),
WindowBounds(Rect(0, 0, naturalY, naturalX), rotatedInsets, Surface.ROTATION_90),
WindowBounds(Rect(0, 0, naturalX, naturalY), naturalInsets, Surface.ROTATION_180),
@@ -256,7 +279,7 @@
}
private fun initializeCommonVars(
- perDisplayBoundsCache: Map<CachedDisplayInfo, Array<WindowBounds>>,
+ perDisplayBoundsCache: Map<CachedDisplayInfo, List<WindowBounds>>,
displayInfo: CachedDisplayInfo,
rotation: Int,
isGestureMode: Boolean = true,
@@ -287,4 +310,27 @@
whenever(displayController.info).thenReturn(info)
whenever(displayController.isTransientTaskbar).thenReturn(isGestureMode)
}
+
+ /** Create a new dump of DeviceProfile, saves to a file in the device and returns it */
+ protected fun dump(context: Context, dp: DeviceProfile, fileName: String): String {
+ val stringWriter = StringWriter()
+ PrintWriter(stringWriter).use { dp.dump(context, "", it) }
+ return stringWriter.toString().also { content -> writeToDevice(context, fileName, content) }
+ }
+
+ /** Read a file from assets/ and return it as a string */
+ protected fun readDumpFromAssets(context: Context, fileName: String): String =
+ context.assets.open("dumpTests/$fileName").bufferedReader().use(BufferedReader::readText)
+
+ private fun writeToDevice(context: Context, fileName: String, content: String) {
+ File(context.getDir("dumpTests", Context.MODE_PRIVATE), fileName).writeText(content)
+ }
+
+ protected fun Float.dpToPx(): Float {
+ return ResourceUtils.pxFromDp(this, context!!.resources.displayMetrics).toFloat()
+ }
+
+ protected fun Int.dpToPx(): Int {
+ return ResourceUtils.pxFromDp(this.toFloat(), context!!.resources.displayMetrics)
+ }
}
diff --git a/tests/src/com/android/launcher3/allapps/OopTaplOpenCloseAllApps.java b/tests/src/com/android/launcher3/allapps/OopTaplOpenCloseAllApps.java
new file mode 100644
index 0000000..7d6b7f9
--- /dev/null
+++ b/tests/src/com/android/launcher3/allapps/OopTaplOpenCloseAllApps.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps;
+
+import static com.android.launcher3.ui.TaplTestsLauncher3.expectFail;
+import static com.android.launcher3.ui.TaplTestsLauncher3.initialize;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.tapl.AllApps;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test that we can open and close the all apps in multiple situations.
+ * The test runs in Out of process (Oop) and in process.
+ */
+public class OopTaplOpenCloseAllApps extends AbstractLauncherUiTest {
+
+ /**
+ * Calls static method initialize
+ */
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ initialize(this);
+ }
+
+ /**
+ * Make sure we can go home after pressing the context menu on an Icon on the AllApps.
+ */
+ @Test
+ public void testPressHomeOnAllAppsContextMenu() {
+ final AllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+ allApps.freeze();
+ try {
+ allApps.getAppIcon("TestActivity7").openMenu();
+ } finally {
+ allApps.unfreeze();
+ }
+ mLauncher.goHome();
+ }
+
+ /**
+ * Make sure we can open AllApps from the Workspace.
+ */
+ @Test
+ @PortraitLandscape
+ public void testWorkspaceSwitchToAllApps() {
+ assertNotNull("switchToAllApps() returned null",
+ mLauncher.getWorkspace().switchToAllApps());
+ assertTrue("Launcher internal state is not All Apps",
+ isInState(() -> LauncherState.ALL_APPS));
+ }
+
+ /**
+ * Make sure we can go to Workspace from AllApps
+ */
+ @Test
+ @PortraitLandscape
+ public void testAllAppsSwitchToWorkspace() {
+ assertNotNull("switchToWorkspace() returned null",
+ mLauncher.getWorkspace().switchToAllApps()
+ .switchToWorkspace(/* swipeDown= */ true));
+ assertTrue("Launcher internal state is not Workspace",
+ isInState(() -> LauncherState.NORMAL));
+ }
+
+ /**
+ * Make sure the swipe up gesture can take us back to the workspace from AllApps
+ */
+ @Test
+ @PortraitLandscape
+ public void testAllAppsSwipeUpToWorkspace() {
+ assertNotNull("testAllAppsSwipeUpToWorkspace() returned null",
+ mLauncher.getWorkspace().switchToAllApps()
+ .switchToWorkspace(/* swipeDown= */ false));
+ assertTrue("Launcher internal state is not Workspace",
+ isInState(() -> LauncherState.NORMAL));
+ }
+
+ /**
+ * Make sure we can go to the Workspace from AllApps on tablets by tapping on the background.
+ */
+ @Test
+ @PortraitLandscape
+ public void testAllAppsDeadzoneForTablet() {
+ assumeTrue(mLauncher.isTablet());
+
+ mLauncher.getWorkspace().switchToAllApps().dismissByTappingOutsideForTablet(
+ true /* tapRight */);
+ mLauncher.getWorkspace().switchToAllApps().dismissByTappingOutsideForTablet(
+ false /* tapRight */);
+ }
+
+ /**
+ * Make sure that AllApps closes when pressing the home button
+ */
+ @Test
+ @PortraitLandscape
+ public void testAllAppsFromHome() {
+ // Test opening all apps
+ assertNotNull("switchToAllApps() returned null",
+ mLauncher.getWorkspace().switchToAllApps());
+
+ runAllAppsTest(mLauncher.getAllApps());
+
+ // Testing pressHome.
+ assertTrue("Launcher internal state is not All Apps",
+ isInState(() -> LauncherState.ALL_APPS));
+ assertNotNull("pressHome returned null", mLauncher.goHome());
+ assertTrue("Launcher internal state is not Home",
+ isInState(() -> LauncherState.NORMAL));
+ assertNotNull("getHome returned null", mLauncher.getWorkspace());
+ }
+
+ /**
+ * Makes sure the state of AllApps is correct.
+ */
+ public void runAllAppsTest(AllApps allApps) {
+ allApps.freeze();
+ try {
+ assertNotNull("allApps parameter is null", allApps);
+
+ assertTrue(
+ "Launcher internal state is not All Apps",
+ isInState(() -> LauncherState.ALL_APPS));
+
+ // Test flinging forward and backward.
+ executeOnLauncher(launcher -> assertEquals(
+ "All Apps started in already scrolled state", 0,
+ getAllAppsScroll(launcher)));
+
+ allApps.flingForward();
+ assertTrue("Launcher internal state is not All Apps",
+ isInState(() -> LauncherState.ALL_APPS));
+ final Integer flingForwardY = getFromLauncher(
+ launcher -> getAllAppsScroll(launcher));
+ executeOnLauncher(
+ launcher -> assertTrue("flingForward() didn't scroll App Apps",
+ flingForwardY > 0));
+
+ allApps.flingBackward();
+ assertTrue(
+ "Launcher internal state is not All Apps",
+ isInState(() -> LauncherState.ALL_APPS));
+ final Integer flingBackwardY = getFromLauncher(
+ launcher -> getAllAppsScroll(launcher));
+ executeOnLauncher(launcher -> assertTrue("flingBackward() didn't scroll App Apps",
+ flingBackwardY < flingForwardY));
+
+ // Test scrolling down to YouTube.
+ assertNotNull("All apps: can't find YouTube", allApps.getAppIcon("YouTube"));
+ // Test scrolling up to Camera.
+ assertNotNull("All apps: can't find Camera", allApps.getAppIcon("Camera"));
+ // Test failing to find a non-existing app.
+ final AllApps allAppsFinal = allApps;
+ expectFail("All apps: could find a non-existing app",
+ () -> allAppsFinal.getAppIcon("NO APP"));
+
+ assertTrue(
+ "Launcher internal state is not All Apps",
+ isInState(() -> LauncherState.ALL_APPS));
+ } finally {
+ allApps.unfreeze();
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java
index 3c2b49a..ff667e6 100644
--- a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java
+++ b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java
@@ -103,6 +103,8 @@
public static final char IGNORE = 'x';
// The cells marked by this will be filled by app icons
public static final char ICON = 'i';
+ // The cells marked by FOLDER will be filled by folders with 27 app icons inside
+ public static final char FOLDER = 'Z';
// Empty space
public static final char EMPTY = '-';
// Widget that will be saved as "main widget" for easier retrieval
@@ -139,9 +141,14 @@
return this.mType == CellType.IGNORE;
}
+ boolean contains(int x, int y) {
+ return mBounds.contains(x, y);
+ }
+
@Override
public String toString() {
- return "WidgetRect type = " + mType + " bounds = " + mBounds.toString();
+ return "WidgetRect type = " + mType + " x = " + getCellX() + " | y " + getCellY()
+ + " xs = " + getSpanX() + " ys = " + getSpanY();
}
}
@@ -171,6 +178,25 @@
}
}
+ public static class FolderPoint {
+ public Point coord;
+ public char mType;
+
+ public FolderPoint(Point coord, char type) {
+ this.coord = coord;
+ mType = type;
+ }
+
+ /**
+ * [A-Z]: Represents a folder and number of icons in the folder is represented by
+ * the order of letter in the alphabet, A=2, B=3, C=4 ... etc.
+ */
+ public int getNumberIconsInside() {
+ return (mType - 'A') + 2;
+ }
+ }
+
+
private HashSet<Character> mUsedWidgetTypes = new HashSet<>();
static final int INFINITE = 99999;
@@ -181,6 +207,7 @@
Map<Character, WidgetRect> mWidgetsMap = new HashMap<>();
List<IconPoint> mIconPoints = new ArrayList<>();
+ List<FolderPoint> mFolderPoints = new ArrayList<>();
WidgetRect mMain = null;
@@ -205,6 +232,17 @@
}
}
+ public boolean pointInsideRect(int x, int y, WidgetRect rect) {
+ Boolean isXInRect = x >= rect.getCellX() && x < rect.getCellX() + rect.getSpanX();
+ Boolean isYInRect = y >= rect.getCellY() && y < rect.getCellY() + rect.getSpanY();
+ return isXInRect && isYInRect;
+ }
+
+ public WidgetRect getWidgetAt(int x, int y) {
+ return mWidgetsRects.stream()
+ .filter(widgetRect -> pointInsideRect(x, y, widgetRect)).findFirst().orElse(null);
+ }
+
public List<WidgetRect> getWidgets() {
return mWidgetsRects;
}
@@ -213,6 +251,10 @@
return mIconPoints;
}
+ public List<FolderPoint> getFolders() {
+ return mFolderPoints;
+ }
+
public WidgetRect getMain() {
return mMain;
}
@@ -248,6 +290,17 @@
}
return true;
}).collect(Collectors.toList());
+
+ // Remove overlapping folders and remove them from the board
+ mFolderPoints = mFolderPoints.stream().filter(folderPoint -> {
+ int x = folderPoint.coord.x;
+ int y = folderPoint.coord.y;
+ if (rect.contains(x, y)) {
+ mWidget[x][y] = '-';
+ return false;
+ }
+ return true;
+ }).collect(Collectors.toList());
}
private void removeOverlappingItems(Point p) {
@@ -269,6 +322,17 @@
}
return true;
}).collect(Collectors.toList());
+
+ // Remove overlapping folders and remove them from the board
+ mFolderPoints = mFolderPoints.stream().filter(folderPoint -> {
+ int x = folderPoint.coord.x;
+ int y = folderPoint.coord.y;
+ if (p.x == x && p.y == y) {
+ mWidget[x][y] = '-';
+ return false;
+ }
+ return true;
+ }).collect(Collectors.toList());
}
private char getNextWidgetType() {
@@ -373,6 +437,18 @@
return iconPoints;
}
+ private static List<FolderPoint> getFolderPoints(char[][] board) {
+ List<FolderPoint> folderPoints = new ArrayList<>();
+ for (int x = 0; x < board.length; x++) {
+ for (int y = 0; y < board[0].length; y++) {
+ if (isFolder(board[x][y])) {
+ folderPoints.add(new FolderPoint(new Point(x, y), board[x][y]));
+ }
+ }
+ }
+ return folderPoints;
+ }
+
public static WidgetRect getMainFromList(List<CellLayoutBoard> boards) {
for (CellLayoutBoard board : boards) {
WidgetRect main = board.getMain();
@@ -383,6 +459,17 @@
return null;
}
+ public static WidgetRect getWidgetIn(List<CellLayoutBoard> boards, int x, int y) {
+ for (CellLayoutBoard board : boards) {
+ WidgetRect main = board.getWidgetAt(x, y);
+ if (main != null) {
+ return main;
+ }
+ x -= board.mWidth;
+ }
+ return null;
+ }
+
public static CellLayoutBoard boardFromString(String boardStr) {
String[] lines = boardStr.split("\n");
CellLayoutBoard board = new CellLayoutBoard();
@@ -406,6 +493,7 @@
board.mWidgetsMap.put(widgetRect.mType, widgetRect);
});
board.mIconPoints = getIconPoints(board.mWidget);
+ board.mFolderPoints = getFolderPoints(board.mWidget);
return board;
}
diff --git a/tests/src/com/android/launcher3/celllayout/CellLayoutTestCaseReader.java b/tests/src/com/android/launcher3/celllayout/CellLayoutTestCaseReader.java
index e33a304..419cb3d 100644
--- a/tests/src/com/android/launcher3/celllayout/CellLayoutTestCaseReader.java
+++ b/tests/src/com/android/launcher3/celllayout/CellLayoutTestCaseReader.java
@@ -63,8 +63,8 @@
}
public static class Board extends TestSection {
- Point gridSize;
- String board;
+ public Point gridSize;
+ public String board;
public Board(Point gridSize, String board) {
super(State.BOARD);
@@ -127,7 +127,7 @@
}
}
- List<TestSection> parse() {
+ public List<TestSection> parse() {
List<TestSection> sections = new ArrayList<>();
String[] lines = mTest.split("\n");
Iterator<String> it = Arrays.stream(lines).iterator();
diff --git a/tests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java b/tests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java
index 0d2f252..86a7bd3 100644
--- a/tests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java
+++ b/tests/src/com/android/launcher3/celllayout/CellLayoutTestUtils.java
@@ -42,8 +42,8 @@
params.getCellX(), params.getCellY(),
launcher.getWorkspace().getIdForScreen(cellLayout), CONTAINER_DESKTOP);
int screenId = pos.screenId;
- if (screenId >= boards.size() - 1) {
- boards.add(new CellLayoutBoard());
+ for (int j = boards.size(); j <= screenId; j++) {
+ boards.add(new CellLayoutBoard(cellLayout.getCountX(), cellLayout.getCountY()));
}
CellLayoutBoard board = boards.get(screenId);
// is icon
@@ -51,7 +51,7 @@
board.addIcon(pos.cellX, pos.cellY);
} else {
// is widget
- board.addWidget(params.getCellX(), params.getCellY(), params.cellHSpan,
+ board.addWidget(pos.cellX, pos.cellY, params.cellHSpan,
params.cellVSpan);
}
}
diff --git a/tests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java b/tests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java
index 8ce932d..bf7a21c 100644
--- a/tests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java
+++ b/tests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java
@@ -15,62 +15,116 @@
*/
package com.android.launcher3.celllayout;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.TestUtil.runOnExecutorSync;
-import android.content.ContentResolver;
-import android.content.ContentValues;
import android.content.Context;
+import androidx.test.uiautomator.UiDevice;
+
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.model.BgDataModel.Callbacks;
+import com.android.launcher3.model.ModelDbController;
+import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
+import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.util.ContentWriter;
import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
+import java.util.function.Supplier;
public class FavoriteItemsTransaction {
- private ArrayList<ItemInfo> mItemsToSubmit;
+ private ArrayList<Supplier<ItemInfo>> mItemsToSubmit;
private Context mContext;
- private ContentResolver mResolver;
- public AbstractLauncherUiTest mTest;
- public FavoriteItemsTransaction(Context context, AbstractLauncherUiTest test) {
+ public FavoriteItemsTransaction(Context context) {
mItemsToSubmit = new ArrayList<>();
mContext = context;
- mResolver = mContext.getContentResolver();
- mTest = test;
}
- public FavoriteItemsTransaction addItem(ItemInfo itemInfo) {
+ public FavoriteItemsTransaction addItem(Supplier<ItemInfo> itemInfo) {
this.mItemsToSubmit.add(itemInfo);
return this;
}
- public FavoriteItemsTransaction removeLast() {
- this.mItemsToSubmit.remove(this.mItemsToSubmit.size() - 1);
- return this;
- }
-
/**
* Commits all the ItemInfo into the database of Favorites
**/
- public void commit() throws ExecutionException, InterruptedException {
- List<ContentValues> values = new ArrayList<>();
- for (ItemInfo item : this.mItemsToSubmit) {
- ContentWriter writer = new ContentWriter(mContext);
- item.onAddToDatabase(writer);
- writer.put(LauncherSettings.Favorites._ID, item.id);
- values.add(writer.getValues(mContext));
- }
- // Submit the icons to the database in the model thread to prevent race conditions
- MODEL_EXECUTOR.submit(() -> mResolver.bulkInsert(LauncherSettings.Favorites.CONTENT_URI,
- values.toArray(new ContentValues[0]))).get();
- // Reload the state of the Launcher
- MAIN_EXECUTOR.submit(() -> LauncherAppState.getInstance(
- mContext).getModel().forceReload()).get();
+ public void commit() {
+ LauncherModel model = LauncherAppState.getInstance(mContext).getModel();
+ // Load the model once so that there is no pending migration:
+ loadModelSync(model);
+
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
+ ModelDbController controller = model.getModelDbController();
+ // Migrate any previous data so that the DB state is correct
+ controller.tryMigrateDB();
+
+ // Create DB again to load fresh data
+ controller.createEmptyDB();
+ controller.clearEmptyDbFlag();
+
+ // Add new data
+ try (SQLiteTransaction transaction = controller.newTransaction()) {
+ int count = mItemsToSubmit.size();
+ ArrayList<ItemInfo> containerItems = new ArrayList<>();
+ for (int i = 0; i < count; i++) {
+ ContentWriter writer = new ContentWriter(mContext);
+ ItemInfo item = mItemsToSubmit.get(i).get();
+
+ if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
+ FolderInfo folderInfo = (FolderInfo) item;
+ for (ItemInfo itemInfo : folderInfo.contents) {
+ itemInfo.container = i;
+ containerItems.add(itemInfo);
+ }
+ }
+
+ item.onAddToDatabase(writer);
+ writer.put(LauncherSettings.Favorites._ID, i);
+ controller.insert(TABLE_NAME, writer.getValues(mContext));
+ }
+
+ for (int i = 0; i < containerItems.size(); i++) {
+ ContentWriter writer = new ContentWriter(mContext);
+ ItemInfo item = containerItems.get(i);
+ item.onAddToDatabase(writer);
+ writer.put(LauncherSettings.Favorites._ID, count + i);
+ controller.insert(TABLE_NAME, writer.getValues(mContext));
+ }
+ transaction.commit();
+ }
+ });
+
+ // Reload model
+ runOnExecutorSync(MAIN_EXECUTOR, model::forceReload);
+ loadModelSync(model);
+ }
+
+ private void loadModelSync(LauncherModel model) {
+ Callbacks mockCb = new Callbacks() { };
+ runOnExecutorSync(MAIN_EXECUTOR, () -> model.addCallbacksAndLoad(mockCb));
+ runOnExecutorSync(MODEL_EXECUTOR, () -> { });
+
+ runOnExecutorSync(MAIN_EXECUTOR, () -> { });
+ runOnExecutorSync(MAIN_EXECUTOR, () -> model.removeCallbacks(mockCb));
+ }
+
+ /**
+ * Commits the transaction and waits for home load
+ */
+ public void commitAndLoadHome(LauncherInstrumentation inst) {
+ commit();
+
+ // Launch the home activity
+ UiDevice.getInstance(getInstrumentation()).pressHome();
+ inst.waitForLauncherInitialized();
}
}
diff --git a/tests/src/com/android/launcher3/celllayout/MultipleCellLayoutsSimpleReorder.java b/tests/src/com/android/launcher3/celllayout/MultipleCellLayoutsSimpleReorder.java
deleted file mode 100644
index 706c1a7..0000000
--- a/tests/src/com/android/launcher3/celllayout/MultipleCellLayoutsSimpleReorder.java
+++ /dev/null
@@ -1,90 +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.celllayout.testcases;
-
-import android.graphics.Point;
-
-import com.android.launcher3.celllayout.ReorderTestCase;
-
-import java.util.Map;
-
-/**
- * The grids represent the workspace to be build by TestWorkspaceBuilder, to see what each character
- * in the board mean refer to {@code CellType}
- */
-public class MultipleCellLayoutsSimpleReorder {
-
- /** 5x5 Test
- **/
- private static final String START_BOARD_STR_5x5 = ""
- + "xxxxx|-----\n"
- + "--mm-|-----\n"
- + "--mm-|-----\n"
- + "-----|-----\n"
- + "-----|-----";
- private static final Point MOVE_TO_5x5 = new Point(8, 3);
- private static final String END_BOARD_STR_5x5 = ""
- + "xxxxx|-----\n"
- + "-----|-----\n"
- + "-----|-----\n"
- + "-----|---mm\n"
- + "-----|---mm";
- private static final ReorderTestCase TEST_CASE_5x5 = new ReorderTestCase(START_BOARD_STR_5x5,
- MOVE_TO_5x5,
- END_BOARD_STR_5x5);
-
- /** 4x4 Test
- **/
- private static final String START_BOARD_STR_4x4 = ""
- + "xxxx|----\n"
- + "--mm|----\n"
- + "--mm|----\n"
- + "----|----";
- private static final Point MOVE_TO_4x4 = new Point(5, 3);
- private static final String END_BOARD_STR_4x4 = ""
- + "xxxx|----\n"
- + "----|----\n"
- + "----|-mm-\n"
- + "----|-mm-";
- private static final ReorderTestCase TEST_CASE_4x4 = new ReorderTestCase(START_BOARD_STR_4x4,
- MOVE_TO_4x4,
- END_BOARD_STR_4x4);
-
-
- /** 6x5 Test
- **/
- private static final String START_BOARD_STR_6x5 = ""
- + "xxxxxx|------\n"
- + "--m---|------\n"
- + "------|------\n"
- + "------|------\n"
- + "------|------";
- private static final Point MOVE_TO_6x5 = new Point(10, 4);
- private static final String END_BOARD_STR_6x5 = ""
- + "xxxxxx|------\n"
- + "------|------\n"
- + "------|------\n"
- + "------|------\n"
- + "------|----m-";
- private static final ReorderTestCase TEST_CASE_6x5 = new ReorderTestCase(START_BOARD_STR_6x5,
- MOVE_TO_6x5,
- END_BOARD_STR_6x5);
-
- public static final Map<Point, ReorderTestCase> TEST_BY_GRID_SIZE =
- Map.of(new Point(5, 5), TEST_CASE_5x5,
- new Point(4, 4), TEST_CASE_4x4,
- new Point(6, 5), TEST_CASE_6x5);
-}
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java b/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java
index ee05fe6..91a0634 100644
--- a/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java
+++ b/tests/src/com/android/launcher3/celllayout/ReorderAlgorithmUnitTest.java
@@ -164,7 +164,7 @@
Context c = new ActivityContextWrapper(getApplicationContext());
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(c).getDeviceProfile(c).copy(c);
mPrevNumColumns = dp.inv.numColumns;
- mPrevNumRows = dp.inv.numColumns;
+ mPrevNumRows = dp.inv.numRows;
}
@After
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
index 243edc3..00d7ce6 100644
--- a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
+++ b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
@@ -18,20 +18,24 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import android.content.ContentResolver;
+import android.content.ContentValues;
import android.graphics.Point;
+import android.net.Uri;
import android.util.Log;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.celllayout.testcases.MultipleCellLayoutsSimpleReorder;
+import com.android.launcher3.MultipageCellLayout;
import com.android.launcher3.tapl.Widget;
import com.android.launcher3.tapl.WidgetResizeFrame;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.util.rule.ShellCommandRule;
+import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
@@ -44,7 +48,6 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.ExecutionException;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -55,13 +58,14 @@
private static final String TAG = ReorderWidgets.class.getSimpleName();
+ private static final List<String> FOLDABLE_GRIDS = List.of("normal", "practical", "reasonable");
+
TestWorkspaceBuilder mWorkspaceBuilder;
@Before
public void setup() throws Throwable {
- mWorkspaceBuilder = new TestWorkspaceBuilder(this, mTargetContext);
+ mWorkspaceBuilder = new TestWorkspaceBuilder(mTargetContext);
TaplTestsLauncher3.initialize(this);
- clearHomescreen();
}
/**
@@ -102,20 +106,63 @@
return getFromLauncher(CellLayoutTestUtils::workspaceToBoards);
}
- private void runTestCase(ReorderTestCase testCase)
- throws ExecutionException, InterruptedException {
+ private CellLayoutBoard.WidgetRect getWidgetClosestTo(Point point) {
+ ArrayList<CellLayoutBoard> workspaceBoards = workspaceToBoards();
+ int maxDistance = 9999;
+ CellLayoutBoard.WidgetRect bestRect = null;
+ for (int i = 0; i < workspaceBoards.get(0).getWidgets().size(); i++) {
+ CellLayoutBoard.WidgetRect widget = workspaceBoards.get(0).getWidgets().get(i);
+ if (widget.getCellX() == 0 && widget.getCellY() == 0) {
+ continue;
+ }
+ int distance = Math.abs(point.x - widget.getCellX())
+ + Math.abs(point.y - widget.getCellY());
+ if (distance == 0) {
+ break;
+ }
+ if (distance < maxDistance) {
+ maxDistance = distance;
+ bestRect = widget;
+ }
+ }
+ return bestRect;
+ }
+
+ /**
+ * This function might be odd, its function is to select a widget and leave it in its place.
+ * The idea is to make the test broader and also test after a widgets resized because the
+ * underlying code does different things in that case
+ */
+ private void triggerWidgetResize(ReorderTestCase testCase) {
+ CellLayoutBoard.WidgetRect widgetRect = getWidgetClosestTo(testCase.moveMainTo);
+ if (widgetRect == null) {
+ // Some test doesn't have a widget in the final position, in those cases we will ignore
+ // them
+ return;
+ }
+ Widget widget = mLauncher.getWorkspace().getWidgetAtCell(widgetRect.getCellX(),
+ widgetRect.getCellY());
+ WidgetResizeFrame resizeFrame = widget.dragWidgetToWorkspace(widgetRect.getCellX(),
+ widgetRect.getCellY(), widgetRect.getSpanX(), widgetRect.getSpanY());
+ resizeFrame.dismiss();
+ }
+
+ private void runTestCase(ReorderTestCase testCase) {
CellLayoutBoard.WidgetRect mainWidgetCellPos = CellLayoutBoard.getMainFromList(
testCase.mStart);
FavoriteItemsTransaction transaction =
- new FavoriteItemsTransaction(mTargetContext, this);
+ new FavoriteItemsTransaction(mTargetContext);
transaction = buildWorkspaceFromBoards(testCase.mStart, transaction);
transaction.commit();
+ mLauncher.waitForLauncherInitialized();
// resetLoaderState triggers the launcher to start loading the workspace which allows
// waitForLauncherCondition to wait for that condition, otherwise the condition would
// always be true and it wouldn't wait for the changes to be applied.
- resetLoaderState();
waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading());
+
+ triggerWidgetResize(testCase);
+
Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.getCellX(),
mainWidgetCellPos.getCellY());
assertNotNull(widget);
@@ -137,41 +184,91 @@
*
* @param testCaseMap map containing all the tests per grid size (Point)
*/
- private void runTestCaseMap(Map<Point, ReorderTestCase> testCaseMap, String testName)
- throws ExecutionException, InterruptedException {
+ private boolean runTestCaseMap(Map<Point, ReorderTestCase> testCaseMap, String testName) {
Point iconGridDimensions = mLauncher.getWorkspace().getIconGridDimensions();
Log.d(TAG, "Running test " + testName + " for grid " + iconGridDimensions);
- Assume.assumeTrue(
- "The test " + testName + " doesn't support " + iconGridDimensions + " grid layout",
- testCaseMap.containsKey(iconGridDimensions));
+ if (!testCaseMap.containsKey(iconGridDimensions)) {
+ Log.d(TAG, "The test " + testName + " doesn't support " + iconGridDimensions
+ + " grid layout");
+ return false;
+ }
runTestCase(testCaseMap.get(iconGridDimensions));
+
+ return true;
+ }
+
+ private void runTestCaseMapForAllGrids(Map<Point, ReorderTestCase> testCaseMap,
+ String testName) {
+ boolean runAtLeastOnce = false;
+ for (String grid : FOLDABLE_GRIDS) {
+ applyGridOption(grid);
+ mLauncher.waitForLauncherInitialized();
+ runAtLeastOnce |= runTestCaseMap(testCaseMap, testName);
+ }
+ Assume.assumeTrue("None of the grids are supported", runAtLeastOnce);
+ }
+
+ private void applyGridOption(Object argValue) {
+ String testProviderAuthority = mTargetContext.getPackageName() + ".grid_control";
+ Uri gridUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(testProviderAuthority)
+ .appendPath("default_grid")
+ .build();
+ ContentValues values = new ContentValues();
+ values.putObject("name", argValue);
+ Assert.assertEquals(1,
+ mTargetContext.getContentResolver().update(gridUri, values, null, null));
}
@Test
public void simpleReorder() throws Exception {
- runTestCaseMap(getTestMap("ReorderWidgets/simple_reorder_case"), "push_reorder_case");
+ runTestCaseMap(getTestMap("ReorderWidgets/simple_reorder_case"),
+ "push_reorder_case");
}
@Test
public void pushTest() throws Exception {
- runTestCaseMap(getTestMap("ReorderWidgets/push_reorder_case"), "push_reorder_case");
+ runTestCaseMap(getTestMap("ReorderWidgets/push_reorder_case"),
+ "push_reorder_case");
}
@Test
public void fullReorder() throws Exception {
- runTestCaseMap(getTestMap("ReorderWidgets/full_reorder_case"), "full_reorder_case");
+ runTestCaseMap(getTestMap("ReorderWidgets/full_reorder_case"),
+ "full_reorder_case");
}
@Test
public void moveOutReorder() throws Exception {
- runTestCaseMap(getTestMap("ReorderWidgets/move_out_reorder_case"), "move_out_reorder_case");
+ runTestCaseMap(getTestMap("ReorderWidgets/move_out_reorder_case"),
+ "move_out_reorder_case");
}
@Test
- public void multipleCellLayoutsSimpleReorder() throws ExecutionException, InterruptedException {
- Assume.assumeTrue("Test doesn't support foldables", !mLauncher.isTwoPanels());
- runTestCaseMap(MultipleCellLayoutsSimpleReorder.TEST_BY_GRID_SIZE,
- MultipleCellLayoutsSimpleReorder.class.getSimpleName());
+ public void multipleCellLayoutsSimpleReorder() throws Exception {
+ Assume.assumeTrue("Test doesn't support foldables", getFromLauncher(
+ l -> l.getWorkspace().getScreenWithId(0) instanceof MultipageCellLayout));
+ runTestCaseMapForAllGrids(getTestMap("ReorderWidgets/multiple_cell_layouts_simple_reorder"),
+ "multiple_cell_layouts_simple_reorder");
+ }
+
+ @Test
+ public void multipleCellLayoutsNoSpaceReorder() throws Exception {
+ Assume.assumeTrue("Test doesn't support foldables", getFromLauncher(
+ l -> l.getWorkspace().getScreenWithId(0) instanceof MultipageCellLayout));
+ runTestCaseMapForAllGrids(
+ getTestMap("ReorderWidgets/multiple_cell_layouts_no_space_reorder"),
+ "multiple_cell_layouts_no_space_reorder");
+ }
+
+ @Test
+ public void multipleCellLayoutsReorderToOtherSide() throws Exception {
+ Assume.assumeTrue("Test doesn't support foldables", getFromLauncher(
+ l -> l.getWorkspace().getScreenWithId(0) instanceof MultipageCellLayout));
+ runTestCaseMapForAllGrids(
+ getTestMap("ReorderWidgets/multiple_cell_layouts_reorder_other_side"),
+ "multiple_cell_layouts_reorder_other_side");
}
private void addTestCase(Iterator<CellLayoutTestCaseReader.TestSection> sections,
@@ -184,7 +281,7 @@
((CellLayoutTestCaseReader.Board) sections.next());
Point moveTo = new Point(Integer.parseInt(point.arguments[0]),
Integer.parseInt(point.arguments[1]));
- testCaseMap.put(startBoard.gridSize,
+ testCaseMap.put(endBoard.gridSize,
new ReorderTestCase(startBoard.board, moveTo, endBoard.board));
}
diff --git a/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java b/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java
index 5945605..6489bc1 100644
--- a/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java
+++ b/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java
@@ -15,6 +15,10 @@
*/
package com.android.launcher3.celllayout;
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.launcher3.ui.TestViewHelpers.findWidgetProvider;
import static com.android.launcher3.util.WidgetUtils.createWidgetInfo;
import android.content.ComponentName;
@@ -25,33 +29,30 @@
import android.os.UserHandle;
import android.util.Log;
-import androidx.test.core.app.ApplicationProvider;
-
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.ui.AbstractLauncherUiTest;
-import com.android.launcher3.ui.TestViewHelpers;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
+import java.util.function.Supplier;
+import java.util.stream.IntStream;
+
public class TestWorkspaceBuilder {
private static final String TAG = "CellLayoutBoardBuilder";
- private static final ComponentName APP_COMPONENT_NAME = new ComponentName(
+ private static final String TEST_ACTIVITY_PACKAGE_PREFIX = "com.android.launcher3.tests.";
+ private ComponentName mAppComponentName = new ComponentName(
"com.google.android.calculator", "com.android.calculator2.Calculator");
-
- public AbstractLauncherUiTest mTest;
-
private UserHandle mMyUser;
private Context mContext;
private ContentResolver mResolver;
- public TestWorkspaceBuilder(AbstractLauncherUiTest test, Context context) {
- mTest = test;
+ public TestWorkspaceBuilder(Context context) {
mMyUser = Process.myUserHandle();
mContext = context;
mResolver = mContext.getContentResolver();
@@ -68,10 +69,9 @@
for (int y = initY; y < initY + widgetRect.getSpanY(); y++) {
try {
// this widgets are filling, we don't care if we can't place them
- ItemInfo item = createWidgetInCell(
+ transaction.addItem(createWidgetInCell(
new CellLayoutBoard.WidgetRect(CellLayoutBoard.CellType.IGNORE,
- new Rect(x, y, x, y)), screenId);
- transaction.addItem(item);
+ new Rect(x, y, x, y)), screenId));
} catch (Exception e) {
Log.d(TAG, "Unable to place filling widget at " + x + "," + y);
}
@@ -80,15 +80,21 @@
return transaction;
}
- private int getID() {
- return LauncherSettings.Settings.call(
- mResolver, LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
- .getInt(LauncherSettings.Settings.EXTRA_VALUE);
+ private AppInfo getApp() {
+ return new AppInfo(mAppComponentName, "test icon", mMyUser,
+ AppInfo.makeLaunchIntent(mAppComponentName));
}
- private AppInfo getApp() {
- return new AppInfo(APP_COMPONENT_NAME, "test icon", mMyUser,
- AppInfo.makeLaunchIntent(APP_COMPONENT_NAME));
+ /**
+ * Helper to set the app to use for the test workspace,
+ * using activity-alias from AndroidManifest-common.
+ * @param testAppName the android:name field of the test app activity-alias to use
+ */
+ public void setTestAppActivityAlias(String testAppName) {
+ this.mAppComponentName = new ComponentName(
+ getInstrumentation().getContext().getPackageName(),
+ TEST_ACTIVITY_PACKAGE_PREFIX + testAppName
+ );
}
private void addCorrespondingWidgetRect(CellLayoutBoard.WidgetRect widgetRect,
@@ -108,7 +114,10 @@
board.getWidgets().forEach(
(widgetRect) -> addCorrespondingWidgetRect(widgetRect, transaction, screenId));
board.getIcons().forEach((iconPoint) ->
- transaction.addItem(createIconInCell(iconPoint, screenId))
+ transaction.addItem(() -> createIconInCell(iconPoint, screenId))
+ );
+ board.getFolders().forEach((folderPoint) ->
+ transaction.addItem(() -> createFolderInCell(folderPoint, screenId))
);
return transaction;
}
@@ -118,29 +127,52 @@
* be clean otherwise this doesn't overrides the existing icons.
*/
public FavoriteItemsTransaction fillHotseatIcons(FavoriteItemsTransaction transaction) {
- int hotseatCount = InvariantDeviceProfile.INSTANCE.get(mContext).numDatabaseHotseatIcons;
- for (int i = 0; i < hotseatCount; i++) {
- transaction.addItem(getHotseatValues(i));
- }
+ IntStream.range(0, InvariantDeviceProfile.INSTANCE.get(mContext).numDatabaseHotseatIcons)
+ .forEach(i -> transaction.addItem(() -> getHotseatValues(i)));
return transaction;
}
- private ItemInfo createWidgetInCell(CellLayoutBoard.WidgetRect widgetRect, int screenId) {
- LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(mTest, false);
- LauncherAppWidgetInfo item = createWidgetInfo(info,
- ApplicationProvider.getApplicationContext(), true);
- item.id = getID();
- item.cellX = widgetRect.getCellX();
- item.cellY = widgetRect.getCellY();
- item.spanX = widgetRect.getSpanX();
- item.spanY = widgetRect.getSpanY();
+ private Supplier<ItemInfo> createWidgetInCell(
+ CellLayoutBoard.WidgetRect widgetRect, int screenId) {
+ // Create the widget lazily since the appWidgetId can get lost during setup
+ return () -> {
+ LauncherAppWidgetProviderInfo info = findWidgetProvider(false);
+ LauncherAppWidgetInfo item = createWidgetInfo(info, getApplicationContext(), true);
+ item.cellX = widgetRect.getCellX();
+ item.cellY = widgetRect.getCellY();
+ item.spanX = widgetRect.getSpanX();
+ item.spanY = widgetRect.getSpanY();
+ item.screenId = screenId;
+ return item;
+ };
+ }
+
+ public FolderInfo createFolderInCell(CellLayoutBoard.FolderPoint folderPoint, int screenId) {
+ FolderInfo folderInfo = new FolderInfo();
+ folderInfo.screenId = screenId;
+ folderInfo.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
+ folderInfo.cellX = folderPoint.coord.x;
+ folderInfo.cellY = folderPoint.coord.y;
+ folderInfo.minSpanY = folderInfo.minSpanX = folderInfo.spanX = folderInfo.spanY = 1;
+ folderInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true, null);
+
+ for (int i = 0; i < folderPoint.getNumberIconsInside(); i++) {
+ folderInfo.add(getDefaultWorkspaceItem(screenId), false);
+ }
+
+ return folderInfo;
+ }
+
+ private WorkspaceItemInfo getDefaultWorkspaceItem(int screenId) {
+ WorkspaceItemInfo item = new WorkspaceItemInfo(getApp());
item.screenId = screenId;
+ item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1;
+ item.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
return item;
}
private ItemInfo createIconInCell(CellLayoutBoard.IconPoint iconPoint, int screenId) {
WorkspaceItemInfo item = new WorkspaceItemInfo(getApp());
- item.id = getID();
item.screenId = screenId;
item.cellX = iconPoint.getCoord().x;
item.cellY = iconPoint.getCoord().y;
@@ -151,7 +183,6 @@
private ItemInfo getHotseatValues(int x) {
WorkspaceItemInfo item = new WorkspaceItemInfo(getApp());
- item.id = getID();
item.cellX = x;
item.cellY = 0;
item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1;
diff --git a/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java b/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java
index f34a29e..032a7b4 100644
--- a/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java
+++ b/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java
@@ -27,7 +27,6 @@
import com.android.launcher3.LauncherState;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
-import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import org.junit.After;
import org.junit.Test;
@@ -74,7 +73,6 @@
}
@Test
- @ScreenRecord // b/202985412
public void testPromiseIcon_addedFromEligibleSession() throws Throwable {
final String appLabel = "Test Promise App " + UUID.randomUUID().toString();
final ItemOperator findPromiseApp = (info, view) ->
@@ -97,7 +95,6 @@
}
@Test
- @ScreenRecord // b/202985412
public void testPromiseIcon_notAddedFromIneligibleSession() throws Throwable {
final String appLabel = "Test Promise App " + UUID.randomUUID().toString();
final ItemOperator findPromiseApp = (info, view) ->
diff --git a/tests/src/com/android/launcher3/dragging/TaplDragTest.java b/tests/src/com/android/launcher3/dragging/TaplDragTest.java
new file mode 100644
index 0000000..c652b98
--- /dev/null
+++ b/tests/src/com/android/launcher3/dragging/TaplDragTest.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.dragging;
+
+import static com.android.launcher3.ui.TaplTestsLauncher3.APP_NAME;
+import static com.android.launcher3.ui.TaplTestsLauncher3.GMAIL_APP_NAME;
+import static com.android.launcher3.ui.TaplTestsLauncher3.MAPS_APP_NAME;
+import static com.android.launcher3.ui.TaplTestsLauncher3.STORE_APP_NAME;
+import static com.android.launcher3.ui.TaplTestsLauncher3.initialize;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.graphics.Point;
+import android.os.SystemClock;
+import android.platform.test.annotations.PlatinumTest;
+import android.util.Log;
+
+import com.android.launcher3.tapl.Folder;
+import com.android.launcher3.tapl.FolderIcon;
+import com.android.launcher3.tapl.HomeAllApps;
+import com.android.launcher3.tapl.HomeAppIcon;
+import com.android.launcher3.tapl.HomeAppIconMenuItem;
+import com.android.launcher3.tapl.Workspace;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
+import com.android.launcher3.util.TestUtil;
+import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * This test run in both Out of process (Oop) and in-process (Ipc).
+ * Tests multiple facets of the drag interaction in the Launcher:
+ * * Can create a folder by dragging items.
+ * * Can create a shortcut by dragging it to Workspace.
+ * * Can create shortcuts in multiple spaces in the Workspace.
+ * * Can cancel a drag icon to workspace by dragging outside of the Workspace.
+ * * Can drag an icon from AllApps into the workspace
+ * * Can drag an icon on the Workspace to other positions of the Workspace.
+ */
+public class TaplDragTest extends AbstractLauncherUiTest {
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ initialize(this);
+ }
+
+ /**
+ * Adds two icons to the Workspace and combines them into a folder, then makes sure the icons
+ * are no longer in the Workspace then adds a third one to test adding an icon to an existing
+ * folder instead of creating one and drags it to the folder.
+ */
+ @Test
+ @PortraitLandscape
+ @ScreenRecord
+ @Ignore // b/233075289
+ @PlatinumTest(focusArea = "launcher")
+ public void testDragToFolder() {
+ // TODO: add the use case to drag an icon to an existing folder. Currently it either fails
+ // on tablets or phones due to difference in resolution.
+ final HomeAppIcon playStoreIcon = createShortcutIfNotExist(STORE_APP_NAME, 0, 1);
+ final HomeAppIcon gmailIcon = createShortcutInCenterIfNotExist(GMAIL_APP_NAME);
+
+ FolderIcon folderIcon = gmailIcon.dragToIcon(playStoreIcon);
+ Folder folder = folderIcon.open();
+ folder.getAppIcon(STORE_APP_NAME);
+ folder.getAppIcon(GMAIL_APP_NAME);
+ Workspace workspace = folder.close();
+
+ workspace.verifyWorkspaceAppIconIsGone(STORE_APP_NAME + " should be moved to a folder.",
+ STORE_APP_NAME);
+ workspace.verifyWorkspaceAppIconIsGone(GMAIL_APP_NAME + " should be moved to a folder.",
+ GMAIL_APP_NAME);
+
+ final HomeAppIcon mapIcon = createShortcutInCenterIfNotExist(MAPS_APP_NAME);
+ folderIcon = mapIcon.dragToIcon(folderIcon);
+ folder = folderIcon.open();
+ folder.getAppIcon(MAPS_APP_NAME);
+ workspace = folder.close();
+
+ workspace.verifyWorkspaceAppIconIsGone(MAPS_APP_NAME + " should be moved to a folder.",
+ MAPS_APP_NAME);
+ }
+
+
+ /** Drags a shortcut from a long press menu into the workspace.
+ * 1. Open all apps and wait for load complete.
+ * 2. Find the app and long press it to show shortcuts.
+ * 3. Press icon center until shortcuts appear
+ * 4. Drags shortcut to any free space in the Workspace.
+ */
+ @Test
+ @PortraitLandscape
+ @PlatinumTest(focusArea = "launcher")
+ public void testDragShortcut() {
+
+ final HomeAllApps allApps = mLauncher
+ .getWorkspace()
+ .switchToAllApps();
+ allApps.freeze();
+ try {
+ final HomeAppIconMenuItem menuItem = allApps
+ .getAppIcon(APP_NAME)
+ .openDeepShortcutMenu()
+ .getMenuItem(0);
+ final String actualShortcutName = menuItem.getText();
+ final String expectedShortcutName = "Shortcut 1";
+
+ assertEquals(expectedShortcutName, actualShortcutName);
+ menuItem.dragToWorkspace(false, false);
+ mLauncher.getWorkspace().getWorkspaceAppIcon(expectedShortcutName)
+ .launch(getAppPackageName());
+ } finally {
+ allApps.unfreeze();
+ }
+ }
+
+ /**
+ * Similar to testDragShortcut but it adds shortcuts to multiple positions of the Workspace
+ * namely the corners and the center.
+ */
+ @Test
+ @PortraitLandscape
+ @PlatinumTest(focusArea = "launcher")
+ public void testDragShortcutToMultipleWorkspaceCells() {
+ Point[] targets = TestUtil.getCornersAndCenterPositions(mLauncher);
+
+ for (Point target : targets) {
+ final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+ allApps.freeze();
+ try {
+ allApps.getAppIcon(APP_NAME)
+ .openDeepShortcutMenu()
+ .getMenuItem(0)
+ .dragToWorkspace(target.x, target.y);
+ } finally {
+ allApps.unfreeze();
+ }
+ }
+ }
+
+ /**
+ * Drags an icon to the workspace but instead of submitting it, it gets dragged outside of the
+ * Workspace to cancel it.
+ */
+
+ @Test
+ @PortraitLandscape
+ @PlatinumTest(focusArea = "launcher")
+ public void testDragAndCancelAppIcon() {
+ final HomeAppIcon homeAppIcon = createShortcutInCenterIfNotExist(GMAIL_APP_NAME);
+ Point positionBeforeDrag =
+ mLauncher.getWorkspace().getWorkspaceIconsPositions().get(GMAIL_APP_NAME);
+ assertNotNull("App not found in Workspace before dragging.", positionBeforeDrag);
+
+ mLauncher.getWorkspace().dragAndCancelAppIcon(homeAppIcon);
+
+ Point positionAfterDrag =
+ mLauncher.getWorkspace().getWorkspaceIconsPositions().get(GMAIL_APP_NAME);
+ assertNotNull("App not found in Workspace after dragging.", positionAfterDrag);
+ assertEquals("App not returned to same position in Workspace after drag & cancel",
+ positionBeforeDrag, positionAfterDrag);
+ }
+
+ /**
+ * Drags app icon from AllApps into the Workspace.
+ * 1. Open all apps and wait for load complete.
+ * 2. Drag icon to homescreen.
+ * 3. Verify that the icon works on homescreen.
+ */
+ @PlatinumTest(focusArea = "launcher")
+ @Test
+ @PortraitLandscape
+ public void testDragAppIcon() {
+
+ final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+ allApps.freeze();
+ try {
+ allApps.getAppIcon(APP_NAME).dragToWorkspace(false, false);
+ mLauncher.getWorkspace().getWorkspaceAppIcon(APP_NAME).launch(getAppPackageName());
+ } finally {
+ allApps.unfreeze();
+ }
+ executeOnLauncher(launcher -> assertTrue(
+ "Launcher activity is the top activity; expecting another activity to be the top "
+ + "one",
+ isInLaunchedApp(launcher)));
+ }
+
+ /**
+ * Similar start to testDragAppIcon but after dragging the icon to the workspace, it drags the
+ * icon inside of the workspace to different positions.
+ * @throws Exception
+ */
+ @Test
+ @PortraitLandscape
+ @PlatinumTest(focusArea = "launcher")
+ public void testDragAppIconToMultipleWorkspaceCells() throws Exception {
+ long startTime, endTime, elapsedTime;
+ Point[] targets = TestUtil.getCornersAndCenterPositions(mLauncher);
+
+ for (Point target : targets) {
+ startTime = SystemClock.uptimeMillis();
+ final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+ allApps.freeze();
+ try {
+ allApps.getAppIcon(APP_NAME).dragToWorkspace(target.x, target.y);
+ } finally {
+ allApps.unfreeze();
+ }
+ // Reset the workspace for the next shortcut creation.
+ initialize(this, true);
+ endTime = SystemClock.uptimeMillis();
+ elapsedTime = endTime - startTime;
+ Log.d("testDragAppIconToWorkspaceCellTime",
+ "Milliseconds taken to drag app icon to workspace cell: " + elapsedTime);
+ }
+
+ // test to move a shortcut to other cell.
+ final HomeAppIcon launcherTestAppIcon = createShortcutInCenterIfNotExist(APP_NAME);
+ for (Point target : targets) {
+ startTime = SystemClock.uptimeMillis();
+ launcherTestAppIcon.dragToWorkspace(target.x, target.y);
+ endTime = SystemClock.uptimeMillis();
+ elapsedTime = endTime - startTime;
+ Log.d("testDragAppIconToWorkspaceCellTime",
+ "Milliseconds taken to move shortcut to other cell: " + elapsedTime);
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/dragging/TaplUninstallRemove.java b/tests/src/com/android/launcher3/dragging/TaplUninstallRemove.java
new file mode 100644
index 0000000..712806c
--- /dev/null
+++ b/tests/src/com/android/launcher3/dragging/TaplUninstallRemove.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.dragging;
+
+import static com.android.launcher3.testing.shared.TestProtocol.ICON_MISSING;
+import static com.android.launcher3.ui.TaplTestsLauncher3.APP_NAME;
+import static com.android.launcher3.ui.TaplTestsLauncher3.DUMMY_APP_NAME;
+import static com.android.launcher3.ui.TaplTestsLauncher3.MAPS_APP_NAME;
+import static com.android.launcher3.ui.TaplTestsLauncher3.STORE_APP_NAME;
+import static com.android.launcher3.ui.TaplTestsLauncher3.initialize;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.graphics.Point;
+import android.platform.test.annotations.PlatinumTest;
+import android.util.Log;
+
+import com.android.launcher3.tapl.HomeAllApps;
+import com.android.launcher3.tapl.HomeAppIcon;
+import com.android.launcher3.tapl.Workspace;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
+import com.android.launcher3.util.TestUtil;
+import com.android.launcher3.util.Wait;
+import com.android.launcher3.util.rule.ScreenRecordRule;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Test runs in Out of process (Oop) and In process (Ipc)
+ * Test the behaviour of uninstalling and removing apps both from AllApps and from the Workspace.
+ */
+public class TaplUninstallRemove extends AbstractLauncherUiTest {
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ initialize(this);
+ }
+
+ /**
+ * Deletes app both built-in and user-installed from the Workspace and makes sure it's no longer
+ * in the Workspace.
+ */
+ @Test
+ @PortraitLandscape
+ public void testDeleteFromWorkspace() {
+ for (String appName : new String[]{"Gmail", "Play Store", APP_NAME}) {
+ final HomeAppIcon homeAppIcon = createShortcutInCenterIfNotExist(appName);
+ Workspace workspace = mLauncher.getWorkspace().deleteAppIcon(homeAppIcon);
+ workspace.verifyWorkspaceAppIconIsGone(
+ appName + " app was found after being deleted from workspace",
+ appName);
+ }
+ }
+
+ private void verifyAppUninstalledFromAllApps(Workspace workspace, String appName) {
+ final HomeAllApps allApps = workspace.switchToAllApps();
+ Wait.atMost(appName + " app was found on all apps after being uninstalled",
+ () -> allApps.tryGetAppIcon(appName) == null,
+ DEFAULT_UI_TIMEOUT, mLauncher);
+ }
+
+ private void installDummyAppAndWaitForUIUpdate() throws IOException {
+ TestUtil.installDummyApp();
+ waitForLauncherUIUpdate();
+ }
+
+ private void waitForLauncherUIUpdate() {
+ // Wait for model thread completion as it may be processing
+ // the install event from the SystemService
+ mLauncher.waitForModelQueueCleared();
+ // Wait for Launcher UI thread completion, as it may be processing updating the UI in
+ // response to the model update. Not that `waitForLauncherInitialized` is just a proxy
+ // method, we can use any method which touches Launcher UI thread,
+ mLauncher.waitForLauncherInitialized();
+ }
+
+ /**
+ * Makes sure you can uninstall an app from the Workspace.
+ * @throws Exception
+ */
+ @Test
+ @PortraitLandscape
+ // TODO(b/293944634): Remove Screenrecord after flaky debug, and add
+ // @PlatinumTest(focusArea = "launcher") back
+ @ScreenRecordRule.ScreenRecord
+ public void testUninstallFromWorkspace() throws Exception {
+ installDummyAppAndWaitForUIUpdate();
+ try {
+ verifyAppUninstalledFromAllApps(
+ createShortcutInCenterIfNotExist(DUMMY_APP_NAME).uninstall(), DUMMY_APP_NAME);
+ } finally {
+ TestUtil.uninstallDummyApp();
+ }
+ }
+
+ /**
+ * Makes sure you can uninstall an app from AllApps.
+ * @throws Exception
+ */
+ @Test
+ @PortraitLandscape
+ @PlatinumTest(focusArea = "launcher")
+ public void testUninstallFromAllApps() throws Exception {
+ installDummyAppAndWaitForUIUpdate();
+ try {
+ Workspace workspace = mLauncher.getWorkspace();
+ final HomeAllApps allApps = workspace.switchToAllApps();
+ workspace = allApps.getAppIcon(DUMMY_APP_NAME).uninstall();
+ verifyAppUninstalledFromAllApps(workspace, DUMMY_APP_NAME);
+ } finally {
+ TestUtil.uninstallDummyApp();
+ }
+ }
+
+ /**
+ * Adds three icons to the workspace and removes one of them by dragging to uninstall.
+ */
+ @Test
+ @PlatinumTest(focusArea = "launcher")
+ public void uninstallWorkspaceIcon() throws IOException {
+ Point[] gridPositions = TestUtil.getCornersAndCenterPositions(mLauncher);
+ StringBuilder sb = new StringBuilder();
+ for (Point p : gridPositions) {
+ sb.append(p).append(", ");
+ }
+ Log.d(ICON_MISSING, "allGridPositions: " + sb);
+ createShortcutIfNotExist(STORE_APP_NAME, gridPositions[0]);
+ createShortcutIfNotExist(MAPS_APP_NAME, gridPositions[1]);
+ installDummyAppAndWaitForUIUpdate();
+ try {
+ createShortcutIfNotExist(DUMMY_APP_NAME, gridPositions[2]);
+ Map<String, Point> initialPositions =
+ mLauncher.getWorkspace().getWorkspaceIconsPositions();
+ assertThat(initialPositions.keySet())
+ .containsAtLeast(DUMMY_APP_NAME, MAPS_APP_NAME, STORE_APP_NAME);
+
+ mLauncher.getWorkspace().getWorkspaceAppIcon(DUMMY_APP_NAME).uninstall();
+ mLauncher.getWorkspace().verifyWorkspaceAppIconIsGone(
+ DUMMY_APP_NAME + " was expected to disappear after uninstall.", DUMMY_APP_NAME);
+
+ Map<String, Point> finalPositions =
+ mLauncher.getWorkspace().getWorkspaceIconsPositions();
+ assertThat(finalPositions).doesNotContainKey(DUMMY_APP_NAME);
+ } finally {
+ TestUtil.uninstallDummyApp();
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/folder/PreviewBackgroundTest.java b/tests/src/com/android/launcher3/folder/PreviewBackgroundTest.java
new file mode 100644
index 0000000..715a1f8
--- /dev/null
+++ b/tests/src/com/android/launcher3/folder/PreviewBackgroundTest.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.folder;
+
+import static com.android.launcher3.folder.PreviewBackground.ACCEPT_SCALE_FACTOR;
+import static com.android.launcher3.folder.PreviewBackground.CONSUMPTION_ANIMATION_DURATION;
+import static com.android.launcher3.folder.PreviewBackground.HOVER_ANIMATION_DURATION;
+import static com.android.launcher3.folder.PreviewBackground.HOVER_SCALE;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.PathInterpolator;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.launcher3.CellLayout;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class PreviewBackgroundTest {
+
+ private static final float REST_SCALE = 1f;
+ private static final float EPSILON = 0.00001f;
+
+ @Mock
+ CellLayout mCellLayout;
+
+ private final PreviewBackground mPreviewBackground = new PreviewBackground();
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mPreviewBackground.mScale = REST_SCALE;
+ mPreviewBackground.mIsAccepting = false;
+ mPreviewBackground.mIsHovered = false;
+ mPreviewBackground.mIsHoveredOrAnimating = false;
+ mPreviewBackground.invalidate();
+ }
+
+ @Test
+ public void testAnimateScale_restToHovered() {
+ mPreviewBackground.setHovered(true);
+ runAnimationToFraction(1f);
+
+ assertEquals("Scale not changed.", mPreviewBackground.mScale, HOVER_SCALE, EPSILON);
+ assertEquals("Duration not correct.", mPreviewBackground.mScaleAnimator.getDuration(),
+ HOVER_ANIMATION_DURATION);
+ assertTrue("Wrong interpolator used.",
+ mPreviewBackground.mScaleAnimator.getInterpolator() instanceof PathInterpolator);
+ endAnimation();
+ assertEquals("Scale progress not 0.", mPreviewBackground.getAcceptScaleProgress(), 0,
+ EPSILON);
+ }
+
+ @Test
+ public void testAnimateScale_restToNotHovered() {
+ mPreviewBackground.setHovered(false);
+
+ assertEquals("Scale changed.", mPreviewBackground.mScale, REST_SCALE, EPSILON);
+ assertNull("Animator not null.", mPreviewBackground.mScaleAnimator);
+ assertEquals("Scale progress not 0.", mPreviewBackground.getAcceptScaleProgress(), 0,
+ EPSILON);
+ }
+
+ @Test
+ public void testAnimateScale_hoveredToHovered() {
+ mPreviewBackground.mScale = HOVER_SCALE;
+ mPreviewBackground.mIsHovered = true;
+ mPreviewBackground.mIsHoveredOrAnimating = true;
+ mPreviewBackground.invalidate();
+
+ mPreviewBackground.setHovered(true);
+
+ assertEquals("Scale changed.", mPreviewBackground.mScale, HOVER_SCALE, EPSILON);
+ assertNull("Animator not null.", mPreviewBackground.mScaleAnimator);
+ assertEquals("Scale progress not 0.", mPreviewBackground.getAcceptScaleProgress(), 0,
+ EPSILON);
+ }
+
+ @Test
+ public void testAnimateScale_hoveredToRest() {
+ mPreviewBackground.mScale = HOVER_SCALE;
+ mPreviewBackground.mIsHovered = true;
+ mPreviewBackground.mIsHoveredOrAnimating = true;
+ mPreviewBackground.invalidate();
+
+ mPreviewBackground.setHovered(false);
+ runAnimationToFraction(1f);
+
+ assertEquals("Scale not changed.", mPreviewBackground.mScale, REST_SCALE, EPSILON);
+ assertEquals("Duration not correct.", mPreviewBackground.mScaleAnimator.getDuration(),
+ HOVER_ANIMATION_DURATION);
+ assertTrue("Wrong interpolator used.",
+ mPreviewBackground.mScaleAnimator.getInterpolator() instanceof PathInterpolator);
+ endAnimation();
+ assertEquals("Scale progress not 0.", mPreviewBackground.getAcceptScaleProgress(), 0,
+ EPSILON);
+ }
+
+ @Test
+ public void testAnimateScale_restToAccept() {
+ mPreviewBackground.animateToAccept(mCellLayout, 0, 0);
+ runAnimationToFraction(1f);
+
+ assertEquals("Scale changed.", mPreviewBackground.mScale, ACCEPT_SCALE_FACTOR, EPSILON);
+ assertEquals("Duration not correct.", mPreviewBackground.mScaleAnimator.getDuration(),
+ CONSUMPTION_ANIMATION_DURATION);
+ assertTrue("Wrong interpolator used.",
+ mPreviewBackground.mScaleAnimator.getInterpolator()
+ instanceof AccelerateDecelerateInterpolator);
+ endAnimation();
+ assertEquals("Scale progress not 1.", mPreviewBackground.getAcceptScaleProgress(), 1,
+ EPSILON);
+ }
+
+ @Test
+ public void testAnimateScale_restToRest() {
+ mPreviewBackground.animateToRest();
+
+ assertEquals("Scale changed.", mPreviewBackground.mScale, REST_SCALE, EPSILON);
+ assertNull("Animator not null.", mPreviewBackground.mScaleAnimator);
+ assertEquals("Scale progress not 0.", mPreviewBackground.getAcceptScaleProgress(), 0,
+ EPSILON);
+ }
+
+ @Test
+ public void testAnimateScale_acceptToRest() {
+ mPreviewBackground.mScale = ACCEPT_SCALE_FACTOR;
+ mPreviewBackground.mIsAccepting = true;
+ mPreviewBackground.invalidate();
+
+ mPreviewBackground.animateToRest();
+ runAnimationToFraction(1f);
+
+ assertEquals("Scale not changed.", mPreviewBackground.mScale, REST_SCALE, EPSILON);
+ assertEquals("Duration not correct.", mPreviewBackground.mScaleAnimator.getDuration(),
+ CONSUMPTION_ANIMATION_DURATION);
+ assertTrue("Wrong interpolator used.",
+ mPreviewBackground.mScaleAnimator.getInterpolator()
+ instanceof AccelerateDecelerateInterpolator);
+ endAnimation();
+ assertEquals("Scale progress not 0.", mPreviewBackground.getAcceptScaleProgress(), 0,
+ EPSILON);
+ }
+
+ @Test
+ public void testAnimateScale_acceptToHover() {
+ mPreviewBackground.mScale = ACCEPT_SCALE_FACTOR;
+ mPreviewBackground.mIsAccepting = true;
+ mPreviewBackground.invalidate();
+
+ mPreviewBackground.mIsAccepting = false;
+ mPreviewBackground.setHovered(true);
+ runAnimationToFraction(1f);
+
+ assertEquals("Scale not changed.", mPreviewBackground.mScale, HOVER_SCALE, EPSILON);
+ assertEquals("Duration not correct.", mPreviewBackground.mScaleAnimator.getDuration(),
+ HOVER_ANIMATION_DURATION);
+ assertTrue("Wrong interpolator used.",
+ mPreviewBackground.mScaleAnimator.getInterpolator() instanceof PathInterpolator);
+ endAnimation();
+ assertEquals("Scale progress not 0.", mPreviewBackground.getAcceptScaleProgress(), 0,
+ EPSILON);
+ }
+
+ @Test
+ public void testAnimateScale_hoverToAccept() {
+ mPreviewBackground.mScale = HOVER_SCALE;
+ mPreviewBackground.mIsHovered = true;
+ mPreviewBackground.mIsHoveredOrAnimating = true;
+ mPreviewBackground.invalidate();
+
+ mPreviewBackground.animateToAccept(mCellLayout, 0, 0);
+ runAnimationToFraction(1f);
+
+ assertEquals("Scale not changed.", mPreviewBackground.mScale, ACCEPT_SCALE_FACTOR, EPSILON);
+ assertEquals("Duration not correct.", mPreviewBackground.mScaleAnimator.getDuration(),
+ CONSUMPTION_ANIMATION_DURATION);
+ assertTrue("Wrong interpolator used.",
+ mPreviewBackground.mScaleAnimator.getInterpolator()
+ instanceof AccelerateDecelerateInterpolator);
+ mPreviewBackground.mIsHovered = false;
+ endAnimation();
+ assertEquals("Scale progress not 1.", mPreviewBackground.getAcceptScaleProgress(), 1,
+ EPSILON);
+ }
+
+ @Test
+ public void testAnimateScale_midwayToHoverToAccept() {
+ mPreviewBackground.setHovered(true);
+ runAnimationToFraction(0.5f);
+ assertTrue("Scale not changed.",
+ mPreviewBackground.mScale > REST_SCALE && mPreviewBackground.mScale < HOVER_SCALE);
+ assertEquals("Scale progress not 0.", mPreviewBackground.getAcceptScaleProgress(), 0,
+ EPSILON);
+
+ mPreviewBackground.animateToAccept(mCellLayout, 0, 0);
+ runAnimationToFraction(1f);
+
+ assertEquals("Scale not changed.", mPreviewBackground.mScale, ACCEPT_SCALE_FACTOR, EPSILON);
+ assertEquals("Duration not correct.", mPreviewBackground.mScaleAnimator.getDuration(),
+ CONSUMPTION_ANIMATION_DURATION);
+ assertTrue("Wrong interpolator used.",
+ mPreviewBackground.mScaleAnimator.getInterpolator()
+ instanceof AccelerateDecelerateInterpolator);
+ mPreviewBackground.mIsHovered = false;
+ endAnimation();
+ assertEquals("Scale progress not 1.", mPreviewBackground.getAcceptScaleProgress(), 1,
+ EPSILON);
+ assertNull("Animator not null.", mPreviewBackground.mScaleAnimator);
+ }
+
+ @Test
+ public void testAnimateScale_partWayToAcceptToHover() {
+ mPreviewBackground.animateToAccept(mCellLayout, 0, 0);
+ runAnimationToFraction(0.25f);
+ assertTrue("Scale not changed part way.", mPreviewBackground.mScale > REST_SCALE
+ && mPreviewBackground.mScale < ACCEPT_SCALE_FACTOR);
+
+ mPreviewBackground.mIsAccepting = false;
+ mPreviewBackground.setHovered(true);
+ runAnimationToFraction(1f);
+
+ assertEquals("Scale not changed.", mPreviewBackground.mScale, HOVER_SCALE, EPSILON);
+ assertEquals("Duration not correct.", mPreviewBackground.mScaleAnimator.getDuration(),
+ HOVER_ANIMATION_DURATION);
+ assertTrue("Wrong interpolator used.",
+ mPreviewBackground.mScaleAnimator.getInterpolator() instanceof PathInterpolator);
+ endAnimation();
+ assertEquals("Scale progress not 0.", mPreviewBackground.getAcceptScaleProgress(), 0,
+ EPSILON);
+ }
+
+ @Test
+ public void testAnimateScale_midwayToAcceptEqualsHover() {
+ mPreviewBackground.animateToAccept(mCellLayout, 0, 0);
+ runAnimationToFraction(0.5f);
+ assertEquals("Scale not changed.", mPreviewBackground.mScale, HOVER_SCALE, EPSILON);
+ mPreviewBackground.mIsAccepting = false;
+
+ mPreviewBackground.setHovered(true);
+
+ assertEquals("Scale changed.", mPreviewBackground.mScale, HOVER_SCALE, EPSILON);
+ assertNull("Animator not null.", mPreviewBackground.mScaleAnimator);
+ assertEquals("Scale progress not 0.", mPreviewBackground.getAcceptScaleProgress(), 0,
+ EPSILON);
+ }
+
+ @Test
+ public void testAnimateScale_midwayToHoverToRest() {
+ mPreviewBackground.setHovered(true);
+ runAnimationToFraction(0.5f);
+ assertTrue("Scale not changed midway.",
+ mPreviewBackground.mScale > REST_SCALE && mPreviewBackground.mScale < HOVER_SCALE);
+
+ mPreviewBackground.mIsHovered = false;
+ mPreviewBackground.animateToRest();
+ runAnimationToFraction(1f);
+
+ assertEquals("Scale not changed.", mPreviewBackground.mScale, REST_SCALE, EPSILON);
+ assertEquals("Duration not correct.", mPreviewBackground.mScaleAnimator.getDuration(),
+ HOVER_ANIMATION_DURATION);
+ assertTrue("Wrong interpolator used.",
+ mPreviewBackground.mScaleAnimator.getInterpolator() instanceof PathInterpolator);
+ endAnimation();
+ assertEquals("Scale progress not 0.", mPreviewBackground.getAcceptScaleProgress(), 0,
+ EPSILON);
+ }
+
+ @Test
+ public void testAnimateScale_midwayToAcceptToRest() {
+ mPreviewBackground.animateToAccept(mCellLayout, 0, 0);
+ runAnimationToFraction(0.5f);
+ assertTrue("Scale not changed.", mPreviewBackground.mScale > REST_SCALE
+ && mPreviewBackground.mScale < ACCEPT_SCALE_FACTOR);
+
+ mPreviewBackground.animateToRest();
+ runAnimationToFraction(1f);
+
+ assertEquals("Scale not changed.", mPreviewBackground.mScale, REST_SCALE, EPSILON);
+ assertEquals("Duration not correct.", mPreviewBackground.mScaleAnimator.getDuration(),
+ CONSUMPTION_ANIMATION_DURATION);
+ assertTrue("Wrong interpolator used.",
+ mPreviewBackground.mScaleAnimator.getInterpolator()
+ instanceof AccelerateDecelerateInterpolator);
+ endAnimation();
+ assertEquals("Scale progress not 0.", mPreviewBackground.getAcceptScaleProgress(), 0,
+ EPSILON);
+ }
+
+ private void runAnimationToFraction(float animationFraction) {
+ mPreviewBackground.mScaleAnimator.setCurrentFraction(animationFraction);
+ }
+
+ private void endAnimation() {
+ mPreviewBackground.mScaleAnimator.end();
+ }
+}
diff --git a/tests/src/com/android/launcher3/icons/FastBitmapDrawableTest.java b/tests/src/com/android/launcher3/icons/FastBitmapDrawableTest.java
new file mode 100644
index 0000000..038c98b
--- /dev/null
+++ b/tests/src/com/android/launcher3/icons/FastBitmapDrawableTest.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.icons;
+
+import static com.android.launcher3.icons.FastBitmapDrawable.CLICK_FEEDBACK_DURATION;
+import static com.android.launcher3.icons.FastBitmapDrawable.HOVERED_SCALE;
+import static com.android.launcher3.icons.FastBitmapDrawable.HOVER_FEEDBACK_DURATION;
+import static com.android.launcher3.icons.FastBitmapDrawable.PRESSED_SCALE;
+import static com.android.launcher3.icons.FastBitmapDrawable.SCALE;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.graphics.Bitmap;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.PathInterpolator;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Spy;
+
+/**
+ * Tests for FastBitmapDrawable.
+ */
+@SmallTest
+@UiThreadTest
+@RunWith(AndroidJUnit4.class)
+public class FastBitmapDrawableTest {
+ private static final float EPSILON = 0.00001f;
+
+ @Spy
+ FastBitmapDrawable mFastBitmapDrawable =
+ spy(new FastBitmapDrawable(Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888)));
+
+ @Before
+ public void setUp() {
+ FastBitmapDrawable.setFlagHoverEnabled(true);
+ when(mFastBitmapDrawable.isVisible()).thenReturn(true);
+ mFastBitmapDrawable.mIsPressed = false;
+ mFastBitmapDrawable.mIsHovered = false;
+ mFastBitmapDrawable.resetScale();
+ }
+
+ @Test
+ public void testOnStateChange_noState() {
+ int[] state = new int[]{};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // No scale changes without state change.
+ assertFalse("State change handled.", isHandled);
+ assertNull("Scale animation not null.", mFastBitmapDrawable.mScaleAnimation);
+ }
+
+ @Test
+ public void testOnStateChange_statePressed() {
+ int[] state = new int[]{android.R.attr.state_pressed};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // Animate to state pressed.
+ assertTrue("State change not handled.", isHandled);
+ assertEquals("Duration not correct.", mFastBitmapDrawable.mScaleAnimation.getDuration(),
+ CLICK_FEEDBACK_DURATION);
+ mFastBitmapDrawable.mScaleAnimation.end();
+ assertEquals("End value not correct.",
+ (float) SCALE.get(mFastBitmapDrawable), PRESSED_SCALE, EPSILON);
+ assertTrue("Wrong interpolator used.",
+ mFastBitmapDrawable.mScaleAnimation.getInterpolator()
+ instanceof AccelerateInterpolator);
+ }
+
+ @Test
+ public void testOnStateChange_stateHovered() {
+ int[] state = new int[]{android.R.attr.state_hovered};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // Animate to state hovered.
+ assertTrue("State change not handled.", isHandled);
+ assertEquals("Duration not correct.", mFastBitmapDrawable.mScaleAnimation.getDuration(),
+ HOVER_FEEDBACK_DURATION);
+ mFastBitmapDrawable.mScaleAnimation.end();
+ assertEquals("End value not correct.",
+ (float) SCALE.get(mFastBitmapDrawable), HOVERED_SCALE, EPSILON);
+ assertTrue("Wrong interpolator used.",
+ mFastBitmapDrawable.mScaleAnimation.getInterpolator() instanceof PathInterpolator);
+ }
+
+ @Test
+ public void testOnStateChange_stateHoveredFlagDisabled() {
+ FastBitmapDrawable.setFlagHoverEnabled(false);
+ int[] state = new int[]{android.R.attr.state_hovered};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // No state change with flag disabled.
+ assertFalse("Hover state change handled with flag disabled.", isHandled);
+ assertNull("Animation should not run with hover flag disabled.",
+ mFastBitmapDrawable.mScaleAnimation);
+ }
+
+ @Test
+ public void testOnStateChange_statePressedAndHovered() {
+ int[] state = new int[]{android.R.attr.state_pressed, android.R.attr.state_hovered};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // Animate to pressed state only.
+ assertTrue("State change not handled.", isHandled);
+ assertEquals("Duration not correct.", mFastBitmapDrawable.mScaleAnimation.getDuration(),
+ CLICK_FEEDBACK_DURATION);
+ mFastBitmapDrawable.mScaleAnimation.end();
+ assertEquals("End value not correct.",
+ (float) SCALE.get(mFastBitmapDrawable), PRESSED_SCALE, EPSILON);
+ assertTrue("Wrong interpolator used.",
+ mFastBitmapDrawable.mScaleAnimation.getInterpolator()
+ instanceof AccelerateInterpolator);
+ }
+
+ @Test
+ public void testOnStateChange_stateHoveredAndPressed() {
+ int[] state = new int[]{android.R.attr.state_hovered, android.R.attr.state_pressed};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // Animate to pressed state only.
+ assertTrue("State change not handled.", isHandled);
+ assertEquals("Duration not correct.", mFastBitmapDrawable.mScaleAnimation.getDuration(),
+ CLICK_FEEDBACK_DURATION);
+ mFastBitmapDrawable.mScaleAnimation.end();
+ assertEquals("End value not correct.",
+ (float) SCALE.get(mFastBitmapDrawable), PRESSED_SCALE, EPSILON);
+ assertTrue("Wrong interpolator used.",
+ mFastBitmapDrawable.mScaleAnimation.getInterpolator()
+ instanceof AccelerateInterpolator);
+ }
+
+ @Test
+ public void testOnStateChange_stateHoveredAndPressedToPressed() {
+ mFastBitmapDrawable.mIsPressed = true;
+ mFastBitmapDrawable.mIsHovered = true;
+ SCALE.setValue(mFastBitmapDrawable, PRESSED_SCALE);
+ int[] state = new int[]{android.R.attr.state_pressed};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // No scale change from pressed state to pressed state.
+ assertTrue("State not changed.", isHandled);
+ assertEquals("End value not correct.",
+ (float) SCALE.get(mFastBitmapDrawable), PRESSED_SCALE, EPSILON);
+ }
+
+ @Test
+ public void testOnStateChange_stateHoveredAndPressedToHovered() {
+ mFastBitmapDrawable.mIsPressed = true;
+ mFastBitmapDrawable.mIsHovered = true;
+ SCALE.setValue(mFastBitmapDrawable, PRESSED_SCALE);
+ int[] state = new int[]{android.R.attr.state_hovered};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // No scale change from pressed state to hovered state.
+ assertTrue("State not changed.", isHandled);
+ assertEquals("End value not correct.",
+ (float) SCALE.get(mFastBitmapDrawable), HOVERED_SCALE, EPSILON);
+ }
+
+ @Test
+ public void testOnStateChange_stateHoveredToPressed() {
+ mFastBitmapDrawable.mIsHovered = true;
+ SCALE.setValue(mFastBitmapDrawable, HOVERED_SCALE);
+ int[] state = new int[]{android.R.attr.state_pressed};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // No scale change from pressed state to hovered state.
+ assertTrue("State not changed.", isHandled);
+ assertEquals("End value not correct.",
+ (float) SCALE.get(mFastBitmapDrawable), PRESSED_SCALE, EPSILON);
+ }
+
+ @Test
+ public void testOnStateChange_statePressedToHovered() {
+ mFastBitmapDrawable.mIsPressed = true;
+ SCALE.setValue(mFastBitmapDrawable, PRESSED_SCALE);
+ int[] state = new int[]{android.R.attr.state_hovered};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // No scale change from pressed state to hovered state.
+ assertTrue("State not changed.", isHandled);
+ assertEquals("End value not correct.",
+ (float) SCALE.get(mFastBitmapDrawable), HOVERED_SCALE, EPSILON);
+ }
+
+ @Test
+ public void testOnStateChange_stateDefaultFromPressed() {
+ mFastBitmapDrawable.mIsPressed = true;
+ SCALE.setValue(mFastBitmapDrawable, PRESSED_SCALE);
+ int[] state = new int[]{};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // Animate to default state from pressed state.
+ assertTrue("State change not handled.", isHandled);
+ assertEquals("Duration not correct.", mFastBitmapDrawable.mScaleAnimation.getDuration(),
+ CLICK_FEEDBACK_DURATION);
+ mFastBitmapDrawable.mScaleAnimation.end();
+ assertEquals("End value not correct.", (float) SCALE.get(mFastBitmapDrawable), 1f, EPSILON);
+ assertTrue("Wrong interpolator used.",
+ mFastBitmapDrawable.mScaleAnimation.getInterpolator()
+ instanceof DecelerateInterpolator);
+ }
+
+ @Test
+ public void testOnStateChange_stateDefaultFromHovered() {
+ mFastBitmapDrawable.mIsHovered = true;
+ SCALE.setValue(mFastBitmapDrawable, HOVERED_SCALE);
+ int[] state = new int[]{};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // Animate to default state from hovered state.
+ assertTrue("State change not handled.", isHandled);
+ assertEquals("Duration not correct.", mFastBitmapDrawable.mScaleAnimation.getDuration(),
+ HOVER_FEEDBACK_DURATION);
+ mFastBitmapDrawable.mScaleAnimation.end();
+ assertEquals("End value not correct.", (float) SCALE.get(mFastBitmapDrawable), 1f, EPSILON);
+ assertTrue("Wrong interpolator used.",
+ mFastBitmapDrawable.mScaleAnimation.getInterpolator() instanceof PathInterpolator);
+ }
+
+ @Test
+ public void testOnStateChange_stateHoveredWhilePartiallyScaled() {
+ SCALE.setValue(mFastBitmapDrawable, 0.5f);
+ int[] state = new int[]{android.R.attr.state_hovered};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // Animate to hovered state from midway to pressed state.
+ assertTrue("State change not handled.", isHandled);
+ assertEquals("Duration not correct.",
+ mFastBitmapDrawable.mScaleAnimation.getDuration(), HOVER_FEEDBACK_DURATION);
+ mFastBitmapDrawable.mScaleAnimation.end();
+ assertEquals("End value not correct.",
+ (float) SCALE.get(mFastBitmapDrawable), HOVERED_SCALE, EPSILON);
+ assertTrue("Wrong interpolator used.",
+ mFastBitmapDrawable.mScaleAnimation.getInterpolator() instanceof PathInterpolator);
+ }
+
+ @Test
+ public void testOnStateChange_statePressedWhilePartiallyScaled() {
+ SCALE.setValue(mFastBitmapDrawable, 0.5f);
+ int[] state = new int[]{android.R.attr.state_pressed};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // Animate to pressed state from midway to hovered state.
+ assertTrue("State change not handled.", isHandled);
+ assertEquals("Duration not correct.",
+ mFastBitmapDrawable.mScaleAnimation.getDuration(), CLICK_FEEDBACK_DURATION);
+ mFastBitmapDrawable.mScaleAnimation.end();
+ assertEquals("End value not correct.",
+ (float) SCALE.get(mFastBitmapDrawable), PRESSED_SCALE, EPSILON);
+ assertTrue("Wrong interpolator used.",
+ mFastBitmapDrawable.mScaleAnimation.getInterpolator()
+ instanceof AccelerateInterpolator);
+ }
+
+ @Test
+ public void testOnStateChange_stateDefaultFromPressedNotVisible() {
+ when(mFastBitmapDrawable.isVisible()).thenReturn(false);
+ mFastBitmapDrawable.mIsPressed = true;
+ SCALE.setValue(mFastBitmapDrawable, PRESSED_SCALE);
+ clearInvocations(mFastBitmapDrawable);
+ int[] state = new int[]{};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // No animations when state was pressed but drawable no longer visible. Set values directly.
+ assertTrue("State change not handled.", isHandled);
+ assertNull("Scale animation not null.", mFastBitmapDrawable.mScaleAnimation);
+ assertEquals("End value not correct.", (float) SCALE.get(mFastBitmapDrawable), 1f, EPSILON);
+ verify(mFastBitmapDrawable).invalidateSelf();
+ }
+
+ @Test
+ public void testOnStateChange_stateDefaultFromHoveredNotVisible() {
+ when(mFastBitmapDrawable.isVisible()).thenReturn(false);
+ mFastBitmapDrawable.mIsHovered = true;
+ SCALE.setValue(mFastBitmapDrawable, HOVERED_SCALE);
+ clearInvocations(mFastBitmapDrawable);
+ int[] state = new int[]{};
+
+ boolean isHandled = mFastBitmapDrawable.onStateChange(state);
+
+ // No animations when state was hovered but drawable no longer visible. Set values directly.
+ assertTrue("State change not handled.", isHandled);
+ assertNull("Scale animation not null.", mFastBitmapDrawable.mScaleAnimation);
+ assertEquals("End value not correct.", (float) SCALE.get(mFastBitmapDrawable), 1f, EPSILON);
+ verify(mFastBitmapDrawable).invalidateSelf();
+ }
+}
diff --git a/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt b/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt
index 03352fe..98191fe 100644
--- a/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt
+++ b/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt
@@ -17,17 +17,18 @@
import android.content.ComponentName
import android.content.Context
-import android.content.Intent
import android.graphics.Rect
import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.LauncherAppState
-import com.android.launcher3.LauncherSettings
+import com.android.launcher3.model.data.AppInfo
import com.android.launcher3.model.data.WorkspaceItemInfo
-import com.android.launcher3.util.ContentWriter
import com.android.launcher3.util.GridOccupancy
import com.android.launcher3.util.IntArray
import com.android.launcher3.util.IntSparseArrayMap
+import com.android.launcher3.util.LauncherLayoutBuilder
import com.android.launcher3.util.LauncherModelHelper
+import com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY
+import com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE
import java.util.UUID
/** Base class for workspace related tests. */
@@ -38,6 +39,7 @@
val nonEmptyScreenSpaces = listOf(Rect(1, 2, 3, 4))
}
+ protected lateinit var mLayoutBuilder: LauncherLayoutBuilder
protected lateinit var mTargetContext: Context
protected lateinit var mIdp: InvariantDeviceProfile
protected lateinit var mAppState: LauncherAppState
@@ -47,6 +49,7 @@
protected lateinit var mScreenOccupancy: IntSparseArrayMap<GridOccupancy>
open fun setup() {
+ mLayoutBuilder = LauncherLayoutBuilder()
mModelHelper = LauncherModelHelper()
mTargetContext = mModelHelper.sandboxContext
mIdp = InvariantDeviceProfile.INSTANCE[mTargetContext]
@@ -64,10 +67,11 @@
/** Sets up workspaces with the given screen IDs with some items and a 2x2 space. */
fun setupWorkspaces(screenIdsWithItems: List<Int>) {
- var nextItemId = 1
- screenIdsWithItems.forEach { screenId ->
- nextItemId = setupWorkspace(nextItemId, screenId, nonEmptyScreenSpaces)
- }
+ screenIdsWithItems.forEach { screenId -> setupWorkspace(screenId, nonEmptyScreenSpaces) }
+ mModelHelper.setupDefaultLayoutProvider(mLayoutBuilder)
+ mIdp.numRows = 5
+ mIdp.numColumns = mIdp.numRows
+ mModelHelper.loadModelSync()
}
/**
@@ -78,30 +82,23 @@
screen1: List<Rect>? = null,
screen2: List<Rect>? = null,
screen3: List<Rect>? = null,
- ) = listOf(screen0, screen1, screen2, screen3).let(this::setupWithSpaces)
+ ) {
+ listOf(screen0, screen1, screen2, screen3).let(this::setupWithSpaces)
+ mModelHelper.setupDefaultLayoutProvider(mLayoutBuilder)
+ mIdp.numRows = 5
+ mIdp.numColumns = mIdp.numRows
+ mModelHelper.loadModelSync()
+ }
private fun setupWithSpaces(workspaceSpaces: List<List<Rect>?>) {
- var nextItemId = 1
workspaceSpaces.forEachIndexed { screenId, spaces ->
if (spaces != null) {
- nextItemId = setupWorkspace(nextItemId, screenId, spaces)
+ setupWorkspace(screenId, spaces)
}
}
}
- private fun setupWorkspace(startId: Int, screenId: Int, spaces: List<Rect>): Int {
- return mModelHelper.executeSimpleTask { dataModel ->
- writeWorkspaceWithSpaces(dataModel, startId, screenId, spaces)
- }
- }
-
- private fun writeWorkspaceWithSpaces(
- bgDataModel: BgDataModel,
- itemStartId: Int,
- screenId: Int,
- spaces: List<Rect>,
- ): Int {
- var itemId = itemStartId
+ private fun setupWorkspace(screenId: Int, spaces: List<Rect>) {
val occupancy = GridOccupancy(mIdp.numColumns, mIdp.numRows)
occupancy.markCells(0, 0, mIdp.numColumns, mIdp.numRows, true)
spaces.forEach { spaceRect -> occupancy.markCells(spaceRect, false) }
@@ -109,35 +106,22 @@
mScreenOccupancy.append(screenId, occupancy)
for (x in 0 until mIdp.numColumns) {
for (y in 0 until mIdp.numRows) {
- if (!occupancy.cells[x][y]) {
- continue
+ if (occupancy.cells[x][y]) {
+ mLayoutBuilder.atWorkspace(x, y, screenId).putApp(TEST_PACKAGE, TEST_ACTIVITY)
}
- val info = getExistingItem()
- info.id = itemId++
- info.screenId = screenId
- info.cellX = x
- info.cellY = y
- info.container = LauncherSettings.Favorites.CONTAINER_DESKTOP
- bgDataModel.addItem(mTargetContext, info, false)
- val writer = ContentWriter(mTargetContext)
- info.writeToValues(writer)
- writer.put(LauncherSettings.Favorites._ID, info.id)
- mTargetContext.contentResolver.insert(
- LauncherSettings.Favorites.CONTENT_URI,
- writer.getValues(mTargetContext)
- )
}
}
- return itemId
}
fun getExistingItem() =
- WorkspaceItemInfo().apply { intent = Intent().setComponent(ComponentName("a", "b")) }
+ WorkspaceItemInfo().apply {
+ intent = AppInfo.makeLaunchIntent(ComponentName(TEST_PACKAGE, TEST_ACTIVITY))
+ }
fun getNewItem(): WorkspaceItemInfo {
val itemPackage = UUID.randomUUID().toString()
return WorkspaceItemInfo().apply {
- intent = Intent().setComponent(ComponentName(itemPackage, itemPackage))
+ intent = AppInfo.makeLaunchIntent(ComponentName(itemPackage, itemPackage))
}
}
}
diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
index 6636b8a..1155227 100644
--- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
+++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
@@ -23,7 +23,7 @@
import com.android.launcher3.model.data.WorkspaceItemInfo
import com.android.launcher3.util.Executors
import com.android.launcher3.util.IntArray
-import com.android.launcher3.util.IntSet
+import com.android.launcher3.util.TestUtil.runOnExecutorSync
import com.android.launcher3.util.any
import com.android.launcher3.util.eq
import com.android.launcher3.util.same
@@ -32,8 +32,6 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.ArgumentCaptor
-import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
@@ -46,11 +44,7 @@
@RunWith(AndroidJUnit4::class)
class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() {
- @Captor private lateinit var mAnimatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
-
- @Captor private lateinit var mNotAnimatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
-
- @Mock private lateinit var mDataModelCallbacks: BgDataModel.Callbacks
+ private lateinit var mDataModelCallbacks: MyCallbacks
@Mock private lateinit var mWorkspaceItemSpaceFinder: WorkspaceItemSpaceFinder
@@ -58,7 +52,7 @@
override fun setup() {
super.setup()
MockitoAnnotations.initMocks(this)
- whenever(mDataModelCallbacks.getPagesToBindSynchronously(any())).thenReturn(IntSet())
+ mDataModelCallbacks = MyCallbacks()
Executors.MAIN_EXECUTOR.submit { mModelHelper.model.addCallbacks(mDataModelCallbacks) }
.get()
}
@@ -105,7 +99,7 @@
val addedItems = testAddItems(nonEmptyScreenIds, itemToAdd)
assertThat(addedItems.size).isEqualTo(0)
- verifyZeroInteractions(mWorkspaceItemSpaceFinder, mDataModelCallbacks)
+ verifyZeroInteractions(mWorkspaceItemSpaceFinder)
}
@Test
@@ -191,22 +185,14 @@
): List<AddedItem> {
setupWorkspaces(nonEmptyScreenIds)
val task = newTask(*itemsToAdd)
- var updateCount = 0
- mModelHelper.executeTaskForTest(task).forEach {
- updateCount++
- it.run()
- }
val addedItems = mutableListOf<AddedItem>()
- if (updateCount > 0) {
- verify(mDataModelCallbacks)
- .bindAppsAdded(
- any(),
- mNotAnimatedItemArgumentCaptor.capture(),
- mAnimatedItemArgumentCaptor.capture()
- )
- addedItems.addAll(mAnimatedItemArgumentCaptor.value.map { AddedItem(it, true) })
- addedItems.addAll(mNotAnimatedItemArgumentCaptor.value.map { AddedItem(it, false) })
+
+ runOnExecutorSync(Executors.MODEL_EXECUTOR) {
+ mDataModelCallbacks.addedItems.clear()
+ mModelHelper.model.enqueueModelUpdateTask(task)
+ runOnExecutorSync(Executors.MAIN_EXECUTOR) {}
+ addedItems.addAll(mDataModelCallbacks.addedItems)
}
return addedItems
@@ -224,3 +210,17 @@
}
private data class AddedItem(val itemInfo: ItemInfo, val isAnimated: Boolean)
+
+private class MyCallbacks : BgDataModel.Callbacks {
+
+ val addedItems = mutableListOf<AddedItem>()
+
+ override fun bindAppsAdded(
+ newScreens: IntArray?,
+ addNotAnimated: ArrayList<ItemInfo>,
+ addAnimated: ArrayList<ItemInfo>
+ ) {
+ addedItems.addAll(addAnimated.map { AddedItem(it, true) })
+ addedItems.addAll(addNotAnimated.map { AddedItem(it, false) })
+ }
+}
diff --git a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
index f55b244..f771052 100644
--- a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
+++ b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
@@ -1,32 +1,31 @@
package com.android.launcher3.model;
+import static android.os.Process.myUserHandle;
+
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY2;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY3;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;
+import static com.android.launcher3.util.TestUtil.runOnExecutorSync;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Color;
-import android.os.Process;
-import android.os.UserHandle;
-import android.os.UserManager;
-import androidx.annotation.NonNull;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.icons.BitmapInfo;
-import com.android.launcher3.icons.IconCache;
-import com.android.launcher3.icons.cache.CachingLogic;
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.util.IntSet;
+import com.android.launcher3.util.LauncherLayoutBuilder;
import com.android.launcher3.util.LauncherModelHelper;
+import com.android.launcher3.util.PackageUserKey;
import org.junit.After;
import org.junit.Before;
@@ -35,6 +34,7 @@
import java.util.Arrays;
import java.util.HashSet;
+import java.util.List;
/**
* Tests for {@link CacheDataUpdatedTask}
@@ -43,49 +43,40 @@
@RunWith(AndroidJUnit4.class)
public class CacheDataUpdatedTaskTest {
- private static final String NEW_LABEL_PREFIX = "new-label-";
+ private static final String PENDING_APP_1 = TEST_PACKAGE + ".pending1";
+ private static final String PENDING_APP_2 = TEST_PACKAGE + ".pending2";
private LauncherModelHelper mModelHelper;
+ private Context mContext;
+
+ private int mSession1;
@Before
public void setup() throws Exception {
mModelHelper = new LauncherModelHelper();
- mModelHelper.initializeData("cache_data_updated_task_data");
+ mContext = mModelHelper.sandboxContext;
+ mSession1 = mModelHelper.createInstallerSession(PENDING_APP_1);
+ mModelHelper.createInstallerSession(PENDING_APP_2);
- // Add placeholder entries in the cache to simulate update
- Context context = mModelHelper.sandboxContext;
- IconCache iconCache = LauncherAppState.getInstance(context).getIconCache();
- CachingLogic<ItemInfo> placeholderLogic = new CachingLogic<ItemInfo>() {
- @Override
- @NonNull
- public ComponentName getComponent(@NonNull ItemInfo info) {
- return info.getTargetComponent();
- }
+ LauncherLayoutBuilder builder = new LauncherLayoutBuilder()
+ .atHotseat(1).putFolder("MyFolder")
+ .addApp(TEST_PACKAGE, TEST_ACTIVITY) // 2
+ .addApp(TEST_PACKAGE, TEST_ACTIVITY2) // 3
+ .addApp(TEST_PACKAGE, TEST_ACTIVITY3) // 4
- @NonNull
- @Override
- public UserHandle getUser(@NonNull ItemInfo info) {
- return info.user;
- }
+ // Pending App 1
+ .addApp(PENDING_APP_1, TEST_ACTIVITY) // 5
+ .addApp(PENDING_APP_1, TEST_ACTIVITY2) // 6
+ .addApp(PENDING_APP_1, TEST_ACTIVITY3) // 7
- @NonNull
- @Override
- public CharSequence getLabel(@NonNull ItemInfo info) {
- return NEW_LABEL_PREFIX + info.id;
- }
-
- @NonNull
- @Override
- public BitmapInfo loadIcon(@NonNull Context context, @NonNull ItemInfo info) {
- return BitmapInfo.of(Bitmap.createBitmap(1, 1, Config.ARGB_8888), Color.RED);
- }
- };
-
- UserManager um = context.getSystemService(UserManager.class);
- for (ItemInfo info : mModelHelper.getBgDataModel().itemsIdMap) {
- iconCache.addIconToDBAndMemCache(info, placeholderLogic, new PackageInfo(),
- um.getSerialNumberForUser(info.user), true);
- }
+ // Pending App 2
+ .addApp(PENDING_APP_2, TEST_ACTIVITY) // 8
+ .addApp(PENDING_APP_2, TEST_ACTIVITY2) // 9
+ .addApp(PENDING_APP_2, TEST_ACTIVITY3) // 10
+ .build();
+ mModelHelper.setupDefaultLayoutProvider(builder);
+ mModelHelper.loadModelSync();
+ assertEquals(10, mModelHelper.getBgDataModel().itemsIdMap.size());
}
@After
@@ -94,27 +85,63 @@
}
private CacheDataUpdatedTask newTask(int op, String... pkg) {
- return new CacheDataUpdatedTask(op, Process.myUserHandle(),
+ return new CacheDataUpdatedTask(op, myUserHandle(),
new HashSet<>(Arrays.asList(pkg)));
}
@Test
- public void testCacheUpdate_update_apps() throws Exception {
- // Clear all icons from apps list so that its easy to check what was updated
- for (AppInfo info : mModelHelper.getAllAppsList().data) {
- info.bitmap = BitmapInfo.LOW_RES_INFO;
- }
+ public void testCacheUpdate_update_apps() {
+ // Run on model executor so that no other task runs in the middle.
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
+ // Clear all icons from apps list so that its easy to check what was updated
+ allItems().forEach(wi -> wi.bitmap = BitmapInfo.LOW_RES_INFO);
- mModelHelper.executeTaskForTest(newTask(CacheDataUpdatedTask.OP_CACHE_UPDATE, "app1"));
+ mModelHelper.getModel().enqueueModelUpdateTask(
+ newTask(CacheDataUpdatedTask.OP_CACHE_UPDATE, TEST_PACKAGE));
- // Verify that only the app icons of app1 (id 1 & 2) are updated. Custom shortcut (id 7)
- // is not updated
- verifyUpdate(1, 2);
+ // Verify that only the app icons of TEST_PACKAGE (id 2, 3, 4) are updated.
+ verifyUpdate(2, 3, 4);
+ });
+ }
- // Verify that only app1 var updated in allAppsList
- assertFalse(mModelHelper.getAllAppsList().data.isEmpty());
- for (AppInfo info : mModelHelper.getAllAppsList().data) {
- if (info.componentName.getPackageName().equals("app1")) {
+ @Test
+ public void testSessionUpdate_ignores_normal_apps() {
+ // Run on model executor so that no other task runs in the middle.
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
+ // Clear all icons from apps list so that its easy to check what was updated
+ allItems().forEach(wi -> wi.bitmap = BitmapInfo.LOW_RES_INFO);
+
+ mModelHelper.getModel().enqueueModelUpdateTask(
+ newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, TEST_PACKAGE));
+
+ // TEST_PACKAGE has no restored shortcuts. Verify that nothing was updated.
+ verifyUpdate();
+ });
+ }
+
+ @Test
+ public void testSessionUpdate_updates_pending_apps() {
+ // Run on model executor so that no other task runs in the middle.
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
+ LauncherAppState.getInstance(mContext).getIconCache().updateSessionCache(
+ new PackageUserKey(PENDING_APP_1, myUserHandle()),
+ mContext.getPackageManager().getPackageInstaller().getSessionInfo(mSession1));
+
+ // Clear all icons from apps list so that its easy to check what was updated
+ allItems().forEach(wi -> wi.bitmap = BitmapInfo.LOW_RES_INFO);
+
+ mModelHelper.getModel().enqueueModelUpdateTask(
+ newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, PENDING_APP_1));
+
+ // Only restored apps from PENDING_APP_1 (id 5, 6, 7) are updated
+ verifyUpdate(5, 6, 7);
+ });
+ }
+
+ private void verifyUpdate(int... idsUpdated) {
+ IntSet updates = IntSet.wrap(idsUpdated);
+ for (WorkspaceItemInfo info : allItems()) {
+ if (updates.contains(info.id)) {
assertFalse(info.bitmap.isNullOrLowRes());
} else {
assertTrue(info.bitmap.isNullOrLowRes());
@@ -122,33 +149,7 @@
}
}
- @Test
- public void testSessionUpdate_ignores_normal_apps() throws Exception {
- mModelHelper.executeTaskForTest(newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, "app1"));
-
- // app1 has no restored shortcuts. Verify that nothing was updated.
- verifyUpdate();
- }
-
- @Test
- public void testSessionUpdate_updates_pending_apps() throws Exception {
- mModelHelper.executeTaskForTest(newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, "app3"));
-
- // app3 has only restored apps (id 5, 6) and shortcuts (id 9). Verify that only apps were
- // were updated
- verifyUpdate(5, 6);
- }
-
- private void verifyUpdate(Integer... idsUpdated) {
- HashSet<Integer> updates = new HashSet<>(Arrays.asList(idsUpdated));
- for (ItemInfo info : mModelHelper.getBgDataModel().itemsIdMap) {
- if (updates.contains(info.id)) {
- assertEquals(NEW_LABEL_PREFIX + info.id, info.title);
- assertFalse(((WorkspaceItemInfo) info).bitmap.isNullOrLowRes());
- } else {
- assertNotSame(NEW_LABEL_PREFIX + info.id, info.title);
- assertTrue(((WorkspaceItemInfo) info).bitmap.isNullOrLowRes());
- }
- }
+ private List<WorkspaceItemInfo> allItems() {
+ return ((FolderInfo) mModelHelper.getBgDataModel().itemsIdMap.get(1)).contents;
}
}
diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
index 3b480ca..04735f2 100644
--- a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
+++ b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
@@ -24,7 +24,6 @@
import android.os.Process
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.LauncherPrefs
import com.android.launcher3.LauncherPrefs.Companion.WORKSPACE_SIZE
@@ -108,8 +107,8 @@
fun testMigration() {
// Src Hotseat icons
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
// Src grid icons
// _ _ _ _ _
@@ -124,7 +123,7 @@
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 3, testPackage9, 9, TMP_TABLE)
// Dest hotseat icons
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2)
// Dest grid icons
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage10)
@@ -190,7 +189,7 @@
intentIndex = c.getColumnIndex(INTENT)
val cellXIndex = c.getColumnIndex(CELLX)
val cellYIndex = c.getColumnIndex(CELLY)
- val locMap = HashMap<String, Point>()
+ val locMap = HashMap<String?, Point>()
while (c.moveToNext()) {
locMap[Intent.parseUri(c.getString(intentIndex), 0).getPackage()] =
Point(c.getInt(cellXIndex), c.getInt(cellYIndex))
@@ -219,8 +218,8 @@
// Hotseat items in grid A
// 1 2 _ 3 4
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
// Workspace items in grid A
// _ _ _ _ _
@@ -235,7 +234,7 @@
// Hotseat items in grid B
// 2 _ _ _
- addItem(ITEM_TYPE_SHORTCUT, 0, CONTAINER_HOTSEAT, 0, 0, testPackage2)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 0, CONTAINER_HOTSEAT, 0, 0, testPackage2)
// Workspace items in grid B
// _ _ _ _
// _ _ _ 10
@@ -291,7 +290,7 @@
null
)
?: throw IllegalStateException()
- var locMap = parseLocMap(context, c)
+ var locMap = parseLocMap(c)
// Expected items in grid B
// _ _ _ _
// 5 6 7 8
@@ -348,7 +347,7 @@
null
)
?: throw IllegalStateException()
- locMap = parseLocMap(context, c)
+ locMap = parseLocMap(c)
// Expected workspace items in grid A
// _ _ _ _ _
// _ _ _ _ 5
@@ -410,7 +409,7 @@
null
)
?: throw IllegalStateException()
- locMap = parseLocMap(context, c)
+ locMap = parseLocMap(c)
// Expected workspace items in grid B
// _ _ _ _
// 5 6 _ 8
@@ -436,13 +435,13 @@
c.close()
}
- private fun parseLocMap(context: Context, c: Cursor): Map<String, Triple<Int, Int, Int>> {
+ private fun parseLocMap(c: Cursor): Map<String?, Triple<Int, Int, Int>> {
// Check workspace items
val intentIndex = c.getColumnIndex(INTENT)
val screenIndex = c.getColumnIndex(SCREEN)
val cellXIndex = c.getColumnIndex(CELLX)
val cellYIndex = c.getColumnIndex(CELLY)
- val locMap = mutableMapOf<String, Triple<Int, Int, Int>>()
+ val locMap = mutableMapOf<String?, Triple<Int, Int, Int>>()
while (c.moveToNext()) {
locMap[Intent.parseUri(c.getString(intentIndex), 0).getPackage()] =
Triple(c.getInt(screenIndex), c.getInt(cellXIndex), c.getInt(cellYIndex))
@@ -465,7 +464,16 @@
1,
TMP_TABLE
),
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE),
+ addItem(
+ ITEM_TYPE_DEEP_SHORTCUT,
+ 1,
+ CONTAINER_HOTSEAT,
+ 0,
+ 0,
+ testPackage2,
+ 2,
+ TMP_TABLE
+ ),
addItem(
ITEM_TYPE_APPLICATION,
2,
@@ -476,7 +484,16 @@
3,
TMP_TABLE
),
- addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
+ addItem(
+ ITEM_TYPE_DEEP_SHORTCUT,
+ 3,
+ CONTAINER_HOTSEAT,
+ 0,
+ 0,
+ testPackage4,
+ 4,
+ TMP_TABLE
+ )
)
val numSrcDatabaseHotseatIcons = srcHotseatItems.size
idp.numDatabaseHotseatIcons = 6
@@ -532,9 +549,9 @@
@Test
fun migrateFromLargerHotseat() {
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 2, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 2, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
addItem(ITEM_TYPE_APPLICATION, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
+ addItem(ITEM_TYPE_DEEP_SHORTCUT, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
addItem(ITEM_TYPE_APPLICATION, 5, CONTAINER_HOTSEAT, 0, 0, testPackage5, 5, TMP_TABLE)
idp.numDatabaseHotseatIcons = 4
@@ -636,7 +653,7 @@
val screenIndex = c.getColumnIndex(SCREEN)
// Get in which screen the icon is
- val locMap = HashMap<String, Int>()
+ val locMap = HashMap<String?, Int>()
while (c.moveToNext()) {
locMap[Intent.parseUri(c.getString(intentIndex), 0).getPackage()] =
c.getInt(screenIndex)
@@ -698,7 +715,7 @@
val screenIndex = c.getColumnIndex(SCREEN)
// Get in which screen the icon is
- val locMap = HashMap<String, Int>()
+ val locMap = HashMap<String?, Int>()
while (c.moveToNext()) {
locMap[Intent.parseUri(c.getString(intentIndex), 0).getPackage()] =
c.getInt(screenIndex)
@@ -758,7 +775,7 @@
val screenIndex = c.getColumnIndex(SCREEN)
// Get in which screen the icon is
- val locMap = HashMap<String, Int>()
+ val locMap = HashMap<String?, Int>()
while (c.moveToNext()) {
locMap[Intent.parseUri(c.getString(intentIndex), 0).getPackage()] =
c.getInt(screenIndex)
diff --git a/tests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
index 78812c0..544ed6b 100644
--- a/tests/src/com/android/launcher3/model/LoaderCursorTest.java
+++ b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
@@ -30,7 +30,7 @@
import static com.android.launcher3.LauncherSettings.Favorites.INTENT;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
import static com.android.launcher3.LauncherSettings.Favorites.OPTIONS;
import static com.android.launcher3.LauncherSettings.Favorites.PROFILE_ID;
import static com.android.launcher3.LauncherSettings.Favorites.RANK;
@@ -158,13 +158,13 @@
@Test
public void loadSimpleShortcut() {
- initCursor(ITEM_TYPE_SHORTCUT, "my-shortcut");
+ initCursor(ITEM_TYPE_DEEP_SHORTCUT, "my-shortcut");
assertTrue(mLoaderCursor.moveToNext());
WorkspaceItemInfo info = mLoaderCursor.loadSimpleWorkspaceItem();
assertTrue(mApp.getIconCache().isDefaultIcon(info.bitmap, info.user));
assertEquals("my-shortcut", info.title);
- assertEquals(ITEM_TYPE_SHORTCUT, info.itemType);
+ assertEquals(ITEM_TYPE_DEEP_SHORTCUT, info.itemType);
}
@Test
diff --git a/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java b/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
index 519191e..4ba61ac 100644
--- a/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
+++ b/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
@@ -1,5 +1,12 @@
package com.android.launcher3.model;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY2;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY3;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;
+import static com.android.launcher3.util.TestUtil.runOnExecutorSync;
+
import static org.junit.Assert.assertEquals;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -9,6 +16,8 @@
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.PackageInstallInfo;
+import com.android.launcher3.util.IntSet;
+import com.android.launcher3.util.LauncherLayoutBuilder;
import com.android.launcher3.util.LauncherModelHelper;
import org.junit.After;
@@ -16,9 +25,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.Arrays;
-import java.util.HashSet;
-
/**
* Tests for {@link PackageInstallStateChangedTask}
*/
@@ -26,12 +32,36 @@
@RunWith(AndroidJUnit4.class)
public class PackageInstallStateChangedTaskTest {
+ private static final String PENDING_APP_1 = TEST_PACKAGE + ".pending1";
+ private static final String PENDING_APP_2 = TEST_PACKAGE + ".pending2";
+
private LauncherModelHelper mModelHelper;
+ private IntSet mDownloadingApps;
@Before
public void setup() throws Exception {
mModelHelper = new LauncherModelHelper();
- mModelHelper.initializeData("package_install_state_change_task_data");
+ mModelHelper.createInstallerSession(PENDING_APP_1);
+ mModelHelper.createInstallerSession(PENDING_APP_2);
+
+ LauncherLayoutBuilder builder = new LauncherLayoutBuilder()
+ .atWorkspace(0, 0, 1).putApp(TEST_PACKAGE, TEST_ACTIVITY) // 1
+ .atWorkspace(0, 0, 2).putApp(TEST_PACKAGE, TEST_ACTIVITY2) // 2
+ .atWorkspace(0, 0, 3).putApp(TEST_PACKAGE, TEST_ACTIVITY3) // 3
+
+ .atWorkspace(0, 0, 4).putApp(PENDING_APP_1, TEST_ACTIVITY) // 4
+ .atWorkspace(0, 0, 5).putApp(PENDING_APP_1, TEST_ACTIVITY2) // 5
+ .atWorkspace(0, 0, 6).putApp(PENDING_APP_1, TEST_ACTIVITY3) // 6
+ .atWorkspace(0, 0, 7).putWidget(PENDING_APP_1, "pending.widget", 1, 1) // 7
+
+ .atWorkspace(0, 0, 8).putApp(PENDING_APP_2, TEST_ACTIVITY) // 8
+ .atWorkspace(0, 0, 9).putApp(PENDING_APP_2, TEST_ACTIVITY2) // 9
+ .atWorkspace(0, 0, 10).putApp(PENDING_APP_2, TEST_ACTIVITY3); // 10
+
+ mDownloadingApps = IntSet.wrap(4, 5, 6, 7, 8, 9, 10);
+ mModelHelper.setupDefaultLayoutProvider(builder);
+ mModelHelper.loadModelSync();
+ assertEquals(10, mModelHelper.getBgDataModel().itemsIdMap.size());
}
@After
@@ -47,36 +77,45 @@
}
@Test
- public void testSessionUpdate_ignore_installed() throws Exception {
- mModelHelper.executeTaskForTest(newTask("app1", 30));
+ public void testSessionUpdate_ignore_installed() {
+ // Run on model executor so that no other task runs in the middle.
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
+ mModelHelper.getModel().enqueueModelUpdateTask(newTask(TEST_PACKAGE, 30));
- // No shortcuts were updated
- verifyProgressUpdate(0);
+ // No shortcuts were updated
+ verifyProgressUpdate(0);
+ });
}
@Test
- public void testSessionUpdate_shortcuts_updated() throws Exception {
- mModelHelper.executeTaskForTest(newTask("app3", 30));
+ public void testSessionUpdate_shortcuts_updated() {
+ // Run on model executor so that no other task runs in the middle.
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
+ mModelHelper.getModel().enqueueModelUpdateTask(newTask(PENDING_APP_1, 30));
- verifyProgressUpdate(30, 5, 6, 7);
+ verifyProgressUpdate(30, 4, 5, 6, 7);
+ });
}
@Test
- public void testSessionUpdate_widgets_updated() throws Exception {
- mModelHelper.executeTaskForTest(newTask("app4", 30));
+ public void testSessionUpdate_widgets_updated() {
+ // Run on model executor so that no other task runs in the middle.
+ runOnExecutorSync(MODEL_EXECUTOR, () -> {
+ mModelHelper.getModel().enqueueModelUpdateTask(newTask(PENDING_APP_2, 30));
- verifyProgressUpdate(30, 8, 9);
+ verifyProgressUpdate(30, 8, 9, 10);
+ });
}
- private void verifyProgressUpdate(int progress, Integer... idsUpdated) {
- HashSet<Integer> updates = new HashSet<>(Arrays.asList(idsUpdated));
+ private void verifyProgressUpdate(int progress, int... idsUpdated) {
+ IntSet updates = IntSet.wrap(idsUpdated);
for (ItemInfo info : mModelHelper.getBgDataModel().itemsIdMap) {
- if (info instanceof WorkspaceItemInfo) {
- assertEquals(updates.contains(info.id) ? progress: 100,
- ((WorkspaceItemInfo) info).getProgressLevel());
+ int expectedProgress = updates.contains(info.id) ? progress
+ : (mDownloadingApps.contains(info.id) ? 0 : 100);
+ if (info instanceof WorkspaceItemInfo wi) {
+ assertEquals(expectedProgress, wi.getProgressLevel());
} else {
- assertEquals(updates.contains(info.id) ? progress: -1,
- ((LauncherAppWidgetInfo) info).installProgress);
+ assertEquals(expectedProgress, ((LauncherAppWidgetInfo) info).installProgress);
}
}
}
diff --git a/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt b/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt
index a81413e..9b67310 100644
--- a/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt
+++ b/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt
@@ -15,14 +15,14 @@
*/
package com.android.launcher3.nonquickstep
+import android.content.Context
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.AbstractDeviceProfileTest
import com.android.launcher3.DeviceProfile
import com.android.launcher3.InvariantDeviceProfile
import com.google.common.truth.Truth.assertThat
-import java.io.PrintWriter
-import java.io.StringWriter
import org.junit.Test
import org.junit.runner.RunWith
@@ -30,141 +30,14 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class DeviceProfileDumpTest : AbstractDeviceProfileTest() {
-
+ private val testContext: Context = InstrumentationRegistry.getInstrumentation().context
+ private val folderName: String = "DeviceProfileDumpTest"
@Test
fun phonePortrait3Button() {
initializeVarsForPhone(deviceSpecs["phone"]!!, isGestureMode = false)
val dp = getDeviceProfileForGrid("5_by_5")
- assertThat(dump(dp))
- .isEqualTo(
- "DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:false\n" +
- "\tisPhone:true\n" +
- "\ttransposeLayoutWithOrientation:true\n" +
- "\tisGestureMode:false\n" +
- "\tisLandscape:false\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 1080.0px (411.42856dp)\n" +
- "\theightPx: 2400.0px (914.2857dp)\n" +
- "\tavailableWidthPx: 1080.0px (411.42856dp)\n" +
- "\tavailableHeightPx: 2156.0px (821.3333dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 118.0px (44.95238dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 126.0px (48.0dp)\n" +
- "\taspectRatio:2.2222223\n" +
- "\tisResponsiveGrid:false\n" +
- "\tisScalableGrid:false\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 5\n" +
- "\tinv.numSearchContainerColumns: 5\n" +
- "\tminCellSize: PointF(0.0, 0.0)dp\n" +
- "\tcellWidthPx: 165.0px (62.857143dp)\n" +
- "\tcellHeightPx: 235.0px (89.52381dp)\n" +
- "\tgetCellSize().x: 207.0px (78.85714dp)\n" +
- "\tgetCellSize().y: 379.0px (144.38095dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 21.0px (8.0dp)\n" +
- "\tcellLayoutPaddingPx.top: 28.0px (10.666667dp)\n" +
- "\tcellLayoutPaddingPx.right: 21.0px (8.0dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 28.0px (10.666667dp)\n" +
- "\ticonSizePx: 147.0px (56.0dp)\n" +
- "\ticonTextSizePx: 38.0px (14.476191dp)\n" +
- "\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
- "\tinv.numFolderRows: 4\n" +
- "\tinv.numFolderColumns: 4\n" +
- "\tfolderCellWidthPx: 195.0px (74.28571dp)\n" +
- "\tfolderCellHeightPx: 230.0px (87.61905dp)\n" +
- "\tfolderChildIconSizePx: 147.0px (56.0dp)\n" +
- "\tfolderChildTextSizePx: 38.0px (14.476191dp)\n" +
- "\tfolderChildDrawablePaddingPx: 10.0px (3.8095238dp)\n" +
- "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
- "\tfolderTopPadding: 63.0px (24.0dp)\n" +
- "\tfolderFooterHeight: 147.0px (56.0dp)\n" +
- "\tbottomSheetTopPadding: 146.0px (55.61905dp)\n" +
- "\tbottomSheetOpenDuration: 267\n" +
- "\tbottomSheetCloseDuration: 267\n" +
- "\tbottomSheetWorkspaceScale: 1.0\n" +
- "\tbottomSheetDepth: 0.0\n" +
- "\tallAppsShiftRange: 788.0px (300.1905dp)\n" +
- "\tallAppsTopPadding: 0.0px (0.0dp)\n" +
- "\tallAppsOpenDuration: 600\n" +
- "\tallAppsCloseDuration: 300\n" +
- "\tallAppsIconSizePx: 147.0px (56.0dp)\n" +
- "\tallAppsIconTextSizePx: 38.0px (14.476191dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
- "\tallAppsCellHeightPx: 315.0px (120.0dp)\n" +
- "\tallAppsCellWidthPx: 189.0px (72.0dp)\n" +
- "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 5\n" +
- "\tallAppsLeftRightPadding: 21.0px (8.0dp)\n" +
- "\tallAppsLeftRightMargin: 0.0px (0.0dp)\n" +
- "\thotseatBarSizePx: 294.0px (112.0dp)\n" +
- "\tinv.hotseatColumnSpan: 5\n" +
- "\thotseatCellHeightPx: 166.0px (63.238094dp)\n" +
- "\thotseatBarBottomSpacePx: 147.0px (56.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
- "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 200.0px (76.190475dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 128.0px (48.761906dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 21.0px (8.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 21.0px (8.0dp)\n" +
- "\tnumShownHotseatIcons: 5\n" +
- "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:false\n" +
- "\ttaskbarHeight: 0.0px (0.0dp)\n" +
- "\tstashedTaskbarHeight: 0.0px (0.0dp)\n" +
- "\ttaskbarBottomMargin: 0.0px (0.0dp)\n" +
- "\ttaskbarIconSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)\n" +
- "\tworkspacePadding.left: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.right: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.bottom: 203.0px (77.333336dp)\n" +
- "\ticonScale: 1.0px (0.3809524dp)\n" +
- "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
- "\textraSpace: 722.0px (275.0476dp)\n" +
- "\tunscaled extraSpace: 722.0px (275.0476dp)\n" +
- "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
- "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
- "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
- "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
- "\toverviewActionsClaimedSpaceBelow: 126.0px (48.0dp)\n" +
- "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
- "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 84.0px (32.0dp)\n" +
- "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 391.0px (148.95238dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1906.0px (726.0952dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.77572966px (0.29551607dp)\n" +
- "\tgetCellLayoutHeight(): 1953.0px (744.0dp)\n" +
- "\tgetCellLayoutWidth(): 1080.0px (411.42856dp)\n"
- )
+ assertDump(dp, "phonePortrait3Button")
}
@Test
@@ -172,135 +45,7 @@
initializeVarsForPhone(deviceSpecs["phone"]!!)
val dp = getDeviceProfileForGrid("5_by_5")
- assertThat(dump(dp))
- .isEqualTo(
- "DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:false\n" +
- "\tisPhone:true\n" +
- "\ttransposeLayoutWithOrientation:true\n" +
- "\tisGestureMode:true\n" +
- "\tisLandscape:false\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 1080.0px (411.42856dp)\n" +
- "\theightPx: 2400.0px (914.2857dp)\n" +
- "\tavailableWidthPx: 1080.0px (411.42856dp)\n" +
- "\tavailableHeightPx: 2219.0px (845.3333dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 118.0px (44.95238dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 63.0px (24.0dp)\n" +
- "\taspectRatio:2.2222223\n" +
- "\tisResponsiveGrid:false\n" +
- "\tisScalableGrid:false\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 5\n" +
- "\tinv.numSearchContainerColumns: 5\n" +
- "\tminCellSize: PointF(0.0, 0.0)dp\n" +
- "\tcellWidthPx: 165.0px (62.857143dp)\n" +
- "\tcellHeightPx: 235.0px (89.52381dp)\n" +
- "\tgetCellSize().x: 207.0px (78.85714dp)\n" +
- "\tgetCellSize().y: 383.0px (145.90475dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 21.0px (8.0dp)\n" +
- "\tcellLayoutPaddingPx.top: 28.0px (10.666667dp)\n" +
- "\tcellLayoutPaddingPx.right: 21.0px (8.0dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 28.0px (10.666667dp)\n" +
- "\ticonSizePx: 147.0px (56.0dp)\n" +
- "\ticonTextSizePx: 38.0px (14.476191dp)\n" +
- "\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
- "\tinv.numFolderRows: 4\n" +
- "\tinv.numFolderColumns: 4\n" +
- "\tfolderCellWidthPx: 195.0px (74.28571dp)\n" +
- "\tfolderCellHeightPx: 230.0px (87.61905dp)\n" +
- "\tfolderChildIconSizePx: 147.0px (56.0dp)\n" +
- "\tfolderChildTextSizePx: 38.0px (14.476191dp)\n" +
- "\tfolderChildDrawablePaddingPx: 10.0px (3.8095238dp)\n" +
- "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
- "\tfolderTopPadding: 63.0px (24.0dp)\n" +
- "\tfolderFooterHeight: 147.0px (56.0dp)\n" +
- "\tbottomSheetTopPadding: 146.0px (55.61905dp)\n" +
- "\tbottomSheetOpenDuration: 267\n" +
- "\tbottomSheetCloseDuration: 267\n" +
- "\tbottomSheetWorkspaceScale: 1.0\n" +
- "\tbottomSheetDepth: 0.0\n" +
- "\tallAppsShiftRange: 788.0px (300.1905dp)\n" +
- "\tallAppsTopPadding: 0.0px (0.0dp)\n" +
- "\tallAppsOpenDuration: 600\n" +
- "\tallAppsCloseDuration: 300\n" +
- "\tallAppsIconSizePx: 147.0px (56.0dp)\n" +
- "\tallAppsIconTextSizePx: 38.0px (14.476191dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
- "\tallAppsCellHeightPx: 315.0px (120.0dp)\n" +
- "\tallAppsCellWidthPx: 189.0px (72.0dp)\n" +
- "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 5\n" +
- "\tallAppsLeftRightPadding: 21.0px (8.0dp)\n" +
- "\tallAppsLeftRightMargin: 0.0px (0.0dp)\n" +
- "\thotseatBarSizePx: 273.0px (104.0dp)\n" +
- "\tinv.hotseatColumnSpan: 5\n" +
- "\thotseatCellHeightPx: 166.0px (63.238094dp)\n" +
- "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
- "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 200.0px (76.190475dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 107.0px (40.761906dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 21.0px (8.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 21.0px (8.0dp)\n" +
- "\tnumShownHotseatIcons: 5\n" +
- "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:false\n" +
- "\ttaskbarHeight: 0.0px (0.0dp)\n" +
- "\tstashedTaskbarHeight: 0.0px (0.0dp)\n" +
- "\ttaskbarBottomMargin: 0.0px (0.0dp)\n" +
- "\ttaskbarIconSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)\n" +
- "\tworkspacePadding.left: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.right: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.bottom: 245.0px (93.333336dp)\n" +
- "\ticonScale: 1.0px (0.3809524dp)\n" +
- "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
- "\textraSpace: 743.0px (283.0476dp)\n" +
- "\tunscaled extraSpace: 743.0px (283.0476dp)\n" +
- "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
- "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
- "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
- "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
- "\toverviewActionsClaimedSpaceBelow: 63.0px (24.0dp)\n" +
- "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
- "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 84.0px (32.0dp)\n" +
- "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 391.0px (148.95238dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1927.0px (734.0952dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.7781155px (0.29642496dp)\n" +
- "\tgetCellLayoutHeight(): 1974.0px (752.0dp)\n" +
- "\tgetCellLayoutWidth(): 1080.0px (411.42856dp)\n"
- )
+ assertDump(dp, "phonePortrait")
}
@Test
@@ -308,135 +53,7 @@
initializeVarsForPhone(deviceSpecs["phone"]!!, isVerticalBar = true, isGestureMode = false)
val dp = getDeviceProfileForGrid("5_by_5")
- assertThat(dump(dp))
- .isEqualTo(
- "DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:false\n" +
- "\tisPhone:true\n" +
- "\ttransposeLayoutWithOrientation:true\n" +
- "\tisGestureMode:false\n" +
- "\tisLandscape:true\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 2400.0px (914.2857dp)\n" +
- "\theightPx: 1080.0px (411.42856dp)\n" +
- "\tavailableWidthPx: 2156.0px (821.3333dp)\n" +
- "\tavailableHeightPx: 1006.0px (383.2381dp)\n" +
- "\tmInsets.left: 118.0px (44.95238dp)\n" +
- "\tmInsets.top: 74.0px (28.190475dp)\n" +
- "\tmInsets.right: 126.0px (48.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:2.2222223\n" +
- "\tisResponsiveGrid:false\n" +
- "\tisScalableGrid:false\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 5\n" +
- "\tinv.numSearchContainerColumns: 5\n" +
- "\tminCellSize: PointF(0.0, 0.0)dp\n" +
- "\tcellWidthPx: 158.0px (60.190475dp)\n" +
- "\tcellHeightPx: 166.0px (63.238094dp)\n" +
- "\tgetCellSize().x: 368.0px (140.19048dp)\n" +
- "\tgetCellSize().y: 193.0px (73.52381dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 53.0px (20.190475dp)\n" +
- "\tcellLayoutPaddingPx.top: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 53.0px (20.190475dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 40.0px (15.238095dp)\n" +
- "\ticonSizePx: 147.0px (56.0dp)\n" +
- "\ticonTextSizePx: 0.0px (0.0dp)\n" +
- "\ticonDrawablePaddingPx: 0.0px (0.0dp)\n" +
- "\tinv.numFolderRows: 4\n" +
- "\tinv.numFolderColumns: 4\n" +
- "\tfolderCellWidthPx: 173.0px (65.90476dp)\n" +
- "\tfolderCellHeightPx: 205.0px (78.09524dp)\n" +
- "\tfolderChildIconSizePx: 131.0px (49.904762dp)\n" +
- "\tfolderChildTextSizePx: 34.0px (12.952381dp)\n" +
- "\tfolderChildDrawablePaddingPx: 9.0px (3.4285715dp)\n" +
- "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
- "\tfolderTopPadding: 56.0px (21.333334dp)\n" +
- "\tfolderFooterHeight: 131.0px (49.904762dp)\n" +
- "\tbottomSheetTopPadding: 114.0px (43.42857dp)\n" +
- "\tbottomSheetOpenDuration: 267\n" +
- "\tbottomSheetCloseDuration: 267\n" +
- "\tbottomSheetWorkspaceScale: 1.0\n" +
- "\tbottomSheetDepth: 0.0\n" +
- "\tallAppsShiftRange: 788.0px (300.1905dp)\n" +
- "\tallAppsTopPadding: 0.0px (0.0dp)\n" +
- "\tallAppsOpenDuration: 600\n" +
- "\tallAppsCloseDuration: 300\n" +
- "\tallAppsIconSizePx: 147.0px (56.0dp)\n" +
- "\tallAppsIconTextSizePx: 38.0px (14.476191dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
- "\tallAppsCellHeightPx: 321.0px (122.28571dp)\n" +
- "\tallAppsCellWidthPx: 189.0px (72.0dp)\n" +
- "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 5\n" +
- "\tallAppsLeftRightPadding: 0.0px (0.0dp)\n" +
- "\tallAppsLeftRightMargin: 0.0px (0.0dp)\n" +
- "\thotseatBarSizePx: 252.0px (96.0dp)\n" +
- "\tinv.hotseatColumnSpan: 5\n" +
- "\thotseatCellHeightPx: 166.0px (63.238094dp)\n" +
- "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 63.0px (24.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 42.0px (16.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
- "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 118.0px (44.95238dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 64.0px (24.380953dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 49.0px (18.666666dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 42.0px (16.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 189.0px (72.0dp)\n" +
- "\tnumShownHotseatIcons: 5\n" +
- "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:false\n" +
- "\ttaskbarHeight: 0.0px (0.0dp)\n" +
- "\tstashedTaskbarHeight: 0.0px (0.0dp)\n" +
- "\ttaskbarBottomMargin: 0.0px (0.0dp)\n" +
- "\ttaskbarIconSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.left: 10.0px (3.8095238dp)\n" +
- "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.right: 199.0px (75.809525dp)\n" +
- "\tworkspacePadding.bottom: 0.0px (0.0dp)\n" +
- "\ticonScale: 1.0px (0.3809524dp)\n" +
- "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
- "\textraSpace: 136.0px (51.809525dp)\n" +
- "\tunscaled extraSpace: 136.0px (51.809525dp)\n" +
- "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
- "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
- "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
- "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
- "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
- "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
- "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 16.0px (6.095238dp)\n" +
- "\tdropTargetBarSizePx: 95.0px (36.190475dp)\n" +
- "\tdropTargetBarBottomMarginPx: 16.0px (6.095238dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 201.0px (76.57143dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1008.0px (384.0dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.8021869px (0.305595dp)\n" +
- "\tgetCellLayoutHeight(): 1006.0px (383.2381dp)\n" +
- "\tgetCellLayoutWidth(): 1947.0px (741.7143dp)\n"
- )
+ assertDump(dp, "phoneVerticalBar3Button")
}
@Test
@@ -444,135 +61,7 @@
initializeVarsForPhone(deviceSpecs["phone"]!!, isVerticalBar = true)
val dp = getDeviceProfileForGrid("5_by_5")
- assertThat(dump(dp))
- .isEqualTo(
- "DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:false\n" +
- "\tisPhone:true\n" +
- "\ttransposeLayoutWithOrientation:true\n" +
- "\tisGestureMode:true\n" +
- "\tisLandscape:true\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 2400.0px (914.2857dp)\n" +
- "\theightPx: 1080.0px (411.42856dp)\n" +
- "\tavailableWidthPx: 2282.0px (869.3333dp)\n" +
- "\tavailableHeightPx: 943.0px (359.2381dp)\n" +
- "\tmInsets.left: 118.0px (44.95238dp)\n" +
- "\tmInsets.top: 74.0px (28.190475dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 63.0px (24.0dp)\n" +
- "\taspectRatio:2.2222223\n" +
- "\tisResponsiveGrid:false\n" +
- "\tisScalableGrid:false\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 5\n" +
- "\tinv.numSearchContainerColumns: 5\n" +
- "\tminCellSize: PointF(0.0, 0.0)dp\n" +
- "\tcellWidthPx: 158.0px (60.190475dp)\n" +
- "\tcellHeightPx: 166.0px (63.238094dp)\n" +
- "\tgetCellSize().x: 393.0px (149.71428dp)\n" +
- "\tgetCellSize().y: 180.0px (68.57143dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 53.0px (20.190475dp)\n" +
- "\tcellLayoutPaddingPx.top: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 53.0px (20.190475dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 40.0px (15.238095dp)\n" +
- "\ticonSizePx: 147.0px (56.0dp)\n" +
- "\ticonTextSizePx: 0.0px (0.0dp)\n" +
- "\ticonDrawablePaddingPx: 0.0px (0.0dp)\n" +
- "\tinv.numFolderRows: 4\n" +
- "\tinv.numFolderColumns: 4\n" +
- "\tfolderCellWidthPx: 163.0px (62.095238dp)\n" +
- "\tfolderCellHeightPx: 192.0px (73.14286dp)\n" +
- "\tfolderChildIconSizePx: 123.0px (46.857143dp)\n" +
- "\tfolderChildTextSizePx: 32.0px (12.190476dp)\n" +
- "\tfolderChildDrawablePaddingPx: 8.0px (3.047619dp)\n" +
- "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
- "\tfolderTopPadding: 53.0px (20.190475dp)\n" +
- "\tfolderFooterHeight: 123.0px (46.857143dp)\n" +
- "\tbottomSheetTopPadding: 114.0px (43.42857dp)\n" +
- "\tbottomSheetOpenDuration: 267\n" +
- "\tbottomSheetCloseDuration: 267\n" +
- "\tbottomSheetWorkspaceScale: 1.0\n" +
- "\tbottomSheetDepth: 0.0\n" +
- "\tallAppsShiftRange: 788.0px (300.1905dp)\n" +
- "\tallAppsTopPadding: 0.0px (0.0dp)\n" +
- "\tallAppsOpenDuration: 600\n" +
- "\tallAppsCloseDuration: 300\n" +
- "\tallAppsIconSizePx: 147.0px (56.0dp)\n" +
- "\tallAppsIconTextSizePx: 38.0px (14.476191dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
- "\tallAppsCellHeightPx: 321.0px (122.28571dp)\n" +
- "\tallAppsCellWidthPx: 189.0px (72.0dp)\n" +
- "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 5\n" +
- "\tallAppsLeftRightPadding: 0.0px (0.0dp)\n" +
- "\tallAppsLeftRightMargin: 0.0px (0.0dp)\n" +
- "\thotseatBarSizePx: 252.0px (96.0dp)\n" +
- "\tinv.hotseatColumnSpan: 5\n" +
- "\thotseatCellHeightPx: 166.0px (63.238094dp)\n" +
- "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 63.0px (24.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 42.0px (16.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
- "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 118.0px (44.95238dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 64.0px (24.380953dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 112.0px (42.666668dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 42.0px (16.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 63.0px (24.0dp)\n" +
- "\tnumShownHotseatIcons: 5\n" +
- "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:false\n" +
- "\ttaskbarHeight: 0.0px (0.0dp)\n" +
- "\tstashedTaskbarHeight: 0.0px (0.0dp)\n" +
- "\ttaskbarBottomMargin: 0.0px (0.0dp)\n" +
- "\ttaskbarIconSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.left: 10.0px (3.8095238dp)\n" +
- "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.right: 199.0px (75.809525dp)\n" +
- "\tworkspacePadding.bottom: 0.0px (0.0dp)\n" +
- "\ticonScale: 1.0px (0.3809524dp)\n" +
- "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
- "\textraSpace: 73.0px (27.809525dp)\n" +
- "\tunscaled extraSpace: 73.0px (27.809525dp)\n" +
- "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
- "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
- "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
- "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
- "\toverviewActionsClaimedSpaceBelow: 63.0px (24.0dp)\n" +
- "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
- "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 16.0px (6.095238dp)\n" +
- "\tdropTargetBarSizePx: 95.0px (36.190475dp)\n" +
- "\tdropTargetBarBottomMarginPx: 16.0px (6.095238dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 201.0px (76.57143dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 952.0px (362.66666dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.79639447px (0.30338836dp)\n" +
- "\tgetCellLayoutHeight(): 943.0px (359.2381dp)\n" +
- "\tgetCellLayoutWidth(): 2073.0px (789.7143dp)\n"
- )
+ assertDump(dp, "phoneVerticalBar")
}
@Test
@@ -581,135 +70,7 @@
val dp = getDeviceProfileForGrid("6_by_5")
dp.isTaskbarPresentInApps = true
- assertThat(dump(dp))
- .isEqualTo(
- "DeviceProfile:\n" +
- "\t1 dp = 2.0 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:false\n" +
- "\tisLandscape:true\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 2560.0px (1280.0dp)\n" +
- "\theightPx: 1600.0px (800.0dp)\n" +
- "\tavailableWidthPx: 2560.0px (1280.0dp)\n" +
- "\tavailableHeightPx: 1496.0px (748.0dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 104.0px (52.0dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.6\n" +
- "\tisResponsiveGrid:false\n" +
- "\tisScalableGrid:true\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 6\n" +
- "\tinv.numSearchContainerColumns: 3\n" +
- "\tminCellSize: PointF(120.0, 104.0)dp\n" +
- "\tcellWidthPx: 240.0px (120.0dp)\n" +
- "\tcellHeightPx: 208.0px (104.0dp)\n" +
- "\tgetCellSize().x: 240.0px (120.0dp)\n" +
- "\tgetCellSize().y: 208.0px (104.0dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 128.0px (64.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 32.0px (16.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 59.0px (29.5dp)\n" +
- "\tcellLayoutPaddingPx.top: 25.0px (12.5dp)\n" +
- "\tcellLayoutPaddingPx.right: 59.0px (29.5dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 59.0px (29.5dp)\n" +
- "\ticonSizePx: 120.0px (60.0dp)\n" +
- "\ticonTextSizePx: 28.0px (14.0dp)\n" +
- "\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tinv.numFolderRows: 3\n" +
- "\tinv.numFolderColumns: 3\n" +
- "\tfolderCellWidthPx: 240.0px (120.0dp)\n" +
- "\tfolderCellHeightPx: 208.0px (104.0dp)\n" +
- "\tfolderChildIconSizePx: 120.0px (60.0dp)\n" +
- "\tfolderChildTextSizePx: 28.0px (14.0dp)\n" +
- "\tfolderChildDrawablePaddingPx: 16.0px (8.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 0.0px (0.0dp)\n" +
- "\tfolderTopPadding: 48.0px (24.0dp)\n" +
- "\tfolderFooterHeight: 112.0px (56.0dp)\n" +
- "\tbottomSheetTopPadding: 104.0px (52.0dp)\n" +
- "\tbottomSheetOpenDuration: 500\n" +
- "\tbottomSheetCloseDuration: 500\n" +
- "\tbottomSheetWorkspaceScale: 0.97\n" +
- "\tbottomSheetDepth: 0.0\n" +
- "\tallAppsShiftRange: 1496.0px (748.0dp)\n" +
- "\tallAppsTopPadding: 104.0px (52.0dp)\n" +
- "\tallAppsOpenDuration: 500\n" +
- "\tallAppsCloseDuration: 500\n" +
- "\tallAppsIconSizePx: 120.0px (60.0dp)\n" +
- "\tallAppsIconTextSizePx: 28.0px (14.0dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tallAppsCellHeightPx: 284.0px (142.0dp)\n" +
- "\tallAppsCellWidthPx: 252.0px (126.0dp)\n" +
- "\tallAppsBorderSpacePxX: 32.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 32.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 6\n" +
- "\tallAppsLeftRightPadding: 32.0px (16.0dp)\n" +
- "\tallAppsLeftRightMargin: 412.0px (206.0dp)\n" +
- "\thotseatBarSizePx: 200.0px (100.0dp)\n" +
- "\tinv.hotseatColumnSpan: 4\n" +
- "\thotseatCellHeightPx: 135.0px (67.5dp)\n" +
- "\thotseatBarBottomSpacePx: 80.0px (40.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
- "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 128.0px (64.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 65.0px (32.5dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 668.0px (334.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 668.0px (334.0dp)\n" +
- "\tnumShownHotseatIcons: 6\n" +
- "\thotseatBorderSpace: 100.0px (50.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 1224.0px (612.0dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarHeight: 0.0px (0.0dp)\n" +
- "\tstashedTaskbarHeight: 0.0px (0.0dp)\n" +
- "\ttaskbarBottomMargin: 0.0px (0.0dp)\n" +
- "\ttaskbarIconSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 240.0px (120.0dp)\n" +
- "\tworkspacePadding.left: 181.0px (90.5dp)\n" +
- "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.right: 181.0px (90.5dp)\n" +
- "\tworkspacePadding.bottom: 244.0px (122.0dp)\n" +
- "\ticonScale: 1.0px (0.5dp)\n" +
- "\tcellScaleToFit : 1.0px (0.5dp)\n" +
- "\textraSpace: 80.0px (40.0dp)\n" +
- "\tunscaled extraSpace: 80.0px (40.0dp)\n" +
- "\tmaxEmptySpace: 200.0px (100.0dp)\n" +
- "\tworkspaceTopPadding: 25.0px (12.5dp)\n" +
- "\tworkspaceBottomPadding: 55.0px (27.5dp)\n" +
- "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
- "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
- "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
- "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 0.0px (0.0dp)\n" +
- "\tdropTargetBarSizePx: 144.0px (72.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 64.0px (32.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 312.0px (156.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1272.0px (636.0dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.76677316px (0.38338658dp)\n" +
- "\tgetCellLayoutHeight(): 1252.0px (626.0dp)\n" +
- "\tgetCellLayoutWidth(): 2198.0px (1099.0dp)\n"
- )
+ assertDump(dp, "tabletLandscape3Button")
}
@Test
@@ -718,135 +79,7 @@
val dp = getDeviceProfileForGrid("6_by_5")
dp.isTaskbarPresentInApps = true
- assertThat(dump(dp))
- .isEqualTo(
- "DeviceProfile:\n" +
- "\t1 dp = 2.0 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:true\n" +
- "\tisLandscape:true\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 2560.0px (1280.0dp)\n" +
- "\theightPx: 1600.0px (800.0dp)\n" +
- "\tavailableWidthPx: 2560.0px (1280.0dp)\n" +
- "\tavailableHeightPx: 1496.0px (748.0dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 104.0px (52.0dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.6\n" +
- "\tisResponsiveGrid:false\n" +
- "\tisScalableGrid:true\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 6\n" +
- "\tinv.numSearchContainerColumns: 3\n" +
- "\tminCellSize: PointF(120.0, 104.0)dp\n" +
- "\tcellWidthPx: 240.0px (120.0dp)\n" +
- "\tcellHeightPx: 208.0px (104.0dp)\n" +
- "\tgetCellSize().x: 240.0px (120.0dp)\n" +
- "\tgetCellSize().y: 208.0px (104.0dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 128.0px (64.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 32.0px (16.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 59.0px (29.5dp)\n" +
- "\tcellLayoutPaddingPx.top: 25.0px (12.5dp)\n" +
- "\tcellLayoutPaddingPx.right: 59.0px (29.5dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 59.0px (29.5dp)\n" +
- "\ticonSizePx: 120.0px (60.0dp)\n" +
- "\ticonTextSizePx: 28.0px (14.0dp)\n" +
- "\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tinv.numFolderRows: 3\n" +
- "\tinv.numFolderColumns: 3\n" +
- "\tfolderCellWidthPx: 240.0px (120.0dp)\n" +
- "\tfolderCellHeightPx: 208.0px (104.0dp)\n" +
- "\tfolderChildIconSizePx: 120.0px (60.0dp)\n" +
- "\tfolderChildTextSizePx: 28.0px (14.0dp)\n" +
- "\tfolderChildDrawablePaddingPx: 16.0px (8.0dp)\n" +
- "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 0.0px (0.0dp)\n" +
- "\tfolderTopPadding: 48.0px (24.0dp)\n" +
- "\tfolderFooterHeight: 112.0px (56.0dp)\n" +
- "\tbottomSheetTopPadding: 104.0px (52.0dp)\n" +
- "\tbottomSheetOpenDuration: 500\n" +
- "\tbottomSheetCloseDuration: 500\n" +
- "\tbottomSheetWorkspaceScale: 0.97\n" +
- "\tbottomSheetDepth: 0.0\n" +
- "\tallAppsShiftRange: 1496.0px (748.0dp)\n" +
- "\tallAppsTopPadding: 104.0px (52.0dp)\n" +
- "\tallAppsOpenDuration: 500\n" +
- "\tallAppsCloseDuration: 500\n" +
- "\tallAppsIconSizePx: 120.0px (60.0dp)\n" +
- "\tallAppsIconTextSizePx: 28.0px (14.0dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tallAppsCellHeightPx: 284.0px (142.0dp)\n" +
- "\tallAppsCellWidthPx: 252.0px (126.0dp)\n" +
- "\tallAppsBorderSpacePxX: 32.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 32.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 6\n" +
- "\tallAppsLeftRightPadding: 32.0px (16.0dp)\n" +
- "\tallAppsLeftRightMargin: 412.0px (206.0dp)\n" +
- "\thotseatBarSizePx: 200.0px (100.0dp)\n" +
- "\tinv.hotseatColumnSpan: 4\n" +
- "\thotseatCellHeightPx: 135.0px (67.5dp)\n" +
- "\thotseatBarBottomSpacePx: 80.0px (40.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
- "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 128.0px (64.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 65.0px (32.5dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 668.0px (334.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 668.0px (334.0dp)\n" +
- "\tnumShownHotseatIcons: 6\n" +
- "\thotseatBorderSpace: 100.0px (50.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 1224.0px (612.0dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarHeight: 0.0px (0.0dp)\n" +
- "\tstashedTaskbarHeight: 0.0px (0.0dp)\n" +
- "\ttaskbarBottomMargin: 0.0px (0.0dp)\n" +
- "\ttaskbarIconSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 240.0px (120.0dp)\n" +
- "\tworkspacePadding.left: 181.0px (90.5dp)\n" +
- "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
- "\tworkspacePadding.right: 181.0px (90.5dp)\n" +
- "\tworkspacePadding.bottom: 244.0px (122.0dp)\n" +
- "\ticonScale: 1.0px (0.5dp)\n" +
- "\tcellScaleToFit : 1.0px (0.5dp)\n" +
- "\textraSpace: 80.0px (40.0dp)\n" +
- "\tunscaled extraSpace: 80.0px (40.0dp)\n" +
- "\tmaxEmptySpace: 200.0px (100.0dp)\n" +
- "\tworkspaceTopPadding: 25.0px (12.5dp)\n" +
- "\tworkspaceBottomPadding: 55.0px (27.5dp)\n" +
- "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
- "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
- "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
- "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 0.0px (0.0dp)\n" +
- "\tdropTargetBarSizePx: 144.0px (72.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 64.0px (32.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 312.0px (156.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1272.0px (636.0dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.76677316px (0.38338658dp)\n" +
- "\tgetCellLayoutHeight(): 1252.0px (626.0dp)\n" +
- "\tgetCellLayoutWidth(): 2198.0px (1099.0dp)\n"
- )
+ assertDump(dp, "tabletLandscape")
}
@Test
@@ -855,135 +88,7 @@
val dp = getDeviceProfileForGrid("6_by_5")
dp.isTaskbarPresentInApps = true
- assertThat(dump(dp))
- .isEqualTo(
- "DeviceProfile:\n" +
- "\t1 dp = 2.0 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:false\n" +
- "\tisLandscape:false\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 1600.0px (800.0dp)\n" +
- "\theightPx: 2560.0px (1280.0dp)\n" +
- "\tavailableWidthPx: 1600.0px (800.0dp)\n" +
- "\tavailableHeightPx: 2456.0px (1228.0dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 104.0px (52.0dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.6\n" +
- "\tisResponsiveGrid:false\n" +
- "\tisScalableGrid:true\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 6\n" +
- "\tinv.numSearchContainerColumns: 3\n" +
- "\tminCellSize: PointF(102.0, 120.0)dp\n" +
- "\tcellWidthPx: 204.0px (102.0dp)\n" +
- "\tcellHeightPx: 240.0px (120.0dp)\n" +
- "\tgetCellSize().x: 204.0px (102.0dp)\n" +
- "\tgetCellSize().y: 240.0px (120.0dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 32.0px (16.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 128.0px (64.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 72.0px (36.0dp)\n" +
- "\tcellLayoutPaddingPx.top: 72.0px (36.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 72.0px (36.0dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 72.0px (36.0dp)\n" +
- "\ticonSizePx: 120.0px (60.0dp)\n" +
- "\ticonTextSizePx: 28.0px (14.0dp)\n" +
- "\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tinv.numFolderRows: 3\n" +
- "\tinv.numFolderColumns: 3\n" +
- "\tfolderCellWidthPx: 204.0px (102.0dp)\n" +
- "\tfolderCellHeightPx: 240.0px (120.0dp)\n" +
- "\tfolderChildIconSizePx: 120.0px (60.0dp)\n" +
- "\tfolderChildTextSizePx: 28.0px (14.0dp)\n" +
- "\tfolderChildDrawablePaddingPx: 27.0px (13.5dp)\n" +
- "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 0.0px (0.0dp)\n" +
- "\tfolderTopPadding: 48.0px (24.0dp)\n" +
- "\tfolderFooterHeight: 112.0px (56.0dp)\n" +
- "\tbottomSheetTopPadding: 704.0px (352.0dp)\n" +
- "\tbottomSheetOpenDuration: 500\n" +
- "\tbottomSheetCloseDuration: 500\n" +
- "\tbottomSheetWorkspaceScale: 0.97\n" +
- "\tbottomSheetDepth: 0.0\n" +
- "\tallAppsShiftRange: 1810.0px (905.0dp)\n" +
- "\tallAppsTopPadding: 750.0px (375.0dp)\n" +
- "\tallAppsOpenDuration: 500\n" +
- "\tallAppsCloseDuration: 500\n" +
- "\tallAppsIconSizePx: 120.0px (60.0dp)\n" +
- "\tallAppsIconTextSizePx: 28.0px (14.0dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tallAppsCellHeightPx: 316.0px (158.0dp)\n" +
- "\tallAppsCellWidthPx: 192.0px (96.0dp)\n" +
- "\tallAppsBorderSpacePxX: 16.0px (8.0dp)\n" +
- "\tallAppsBorderSpacePxY: 32.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 6\n" +
- "\tallAppsLeftRightPadding: 32.0px (16.0dp)\n" +
- "\tallAppsLeftRightMargin: 152.0px (76.0dp)\n" +
- "\thotseatBarSizePx: 272.0px (136.0dp)\n" +
- "\tinv.hotseatColumnSpan: 6\n" +
- "\thotseatCellHeightPx: 135.0px (67.5dp)\n" +
- "\thotseatBarBottomSpacePx: 152.0px (76.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
- "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 216.0px (108.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 137.0px (68.5dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 150.0px (75.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 150.0px (75.0dp)\n" +
- "\tnumShownHotseatIcons: 6\n" +
- "\thotseatBorderSpace: 116.0px (58.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 1300.0px (650.0dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarHeight: 0.0px (0.0dp)\n" +
- "\tstashedTaskbarHeight: 0.0px (0.0dp)\n" +
- "\ttaskbarBottomMargin: 0.0px (0.0dp)\n" +
- "\ttaskbarIconSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 108.0px (54.0dp)\n" +
- "\tworkspacePadding.left: 36.0px (18.0dp)\n" +
- "\tworkspacePadding.top: 132.0px (66.0dp)\n" +
- "\tworkspacePadding.right: 36.0px (18.0dp)\n" +
- "\tworkspacePadding.bottom: 468.0px (234.0dp)\n" +
- "\ticonScale: 1.0px (0.5dp)\n" +
- "\tcellScaleToFit : 1.0px (0.5dp)\n" +
- "\textraSpace: 424.0px (212.0dp)\n" +
- "\tunscaled extraSpace: 424.0px (212.0dp)\n" +
- "\tmaxEmptySpace: 19998.0px (9999.0dp)\n" +
- "\tworkspaceTopPadding: 204.0px (102.0dp)\n" +
- "\tworkspaceBottomPadding: 220.0px (110.0dp)\n" +
- "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
- "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
- "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
- "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 220.0px (110.0dp)\n" +
- "\tdropTargetBarSizePx: 144.0px (72.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 96.0px (48.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 564.0px (282.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 2072.0px (1036.0dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.8125px (0.40625dp)\n" +
- "\tgetCellLayoutHeight(): 1856.0px (928.0dp)\n" +
- "\tgetCellLayoutWidth(): 1528.0px (764.0dp)\n"
- )
+ assertDump(dp, "tabletPortrait3Button")
}
@Test
@@ -992,135 +97,7 @@
val dp = getDeviceProfileForGrid("6_by_5")
dp.isTaskbarPresentInApps = true
- assertThat(dump(dp))
- .isEqualTo(
- "DeviceProfile:\n" +
- "\t1 dp = 2.0 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:true\n" +
- "\tisLandscape:false\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:false\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 1600.0px (800.0dp)\n" +
- "\theightPx: 2560.0px (1280.0dp)\n" +
- "\tavailableWidthPx: 1600.0px (800.0dp)\n" +
- "\tavailableHeightPx: 2456.0px (1228.0dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 104.0px (52.0dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.6\n" +
- "\tisResponsiveGrid:false\n" +
- "\tisScalableGrid:true\n" +
- "\tinv.numRows: 5\n" +
- "\tinv.numColumns: 6\n" +
- "\tinv.numSearchContainerColumns: 3\n" +
- "\tminCellSize: PointF(102.0, 120.0)dp\n" +
- "\tcellWidthPx: 204.0px (102.0dp)\n" +
- "\tcellHeightPx: 240.0px (120.0dp)\n" +
- "\tgetCellSize().x: 204.0px (102.0dp)\n" +
- "\tgetCellSize().y: 240.0px (120.0dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 32.0px (16.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 128.0px (64.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 72.0px (36.0dp)\n" +
- "\tcellLayoutPaddingPx.top: 72.0px (36.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 72.0px (36.0dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 72.0px (36.0dp)\n" +
- "\ticonSizePx: 120.0px (60.0dp)\n" +
- "\ticonTextSizePx: 28.0px (14.0dp)\n" +
- "\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tinv.numFolderRows: 3\n" +
- "\tinv.numFolderColumns: 3\n" +
- "\tfolderCellWidthPx: 204.0px (102.0dp)\n" +
- "\tfolderCellHeightPx: 240.0px (120.0dp)\n" +
- "\tfolderChildIconSizePx: 120.0px (60.0dp)\n" +
- "\tfolderChildTextSizePx: 28.0px (14.0dp)\n" +
- "\tfolderChildDrawablePaddingPx: 27.0px (13.5dp)\n" +
- "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 0.0px (0.0dp)\n" +
- "\tfolderTopPadding: 48.0px (24.0dp)\n" +
- "\tfolderFooterHeight: 112.0px (56.0dp)\n" +
- "\tbottomSheetTopPadding: 704.0px (352.0dp)\n" +
- "\tbottomSheetOpenDuration: 500\n" +
- "\tbottomSheetCloseDuration: 500\n" +
- "\tbottomSheetWorkspaceScale: 0.97\n" +
- "\tbottomSheetDepth: 0.0\n" +
- "\tallAppsShiftRange: 1810.0px (905.0dp)\n" +
- "\tallAppsTopPadding: 750.0px (375.0dp)\n" +
- "\tallAppsOpenDuration: 500\n" +
- "\tallAppsCloseDuration: 500\n" +
- "\tallAppsIconSizePx: 120.0px (60.0dp)\n" +
- "\tallAppsIconTextSizePx: 28.0px (14.0dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 14.0px (7.0dp)\n" +
- "\tallAppsCellHeightPx: 316.0px (158.0dp)\n" +
- "\tallAppsCellWidthPx: 192.0px (96.0dp)\n" +
- "\tallAppsBorderSpacePxX: 16.0px (8.0dp)\n" +
- "\tallAppsBorderSpacePxY: 32.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 6\n" +
- "\tallAppsLeftRightPadding: 32.0px (16.0dp)\n" +
- "\tallAppsLeftRightMargin: 152.0px (76.0dp)\n" +
- "\thotseatBarSizePx: 272.0px (136.0dp)\n" +
- "\tinv.hotseatColumnSpan: 6\n" +
- "\thotseatCellHeightPx: 135.0px (67.5dp)\n" +
- "\thotseatBarBottomSpacePx: 152.0px (76.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
- "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 216.0px (108.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 137.0px (68.5dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 150.0px (75.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 150.0px (75.0dp)\n" +
- "\tnumShownHotseatIcons: 6\n" +
- "\thotseatBorderSpace: 116.0px (58.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 1300.0px (650.0dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarHeight: 0.0px (0.0dp)\n" +
- "\tstashedTaskbarHeight: 0.0px (0.0dp)\n" +
- "\ttaskbarBottomMargin: 0.0px (0.0dp)\n" +
- "\ttaskbarIconSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 108.0px (54.0dp)\n" +
- "\tworkspacePadding.left: 36.0px (18.0dp)\n" +
- "\tworkspacePadding.top: 132.0px (66.0dp)\n" +
- "\tworkspacePadding.right: 36.0px (18.0dp)\n" +
- "\tworkspacePadding.bottom: 468.0px (234.0dp)\n" +
- "\ticonScale: 1.0px (0.5dp)\n" +
- "\tcellScaleToFit : 1.0px (0.5dp)\n" +
- "\textraSpace: 424.0px (212.0dp)\n" +
- "\tunscaled extraSpace: 424.0px (212.0dp)\n" +
- "\tmaxEmptySpace: 19998.0px (9999.0dp)\n" +
- "\tworkspaceTopPadding: 204.0px (102.0dp)\n" +
- "\tworkspaceBottomPadding: 220.0px (110.0dp)\n" +
- "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
- "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
- "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
- "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 220.0px (110.0dp)\n" +
- "\tdropTargetBarSizePx: 144.0px (72.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 96.0px (48.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 564.0px (282.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 2072.0px (1036.0dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.8125px (0.40625dp)\n" +
- "\tgetCellLayoutHeight(): 1856.0px (928.0dp)\n" +
- "\tgetCellLayoutWidth(): 1528.0px (764.0dp)\n"
- )
+ assertDump(dp, "tabletPortrait")
}
@Test
@@ -1134,135 +111,7 @@
val dp = getDeviceProfileForGrid("4_by_4")
dp.isTaskbarPresentInApps = true
- assertThat(dump(dp))
- .isEqualTo(
- "DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:false\n" +
- "\tisLandscape:true\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:true\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 2208.0px (841.1429dp)\n" +
- "\theightPx: 1840.0px (700.9524dp)\n" +
- "\tavailableWidthPx: 2208.0px (841.1429dp)\n" +
- "\tavailableHeightPx: 1730.0px (659.0476dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 110.0px (41.904762dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.2\n" +
- "\tisResponsiveGrid:false\n" +
- "\tisScalableGrid:false\n" +
- "\tinv.numRows: 4\n" +
- "\tinv.numColumns: 4\n" +
- "\tinv.numSearchContainerColumns: 4\n" +
- "\tminCellSize: PointF(0.0, 0.0)dp\n" +
- "\tcellWidthPx: 159.0px (60.57143dp)\n" +
- "\tcellHeightPx: 223.0px (84.95238dp)\n" +
- "\tgetCellSize().x: 270.0px (102.85714dp)\n" +
- "\tgetCellSize().y: 342.0px (130.28572dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.top: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 0.0px (0.0dp)\n" +
- "\ticonSizePx: 141.0px (53.714287dp)\n" +
- "\ticonTextSizePx: 34.0px (12.952381dp)\n" +
- "\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
- "\tinv.numFolderRows: 3\n" +
- "\tinv.numFolderColumns: 4\n" +
- "\tfolderCellWidthPx: 189.0px (72.0dp)\n" +
- "\tfolderCellHeightPx: 219.0px (83.42857dp)\n" +
- "\tfolderChildIconSizePx: 141.0px (53.714287dp)\n" +
- "\tfolderChildTextSizePx: 34.0px (12.952381dp)\n" +
- "\tfolderChildDrawablePaddingPx: 10.0px (3.8095238dp)\n" +
- "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
- "\tfolderTopPadding: 63.0px (24.0dp)\n" +
- "\tfolderFooterHeight: 147.0px (56.0dp)\n" +
- "\tbottomSheetTopPadding: 110.0px (41.904762dp)\n" +
- "\tbottomSheetOpenDuration: 500\n" +
- "\tbottomSheetCloseDuration: 500\n" +
- "\tbottomSheetWorkspaceScale: 0.97\n" +
- "\tbottomSheetDepth: 1.0\n" +
- "\tallAppsShiftRange: 1730.0px (659.0476dp)\n" +
- "\tallAppsTopPadding: 110.0px (41.904762dp)\n" +
- "\tallAppsOpenDuration: 500\n" +
- "\tallAppsCloseDuration: 500\n" +
- "\tallAppsIconSizePx: 141.0px (53.714287dp)\n" +
- "\tallAppsIconTextSizePx: 34.0px (12.952381dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
- "\tallAppsCellHeightPx: 315.0px (120.0dp)\n" +
- "\tallAppsCellWidthPx: 183.0px (69.71429dp)\n" +
- "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 8\n" +
- "\tallAppsLeftRightPadding: 42.0px (16.0dp)\n" +
- "\tallAppsLeftRightMargin: 183.0px (69.71429dp)\n" +
- "\thotseatBarSizePx: 267.0px (101.71429dp)\n" +
- "\tinv.hotseatColumnSpan: 4\n" +
- "\thotseatCellHeightPx: 159.0px (60.57143dp)\n" +
- "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
- "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 116.0px (44.190475dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 113.0px (43.04762dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 113.0px (43.04762dp)\n" +
- "\tnumShownHotseatIcons: 6\n" +
- "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarHeight: 0.0px (0.0dp)\n" +
- "\tstashedTaskbarHeight: 0.0px (0.0dp)\n" +
- "\ttaskbarBottomMargin: 0.0px (0.0dp)\n" +
- "\ttaskbarIconSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)\n" +
- "\tworkspacePadding.left: 21.0px (8.0dp)\n" +
- "\tworkspacePadding.top: 30.0px (11.428572dp)\n" +
- "\tworkspacePadding.right: 21.0px (8.0dp)\n" +
- "\tworkspacePadding.bottom: 330.0px (125.71429dp)\n" +
- "\ticonScale: 1.0px (0.3809524dp)\n" +
- "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
- "\textraSpace: 478.0px (182.09525dp)\n" +
- "\tunscaled extraSpace: 478.0px (182.09525dp)\n" +
- "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
- "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
- "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
- "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
- "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
- "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
- "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 0.0px (0.0dp)\n" +
- "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 299.0px (113.90476dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1457.0px (555.0476dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.8452555px (0.32200208dp)\n" +
- "\tgetCellLayoutHeight(): 1370.0px (521.9048dp)\n" +
- "\tgetCellLayoutWidth(): 1083.0px (412.57144dp)\n"
- )
+ assertDump(dp, "twoPanelLandscape3Button")
}
@Test
@@ -1275,135 +124,7 @@
val dp = getDeviceProfileForGrid("4_by_4")
dp.isTaskbarPresentInApps = true
- assertThat(dump(dp))
- .isEqualTo(
- "DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:true\n" +
- "\tisLandscape:true\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:true\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 2208.0px (841.1429dp)\n" +
- "\theightPx: 1840.0px (700.9524dp)\n" +
- "\tavailableWidthPx: 2208.0px (841.1429dp)\n" +
- "\tavailableHeightPx: 1730.0px (659.0476dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 110.0px (41.904762dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.2\n" +
- "\tisResponsiveGrid:false\n" +
- "\tisScalableGrid:false\n" +
- "\tinv.numRows: 4\n" +
- "\tinv.numColumns: 4\n" +
- "\tinv.numSearchContainerColumns: 4\n" +
- "\tminCellSize: PointF(0.0, 0.0)dp\n" +
- "\tcellWidthPx: 159.0px (60.57143dp)\n" +
- "\tcellHeightPx: 223.0px (84.95238dp)\n" +
- "\tgetCellSize().x: 270.0px (102.85714dp)\n" +
- "\tgetCellSize().y: 342.0px (130.28572dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.top: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 0.0px (0.0dp)\n" +
- "\ticonSizePx: 141.0px (53.714287dp)\n" +
- "\ticonTextSizePx: 34.0px (12.952381dp)\n" +
- "\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
- "\tinv.numFolderRows: 3\n" +
- "\tinv.numFolderColumns: 4\n" +
- "\tfolderCellWidthPx: 189.0px (72.0dp)\n" +
- "\tfolderCellHeightPx: 219.0px (83.42857dp)\n" +
- "\tfolderChildIconSizePx: 141.0px (53.714287dp)\n" +
- "\tfolderChildTextSizePx: 34.0px (12.952381dp)\n" +
- "\tfolderChildDrawablePaddingPx: 10.0px (3.8095238dp)\n" +
- "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
- "\tfolderTopPadding: 63.0px (24.0dp)\n" +
- "\tfolderFooterHeight: 147.0px (56.0dp)\n" +
- "\tbottomSheetTopPadding: 110.0px (41.904762dp)\n" +
- "\tbottomSheetOpenDuration: 500\n" +
- "\tbottomSheetCloseDuration: 500\n" +
- "\tbottomSheetWorkspaceScale: 0.97\n" +
- "\tbottomSheetDepth: 1.0\n" +
- "\tallAppsShiftRange: 1730.0px (659.0476dp)\n" +
- "\tallAppsTopPadding: 110.0px (41.904762dp)\n" +
- "\tallAppsOpenDuration: 500\n" +
- "\tallAppsCloseDuration: 500\n" +
- "\tallAppsIconSizePx: 141.0px (53.714287dp)\n" +
- "\tallAppsIconTextSizePx: 34.0px (12.952381dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
- "\tallAppsCellHeightPx: 315.0px (120.0dp)\n" +
- "\tallAppsCellWidthPx: 183.0px (69.71429dp)\n" +
- "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 8\n" +
- "\tallAppsLeftRightPadding: 42.0px (16.0dp)\n" +
- "\tallAppsLeftRightMargin: 183.0px (69.71429dp)\n" +
- "\thotseatBarSizePx: 267.0px (101.71429dp)\n" +
- "\tinv.hotseatColumnSpan: 4\n" +
- "\thotseatCellHeightPx: 159.0px (60.57143dp)\n" +
- "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
- "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 116.0px (44.190475dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 113.0px (43.04762dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 113.0px (43.04762dp)\n" +
- "\tnumShownHotseatIcons: 6\n" +
- "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarHeight: 0.0px (0.0dp)\n" +
- "\tstashedTaskbarHeight: 0.0px (0.0dp)\n" +
- "\ttaskbarBottomMargin: 0.0px (0.0dp)\n" +
- "\ttaskbarIconSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)\n" +
- "\tworkspacePadding.left: 21.0px (8.0dp)\n" +
- "\tworkspacePadding.top: 30.0px (11.428572dp)\n" +
- "\tworkspacePadding.right: 21.0px (8.0dp)\n" +
- "\tworkspacePadding.bottom: 330.0px (125.71429dp)\n" +
- "\ticonScale: 1.0px (0.3809524dp)\n" +
- "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
- "\textraSpace: 478.0px (182.09525dp)\n" +
- "\tunscaled extraSpace: 478.0px (182.09525dp)\n" +
- "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
- "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
- "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
- "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
- "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
- "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
- "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 0.0px (0.0dp)\n" +
- "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 299.0px (113.90476dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1457.0px (555.0476dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.8452555px (0.32200208dp)\n" +
- "\tgetCellLayoutHeight(): 1370.0px (521.9048dp)\n" +
- "\tgetCellLayoutWidth(): 1083.0px (412.57144dp)\n"
- )
+ assertDump(dp, "twoPanelLandscape")
}
@Test
@@ -1416,135 +137,7 @@
val dp = getDeviceProfileForGrid("4_by_4")
dp.isTaskbarPresentInApps = true
- assertThat(dump(dp))
- .isEqualTo(
- "DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:false\n" +
- "\tisLandscape:false\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:true\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 1840.0px (700.9524dp)\n" +
- "\theightPx: 2208.0px (841.1429dp)\n" +
- "\tavailableWidthPx: 1840.0px (700.9524dp)\n" +
- "\tavailableHeightPx: 2075.0px (790.4762dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 133.0px (50.666668dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.2\n" +
- "\tisResponsiveGrid:false\n" +
- "\tisScalableGrid:false\n" +
- "\tinv.numRows: 4\n" +
- "\tinv.numColumns: 4\n" +
- "\tinv.numSearchContainerColumns: 4\n" +
- "\tminCellSize: PointF(0.0, 0.0)dp\n" +
- "\tcellWidthPx: 159.0px (60.57143dp)\n" +
- "\tcellHeightPx: 223.0px (84.95238dp)\n" +
- "\tgetCellSize().x: 224.0px (85.333336dp)\n" +
- "\tgetCellSize().y: 430.0px (163.80952dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.top: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 0.0px (0.0dp)\n" +
- "\ticonSizePx: 141.0px (53.714287dp)\n" +
- "\ticonTextSizePx: 34.0px (12.952381dp)\n" +
- "\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
- "\tinv.numFolderRows: 3\n" +
- "\tinv.numFolderColumns: 4\n" +
- "\tfolderCellWidthPx: 189.0px (72.0dp)\n" +
- "\tfolderCellHeightPx: 219.0px (83.42857dp)\n" +
- "\tfolderChildIconSizePx: 141.0px (53.714287dp)\n" +
- "\tfolderChildTextSizePx: 34.0px (12.952381dp)\n" +
- "\tfolderChildDrawablePaddingPx: 10.0px (3.8095238dp)\n" +
- "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
- "\tfolderTopPadding: 63.0px (24.0dp)\n" +
- "\tfolderFooterHeight: 147.0px (56.0dp)\n" +
- "\tbottomSheetTopPadding: 133.0px (50.666668dp)\n" +
- "\tbottomSheetOpenDuration: 500\n" +
- "\tbottomSheetCloseDuration: 500\n" +
- "\tbottomSheetWorkspaceScale: 0.97\n" +
- "\tbottomSheetDepth: 1.0\n" +
- "\tallAppsShiftRange: 1826.0px (695.619dp)\n" +
- "\tallAppsTopPadding: 382.0px (145.5238dp)\n" +
- "\tallAppsOpenDuration: 500\n" +
- "\tallAppsCloseDuration: 500\n" +
- "\tallAppsIconSizePx: 141.0px (53.714287dp)\n" +
- "\tallAppsIconTextSizePx: 34.0px (12.952381dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
- "\tallAppsCellHeightPx: 315.0px (120.0dp)\n" +
- "\tallAppsCellWidthPx: 183.0px (69.71429dp)\n" +
- "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 8\n" +
- "\tallAppsLeftRightPadding: 42.0px (16.0dp)\n" +
- "\tallAppsLeftRightMargin: 1.0px (0.3809524dp)\n" +
- "\thotseatBarSizePx: 267.0px (101.71429dp)\n" +
- "\tinv.hotseatColumnSpan: 4\n" +
- "\thotseatCellHeightPx: 159.0px (60.57143dp)\n" +
- "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
- "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 171.0px (65.14286dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 98.0px (37.333332dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 98.0px (37.333332dp)\n" +
- "\tnumShownHotseatIcons: 6\n" +
- "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarHeight: 0.0px (0.0dp)\n" +
- "\tstashedTaskbarHeight: 0.0px (0.0dp)\n" +
- "\ttaskbarBottomMargin: 0.0px (0.0dp)\n" +
- "\ttaskbarIconSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)\n" +
- "\tworkspacePadding.left: 21.0px (8.0dp)\n" +
- "\tworkspacePadding.top: 24.0px (9.142858dp)\n" +
- "\tworkspacePadding.right: 21.0px (8.0dp)\n" +
- "\tworkspacePadding.bottom: 330.0px (125.71429dp)\n" +
- "\ticonScale: 1.0px (0.3809524dp)\n" +
- "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
- "\textraSpace: 829.0px (315.8095dp)\n" +
- "\tunscaled extraSpace: 829.0px (315.8095dp)\n" +
- "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
- "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
- "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
- "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
- "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
- "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
- "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 168.0px (64.0dp)\n" +
- "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 490.0px (186.66667dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1770.0px (674.2857dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.7437536px (0.2833347dp)\n" +
- "\tgetCellLayoutHeight(): 1721.0px (655.619dp)\n" +
- "\tgetCellLayoutWidth(): 899.0px (342.4762dp)\n"
- )
+ assertDump(dp, "twoPanelPortrait3Button")
}
@Test
@@ -1553,146 +146,17 @@
val dp = getDeviceProfileForGrid("4_by_4")
dp.isTaskbarPresentInApps = true
- assertThat(dump(dp))
- .isEqualTo(
- "DeviceProfile:\n" +
- "\t1 dp = 2.625 px\n" +
- "\tisTablet:true\n" +
- "\tisPhone:false\n" +
- "\ttransposeLayoutWithOrientation:false\n" +
- "\tisGestureMode:true\n" +
- "\tisLandscape:false\n" +
- "\tisMultiWindowMode:false\n" +
- "\tisTwoPanels:true\n" +
- "\twindowX: 0.0px (0.0dp)\n" +
- "\twindowY: 0.0px (0.0dp)\n" +
- "\twidthPx: 1840.0px (700.9524dp)\n" +
- "\theightPx: 2208.0px (841.1429dp)\n" +
- "\tavailableWidthPx: 1840.0px (700.9524dp)\n" +
- "\tavailableHeightPx: 2075.0px (790.4762dp)\n" +
- "\tmInsets.left: 0.0px (0.0dp)\n" +
- "\tmInsets.top: 133.0px (50.666668dp)\n" +
- "\tmInsets.right: 0.0px (0.0dp)\n" +
- "\tmInsets.bottom: 0.0px (0.0dp)\n" +
- "\taspectRatio:1.2\n" +
- "\tisResponsiveGrid:false\n" +
- "\tisScalableGrid:false\n" +
- "\tinv.numRows: 4\n" +
- "\tinv.numColumns: 4\n" +
- "\tinv.numSearchContainerColumns: 4\n" +
- "\tminCellSize: PointF(0.0, 0.0)dp\n" +
- "\tcellWidthPx: 159.0px (60.57143dp)\n" +
- "\tcellHeightPx: 223.0px (84.95238dp)\n" +
- "\tgetCellSize().x: 224.0px (85.333336dp)\n" +
- "\tgetCellSize().y: 430.0px (163.80952dp)\n" +
- "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
- "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.left: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.top: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.right: 0.0px (0.0dp)\n" +
- "\tcellLayoutPaddingPx.bottom: 0.0px (0.0dp)\n" +
- "\ticonSizePx: 141.0px (53.714287dp)\n" +
- "\ticonTextSizePx: 34.0px (12.952381dp)\n" +
- "\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
- "\tinv.numFolderRows: 3\n" +
- "\tinv.numFolderColumns: 4\n" +
- "\tfolderCellWidthPx: 189.0px (72.0dp)\n" +
- "\tfolderCellHeightPx: 219.0px (83.42857dp)\n" +
- "\tfolderChildIconSizePx: 141.0px (53.714287dp)\n" +
- "\tfolderChildTextSizePx: 34.0px (12.952381dp)\n" +
- "\tfolderChildDrawablePaddingPx: 10.0px (3.8095238dp)\n" +
- "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
- "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
- "\tfolderTopPadding: 63.0px (24.0dp)\n" +
- "\tfolderFooterHeight: 147.0px (56.0dp)\n" +
- "\tbottomSheetTopPadding: 133.0px (50.666668dp)\n" +
- "\tbottomSheetOpenDuration: 500\n" +
- "\tbottomSheetCloseDuration: 500\n" +
- "\tbottomSheetWorkspaceScale: 0.97\n" +
- "\tbottomSheetDepth: 1.0\n" +
- "\tallAppsShiftRange: 1826.0px (695.619dp)\n" +
- "\tallAppsTopPadding: 382.0px (145.5238dp)\n" +
- "\tallAppsOpenDuration: 500\n" +
- "\tallAppsCloseDuration: 500\n" +
- "\tallAppsIconSizePx: 141.0px (53.714287dp)\n" +
- "\tallAppsIconTextSizePx: 34.0px (12.952381dp)\n" +
- "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
- "\tallAppsCellHeightPx: 315.0px (120.0dp)\n" +
- "\tallAppsCellWidthPx: 183.0px (69.71429dp)\n" +
- "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
- "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
- "\tnumShownAllAppsColumns: 8\n" +
- "\tallAppsLeftRightPadding: 42.0px (16.0dp)\n" +
- "\tallAppsLeftRightMargin: 1.0px (0.3809524dp)\n" +
- "\thotseatBarSizePx: 267.0px (101.71429dp)\n" +
- "\tinv.hotseatColumnSpan: 4\n" +
- "\thotseatCellHeightPx: 159.0px (60.57143dp)\n" +
- "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
- "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
- "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
- "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
- "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
- "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
- "\tspringLoadedHotseatBarTopMarginPx: 171.0px (65.14286dp)\n" +
- "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
- "\tgetHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)\n" +
- "\tgetHotseatLayoutPadding(context).left: 98.0px (37.333332dp)\n" +
- "\tgetHotseatLayoutPadding(context).right: 98.0px (37.333332dp)\n" +
- "\tnumShownHotseatIcons: 6\n" +
- "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
- "\tisQsbInline: false\n" +
- "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
- "\tisTaskbarPresent:false\n" +
- "\tisTaskbarPresentInApps:true\n" +
- "\ttaskbarHeight: 0.0px (0.0dp)\n" +
- "\tstashedTaskbarHeight: 0.0px (0.0dp)\n" +
- "\ttaskbarBottomMargin: 0.0px (0.0dp)\n" +
- "\ttaskbarIconSize: 0.0px (0.0dp)\n" +
- "\tdesiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)\n" +
- "\tworkspacePadding.left: 21.0px (8.0dp)\n" +
- "\tworkspacePadding.top: 24.0px (9.142858dp)\n" +
- "\tworkspacePadding.right: 21.0px (8.0dp)\n" +
- "\tworkspacePadding.bottom: 330.0px (125.71429dp)\n" +
- "\ticonScale: 1.0px (0.3809524dp)\n" +
- "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
- "\textraSpace: 829.0px (315.8095dp)\n" +
- "\tunscaled extraSpace: 829.0px (315.8095dp)\n" +
- "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
- "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
- "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
- "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
- "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
- "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
- "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
- "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
- "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
- "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
- "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
- "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
- "\tdropTargetBarTopMarginPx: 168.0px (64.0dp)\n" +
- "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
- "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkTop(): 490.0px (186.66667dp)\n" +
- "\tgetCellLayoutSpringLoadShrunkBottom(): 1770.0px (674.2857dp)\n" +
- "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
- "\tgetWorkspaceSpringLoadScale(): 0.7437536px (0.2833347dp)\n" +
- "\tgetCellLayoutHeight(): 1721.0px (655.619dp)\n" +
- "\tgetCellLayoutWidth(): 899.0px (342.4762dp)\n"
- )
+ assertDump(dp, "twoPanelPortrait")
}
private fun getDeviceProfileForGrid(gridName: String): DeviceProfile {
return InvariantDeviceProfile(context, gridName).getDeviceProfile(context)
}
- private fun dump(dp: DeviceProfile): String {
- val stringWriter = StringWriter()
- val printWriter = PrintWriter(stringWriter)
- dp.dump(context, "", printWriter)
- printWriter.flush()
- return stringWriter.toString()
+ private fun assertDump(dp: DeviceProfile, filename: String) {
+ val dump = dump(context!!, dp, "${folderName}_$filename.txt")
+ val expected = readDumpFromAssets(testContext, "$folderName/$filename.txt")
+
+ assertThat(dump).isEqualTo(expected)
}
}
diff --git a/tests/src/com/android/launcher3/nonquickstep/HotseatWidthCalculationTest.kt b/tests/src/com/android/launcher3/nonquickstep/HotseatWidthCalculationTest.kt
index 2a27487..d102397 100644
--- a/tests/src/com/android/launcher3/nonquickstep/HotseatWidthCalculationTest.kt
+++ b/tests/src/com/android/launcher3/nonquickstep/HotseatWidthCalculationTest.kt
@@ -158,4 +158,25 @@
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.hotseatQsbWidth).isEqualTo(1095)
}
+
+ @Test
+ fun border_space_should_be_zero_when_numHotseatIcons_is_smallerOrEqual_1() {
+ initializeVarsForTablet(isGestureMode = false)
+ windowBounds = WindowBounds(Rect(0, 0, 1800, 2560), Rect(0, 104, 0, 0))
+
+ val numShownHotseatIcons = listOf(-1, 0, 1)
+ for (numHotseatIcons in numShownHotseatIcons) {
+ inv?.numShownHotseatIcons = numHotseatIcons
+
+ val dp = newDP()
+ dp.isTaskbarPresentInApps = true
+
+ assertThat(dp.numShownHotseatIcons).isEqualTo(numHotseatIcons)
+ assertThat(dp.hotseatBorderSpace).isEqualTo(0)
+
+ assertThat(dp.getHotseatLayoutPadding(context).left).isEqualTo(177)
+ assertThat(dp.getHotseatLayoutPadding(context).right).isEqualTo(177)
+ assertThat(dp.hotseatQsbWidth).isEqualTo(1445)
+ }
+ }
}
diff --git a/tests/src/com/android/launcher3/popup/PopupPopulatorTest.java b/tests/src/com/android/launcher3/popup/PopupPopulatorTest.java
index 6764e09..f3eb0a9 100644
--- a/tests/src/com/android/launcher3/popup/PopupPopulatorTest.java
+++ b/tests/src/com/android/launcher3/popup/PopupPopulatorTest.java
@@ -64,34 +64,14 @@
MAX_SHORTCUTS - NUM_DYNAMIC, NUM_DYNAMIC);
}
- @Test
- public void testDeDupeShortcutId() {
- // Successfully remove one of the shortcuts
- filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(3, 0), 2, 0, generateId(true, 1));
- filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(0, 3), 0, 2, generateId(false, 1));
- filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(2, 2), 2, 1, generateId(false, 1));
- filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(2, 2), 1, 2, generateId(true, 1));
- // Successfully keep all shortcuts when id doesn't exist
- filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(3, 0), 3, 0, generateId(false, 1));
- filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(3, 0), 3, 0, generateId(true, 4));
- filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(2, 2), 2, 2, generateId(false, 4));
- filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(2, 2), 2, 2, generateId(true, 4));
- }
-
private String generateId(boolean isStatic, int rank) {
return (isStatic ? "static" : "dynamic") + rank;
}
private void filterShortcutsAndAssertNumStaticAndDynamic(
List<ShortcutInfo> shortcuts, int expectedStatic, int expectedDynamic) {
- filterShortcutsAndAssertNumStaticAndDynamic(shortcuts, expectedStatic, expectedDynamic, null);
- }
-
- private void filterShortcutsAndAssertNumStaticAndDynamic(List<ShortcutInfo> shortcuts,
- int expectedStatic, int expectedDynamic, String shortcutIdToRemove) {
Collections.shuffle(shortcuts);
- List<ShortcutInfo> filteredShortcuts = PopupPopulator.sortAndFilterShortcuts(
- shortcuts, shortcutIdToRemove);
+ List<ShortcutInfo> filteredShortcuts = PopupPopulator.sortAndFilterShortcuts(shortcuts);
assertIsSorted(filteredShortcuts);
int numStatic = 0;
diff --git a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
index 73bb586..a21c9b9 100644
--- a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
+++ b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
@@ -19,17 +19,30 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static com.android.launcher3.LauncherPrefs.APP_WIDGET_IDS;
+import static com.android.launcher3.LauncherPrefs.OLD_APP_WIDGET_IDS;
+import static com.android.launcher3.LauncherPrefs.RESTORE_DEVICE;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
+import static com.android.launcher3.widget.LauncherWidgetHolder.APPWIDGET_HOST_ID;
+
+import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
import android.app.backup.BackupManager;
+import android.appwidget.AppWidgetHost;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
@@ -43,6 +56,7 @@
import androidx.test.filters.SmallTest;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.model.ModelDbController;
@@ -52,6 +66,10 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+import java.util.Arrays;
+import java.util.stream.IntStream;
/**
* Tests for {@link RestoreDbTask}
@@ -66,16 +84,27 @@
private LauncherModelHelper mModelHelper;
private Context mContext;
+ private RestoreDbTask mTask;
+ private ModelDbController mMockController;
+ private SQLiteDatabase mMockDb;
+ private Cursor mMockCursor;
+ private LauncherPrefs mPrefs;
@Before
public void setup() {
mModelHelper = new LauncherModelHelper();
mContext = mModelHelper.sandboxContext;
+ mTask = new RestoreDbTask();
+ mMockController = Mockito.mock(ModelDbController.class);
+ mMockDb = mock(SQLiteDatabase.class);
+ mMockCursor = mock(Cursor.class);
+ mPrefs = new LauncherPrefs(mContext);
}
@After
public void teardown() {
mModelHelper.destroy();
+ LauncherPrefs.get(mContext).removeSync(RESTORE_DEVICE);
}
@Test
@@ -148,8 +177,7 @@
assertEquals(10, getItemCountForProfile(db, myProfileId_old));
assertEquals(6, getItemCountForProfile(db, workProfileId_old));
- RestoreDbTask task = new RestoreDbTask();
- task.sanitizeDB(mContext, controller, controller.getDb(), bm);
+ mTask.sanitizeDB(mContext, controller, controller.getDb(), bm);
// All the data has been migrated to the new user ids
assertEquals(0, getItemCountForProfile(db, myProfileId_old));
@@ -178,8 +206,7 @@
assertEquals(10, getItemCountForProfile(db, myProfileId_old));
assertEquals(6, getItemCountForProfile(db, workProfileId_old));
- RestoreDbTask task = new RestoreDbTask();
- task.sanitizeDB(mContext, controller, controller.getDb(), bm);
+ mTask.sanitizeDB(mContext, controller, controller.getDb(), bm);
// All the data has been migrated to the new user ids
assertEquals(0, getItemCountForProfile(db, myProfileId_old));
@@ -188,6 +215,83 @@
assertEquals(10, getCount(db, "select * from favorites"));
}
+ @Test
+ public void givenLauncherPrefsHasNoIds_whenRestoreAppWidgetIdsIfExists_thenIdsAreRemoved() {
+ // When
+ mTask.restoreAppWidgetIdsIfExists(mContext, mMockController);
+ // Then
+ assertThat(mPrefs.has(OLD_APP_WIDGET_IDS, APP_WIDGET_IDS)).isFalse();
+ }
+
+ @Test
+ public void givenNoPendingRestore_WhenRestoreAppWidgetIds_ThenRemoveNewWidgetIds() {
+ // Given
+ AppWidgetHost expectedHost = new AppWidgetHost(mContext, APPWIDGET_HOST_ID);
+ int[] expectedOldIds = generateOldWidgetIds(expectedHost);
+ int[] expectedNewIds = generateNewWidgetIds(expectedHost, expectedOldIds);
+ when(mMockController.getDb()).thenReturn(mMockDb);
+ mPrefs.remove(RESTORE_DEVICE);
+
+ // When
+ RestoreDbTask.setRestoredAppWidgetIds(mContext, expectedOldIds, expectedNewIds);
+ mTask.restoreAppWidgetIdsIfExists(mContext, mMockController);
+
+ // Then
+ assertThat(expectedHost.getAppWidgetIds()).isEqualTo(expectedOldIds);
+ assertThat(mPrefs.has(OLD_APP_WIDGET_IDS, APP_WIDGET_IDS)).isFalse();
+ verifyZeroInteractions(mMockController);
+ }
+
+ @Test
+ public void givenRestoreWithNonExistingWidgets_WhenRestoreAppWidgetIds_ThenRemoveNewIds() {
+ // Given
+ AppWidgetHost expectedHost = new AppWidgetHost(mContext, APPWIDGET_HOST_ID);
+ int[] expectedOldIds = generateOldWidgetIds(expectedHost);
+ int[] expectedNewIds = generateNewWidgetIds(expectedHost, expectedOldIds);
+ when(mMockController.getDb()).thenReturn(mMockDb);
+ when(mMockDb.query(any(), any(), any(), any(), any(), any(), any())).thenReturn(
+ mMockCursor);
+ when(mMockCursor.moveToFirst()).thenReturn(false);
+ RestoreDbTask.setPending(mContext);
+
+ // When
+ RestoreDbTask.setRestoredAppWidgetIds(mContext, expectedOldIds, expectedNewIds);
+ mTask.restoreAppWidgetIdsIfExists(mContext, mMockController);
+
+ // Then
+ assertThat(expectedHost.getAppWidgetIds()).isEqualTo(expectedOldIds);
+ assertThat(mPrefs.has(OLD_APP_WIDGET_IDS, APP_WIDGET_IDS)).isFalse();
+ verify(mMockController, times(expectedOldIds.length)).update(any(), any(), any(), any());
+ }
+
+ @Test
+ public void givenRestore_WhenRestoreAppWidgetIds_ThenAddNewIds() {
+ // Given
+ AppWidgetHost expectedHost = new AppWidgetHost(mContext, APPWIDGET_HOST_ID);
+ int[] expectedOldIds = generateOldWidgetIds(expectedHost);
+ int[] expectedNewIds = generateNewWidgetIds(expectedHost, expectedOldIds);
+ int[] allExpectedIds = IntStream.concat(
+ Arrays.stream(expectedOldIds),
+ Arrays.stream(expectedNewIds)
+ ).toArray();
+
+ when(mMockController.getDb()).thenReturn(mMockDb);
+ when(mMockDb.query(any(), any(), any(), any(), any(), any(), any()))
+ .thenReturn(mMockCursor);
+ when(mMockCursor.moveToFirst()).thenReturn(true);
+ when(mMockCursor.isAfterLast()).thenReturn(true);
+ RestoreDbTask.setPending(mContext);
+
+ // When
+ RestoreDbTask.setRestoredAppWidgetIds(mContext, expectedOldIds, expectedNewIds);
+ mTask.restoreAppWidgetIdsIfExists(mContext, mMockController);
+
+ // Then
+ assertThat(expectedHost.getAppWidgetIds()).isEqualTo(allExpectedIds);
+ assertThat(mPrefs.has(OLD_APP_WIDGET_IDS, APP_WIDGET_IDS)).isFalse();
+ verify(mMockController, times(expectedOldIds.length)).update(any(), any(), any(), any());
+ }
+
private void addIconsBulk(MyModelDbController controller,
int count, int screen, long profileId) {
int columns = LauncherAppState.getIDP(mContext).numColumns;
@@ -270,6 +374,19 @@
}
}
+ private int[] generateOldWidgetIds(AppWidgetHost host) {
+ // generate some widget ids in case there are none
+ host.allocateAppWidgetId();
+ host.allocateAppWidgetId();
+ return host.getAppWidgetIds();
+ }
+
+ private int[] generateNewWidgetIds(AppWidgetHost host, int[] oldWidgetIds) {
+ // map as many new ids as old ids
+ return Arrays.stream(oldWidgetIds)
+ .map(id -> host.allocateAppWidgetId()).toArray();
+ }
+
private class MyModelDbController extends ModelDbController {
public final LongSparseArray<UserHandle> users = new LongSparseArray<>();
diff --git a/tests/src/com/android/launcher3/responsive/AllAppsSpecsTest.kt b/tests/src/com/android/launcher3/responsive/AllAppsSpecsTest.kt
new file mode 100644
index 0000000..cd95e99
--- /dev/null
+++ b/tests/src/com/android/launcher3/responsive/AllAppsSpecsTest.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.responsive
+
+import android.content.Context
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.tests.R as TestR
+import com.android.launcher3.util.TestResourceHelper
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class AllAppsSpecsTest : AbstractDeviceProfileTest() {
+ override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
+
+ @Before
+ fun setup() {
+ initializeVarsForPhone(deviceSpecs["phone"]!!)
+ }
+
+ @Test
+ fun parseValidFile() {
+ val allAppsSpecs =
+ AllAppsSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_all_apps_file))
+ assertThat(allAppsSpecs.heightSpecs.size).isEqualTo(1)
+ assertThat(allAppsSpecs.heightSpecs[0].toString())
+ .isEqualTo(
+ "AllAppsSpec(" +
+ "maxAvailableSize=26247, " +
+ "specType=HEIGHT, " +
+ "startPadding=SizeSpec(fixedSize=0.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
+ "endPadding=SizeSpec(fixedSize=0.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
+ "gutter=SizeSpec(fixedSize=0.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=true, " +
+ "maxSize=2147483647), " +
+ "cellSize=SizeSpec(fixedSize=0.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=true, " +
+ "maxSize=2147483647)" +
+ ")"
+ )
+
+ assertThat(allAppsSpecs.widthSpecs.size).isEqualTo(1)
+ assertThat(allAppsSpecs.widthSpecs[0].toString())
+ .isEqualTo(
+ "AllAppsSpec(" +
+ "maxAvailableSize=26247, " +
+ "specType=WIDTH, " +
+ "startPadding=SizeSpec(fixedSize=0.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=true, " +
+ "maxSize=2147483647), " +
+ "endPadding=SizeSpec(fixedSize=0.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=true, " +
+ "maxSize=2147483647), " +
+ "gutter=SizeSpec(fixedSize=0.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=true, " +
+ "maxSize=2147483647), " +
+ "cellSize=SizeSpec(fixedSize=0.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=true, " +
+ "maxSize=2147483647)" +
+ ")"
+ )
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_missingTag_throwsError() {
+ AllAppsSpecs.create(TestResourceHelper(context!!, TestR.xml.invalid_all_apps_file_case_1))
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_moreThanOneValuePerTag_throwsError() {
+ AllAppsSpecs.create(TestResourceHelper(context!!, TestR.xml.invalid_all_apps_file_case_2))
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_valueBiggerThan1_throwsError() {
+ AllAppsSpecs.create(TestResourceHelper(context!!, TestR.xml.invalid_all_apps_file_case_3))
+ }
+}
diff --git a/tests/src/com/android/launcher3/responsive/CalculatedAllAppsSpecTest.kt b/tests/src/com/android/launcher3/responsive/CalculatedAllAppsSpecTest.kt
new file mode 100644
index 0000000..0f12e58
--- /dev/null
+++ b/tests/src/com/android/launcher3/responsive/CalculatedAllAppsSpecTest.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.responsive
+
+import android.content.Context
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.tests.R as TestR
+import com.android.launcher3.util.TestResourceHelper
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CalculatedAllAppsSpecTest : AbstractDeviceProfileTest() {
+ override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
+
+ /**
+ * This test tests:
+ * - (height spec) copy values from workspace
+ * - (width spec) copy values from workspace
+ */
+ @Test
+ fun normalPhone_copiesFromWorkspace() {
+ val deviceSpec = deviceSpecs["phone"]!!
+ initializeVarsForPhone(deviceSpec)
+
+ val availableWidth = deviceSpec.naturalSize.first
+ // Hotseat size is roughly 495px on a real device,
+ // it doesn't need to be precise on unit tests
+ val availableHeight = deviceSpec.naturalSize.second - deviceSpec.statusBarNaturalPx - 495
+
+ val workspaceSpecs =
+ WorkspaceSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_workspace_file))
+ val widthSpec = workspaceSpecs.getCalculatedWidthSpec(4, availableWidth)
+ val heightSpec = workspaceSpecs.getCalculatedHeightSpec(5, availableHeight)
+
+ val allAppsSpecs =
+ AllAppsSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_all_apps_file))
+
+ with(allAppsSpecs.getCalculatedWidthSpec(4, availableWidth, widthSpec)) {
+ assertThat(availableSpace).isEqualTo(availableWidth)
+ assertThat(cells).isEqualTo(4)
+ assertThat(startPaddingPx).isEqualTo(widthSpec.startPaddingPx)
+ assertThat(endPaddingPx).isEqualTo(widthSpec.endPaddingPx)
+ assertThat(gutterPx).isEqualTo(widthSpec.gutterPx)
+ assertThat(cellSizePx).isEqualTo(widthSpec.cellSizePx)
+ }
+
+ with(allAppsSpecs.getCalculatedHeightSpec(5, availableHeight, heightSpec)) {
+ assertThat(availableSpace).isEqualTo(availableHeight)
+ assertThat(cells).isEqualTo(5)
+ assertThat(startPaddingPx).isEqualTo(0)
+ assertThat(endPaddingPx).isEqualTo(0)
+ assertThat(gutterPx).isEqualTo(heightSpec.gutterPx)
+ assertThat(cellSizePx).isEqualTo(heightSpec.cellSizePx)
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/responsive/CalculatedFolderSpecsTest.kt b/tests/src/com/android/launcher3/responsive/CalculatedFolderSpecsTest.kt
new file mode 100644
index 0000000..f2a269a
--- /dev/null
+++ b/tests/src/com/android/launcher3/responsive/CalculatedFolderSpecsTest.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.responsive
+
+import android.content.Context
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.tests.R
+import com.android.launcher3.util.TestResourceHelper
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CalculatedFolderSpecsTest : AbstractDeviceProfileTest() {
+ override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
+
+ private val deviceSpec = deviceSpecs["phone"]!!
+
+ @Before
+ fun setup() {
+ initializeVarsForPhone(deviceSpec)
+ }
+
+ @Test
+ fun validate_matchWidthWorkspace() {
+ val columns = 6
+
+ // Loading workspace specs
+ val resourceHelperWorkspace = TestResourceHelper(context!!, R.xml.valid_workspace_file)
+ val workspaceSpecs = WorkspaceSpecs.create(resourceHelperWorkspace)
+
+ // Loading folders specs
+ val resourceHelperFolder = TestResourceHelper(context!!, R.xml.valid_folders_specs)
+ val folderSpecs = FolderSpecs.create(resourceHelperFolder)
+
+ assertThat(folderSpecs.widthSpecs.size).isEqualTo(2)
+ assertThat(folderSpecs.widthSpecs[0].cellSize.matchWorkspace).isEqualTo(true)
+ assertThat(folderSpecs.widthSpecs[1].cellSize.matchWorkspace).isEqualTo(false)
+
+ // Validate width spec <= 800
+ var availableWidth = deviceSpec.naturalSize.first
+ var calculatedWorkspace = workspaceSpecs.getCalculatedWidthSpec(columns, availableWidth)
+ var calculatedWidthFolderSpec =
+ folderSpecs.getCalculatedWidthSpec(columns, availableWidth, calculatedWorkspace)
+ with(calculatedWidthFolderSpec) {
+ assertThat(availableSpace).isEqualTo(availableWidth)
+ assertThat(cells).isEqualTo(columns)
+ assertThat(startPaddingPx).isEqualTo(16.dpToPx())
+ assertThat(endPaddingPx).isEqualTo(16.dpToPx())
+ assertThat(gutterPx).isEqualTo(16.dpToPx())
+ assertThat(cellSizePx).isEqualTo(calculatedWorkspace.cellSizePx)
+ }
+
+ // Validate width spec > 800
+ availableWidth = 2000.dpToPx()
+ calculatedWorkspace = workspaceSpecs.getCalculatedWidthSpec(columns, availableWidth)
+ calculatedWidthFolderSpec =
+ folderSpecs.getCalculatedWidthSpec(columns, availableWidth, calculatedWorkspace)
+ with(calculatedWidthFolderSpec) {
+ assertThat(availableSpace).isEqualTo(availableWidth)
+ assertThat(cells).isEqualTo(columns)
+ assertThat(startPaddingPx).isEqualTo(16.dpToPx())
+ assertThat(endPaddingPx).isEqualTo(16.dpToPx())
+ assertThat(gutterPx).isEqualTo(16.dpToPx())
+ assertThat(cellSizePx).isEqualTo(102.dpToPx())
+ }
+ }
+
+ @Test
+ fun validate_matchHeightWorkspace() {
+ // Hotseat is roughly 495px on a real device, it doesn't need to be precise on unit tests
+ val hotseatSize = 495
+ val statusBarHeight = deviceSpec.statusBarNaturalPx
+ val availableHeight = deviceSpec.naturalSize.second - statusBarHeight - hotseatSize
+ val rows = 5
+
+ // Loading workspace specs
+ val resourceHelperWorkspace = TestResourceHelper(context!!, R.xml.valid_workspace_file)
+ val workspaceSpecs = WorkspaceSpecs.create(resourceHelperWorkspace)
+
+ // Loading folders specs
+ val resourceHelperFolder = TestResourceHelper(context!!, R.xml.valid_folders_specs)
+ val folderSpecs = FolderSpecs.create(resourceHelperFolder)
+
+ assertThat(folderSpecs.heightSpecs.size).isEqualTo(1)
+ assertThat(folderSpecs.heightSpecs[0].cellSize.matchWorkspace).isEqualTo(true)
+
+ // Validate height spec
+ val calculatedWorkspace = workspaceSpecs.getCalculatedHeightSpec(rows, availableHeight)
+ val calculatedFolderSpec =
+ folderSpecs.getCalculatedHeightSpec(rows, availableHeight, calculatedWorkspace)
+ with(calculatedFolderSpec) {
+ assertThat(availableSpace).isEqualTo(availableHeight)
+ assertThat(cells).isEqualTo(rows)
+ assertThat(startPaddingPx).isEqualTo(24.dpToPx())
+ assertThat(endPaddingPx).isEqualTo(64.dpToPx())
+ assertThat(gutterPx).isEqualTo(16.dpToPx())
+ assertThat(cellSizePx).isEqualTo(calculatedWorkspace.cellSizePx)
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt b/tests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt
new file mode 100644
index 0000000..5865036
--- /dev/null
+++ b/tests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.responsive
+
+import android.content.Context
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.tests.R as TestR
+import com.android.launcher3.util.TestResourceHelper
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CalculatedHotseatSpecTest : AbstractDeviceProfileTest() {
+ override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
+
+ /**
+ * This test tests:
+ * - (height spec) gets the correct breakpoint from the XML - skips the first breakpoint
+ */
+ @Test
+ fun normalPhone_returnsSecondBreakpointSpec() {
+ val deviceSpec = deviceSpecs["phone"]!!
+ initializeVarsForPhone(deviceSpec)
+
+ // Hotseat uses the whole device height
+ val availableHeight = deviceSpec.naturalSize.second
+
+ val hotseatSpecs =
+ HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_hotseat_file))
+ val heightSpec = hotseatSpecs.getCalculatedHeightSpec(availableHeight)
+
+ assertThat(heightSpec.availableSpace).isEqualTo(availableHeight)
+ assertThat(heightSpec.hotseatQsbSpace).isEqualTo(95)
+ assertThat(heightSpec.edgePadding).isEqualTo(126)
+ }
+
+ /**
+ * This test tests:
+ * - (height spec) gets the correct breakpoint from the XML - use the first breakpoint
+ */
+ @Test
+ fun smallPhone_returnsFirstBreakpointSpec() {
+ val deviceSpec = deviceSpecs["phone"]!!
+ deviceSpec.densityDpi = 540 // larger display size
+ initializeVarsForPhone(deviceSpec)
+
+ // Hotseat uses the whole device height
+ val availableHeight = deviceSpec.naturalSize.second
+
+ val hotseatSpecs =
+ HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_hotseat_file))
+ val heightSpec = hotseatSpecs.getCalculatedHeightSpec(availableHeight)
+
+ assertThat(heightSpec.availableSpace).isEqualTo(availableHeight)
+ assertThat(heightSpec.hotseatQsbSpace).isEqualTo(81)
+ assertThat(heightSpec.edgePadding).isEqualTo(162)
+ }
+
+ /**
+ * This test tests:
+ * - (width spec) gets the correct breakpoint from the XML - skips the first breakpoint
+ */
+ @Test
+ fun normalPhoneLandscape_returnsSecondBreakpointSpec() {
+ val deviceSpec = deviceSpecs["phone"]!!
+ initializeVarsForPhone(deviceSpec, isVerticalBar = true)
+
+ // Hotseat uses the whole device width
+ val availableWidth = deviceSpec.naturalSize.second
+
+ val hotseatSpecs =
+ HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_hotseat_land_file))
+ val widthSpec = hotseatSpecs.getCalculatedWidthSpec(availableWidth)
+
+ assertThat(widthSpec.availableSpace).isEqualTo(availableWidth)
+ assertThat(widthSpec.hotseatQsbSpace).isEqualTo(0)
+ assertThat(widthSpec.edgePadding).isEqualTo(168)
+ }
+}
diff --git a/tests/src/com/android/launcher3/workspace/CalculatedWorkspaceSpecTest.kt b/tests/src/com/android/launcher3/responsive/CalculatedWorkspaceSpecTest.kt
similarity index 68%
rename from tests/src/com/android/launcher3/workspace/CalculatedWorkspaceSpecTest.kt
rename to tests/src/com/android/launcher3/responsive/CalculatedWorkspaceSpecTest.kt
index 7f03ba2..8f56c5f 100644
--- a/tests/src/com/android/launcher3/workspace/CalculatedWorkspaceSpecTest.kt
+++ b/tests/src/com/android/launcher3/responsive/CalculatedWorkspaceSpecTest.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.launcher3.workspace
+package com.android.launcher3.responsive
import android.content.Context
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -49,7 +49,7 @@
val availableHeight = deviceSpec.naturalSize.second - deviceSpec.statusBarNaturalPx - 495
val workspaceSpecs =
- WorkspaceSpecs(TestResourceHelper(context!!, TestR.xml.valid_workspace_file))
+ WorkspaceSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_workspace_file))
val widthSpec = workspaceSpecs.getCalculatedWidthSpec(4, availableWidth)
val heightSpec = workspaceSpecs.getCalculatedHeightSpec(5, availableHeight)
@@ -86,7 +86,46 @@
val availableHeight = deviceSpec.naturalSize.second - deviceSpec.statusBarNaturalPx - 640
val workspaceSpecs =
- WorkspaceSpecs(TestResourceHelper(context!!, TestR.xml.valid_workspace_file))
+ WorkspaceSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_workspace_file))
+ val widthSpec = workspaceSpecs.getCalculatedWidthSpec(4, availableWidth)
+ val heightSpec = workspaceSpecs.getCalculatedHeightSpec(5, availableHeight)
+
+ assertThat(widthSpec.availableSpace).isEqualTo(availableWidth)
+ assertThat(widthSpec.cells).isEqualTo(4)
+ assertThat(widthSpec.startPaddingPx).isEqualTo(74)
+ assertThat(widthSpec.endPaddingPx).isEqualTo(74)
+ assertThat(widthSpec.gutterPx).isEqualTo(54)
+ assertThat(widthSpec.cellSizePx).isEqualTo(193)
+
+ assertThat(heightSpec.availableSpace).isEqualTo(availableHeight)
+ assertThat(heightSpec.cells).isEqualTo(5)
+ assertThat(heightSpec.startPaddingPx).isEqualTo(0)
+ assertThat(heightSpec.endPaddingPx).isEqualTo(108)
+ assertThat(heightSpec.gutterPx).isEqualTo(54)
+ assertThat(heightSpec.cellSizePx).isEqualTo(260)
+ }
+
+ /**
+ * This test tests:
+ * - (height spec) gets the correct breakpoint from the XML - use the first breakpoint
+ * - (height spec) do the correct calculations for remainder space and fixed size
+ * - (width spec) do the correct calculations for remainder space and fixed size
+ */
+ @Test
+ fun smallPhone_returnsFirstBreakpointSpec_unsortedFile() {
+ val deviceSpec = deviceSpecs["phone"]!!
+ deviceSpec.densityDpi = 540 // larger display size
+ initializeVarsForPhone(deviceSpec)
+
+ val availableWidth = deviceSpec.naturalSize.first
+ // Hotseat size is roughly 640px on a real device,
+ // it doesn't need to be precise on unit tests
+ val availableHeight = deviceSpec.naturalSize.second - deviceSpec.statusBarNaturalPx - 640
+
+ val workspaceSpecs =
+ WorkspaceSpecs.create(
+ TestResourceHelper(context!!, TestR.xml.valid_workspace_unsorted_file)
+ )
val widthSpec = workspaceSpecs.getCalculatedWidthSpec(4, availableWidth)
val heightSpec = workspaceSpecs.getCalculatedHeightSpec(5, availableHeight)
diff --git a/tests/src/com/android/launcher3/responsive/FolderSpecsTest.kt b/tests/src/com/android/launcher3/responsive/FolderSpecsTest.kt
new file mode 100644
index 0000000..4b05949
--- /dev/null
+++ b/tests/src/com/android/launcher3/responsive/FolderSpecsTest.kt
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.responsive
+
+import android.content.Context
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.responsive.ResponsiveSpec.SpecType
+import com.android.launcher3.tests.R
+import com.android.launcher3.util.TestResourceHelper
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class FolderSpecsTest : AbstractDeviceProfileTest() {
+ override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
+
+ @Before
+ fun setup() {
+ initializeVarsForPhone(deviceSpecs["tablet"]!!)
+ }
+
+ @Test
+ fun parseValidFile() {
+ val resourceHelper = TestResourceHelper(context!!, R.xml.valid_folders_specs)
+ val folderSpecs = FolderSpecs.create(resourceHelper)
+
+ val sizeSpec16 = SizeSpec(16f.dpToPx())
+ val widthSpecsExpected =
+ listOf(
+ FolderSpec(
+ maxAvailableSize = 800.dpToPx(),
+ specType = SpecType.WIDTH,
+ startPadding = sizeSpec16,
+ endPadding = sizeSpec16,
+ gutter = sizeSpec16,
+ cellSize = SizeSpec(matchWorkspace = true)
+ ),
+ FolderSpec(
+ maxAvailableSize = 9999.dpToPx(),
+ specType = SpecType.WIDTH,
+ startPadding = sizeSpec16,
+ endPadding = sizeSpec16,
+ gutter = sizeSpec16,
+ cellSize = SizeSpec(102f.dpToPx())
+ )
+ )
+
+ val heightSpecsExpected =
+ FolderSpec(
+ maxAvailableSize = 9999.dpToPx(),
+ specType = SpecType.HEIGHT,
+ startPadding = SizeSpec(24f.dpToPx()),
+ endPadding = SizeSpec(64f.dpToPx()),
+ gutter = sizeSpec16,
+ cellSize = SizeSpec(matchWorkspace = true)
+ )
+
+ assertThat(folderSpecs.widthSpecs.size).isEqualTo(widthSpecsExpected.size)
+ assertThat(folderSpecs.widthSpecs[0]).isEqualTo(widthSpecsExpected[0])
+ assertThat(folderSpecs.widthSpecs[1]).isEqualTo(widthSpecsExpected[1])
+
+ assertThat(folderSpecs.heightSpecs.size).isEqualTo(1)
+ assertThat(folderSpecs.heightSpecs[0]).isEqualTo(heightSpecsExpected)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_missingTag_throwsError() {
+ val resourceHelper = TestResourceHelper(context!!, R.xml.invalid_folders_specs_1)
+ FolderSpecs.create(resourceHelper)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_moreThanOneValuePerTag_throwsError() {
+ val resourceHelper = TestResourceHelper(context!!, R.xml.invalid_folders_specs_2)
+ FolderSpecs.create(resourceHelper)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_valueBiggerThan1_throwsError() {
+ val resourceHelper = TestResourceHelper(context!!, R.xml.invalid_folders_specs_3)
+ FolderSpecs.create(resourceHelper)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_missingSpecs_throwsError() {
+ val resourceHelper = TestResourceHelper(context!!, R.xml.invalid_folders_specs_4)
+ FolderSpecs.create(resourceHelper)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_missingWidthBreakpoint_throwsError() {
+ val availableSpace = 900.dpToPx()
+ val cells = 3
+
+ val workspaceSpec =
+ WorkspaceSpec(
+ maxAvailableSize = availableSpace,
+ specType = SpecType.WIDTH,
+ startPadding = SizeSpec(fixedSize = 10f),
+ endPadding = SizeSpec(fixedSize = 10f),
+ gutter = SizeSpec(fixedSize = 10f),
+ cellSize = SizeSpec(fixedSize = 10f)
+ )
+ val calculatedWorkspaceSpec = CalculatedWorkspaceSpec(availableSpace, cells, workspaceSpec)
+
+ val resourceHelper = TestResourceHelper(context!!, R.xml.invalid_folders_specs_5)
+ val folderSpecs = FolderSpecs.create(resourceHelper)
+ folderSpecs.getCalculatedWidthSpec(cells, availableSpace, calculatedWorkspaceSpec)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_missingHeightBreakpoint_throwsError() {
+ val availableSpace = 900.dpToPx()
+ val cells = 3
+
+ val workspaceSpec =
+ WorkspaceSpec(
+ maxAvailableSize = availableSpace,
+ specType = SpecType.HEIGHT,
+ startPadding = SizeSpec(fixedSize = 10f),
+ endPadding = SizeSpec(fixedSize = 10f),
+ gutter = SizeSpec(fixedSize = 10f),
+ cellSize = SizeSpec(fixedSize = 10f)
+ )
+ val calculatedWorkspaceSpec = CalculatedWorkspaceSpec(availableSpace, cells, workspaceSpec)
+
+ val resourceHelper = TestResourceHelper(context!!, R.xml.invalid_folders_specs_5)
+ val folderSpecs = FolderSpecs.create(resourceHelper)
+ folderSpecs.getCalculatedHeightSpec(cells, availableSpace, calculatedWorkspaceSpec)
+ }
+
+ @Test
+ fun retrievesCalculatedWidthSpec() {
+ val availableSpace = 800.dpToPx()
+ val cells = 3
+
+ val workspaceSpec =
+ WorkspaceSpec(
+ maxAvailableSize = availableSpace,
+ specType = SpecType.WIDTH,
+ startPadding = SizeSpec(fixedSize = 10f),
+ endPadding = SizeSpec(fixedSize = 10f),
+ gutter = SizeSpec(fixedSize = 10f),
+ cellSize = SizeSpec(fixedSize = 10f)
+ )
+ val calculatedWorkspaceSpec = CalculatedWorkspaceSpec(availableSpace, cells, workspaceSpec)
+
+ val resourceHelper = TestResourceHelper(context!!, R.xml.valid_folders_specs)
+ val folderSpecs = FolderSpecs.create(resourceHelper)
+ val calculatedWidthSpec =
+ folderSpecs.getCalculatedWidthSpec(cells, availableSpace, calculatedWorkspaceSpec)
+
+ assertThat(calculatedWidthSpec.cells).isEqualTo(cells)
+ assertThat(calculatedWidthSpec.availableSpace).isEqualTo(availableSpace)
+ assertThat(calculatedWidthSpec.startPaddingPx).isEqualTo(16.dpToPx())
+ assertThat(calculatedWidthSpec.endPaddingPx).isEqualTo(16.dpToPx())
+ assertThat(calculatedWidthSpec.gutterPx).isEqualTo(16.dpToPx())
+ assertThat(calculatedWidthSpec.cellSizePx).isEqualTo(calculatedWorkspaceSpec.cellSizePx)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun retrievesCalculatedWidthSpec_invalidCalculatedWorkspaceSpecType_throwsError() {
+ val availableSpace = 10.dpToPx()
+ val cells = 3
+
+ val workspaceSpec =
+ WorkspaceSpec(
+ maxAvailableSize = availableSpace,
+ specType = SpecType.HEIGHT,
+ startPadding = SizeSpec(fixedSize = 10f),
+ endPadding = SizeSpec(fixedSize = 10f),
+ gutter = SizeSpec(fixedSize = 10f),
+ cellSize = SizeSpec(fixedSize = 10f)
+ )
+ val calculatedWorkspaceSpec = CalculatedWorkspaceSpec(availableSpace, cells, workspaceSpec)
+
+ val resourceHelper = TestResourceHelper(context!!, R.xml.valid_folders_specs)
+ val folderSpecs = FolderSpecs.create(resourceHelper)
+ folderSpecs.getCalculatedWidthSpec(cells, availableSpace, calculatedWorkspaceSpec)
+ }
+
+ @Test
+ fun retrievesCalculatedHeightSpec() {
+ val availableSpace = 700.dpToPx()
+ val cells = 3
+
+ val workspaceSpec =
+ WorkspaceSpec(
+ maxAvailableSize = availableSpace,
+ specType = SpecType.HEIGHT,
+ startPadding = SizeSpec(fixedSize = 10f),
+ endPadding = SizeSpec(fixedSize = 10f),
+ gutter = SizeSpec(fixedSize = 10f),
+ cellSize = SizeSpec(fixedSize = 10f)
+ )
+ val calculatedWorkspaceSpec = CalculatedWorkspaceSpec(availableSpace, cells, workspaceSpec)
+
+ val resourceHelper = TestResourceHelper(context!!, R.xml.valid_folders_specs)
+ val folderSpecs = FolderSpecs.create(resourceHelper)
+ val calculatedHeightSpec =
+ folderSpecs.getCalculatedHeightSpec(cells, availableSpace, calculatedWorkspaceSpec)
+
+ assertThat(calculatedHeightSpec.cells).isEqualTo(cells)
+ assertThat(calculatedHeightSpec.availableSpace).isEqualTo(availableSpace)
+ assertThat(calculatedHeightSpec.startPaddingPx).isEqualTo(24.dpToPx())
+ assertThat(calculatedHeightSpec.endPaddingPx).isEqualTo(64.dpToPx())
+ assertThat(calculatedHeightSpec.gutterPx).isEqualTo(16.dpToPx())
+ assertThat(calculatedHeightSpec.cellSizePx).isEqualTo(calculatedWorkspaceSpec.cellSizePx)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun retrievesCalculatedHeightSpec_invalidCalculatedWorkspaceSpecType_throwsError() {
+ val availableSpace = 10.dpToPx()
+ val cells = 3
+
+ val workspaceSpec =
+ WorkspaceSpec(
+ maxAvailableSize = availableSpace,
+ specType = SpecType.WIDTH,
+ startPadding = SizeSpec(fixedSize = 10f),
+ endPadding = SizeSpec(fixedSize = 10f),
+ gutter = SizeSpec(fixedSize = 10f),
+ cellSize = SizeSpec(fixedSize = 10f)
+ )
+ val calculatedWorkspaceSpec = CalculatedWorkspaceSpec(availableSpace, cells, workspaceSpec)
+
+ val resourceHelper = TestResourceHelper(context!!, R.xml.valid_folders_specs)
+ val folderSpecs = FolderSpecs.create(resourceHelper)
+ folderSpecs.getCalculatedHeightSpec(cells, availableSpace, calculatedWorkspaceSpec)
+ }
+}
diff --git a/tests/src/com/android/launcher3/responsive/HotseatSpecsTest.kt b/tests/src/com/android/launcher3/responsive/HotseatSpecsTest.kt
new file mode 100644
index 0000000..f650e91
--- /dev/null
+++ b/tests/src/com/android/launcher3/responsive/HotseatSpecsTest.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.responsive
+
+import android.content.Context
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.tests.R as TestR
+import com.android.launcher3.util.TestResourceHelper
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class HotseatSpecsTest : AbstractDeviceProfileTest() {
+ override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
+
+ @Before
+ fun setup() {
+ initializeVarsForPhone(deviceSpecs["phone"]!!)
+ }
+
+ @Test
+ fun parseValidFile() {
+ val hotseatSpecs =
+ HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_hotseat_file))
+
+ val expectedHeightSpecs =
+ listOf(
+ HotseatSpec(
+ maxAvailableSize = 847.dpToPx(),
+ specType = ResponsiveSpec.SpecType.HEIGHT,
+ hotseatQsbSpace = SizeSpec(24f.dpToPx()),
+ edgePadding = SizeSpec(48f.dpToPx())
+ ),
+ HotseatSpec(
+ maxAvailableSize = 9999.dpToPx(),
+ specType = ResponsiveSpec.SpecType.HEIGHT,
+ hotseatQsbSpace = SizeSpec(36f.dpToPx()),
+ edgePadding = SizeSpec(48f.dpToPx())
+ ),
+ )
+
+ assertThat(hotseatSpecs.heightSpecs.size).isEqualTo(expectedHeightSpecs.size)
+ assertThat(hotseatSpecs.heightSpecs[0]).isEqualTo(expectedHeightSpecs[0])
+ assertThat(hotseatSpecs.heightSpecs[1]).isEqualTo(expectedHeightSpecs[1])
+
+ assertThat(hotseatSpecs.widthSpecs.size).isEqualTo(0)
+ }
+
+ @Test
+ fun parseValidLandscapeFile() {
+ val hotseatSpecs =
+ HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_hotseat_land_file))
+ assertThat(hotseatSpecs.heightSpecs.size).isEqualTo(0)
+
+ val expectedWidthSpecs =
+ listOf(
+ HotseatSpec(
+ maxAvailableSize = 743.dpToPx(),
+ specType = ResponsiveSpec.SpecType.WIDTH,
+ hotseatQsbSpace = SizeSpec(0f),
+ edgePadding = SizeSpec(48f.dpToPx())
+ ),
+ HotseatSpec(
+ maxAvailableSize = 9999.dpToPx(),
+ specType = ResponsiveSpec.SpecType.WIDTH,
+ hotseatQsbSpace = SizeSpec(0f),
+ edgePadding = SizeSpec(64f.dpToPx())
+ ),
+ )
+
+ assertThat(hotseatSpecs.widthSpecs.size).isEqualTo(expectedWidthSpecs.size)
+ assertThat(hotseatSpecs.widthSpecs[0]).isEqualTo(expectedWidthSpecs[0])
+ assertThat(hotseatSpecs.widthSpecs[1]).isEqualTo(expectedWidthSpecs[1])
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_spaceIsNotFixedSize_throwsError() {
+ HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.invalid_hotseat_file_case_1))
+ }
+}
diff --git a/tests/src/com/android/launcher3/responsive/SizeSpecTest.kt b/tests/src/com/android/launcher3/responsive/SizeSpecTest.kt
new file mode 100644
index 0000000..8ca07c6
--- /dev/null
+++ b/tests/src/com/android/launcher3/responsive/SizeSpecTest.kt
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.responsive
+
+import android.content.Context
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.AbstractDeviceProfileTest
+import com.google.common.truth.Truth.assertThat
+import kotlin.math.roundToInt
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class SizeSpecTest : AbstractDeviceProfileTest() {
+ override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
+
+ @Before
+ fun setup() {
+ initializeVarsForPhone(deviceSpecs["phone"]!!)
+ }
+
+ @Test
+ fun valid_values() {
+ val combinations =
+ listOf(
+ SizeSpec(100f, 0f, 0f, false),
+ SizeSpec(0f, 1f, 0f, false),
+ SizeSpec(0f, 0f, 1f, false),
+ SizeSpec(0f, 0f, 0f, false),
+ SizeSpec(0f, 0f, 0f, true),
+ SizeSpec(100f, 0f, 0f, false, 100),
+ SizeSpec(0f, 1f, 0f, false, 100),
+ SizeSpec(0f, 0f, 1f, false, 100),
+ SizeSpec(0f, 0f, 0f, false, 100),
+ SizeSpec(0f, 0f, 0f, true, 100)
+ )
+
+ for (instance in combinations) {
+ assertThat(instance.isValid()).isEqualTo(true)
+ }
+ }
+
+ @Test
+ fun validate_getCalculatedValue() {
+ val availableSpace = 100
+ val matchWorkspaceValue = 101
+ val combinations =
+ listOf(
+ SizeSpec(100f) to 100,
+ SizeSpec(ofAvailableSpace = .5f) to (availableSpace * .5f).roundToInt(),
+ SizeSpec(ofRemainderSpace = .5f) to 0,
+ SizeSpec(matchWorkspace = true) to matchWorkspaceValue,
+ // Restricts max size up to 10 (calculated value > 10)
+ SizeSpec(100f, maxSize = 10) to 10,
+ SizeSpec(ofAvailableSpace = .5f, maxSize = 10) to 10,
+ SizeSpec(ofRemainderSpace = .5f, maxSize = 10) to 0,
+ SizeSpec(matchWorkspace = true, maxSize = 10) to 10
+ )
+
+ for ((sizeSpec, expectedValue) in combinations) {
+ val value = sizeSpec.getCalculatedValue(availableSpace, matchWorkspaceValue)
+ assertThat(value).isEqualTo(expectedValue)
+ }
+ }
+
+ @Test
+ fun validate_getRemainderSpaceValue() {
+ val remainderSpace = 100
+ val defaultValue = 50
+ val combinations =
+ listOf(
+ SizeSpec(100f) to defaultValue,
+ SizeSpec(ofAvailableSpace = .5f) to defaultValue,
+ SizeSpec(ofRemainderSpace = .5f) to (remainderSpace * .5f).roundToInt(),
+ SizeSpec(matchWorkspace = true) to defaultValue,
+ // Restricts max size up to 10 (defaultValue > 10)
+ SizeSpec(100f, maxSize = 10) to 10,
+ SizeSpec(ofAvailableSpace = .5f, maxSize = 10) to 10,
+ SizeSpec(ofRemainderSpace = .5f, maxSize = 10) to 10,
+ SizeSpec(matchWorkspace = true, maxSize = 10) to 10,
+ )
+
+ for ((sizeSpec, expectedValue) in combinations) {
+ val value = sizeSpec.getRemainderSpaceValue(remainderSpace, defaultValue)
+ assertThat(value).isEqualTo(expectedValue)
+ }
+ }
+
+ @Test
+ fun multiple_values_assigned() {
+ val combinations =
+ listOf(
+ SizeSpec(1f, 1f, 0f, false),
+ SizeSpec(1f, 0f, 1f, false),
+ SizeSpec(1f, 0f, 0f, true),
+ SizeSpec(0f, 1f, 1f, false),
+ SizeSpec(0f, 1f, 0f, true),
+ SizeSpec(0f, 0f, 1f, true),
+ SizeSpec(1f, 1f, 1f, true)
+ )
+
+ for (instance in combinations) {
+ assertThat(instance.isValid()).isEqualTo(false)
+ }
+ }
+
+ @Test
+ fun invalid_values() {
+ val combinations =
+ listOf(
+ SizeSpec(-1f, 0f, 0f, false),
+ SizeSpec(0f, 1.1f, 0f, false),
+ SizeSpec(0f, -0.1f, 0f, false),
+ SizeSpec(0f, 0f, 1.1f, false),
+ SizeSpec(0f, 0f, -0.1f, false),
+ SizeSpec(0f, 0f, 0f, false, -10),
+ SizeSpec(50f, 0f, 0f, false, 10)
+ )
+
+ for (instance in combinations) {
+ assertThat(instance.isValid()).isEqualTo(false)
+ }
+ }
+
+ @Test
+ fun onlyFixedSize() {
+ assertThat(SizeSpec(fixedSize = 16f).onlyFixedSize()).isEqualTo(true)
+
+ val combinations =
+ listOf(
+ SizeSpec(0f, 1.1f, 0f, false),
+ SizeSpec(0f, 0f, 1.1f, false),
+ SizeSpec(0f, 0f, 0f, true)
+ )
+
+ for (instance in combinations) {
+ assertThat(instance.onlyFixedSize()).isEqualTo(false)
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/responsive/WorkspaceSpecsTest.kt b/tests/src/com/android/launcher3/responsive/WorkspaceSpecsTest.kt
new file mode 100644
index 0000000..0364069
--- /dev/null
+++ b/tests/src/com/android/launcher3/responsive/WorkspaceSpecsTest.kt
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.responsive
+
+import android.content.Context
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.tests.R as TestR
+import com.android.launcher3.util.TestResourceHelper
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class WorkspaceSpecsTest : AbstractDeviceProfileTest() {
+ override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
+
+ @Before
+ fun setup() {
+ initializeVarsForPhone(deviceSpecs["phone"]!!)
+ }
+
+ @Test
+ fun parseValidFile() {
+ val workspaceSpecs =
+ WorkspaceSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_workspace_file))
+ assertThat(workspaceSpecs.heightSpecs.size).isEqualTo(3)
+ assertThat(workspaceSpecs.heightSpecs[0].toString())
+ .isEqualTo(
+ "WorkspaceSpec(" +
+ "maxAvailableSize=1533, " +
+ "specType=HEIGHT, " +
+ "startPadding=SizeSpec(fixedSize=0.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
+ "endPadding=SizeSpec(fixedSize=84.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
+ "gutter=SizeSpec(fixedSize=42.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
+ "cellSize=SizeSpec(fixedSize=0.0, " +
+ "ofAvailableSpace=0.15808, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647)" +
+ ")"
+ )
+ assertThat(workspaceSpecs.heightSpecs[1].toString())
+ .isEqualTo(
+ "WorkspaceSpec(" +
+ "maxAvailableSize=1607, " +
+ "specType=HEIGHT, " +
+ "startPadding=SizeSpec(fixedSize=0.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
+ "endPadding=SizeSpec(fixedSize=0.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=1.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
+ "gutter=SizeSpec(fixedSize=42.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
+ "cellSize=SizeSpec(fixedSize=273.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647)" +
+ ")"
+ )
+ assertThat(workspaceSpecs.heightSpecs[2].toString())
+ .isEqualTo(
+ "WorkspaceSpec(" +
+ "maxAvailableSize=26247, " +
+ "specType=HEIGHT, " +
+ "startPadding=SizeSpec(fixedSize=21.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
+ "endPadding=SizeSpec(fixedSize=0.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=1.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
+ "gutter=SizeSpec(fixedSize=42.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
+ "cellSize=SizeSpec(fixedSize=273.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647)" +
+ ")"
+ )
+ assertThat(workspaceSpecs.widthSpecs.size).isEqualTo(1)
+ assertThat(workspaceSpecs.widthSpecs[0].toString())
+ .isEqualTo(
+ "WorkspaceSpec(" +
+ "maxAvailableSize=26247, " +
+ "specType=WIDTH, " +
+ "startPadding=SizeSpec(fixedSize=58.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
+ "endPadding=SizeSpec(fixedSize=58.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
+ "gutter=SizeSpec(fixedSize=42.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.0, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647), " +
+ "cellSize=SizeSpec(fixedSize=0.0, " +
+ "ofAvailableSpace=0.0, " +
+ "ofRemainderSpace=0.25, " +
+ "matchWorkspace=false, " +
+ "maxSize=2147483647)" +
+ ")"
+ )
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_missingTag_throwsError() {
+ WorkspaceSpecs.create(
+ TestResourceHelper(context!!, TestR.xml.invalid_workspace_file_case_1)
+ )
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_moreThanOneValuePerTag_throwsError() {
+ WorkspaceSpecs.create(
+ TestResourceHelper(context!!, TestR.xml.invalid_workspace_file_case_2)
+ )
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_valueBiggerThan1_throwsError() {
+ WorkspaceSpecs.create(
+ TestResourceHelper(context!!, TestR.xml.invalid_workspace_file_case_3)
+ )
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun parseInvalidFile_matchWorkspace_true_throwsError() {
+ WorkspaceSpecs.create(
+ TestResourceHelper(context!!, TestR.xml.invalid_workspace_file_case_4)
+ )
+ }
+}
diff --git a/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java b/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java
index 7e9d9da..c7431f2 100644
--- a/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java
+++ b/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java
@@ -184,7 +184,7 @@
mStartPoint = icon.getVisibleCenter();
mEndPoint = new Point(mStartPoint.x, mStartPoint.y);
mLauncher.sendPointer(mDownTime, mDownTime, ACTION_DOWN, mStartPoint,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
assertThat(findObjectByResourceName("popup_container")).isNotNull();
return appName;
}
@@ -206,7 +206,7 @@
mStartPoint = icon.getVisibleCenter();
mEndPoint = new Point(mStartPoint.x, mStartPoint.y);
mLauncher.sendPointer(mDownTime, mDownTime, ACTION_DOWN, mStartPoint,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
assertThat(findObjectByResourceName("popup_container")).isNotNull();
return appName;
}
@@ -214,12 +214,12 @@
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);
+ mStartPoint, mEndPoint, LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
}
private void dropApp() {
mLauncher.sendPointer(mDownTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP,
- mEndPoint, LauncherInstrumentation.GestureScope.INSIDE);
+ mEndPoint, LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
}
private void removeAppByName(String appName) {
diff --git a/tests/src/com/android/launcher3/tapl/TaplUtilityTests.java b/tests/src/com/android/launcher3/tapl/TaplUtilityTests.java
new file mode 100644
index 0000000..15db1d8
--- /dev/null
+++ b/tests/src/com/android/launcher3/tapl/TaplUtilityTests.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.tapl;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class TaplUtilityTests {
+
+ @Test
+ public void testNewStringWithRegex() {
+ assertTrue(AppIcon.makeMultilinePattern("Play Store")
+ .matcher("Play Store has 7 notifications").matches());
+ assertTrue(AppIcon.makeMultilinePattern("Play Store")
+ .matcher("Play Store!").matches());
+ assertFalse(AppIcon.makeMultilinePattern("Play Store")
+ .matcher("play store").matches());
+ assertFalse(AppIcon.makeMultilinePattern("Play Store")
+ .matcher("").matches());
+ assertTrue(AppIcon.makeMultilinePattern("Play Store")
+ .matcher("Play \n Store").matches());
+ }
+}
diff --git a/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java b/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
index d3ce67c..81a59b9 100644
--- a/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
+++ b/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
@@ -69,7 +69,10 @@
mView.setBackgroundColor(Color.BLUE);
setContentView(mView);
- registerReceiver(mCommandReceiver, new IntentFilter(mAction + SUFFIX_COMMAND));
+ registerReceiver(
+ mCommandReceiver,
+ new IntentFilter(mAction + SUFFIX_COMMAND),
+ RECEIVER_EXPORTED);
}
protected void addButton(String title, String method) {
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 604fe42..f734fe5 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -16,10 +16,9 @@
package com.android.launcher3.ui;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
-
+import static com.android.launcher3.testing.shared.TestProtocol.ICON_MISSING;
import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -49,11 +48,8 @@
import androidx.test.uiautomator.Until;
import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
-import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.tapl.HomeAllApps;
import com.android.launcher3.tapl.HomeAppIcon;
@@ -64,13 +60,13 @@
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.SimpleBroadcastReceiver;
+import com.android.launcher3.util.TestUtil;
import com.android.launcher3.util.Wait;
-import com.android.launcher3.util.WidgetUtils;
import com.android.launcher3.util.rule.FailureWatcher;
-import com.android.launcher3.util.rule.LauncherActivityRule;
import com.android.launcher3.util.rule.SamplerRule;
import com.android.launcher3.util.rule.ScreenRecordRule;
import com.android.launcher3.util.rule.ShellCommandRule;
+import com.android.launcher3.util.rule.TestIsolationRule;
import com.android.launcher3.util.rule.TestStabilityRule;
import com.android.launcher3.util.rule.ViewCaptureRule;
@@ -82,10 +78,6 @@
import org.junit.rules.TestRule;
import java.io.IOException;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -102,12 +94,12 @@
public static final long DEFAULT_ACTIVITY_TIMEOUT = TimeUnit.SECONDS.toMillis(10);
public static final long DEFAULT_BROADCAST_TIMEOUT_SECS = 5;
- public static final long DEFAULT_UI_TIMEOUT = 10000;
+ public static final long DEFAULT_UI_TIMEOUT = TestUtil.DEFAULT_UI_TIMEOUT;
private static final String TAG = "AbstractLauncherUiTest";
private static boolean sDumpWasGenerated = false;
private static boolean sActivityLeakReported = false;
- private static boolean sSeenKeygard = false;
+ private static boolean sSeenKeyguard = false;
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
@@ -130,6 +122,10 @@
}, DEFAULT_UI_TIMEOUT, launcher);
}
+ public static String getAppPackageName() {
+ return getInstrumentation().getContext().getPackageName();
+ }
+
private static String getActivityLeakErrorMessage(LauncherInstrumentation launcher) {
sActivityLeakReported = true;
return "Activity leak detector has found leaked activities, "
@@ -188,8 +184,6 @@
mLauncher.setOnLauncherCrashed(() -> mLauncherPid = 0);
}
- protected final LauncherActivityRule mActivityMonitor = new LauncherActivityRule();
-
@Rule
public ShellCommandRule mDisableHeadsUpNotification =
ShellCommandRule.disableHeadsUpNotification();
@@ -209,18 +203,14 @@
mTargetContext.unregisterReceiver(broadcastReceiver);
}
- // Annotation for tests that need to be run in portrait and landscape modes.
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.METHOD)
- protected @interface PortraitLandscape {
- }
-
protected TestRule getRulesInsideActivityMonitor() {
- final ViewCaptureRule viewCaptureRule = new ViewCaptureRule();
+ final ViewCaptureRule viewCaptureRule = new ViewCaptureRule(
+ Launcher.ACTIVITY_TRACKER::getCreatedActivity);
final RuleChain inner = RuleChain
.outerRule(new PortraitLandscapeRunner(this))
+ .around(new FailureWatcher(mLauncher, viewCaptureRule::getViewCaptureData))
.around(viewCaptureRule)
- .around(new FailureWatcher(mDevice, mLauncher, viewCaptureRule.getViewCapture()));
+ .around(new TestIsolationRule(mLauncher));
return TestHelpers.isInLauncherProcess()
? RuleChain.outerRule(ShellCommandRule.setDefaultLauncher()).around(inner)
@@ -231,7 +221,6 @@
public TestRule mOrderSensitiveRules = RuleChain
.outerRule(new SamplerRule())
.around(new TestStabilityRule())
- .around(mActivityMonitor)
.around(getRulesInsideActivityMonitor());
public UiDevice getDevice() {
@@ -276,9 +265,9 @@
}
private static void verifyKeyguardInvisible() {
- final boolean keyguardAlreadyVisible = sSeenKeygard;
+ final boolean keyguardAlreadyVisible = sSeenKeyguard;
- sSeenKeygard = sSeenKeygard
+ sSeenKeyguard = sSeenKeyguard
|| !TestHelpers.wait(
Until.gone(By.res(SYSTEMUI_PACKAGE, "keyguard_status_view")), 60000);
@@ -286,7 +275,7 @@
"Keyguard is visible, which is likely caused by a crash in SysUI, seeing keyguard"
+ " for the first time = "
+ !keyguardAlreadyVisible,
- sSeenKeygard);
+ sSeenKeyguard);
}
@After
@@ -303,46 +292,20 @@
}
}
- protected void clearLauncherData() {
- mLauncher.clearLauncherData();
- mLauncher.waitForLauncherInitialized();
+ protected void reinitializeLauncherData() {
+ reinitializeLauncherData(false);
}
- /**
- * Removes all icons from homescreen and hotseat.
- */
- public void clearHomescreen() {
- LauncherSettings.Settings.call(mTargetContext.getContentResolver(),
- LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
- LauncherSettings.Settings.call(mTargetContext.getContentResolver(),
- LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG);
- resetLoaderState();
- }
-
- protected void resetLoaderState() {
- try {
- mMainThreadExecutor.execute(
- () -> LauncherAppState.getInstance(
- mTargetContext).getModel().forceReload());
- } catch (Throwable t) {
- throw new IllegalArgumentException(t);
+ protected void reinitializeLauncherData(boolean clearWorkspace) {
+ if (clearWorkspace) {
+ mLauncher.clearLauncherData();
+ } else {
+ mLauncher.reinitializeLauncherData();
}
mLauncher.waitForLauncherInitialized();
}
/**
- * Adds {@param item} on the homescreen on the 0th screen
- */
- public void addItemToScreen(ItemInfo item) {
- WidgetUtils.addItemToScreen(item, mTargetContext);
- resetLoaderState();
-
- // Launch the home activity
- mDevice.pressHome();
- mLauncher.waitForLauncherInitialized();
- }
-
- /**
* Runs the callback on the UI thread and returns the result.
*/
protected <T> T getOnUiThread(final Callable<T> callback) {
@@ -360,7 +323,7 @@
protected <T> T getFromLauncher(Function<Launcher, T> f) {
if (!TestHelpers.isInLauncherProcess()) return null;
- return getOnUiThread(() -> f.apply(mActivityMonitor.getActivity()));
+ return getOnUiThread(() -> f.apply(Launcher.ACTIVITY_TRACKER.getCreatedActivity()));
}
protected void executeOnLauncher(Consumer<Launcher> f) {
@@ -648,6 +611,8 @@
protected HomeAppIcon createShortcutIfNotExist(String name, int cellX, int cellY) {
HomeAppIcon homeAppIcon = mLauncher.getWorkspace().tryGetWorkspaceAppIcon(name);
+ Log.d(ICON_MISSING, "homeAppIcon: " + homeAppIcon + " name: " + name +
+ " cell: " + cellX + ", " + cellY);
if (homeAppIcon == null) {
HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
allApps.freeze();
diff --git a/tests/src/com/android/launcher3/ui/ActivityAllAppsContainerViewTest.java b/tests/src/com/android/launcher3/ui/ActivityAllAppsContainerViewTest.java
new file mode 100644
index 0000000..ba416ae
--- /dev/null
+++ b/tests/src/com/android/launcher3/ui/ActivityAllAppsContainerViewTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.ui;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static com.android.launcher3.model.data.AppInfo.EMPTY_ARRAY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
+import com.android.launcher3.allapps.WorkProfileManager;
+import com.android.launcher3.logging.StatsLogManager;
+import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.util.ActivityContextWrapper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ActivityAllAppsContainerViewTest {
+
+ private static final UserHandle WORK_HANDLE = new UserHandle(13);
+ @Mock
+ private StatsLogManager mStatsLogManager;
+ private AppInfo[] mWorkAppInfo;
+ private ActivityAllAppsContainerView<?> mActivityAllAppsContainerView;
+ private WorkProfileManager mWorkManager;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ Context context = new ActivityContextWrapper(getApplicationContext());
+ mActivityAllAppsContainerView = new ActivityAllAppsContainerView(context);
+ mWorkManager = new WorkProfileManager(context.getSystemService(UserManager.class),
+ mActivityAllAppsContainerView, mStatsLogManager);
+ mActivityAllAppsContainerView.setWorkManager(mWorkManager);
+ ComponentName componentName = new ComponentName(context,
+ "com.android.launcher3.tests.Activity" + "Gmail");
+ AppInfo gmailWorkAppInfo = new AppInfo(componentName, "Gmail", WORK_HANDLE, new Intent());
+ mWorkAppInfo = new AppInfo[]{gmailWorkAppInfo};
+ }
+
+ @Test
+ public void testOnAppsUpdatedWithoutWorkApps_shouldShowTabsIsFalse() {
+ mActivityAllAppsContainerView.getAppsStore().setApps(EMPTY_ARRAY, 0, null);
+
+ mActivityAllAppsContainerView.onAppsUpdated();
+
+ assertThat(mActivityAllAppsContainerView.shouldShowTabs()).isEqualTo(false);
+ }
+
+ @Test
+ public void testOnAppsUpdatedWithWorkApps_shouldShowTabsIsTrue() {
+ mActivityAllAppsContainerView.getAppsStore().setApps(mWorkAppInfo, 0, null);
+
+ mActivityAllAppsContainerView.onAppsUpdated();
+
+ assertThat(mActivityAllAppsContainerView.shouldShowTabs()).isEqualTo(true);
+ }
+}
diff --git a/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java b/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java
index fdba4eb..bba8c89 100644
--- a/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java
+++ b/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java
@@ -18,6 +18,8 @@
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static com.android.launcher3.BubbleTextView.DISPLAY_ALL_APPS;
+import static com.android.launcher3.BubbleTextView.DISPLAY_PREDICTION_ROW;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TWOLINE_ALLAPPS;
import static org.junit.Assert.assertEquals;
@@ -28,16 +30,21 @@
import android.view.ViewGroup;
import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.Flags;
import com.android.launcher3.Utilities;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.search.StringMatcherUtility;
import com.android.launcher3.util.ActivityContextWrapper;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.TestUtil;
+import com.android.launcher3.util.rule.StaticMockitoRule;
import com.android.launcher3.views.BaseDragLayer;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
/**
* Unit tests for testing modifyTitleToSupportMultiLine() in BubbleTextView.java
@@ -48,6 +55,7 @@
*/
public class BubbleTextViewTest {
+ @Rule public StaticMockitoRule mockitoRule = new StaticMockitoRule(Flags.class);
private static final StringMatcherUtility.StringMatcher
MATCHER = StringMatcherUtility.StringMatcher.getInstance();
private static final int ONE_LINE = 1;
@@ -75,11 +83,12 @@
@Before
public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ Mockito.when(Flags.enableTwolineAllapps()).thenReturn(false);
Utilities.enableRunningInTestHarnessForTests();
mContext = new ActivityContextWrapper(getApplicationContext());
mBubbleTextView = new BubbleTextView(mContext);
mBubbleTextView.reset();
- mBubbleTextView.setDisplayAllApps();
BubbleTextView testView = new BubbleTextView(mContext);
testView.setTypeface(Typeface.MONOSPACE);
@@ -104,6 +113,7 @@
public void testEmptyString_flagOn() {
try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
mItemInfoWithIcon.title = EMPTY_STRING;
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.applyLabel(mItemInfoWithIcon);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
@@ -118,6 +128,7 @@
public void testEmptyString_flagOff() {
try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
mItemInfoWithIcon.title = EMPTY_STRING;
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.applyLabel(mItemInfoWithIcon);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
@@ -134,6 +145,7 @@
// test string: "Battery Stats"
mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -149,6 +161,7 @@
// test string: "Battery Stats"
mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -164,6 +177,7 @@
// test string: "flutterappflorafy"
mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -179,6 +193,7 @@
// test string: "flutterappflorafy"
mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -194,6 +209,7 @@
// test string: "System UWB Field Test"
mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -209,6 +225,7 @@
// test string: "System UWB Field Test"
mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -224,6 +241,7 @@
// test string: "LEGO®Builder"
mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -239,6 +257,7 @@
// test string: "LEGO®Builder"
mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setDisplay(DISPLAY_ALL_APPS);
mBubbleTextView.setTypeface(Typeface.MONOSPACE);
mBubbleTextView.measure(mLimitedWidth, 0);
mBubbleTextView.onPreDraw();
@@ -291,4 +310,20 @@
breakPoints);
assertEquals(TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT_RESULT, newString);
}
+
+ @Test
+ public void testEnsurePredictionRowIsOneLine() {
+ try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
+ // test string: "Battery Stats"
+ mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
+ mBubbleTextView.setDisplay(DISPLAY_PREDICTION_ROW);
+ mBubbleTextView.applyLabel(mItemInfoWithIcon);
+ mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+ mBubbleTextView.measure(mLimitedWidth, 0);
+ mBubbleTextView.onPreDraw();
+ assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
index 266f0ae..ad11268 100644
--- a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
+++ b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
@@ -1,26 +1,44 @@
package com.android.launcher3.ui;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_PRESUBMIT;
+
import android.util.Log;
import android.view.Surface;
import com.android.launcher3.tapl.TestHelpers;
+import com.android.launcher3.util.rule.TestStabilityRule;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
-class PortraitLandscapeRunner implements TestRule {
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+public class PortraitLandscapeRunner implements TestRule {
private static final String TAG = "PortraitLandscapeRunner";
private AbstractLauncherUiTest mTest;
+ // Annotation for tests that need to be run in portrait and landscape modes.
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.METHOD)
+ public @interface PortraitLandscape {
+ }
+
public PortraitLandscapeRunner(AbstractLauncherUiTest test) {
mTest = test;
}
@Override
public Statement apply(Statement base, Description description) {
- if (!TestHelpers.isInLauncherProcess() ||
- description.getAnnotation(AbstractLauncherUiTest.PortraitLandscape.class) == null) {
+ if (!TestHelpers.isInLauncherProcess()
+ || description.getAnnotation(PortraitLandscape.class) == null
+ // If running in presubmit, don't run in both orientations.
+ // It's important to keep presubmits fast even if we will occasionally miss
+ // regressions in presubmit.
+ || TestStabilityRule.getRunFlavor() == PLATFORM_PRESUBMIT) {
return base;
}
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 0b10603..8f2ac98 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -16,23 +16,17 @@
package com.android.launcher3.ui;
-import static androidx.test.InstrumentationRegistry.getInstrumentation;
-
-import static com.google.common.truth.Truth.assertThat;
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
-import static org.junit.Assume.assumeTrue;
import android.content.Intent;
-import android.graphics.Point;
-import android.os.SystemClock;
import android.platform.test.annotations.PlatinumTest;
-import android.util.Log;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
@@ -47,38 +41,33 @@
import com.android.launcher3.tapl.AppIcon;
import com.android.launcher3.tapl.AppIconMenu;
import com.android.launcher3.tapl.AppIconMenuItem;
-import com.android.launcher3.tapl.Folder;
-import com.android.launcher3.tapl.FolderIcon;
import com.android.launcher3.tapl.HomeAllApps;
import com.android.launcher3.tapl.HomeAppIcon;
-import com.android.launcher3.tapl.HomeAppIconMenuItem;
import com.android.launcher3.tapl.Widgets;
import com.android.launcher3.tapl.Workspace;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.util.LauncherLayoutBuilder;
import com.android.launcher3.util.TestUtil;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.launcher3.util.rule.TISBindRule;
+import com.android.launcher3.util.rule.TestStabilityRule.Stability;
import com.android.launcher3.widget.picker.WidgetsFullSheet;
import com.android.launcher3.widget.picker.WidgetsRecyclerView;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.IOException;
-import java.util.Map;
-
@LargeTest
@RunWith(AndroidJUnit4.class)
public class TaplTestsLauncher3 extends AbstractLauncherUiTest {
- private static final String APP_NAME = "LauncherTestApp";
- private static final String DUMMY_APP_NAME = "Aardwolf";
- private static final String MAPS_APP_NAME = "Maps";
- private static final String STORE_APP_NAME = "Play Store";
- private static final String GMAIL_APP_NAME = "Gmail";
+ public static final String APP_NAME = "LauncherTestApp";
+ public static final String DUMMY_APP_NAME = "Aardwolf";
+ public static final String MAPS_APP_NAME = "Maps";
+ public static final String STORE_APP_NAME = "Play Store";
+ public static final String GMAIL_APP_NAME = "Gmail";
private static final String READ_DEVICE_CONFIG_PERMISSION =
"android.permission.READ_DEVICE_CONFIG";
@@ -94,7 +83,12 @@
}
public static void initialize(AbstractLauncherUiTest test) throws Exception {
- test.clearLauncherData();
+ initialize(test, false);
+ }
+
+ public static void initialize(
+ AbstractLauncherUiTest test, boolean clearWorkspace) throws Exception {
+ test.reinitializeLauncherData(clearWorkspace);
test.mDevice.pressHome();
test.waitForLauncherCondition("Launcher didn't start", launcher -> launcher != null);
test.waitForState("Launcher internal state didn't switch to Home",
@@ -146,106 +140,14 @@
mLauncher.goHome();
}
- @Test
- @ScreenRecord
- public void testPressHomeOnAllAppsContextMenu() throws Exception {
- final AllApps allApps = mLauncher.getWorkspace().switchToAllApps();
- allApps.freeze();
- try {
- allApps.getAppIcon("TestActivity7").openMenu();
- } finally {
- allApps.unfreeze();
- }
- mLauncher.goHome();
- }
-
- public static void runAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) {
- allApps.freeze();
- try {
- assertNotNull("allApps parameter is null", allApps);
-
- assertTrue(
- "Launcher internal state is not All Apps",
- test.isInState(() -> LauncherState.ALL_APPS));
-
- // Test flinging forward and backward.
- test.executeOnLauncher(launcher -> assertEquals(
- "All Apps started in already scrolled state", 0,
- test.getAllAppsScroll(launcher)));
-
- allApps.flingForward();
- assertTrue("Launcher internal state is not All Apps",
- test.isInState(() -> LauncherState.ALL_APPS));
- final Integer flingForwardY = test.getFromLauncher(
- launcher -> test.getAllAppsScroll(launcher));
- test.executeOnLauncher(
- launcher -> assertTrue("flingForward() didn't scroll App Apps",
- flingForwardY > 0));
-
- allApps.flingBackward();
- assertTrue(
- "Launcher internal state is not All Apps",
- test.isInState(() -> LauncherState.ALL_APPS));
- final Integer flingBackwardY = test.getFromLauncher(
- launcher -> test.getAllAppsScroll(launcher));
- test.executeOnLauncher(launcher -> assertTrue("flingBackward() didn't scroll App Apps",
- flingBackwardY < flingForwardY));
-
- // Test scrolling down to YouTube.
- assertNotNull("All apps: can't find YouTube", allApps.getAppIcon("YouTube"));
- // Test scrolling up to Camera.
- assertNotNull("All apps: can't find Camera", allApps.getAppIcon("Camera"));
- // Test failing to find a non-existing app.
- final AllApps allAppsFinal = allApps;
- expectFail("All apps: could find a non-existing app",
- () -> allAppsFinal.getAppIcon("NO APP"));
-
- assertTrue(
- "Launcher internal state is not All Apps",
- test.isInState(() -> LauncherState.ALL_APPS));
- } finally {
- allApps.unfreeze();
- }
- }
-
- @Test
- @PortraitLandscape
- public void testWorkspaceSwitchToAllApps() {
- assertNotNull("switchToAllApps() returned null",
- mLauncher.getWorkspace().switchToAllApps());
- assertTrue("Launcher internal state is not All Apps",
- isInState(() -> LauncherState.ALL_APPS));
- }
-
- @Test
- @PortraitLandscape
- public void testAllAppsSwitchToWorkspace() {
- assertNotNull("switchToWorkspace() returned null",
- mLauncher.getWorkspace().switchToAllApps().switchToWorkspace());
- assertTrue("Launcher internal state is not Workspace",
- isInState(() -> LauncherState.NORMAL));
- }
-
- @Test
- @PortraitLandscape
- public void testAllAppsDeadzoneForTablet() throws Exception {
- assumeTrue(mLauncher.isTablet());
-
- mLauncher.getWorkspace().switchToAllApps().dismissByTappingOutsideForTablet(
- true /* tapRight */);
- mLauncher.getWorkspace().switchToAllApps().dismissByTappingOutsideForTablet(
- false /* tapRight */);
- }
-
@PlatinumTest(focusArea = "launcher")
@Test
- @ScreenRecord // b/202433017
public void testWorkspace() throws Exception {
// Set workspace that includes the chrome Activity app icon on the hotseat.
LauncherLayoutBuilder builder = new LauncherLayoutBuilder()
.atHotseat(0).putApp("com.android.chrome", "com.google.android.apps.chrome.Main");
mLauncherLayout = TestUtil.setLauncherDefaultLayout(mTargetContext, builder);
- clearLauncherData();
+ reinitializeLauncherData();
final Workspace workspace = mLauncher.getWorkspace();
@@ -310,6 +212,8 @@
}
@Test
+ @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/293191790
+ @ScreenRecord
@PortraitLandscape
public void testWidgets() throws Exception {
// Test opening widgets.
@@ -371,88 +275,27 @@
}
}
- @PlatinumTest(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.
- // 3. Verify that the icon works on homescreen.
+ public void testLaunchHomeScreenMenuItem() {
+ // Drag the test app icon to home screen and open short cut menu from the icon
final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
allApps.freeze();
try {
allApps.getAppIcon(APP_NAME).dragToWorkspace(false, false);
- mLauncher.getWorkspace().getWorkspaceAppIcon(APP_NAME).launch(getAppPackageName());
- } finally {
- allApps.unfreeze();
- }
- executeOnLauncher(launcher -> assertTrue(
- "Launcher activity is the top activity; expecting another activity to be the top "
- + "one",
- isInLaunchedApp(launcher)));
- }
+ final AppIconMenu menu = mLauncher.getWorkspace().getWorkspaceAppIcon(
+ APP_NAME).openDeepShortcutMenu();
- @Test
- @PortraitLandscape
- @PlatinumTest(focusArea = "launcher")
- public void testDragShortcut() throws Throwable {
- // 1. Open all apps and wait for load complete.
- // 2. Find the app and long press it to show shortcuts.
- // 3. Press icon center until shortcuts appear
- final HomeAllApps allApps = mLauncher
- .getWorkspace()
- .switchToAllApps();
- allApps.freeze();
- try {
- final HomeAppIconMenuItem menuItem = allApps
- .getAppIcon(APP_NAME)
- .openDeepShortcutMenu()
- .getMenuItem(0);
- final String actualShortcutName = menuItem.getText();
- final String expectedShortcutName = "Shortcut 1";
+ executeOnLauncher(
+ launcher -> assertTrue("Launcher internal state didn't switch to Showing Menu",
+ isOptionsPopupVisible(launcher)));
- assertEquals(expectedShortcutName, actualShortcutName);
- menuItem.dragToWorkspace(false, false);
- mLauncher.getWorkspace().getWorkspaceAppIcon(expectedShortcutName)
- .launch(getAppPackageName());
+ final AppIconMenuItem menuItem = menu.getMenuItem(1);
+ assertEquals("Wrong menu item", "Shortcut 2", menuItem.getText());
+ menuItem.launch(getAppPackageName());
} finally {
allApps.unfreeze();
}
}
-
- @Test
- @PortraitLandscape
- @ScreenRecord
- @Ignore // b/233075289
- @PlatinumTest(focusArea = "launcher")
- public void testDragToFolder() {
- // TODO: add the use case to drag an icon to an existing folder. Currently it either fails
- // on tablets or phones due to difference in resolution.
- final HomeAppIcon playStoreIcon = createShortcutIfNotExist(STORE_APP_NAME, 0, 1);
- final HomeAppIcon gmailIcon = createShortcutInCenterIfNotExist(GMAIL_APP_NAME);
-
- FolderIcon folderIcon = gmailIcon.dragToIcon(playStoreIcon);
- Folder folder = folderIcon.open();
- folder.getAppIcon(STORE_APP_NAME);
- folder.getAppIcon(GMAIL_APP_NAME);
- Workspace workspace = folder.close();
-
- workspace.verifyWorkspaceAppIconIsGone(STORE_APP_NAME + " should be moved to a folder.",
- STORE_APP_NAME);
- workspace.verifyWorkspaceAppIconIsGone(GMAIL_APP_NAME + " should be moved to a folder.",
- GMAIL_APP_NAME);
-
- final HomeAppIcon mapIcon = createShortcutInCenterIfNotExist(MAPS_APP_NAME);
- folderIcon = mapIcon.dragToIcon(folderIcon);
- folder = folderIcon.open();
- folder.getAppIcon(MAPS_APP_NAME);
- workspace = folder.close();
-
- workspace.verifyWorkspaceAppIconIsGone(MAPS_APP_NAME + " should be moved to a folder.",
- MAPS_APP_NAME);
- }
-
@FlakyTest(bugId = 256615483)
@Test
@PortraitLandscape
@@ -472,162 +315,6 @@
@Test
@PortraitLandscape
- @PlatinumTest(focusArea = "launcher")
- public void testDragAndCancelAppIcon() {
- final HomeAppIcon homeAppIcon = createShortcutInCenterIfNotExist(GMAIL_APP_NAME);
- Point positionBeforeDrag =
- mLauncher.getWorkspace().getWorkspaceIconsPositions().get(GMAIL_APP_NAME);
- assertNotNull("App not found in Workspace before dragging.", positionBeforeDrag);
-
- mLauncher.getWorkspace().dragAndCancelAppIcon(homeAppIcon);
-
- Point positionAfterDrag =
- mLauncher.getWorkspace().getWorkspaceIconsPositions().get(GMAIL_APP_NAME);
- assertNotNull("App not found in Workspace after dragging.", positionAfterDrag);
- assertEquals("App not returned to same position in Workspace after drag & cancel",
- positionBeforeDrag, positionAfterDrag);
- }
-
- @Test
- @PortraitLandscape
- public void testDeleteFromWorkspace() throws Exception {
- // test delete both built-in apps and user-installed app from workspace
- for (String appName : new String[]{"Gmail", "Play Store", APP_NAME}) {
- final HomeAppIcon homeAppIcon = createShortcutInCenterIfNotExist(appName);
- Workspace workspace = mLauncher.getWorkspace().deleteAppIcon(homeAppIcon);
- workspace.verifyWorkspaceAppIconIsGone(
- appName + " app was found after being deleted from workspace",
- appName);
- }
- }
-
- private void verifyAppUninstalledFromAllApps(Workspace workspace, String appName) {
- final HomeAllApps allApps = workspace.switchToAllApps();
- allApps.freeze();
- try {
- assertNull(appName + " app was found on all apps after being uninstalled",
- allApps.tryGetAppIcon(appName));
- } finally {
- allApps.unfreeze();
- }
- }
-
- @Ignore("b/256615483")
- @Test
- @PortraitLandscape
- @PlatinumTest(focusArea = "launcher")
- public void testUninstallFromWorkspace() throws Exception {
- installDummyAppAndWaitForUIUpdate();
- try {
- verifyAppUninstalledFromAllApps(
- createShortcutInCenterIfNotExist(DUMMY_APP_NAME).uninstall(), DUMMY_APP_NAME);
- } finally {
- TestUtil.uninstallDummyApp();
- }
- }
-
- @Test
- @ScreenRecord // b/258071914
- @PortraitLandscape
- @PlatinumTest(focusArea = "launcher")
- public void testUninstallFromAllApps() throws Exception {
- installDummyAppAndWaitForUIUpdate();
- try {
- Workspace workspace = mLauncher.getWorkspace();
- final HomeAllApps allApps = workspace.switchToAllApps();
- workspace = allApps.getAppIcon(DUMMY_APP_NAME).uninstall();
- waitForLauncherUIUpdate();
- verifyAppUninstalledFromAllApps(workspace, DUMMY_APP_NAME);
- } finally {
- TestUtil.uninstallDummyApp();
- }
- }
-
- @Test
- @PortraitLandscape
- @PlatinumTest(focusArea = "launcher")
- public void testDragAppIconToWorkspaceCell() throws Exception {
- long startTime, endTime, elapsedTime;
- Point[] targets = getCornersAndCenterPositions();
-
- for (Point target : targets) {
- startTime = SystemClock.uptimeMillis();
- final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
- allApps.freeze();
- try {
- allApps.getAppIcon(APP_NAME).dragToWorkspace(target.x, target.y);
- } finally {
- allApps.unfreeze();
- }
- // Reset the workspace for the next shortcut creation.
- initialize(this);
- endTime = SystemClock.uptimeMillis();
- elapsedTime = endTime - startTime;
- Log.d("testDragAppIconToWorkspaceCellTime",
- "Milliseconds taken to drag app icon to workspace cell: " + elapsedTime);
- }
-
- // test to move a shortcut to other cell.
- final HomeAppIcon launcherTestAppIcon = createShortcutInCenterIfNotExist(APP_NAME);
- for (Point target : targets) {
- startTime = SystemClock.uptimeMillis();
- launcherTestAppIcon.dragToWorkspace(target.x, target.y);
- endTime = SystemClock.uptimeMillis();
- elapsedTime = endTime - startTime;
- Log.d("testDragAppIconToWorkspaceCellTime",
- "Milliseconds taken to move shortcut to other cell: " + elapsedTime);
- }
- }
-
- @Test
- @ScreenRecord // b/241821721
- @PlatinumTest(focusArea = "launcher")
- public void getIconsPosition_afterIconRemoved_notContained() throws IOException {
- Point[] gridPositions = getCornersAndCenterPositions();
- createShortcutIfNotExist(STORE_APP_NAME, gridPositions[0]);
- createShortcutIfNotExist(MAPS_APP_NAME, gridPositions[1]);
- installDummyAppAndWaitForUIUpdate();
- try {
- createShortcutIfNotExist(DUMMY_APP_NAME, gridPositions[2]);
- Map<String, Point> initialPositions =
- mLauncher.getWorkspace().getWorkspaceIconsPositions();
- assertThat(initialPositions.keySet())
- .containsAtLeast(DUMMY_APP_NAME, MAPS_APP_NAME, STORE_APP_NAME);
-
- mLauncher.getWorkspace().getWorkspaceAppIcon(DUMMY_APP_NAME).uninstall();
- mLauncher.getWorkspace().verifyWorkspaceAppIconIsGone(
- DUMMY_APP_NAME + " was expected to disappear after uninstall.", DUMMY_APP_NAME);
-
- Map<String, Point> finalPositions =
- mLauncher.getWorkspace().getWorkspaceIconsPositions();
- assertThat(finalPositions).doesNotContainKey(DUMMY_APP_NAME);
- } finally {
- TestUtil.uninstallDummyApp();
- }
- }
-
- @Test
- @PortraitLandscape
- @PlatinumTest(focusArea = "launcher")
- public void testDragShortcutToWorkspaceCell() throws Exception {
- Point[] targets = getCornersAndCenterPositions();
-
- for (Point target : targets) {
- final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
- allApps.freeze();
- try {
- allApps.getAppIcon(APP_NAME)
- .openDeepShortcutMenu()
- .getMenuItem(0)
- .dragToWorkspace(target.x, target.y);
- } finally {
- allApps.unfreeze();
- }
- }
- }
-
- @Test
- @PortraitLandscape
public void testAddDeleteShortcutOnHotseat() {
mLauncher.getWorkspace()
.deleteAppIcon(mLauncher.getWorkspace().getHotseatAppIcon(0))
@@ -638,49 +325,39 @@
mLauncher.getWorkspace().getHotseatAppIcon(APP_NAME));
}
- private void installDummyAppAndWaitForUIUpdate() throws IOException {
- TestUtil.installDummyApp();
- waitForLauncherUIUpdate();
- }
-
- private void waitForLauncherUIUpdate() {
- // Wait for model thread completion as it may be processing
- // the install event from the SystemService
- mLauncher.waitForModelQueueCleared();
- // Wait for Launcher UI thread completion, as it may be processing updating the UI in
- // response to the model update. Not that `waitForLauncherInitialized` is just a proxy
- // method, we can use any method which touches Launcher UI thread,
- mLauncher.waitForLauncherInitialized();
- }
-
- /**
- * @return List of workspace grid coordinates. Those are not pixels. See {@link
- * Workspace#getIconGridDimensions()}
- */
- private Point[] getCornersAndCenterPositions() {
- final Point dimensions = mLauncher.getWorkspace().getIconGridDimensions();
- return new Point[]{
- new Point(0, 1),
- new Point(0, dimensions.y - 2),
- new Point(dimensions.x - 1, 1),
- new Point(dimensions.x - 1, dimensions.y - 2),
- new Point(dimensions.x / 2, dimensions.y / 2)
- };
- }
-
- public static String getAppPackageName() {
- return getInstrumentation().getContext().getPackageName();
- }
-
@Test
public void testGetAppIconName() {
HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
allApps.freeze();
try {
- HomeAppIcon icon = allApps.getAppIcon(APP_NAME);
- assertEquals("Wrong app icon name.", icon.getIconName(), APP_NAME);
+ // getAppIcon() already verifies that the icon is not null and is the correct icon name.
+ allApps.getAppIcon(APP_NAME);
} finally {
allApps.unfreeze();
}
}
+
+ @PlatinumTest(focusArea = "launcher")
+ @Test
+ public void testAddAndDeletePageAndFling() {
+ Workspace workspace = mLauncher.getWorkspace();
+ // Get the first app from the hotseat
+ HomeAppIcon hotSeatIcon = workspace.getHotseatAppIcon(0);
+ String appName = hotSeatIcon.getIconName();
+
+ // Add one page by dragging app to page 1.
+ workspace.dragIcon(hotSeatIcon, workspace.pagesPerScreen());
+ assertEquals("Incorrect Page count Number",
+ workspace.pagesPerScreen() * 2,
+ workspace.getPageCount());
+
+ // Delete one page by dragging app to hot seat.
+ workspace.getWorkspaceAppIcon(appName).dragToHotseat(0);
+
+ // Refresh workspace to avoid using stale container error.
+ workspace = mLauncher.getWorkspace();
+ assertEquals("Incorrect Page count Number",
+ workspace.pagesPerScreen(),
+ workspace.getPageCount());
+ }
}
diff --git a/tests/src/com/android/launcher3/ui/TestViewHelpers.java b/tests/src/com/android/launcher3/ui/TestViewHelpers.java
index 083f580..4b2bade 100644
--- a/tests/src/com/android/launcher3/ui/TestViewHelpers.java
+++ b/tests/src/com/android/launcher3/ui/TestViewHelpers.java
@@ -15,11 +15,14 @@
*/
package com.android.launcher3.ui;
-import static androidx.test.InstrumentationRegistry.getInstrumentation;
-import static androidx.test.InstrumentationRegistry.getTargetContext;
+import static android.os.Process.myUserHandle;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.launcher3.util.TestUtil.getOnUiThread;
+
+import android.app.Instrumentation;
import android.content.ComponentName;
-import android.os.Process;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -29,7 +32,6 @@
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
-import java.util.concurrent.Callable;
import java.util.function.Function;
public class TestViewHelpers {
@@ -38,23 +40,16 @@
/**
* Finds a widget provider which can fit on the home screen.
*
- * @param test test suite.
* @param hasConfigureScreen if true, a provider with a config screen is returned.
*/
- public static LauncherAppWidgetProviderInfo findWidgetProvider(AbstractLauncherUiTest test,
- final boolean hasConfigureScreen) {
- LauncherAppWidgetProviderInfo info =
- test.getOnUiThread(new Callable<LauncherAppWidgetProviderInfo>() {
- @Override
- public LauncherAppWidgetProviderInfo call() throws Exception {
- ComponentName cn = new ComponentName(getInstrumentation().getContext(),
- hasConfigureScreen ? AppWidgetWithConfig.class
- : AppWidgetNoConfig.class);
- Log.d(TAG, "findWidgetProvider componentName=" + cn.flattenToString());
- return new WidgetManagerHelper(getTargetContext())
- .findProvider(cn, Process.myUserHandle());
- }
- });
+ public static LauncherAppWidgetProviderInfo findWidgetProvider(boolean hasConfigureScreen) {
+ LauncherAppWidgetProviderInfo info = getOnUiThread(() -> {
+ Instrumentation i = getInstrumentation();
+ ComponentName cn = new ComponentName(i.getContext(),
+ hasConfigureScreen ? AppWidgetWithConfig.class : AppWidgetNoConfig.class);
+ Log.d(TAG, "findWidgetProvider componentName=" + cn.flattenToString());
+ return new WidgetManagerHelper(i.getTargetContext()).findProvider(cn, myUserHandle());
+ });
if (info == null) {
throw new IllegalArgumentException("No valid widget provider");
}
diff --git a/tests/src/com/android/launcher3/ui/WorkProfileTest.java b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
index 026766c..ac710fd 100644
--- a/tests/src/com/android/launcher3/ui/WorkProfileTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
@@ -18,10 +18,7 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.allapps.AllAppsStore.DEFER_UPDATES_TEST;
-import static com.android.launcher3.testing.shared.TestProtocol.WORK_TAB_MISSING;
import static com.android.launcher3.util.TestUtil.installDummyAppForUser;
-import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
-import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -39,9 +36,7 @@
import com.android.launcher3.allapps.WorkPausedCard;
import com.android.launcher3.allapps.WorkProfileManager;
import com.android.launcher3.tapl.LauncherInstrumentation;
-import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.util.TestUtil;
-import com.android.launcher3.util.rule.TestStabilityRule.Stability;
import org.junit.After;
import org.junit.Before;
@@ -78,8 +73,6 @@
installDummyAppForUser(mProfileUserId);
updateWorkProfileSetupSuccessful("am start-user", output);
- Log.d(WORK_TAB_MISSING, "workProfileSuccessful? " + mWorkProfileSetupSuccessful +
- " shellCmd: " + logStr);
if (!mWorkProfileSetupSuccessful) {
return; // no need to setup launcher since all tests will skip.
}
@@ -89,14 +82,13 @@
waitForStateTransitionToEnd("Launcher internal state didn't switch to Normal",
() -> NORMAL);
waitForResumed("Launcher internal state is still Background");
- executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
+ mLauncher.getWorkspace().switchToAllApps();
waitForStateTransitionToEnd("Launcher internal state didn't switch to All Apps",
() -> ALL_APPS);
}
@After
public void removeWorkProfile() throws Exception {
- Log.d(TestProtocol.WORK_TAB_MISSING, "WorkProfileTest teardown");
executeOnLauncher(launcher -> {
if (launcher == null || launcher.getAppsView() == null) {
return;
@@ -108,11 +100,8 @@
}
private void waitForWorkTabSetup() {
- // Added for b/243688989 flake to determine if we really are in allApps or not at this point
- mLauncher.getAllApps();
waitForLauncherCondition("Work tab not setup", launcher -> {
if (launcher.getAppsView().getContentView() instanceof AllAppsPagedView) {
- Log.d(WORK_TAB_MISSING, "Deferring AppsStore updates");
launcher.getAppsView().getAppsStore().enableDeferUpdates(DEFER_UPDATES_TEST);
return true;
}
@@ -121,7 +110,6 @@
}
@Test
- @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/243688989
public void workTabExists() {
assumeTrue(mWorkProfileSetupSuccessful);
waitForWorkTabSetup();
@@ -182,7 +170,6 @@
}
@Test
- @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/243688989
public void testEdu() {
assumeTrue(mWorkProfileSetupSuccessful);
waitForWorkTabSetup();
diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
index e9a2b0f..b2ce400 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
@@ -30,10 +30,13 @@
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.celllayout.FavoriteItemsTransaction;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.testcomponent.WidgetConfigActivity;
import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.ui.TestViewHelpers;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.ShellCommandRule;
@@ -63,7 +66,7 @@
@Before
public void setUp() throws Exception {
super.setUp();
- mWidgetInfo = TestViewHelpers.findWidgetProvider(this, true /* hasConfigureScreen */);
+ mWidgetInfo = TestViewHelpers.findWidgetProvider(true /* hasConfigureScreen */);
mAppWidgetManager = AppWidgetManager.getInstance(mTargetContext);
}
@@ -84,8 +87,7 @@
* @param acceptConfig accept the config activity
*/
private void runTest(boolean acceptConfig) throws Throwable {
- clearHomescreen();
- mDevice.pressHome();
+ new FavoriteItemsTransaction(mTargetContext).commitAndLoadHome(mLauncher);
// Drag widget to homescreen
WidgetConfigStartupMonitor monitor = new WidgetConfigStartupMonitor();
@@ -123,7 +125,10 @@
@Override
public boolean isTrue() throws Throwable {
- return mMainThreadExecutor.submit(mActivityMonitor.itemExists(this)).get();
+ return mMainThreadExecutor.submit(() -> {
+ Launcher l = Launcher.ACTIVITY_TRACKER.getCreatedActivity();
+ return l != null && l.getWorkspace().getFirstMatch(this) != null;
+ }).get();
}
@Override
diff --git a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
index 3eb20e3..64ab206 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
@@ -16,19 +16,19 @@
package com.android.launcher3.ui.widget;
import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
-
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
import android.platform.test.annotations.PlatinumTest;
+import android.platform.test.rule.ScreenRecordRule;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
-import androidx.test.runner.AndroidJUnit4;
-import com.android.launcher3.model.data.LauncherAppWidgetInfo;
+import com.android.launcher3.celllayout.FavoriteItemsTransaction;
import com.android.launcher3.tapl.Widget;
import com.android.launcher3.tapl.WidgetResizeFrame;
import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.ui.TestViewHelpers;
import com.android.launcher3.util.rule.ShellCommandRule;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
@@ -51,14 +51,15 @@
@PlatinumTest(focusArea = "launcher")
@Test
@PortraitLandscape
+ @ScreenRecordRule.ScreenRecord // b/289161193
public void testDragIcon() throws Throwable {
- clearHomescreen();
- mDevice.pressHome();
+ mLauncher.enableDebugTracing(); // b/289161193
+ new FavoriteItemsTransaction(mTargetContext).commitAndLoadHome(mLauncher);
waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading());
final LauncherAppWidgetProviderInfo widgetInfo =
- TestViewHelpers.findWidgetProvider(this, false /* hasConfigureScreen */);
+ TestViewHelpers.findWidgetProvider(false /* hasConfigureScreen */);
WidgetResizeFrame resizeFrame = mLauncher
.getWorkspace()
@@ -66,11 +67,6 @@
.getWidget(widgetInfo.getLabel(mTargetContext.getPackageManager()))
.dragWidgetToWorkspace();
- assertTrue(mActivityMonitor.itemExists(
- (info, view) -> info instanceof LauncherAppWidgetInfo &&
- ((LauncherAppWidgetInfo) info).providerName.getClassName().equals(
- widgetInfo.provider.getClassName())).call());
-
assertNotNull("Widget resize frame not shown after widget add", resizeFrame);
resizeFrame.dismiss();
@@ -78,6 +74,7 @@
DEFAULT_UI_TIMEOUT);
assertNotNull("Widget not found on the workspace", widget);
widget.launch(getAppPackageName());
+ mLauncher.disableDebugTracing(); // b/289161193
}
/**
@@ -90,12 +87,34 @@
@Test
@PortraitLandscape
public void testDragCustomShortcut() throws Throwable {
- clearHomescreen();
- mDevice.pressHome();
+ new FavoriteItemsTransaction(mTargetContext).commitAndLoadHome(mLauncher);
+
mLauncher.getWorkspace().openAllWidgets()
.getWidget("com.android.launcher3.testcomponent.CustomShortcutConfigActivity")
.dragToWorkspace(false, true);
mLauncher.getWorkspace().getWorkspaceAppIcon("Shortcut")
.launch(getAppPackageName());
}
+
+ /**
+ * Test dragging a widget to the workspace and resize it.
+ */
+ @Test
+ public void testResizeWidget() throws Throwable {
+ new FavoriteItemsTransaction(mTargetContext).commitAndLoadHome(mLauncher);
+
+ waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading());
+
+ final LauncherAppWidgetProviderInfo widgetInfo =
+ TestViewHelpers.findWidgetProvider(false /* hasConfigureScreen */);
+
+ WidgetResizeFrame resizeFrame = mLauncher
+ .getWorkspace()
+ .openAllWidgets()
+ .getWidget(widgetInfo.getLabel(mTargetContext.getPackageManager()))
+ .dragWidgetToWorkspace();
+
+ assertNotNull("Widget resize frame not shown after widget add", resizeFrame);
+ resizeFrame.resize();
+ }
}
diff --git a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
index 0f861eb..7db3161 100644
--- a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
@@ -15,8 +15,13 @@
*/
package com.android.launcher3.ui.widget;
-import static androidx.test.InstrumentationRegistry.getTargetContext;
-
+import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
+import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
+import static com.android.launcher3.model.data.LauncherAppWidgetInfo.FLAG_ID_NOT_VALID;
+import static com.android.launcher3.model.data.LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
+import static com.android.launcher3.model.data.LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
+import static com.android.launcher3.provider.LauncherDbUtils.itemIdMatch;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.util.WidgetUtils.createWidgetInfo;
import static org.junit.Assert.assertEquals;
@@ -26,7 +31,6 @@
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionParams;
import android.content.pm.PackageManager;
@@ -34,11 +38,14 @@
import android.os.Bundle;
import android.widget.RemoteViews;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
-import androidx.test.runner.AndroidJUnit4;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
+import com.android.launcher3.celllayout.FavoriteItemsTransaction;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.tapl.Widget;
@@ -57,6 +64,7 @@
import java.util.HashSet;
import java.util.Set;
+import java.util.function.Consumer;
/**
* Tests for bind widget flow.
@@ -70,24 +78,18 @@
@Rule
public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
- private ContentResolver mResolver;
-
// Objects created during test, which should be cleaned up in the end.
private Cursor mCursor;
// App install session id.
private int mSessionId = -1;
+ private LauncherModel mModel;
+
@Override
@Before
public void setUp() throws Exception {
super.setUp();
-
- mResolver = mTargetContext.getContentResolver();
-
- // Clear all existing data
- LauncherSettings.Settings.call(mResolver, LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
- LauncherSettings.Settings.call(mResolver,
- LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG);
+ mModel = LauncherAppState.getInstance(mTargetContext).getModel();
}
@After
@@ -103,34 +105,24 @@
@Test
public void testBindNormalWidget_withConfig() {
- LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, true);
- LauncherAppWidgetInfo item = createWidgetInfo(info, getTargetContext(), true);
-
- addItemToScreen(item);
+ LauncherAppWidgetProviderInfo info = addWidgetToScreen(true, true, i -> { });
verifyWidgetPresent(info);
}
@Test
public void testBindNormalWidget_withoutConfig() {
- LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, false);
- LauncherAppWidgetInfo item = createWidgetInfo(info, getTargetContext(), true);
-
- addItemToScreen(item);
+ LauncherAppWidgetProviderInfo info = addWidgetToScreen(false, true, i -> { });
verifyWidgetPresent(info);
}
@Test
public void testUnboundWidget_removed() {
- LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, false);
- LauncherAppWidgetInfo item = createWidgetInfo(info, getTargetContext(), false);
- item.appWidgetId = -33;
-
- addItemToScreen(item);
+ LauncherAppWidgetProviderInfo info = addWidgetToScreen(false, false,
+ item -> item.appWidgetId = -33);
final Workspace workspace = mLauncher.getWorkspace();
// Item deleted from db
- mCursor = mResolver.query(LauncherSettings.Favorites.getContentUri(item.id),
- null, null, null, null, null);
+ mCursor = queryItem();
assertEquals(0, mCursor.getCount());
// The view does not exist
@@ -140,36 +132,26 @@
@Test
public void testPendingWidget_autoRestored() {
// A non-restored widget with no config screen gets restored automatically.
- LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, false);
-
// Do not bind the widget
- LauncherAppWidgetInfo item = createWidgetInfo(info, getTargetContext(), false);
- item.restoreStatus = LauncherAppWidgetInfo.FLAG_ID_NOT_VALID;
-
- addItemToScreen(item);
+ LauncherAppWidgetProviderInfo info = addWidgetToScreen(false, false,
+ item -> item.restoreStatus = FLAG_ID_NOT_VALID);
verifyWidgetPresent(info);
}
@Test
public void testPendingWidget_withConfigScreen() {
// A non-restored widget with config screen get bound and shows a 'Click to setup' UI.
- LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, true);
-
// Do not bind the widget
- LauncherAppWidgetInfo item = createWidgetInfo(info, getTargetContext(), false);
- item.restoreStatus = LauncherAppWidgetInfo.FLAG_ID_NOT_VALID;
-
- addItemToScreen(item);
+ LauncherAppWidgetProviderInfo info = addWidgetToScreen(true, false,
+ item -> item.restoreStatus = FLAG_ID_NOT_VALID);
verifyPendingWidgetPresent();
- // Item deleted from db
- mCursor = mResolver.query(LauncherSettings.Favorites.getContentUri(item.id),
- null, null, null, null, null);
+ mCursor = queryItem();
mCursor.moveToNext();
// Widget has a valid Id now.
assertEquals(0, mCursor.getInt(mCursor.getColumnIndex(LauncherSettings.Favorites.RESTORED))
- & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID);
+ & FLAG_ID_NOT_VALID);
assertNotNull(AppWidgetManager.getInstance(mTargetContext)
.getAppWidgetInfo(mCursor.getInt(mCursor.getColumnIndex(
LauncherSettings.Favorites.APPWIDGET_ID))));
@@ -185,7 +167,6 @@
appWidgetManager.updateAppWidgetOptions(appWidgetId, b);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
-
// verify changes are reflected
waitForLauncherCondition("App widget options did not update",
l -> appWidgetManager.getAppWidgetOptions(appWidgetId).getBoolean(
@@ -197,17 +178,12 @@
@Test
public void testPendingWidget_notRestored_removed() {
- LauncherAppWidgetInfo item = getInvalidWidgetInfo();
- item.restoreStatus = LauncherAppWidgetInfo.FLAG_ID_NOT_VALID
- | LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
-
- addItemToScreen(item);
+ addPendingItemToScreen(getInvalidWidgetInfo(), FLAG_ID_NOT_VALID | FLAG_PROVIDER_NOT_READY);
assertTrue("Pending widget exists",
mLauncher.getWorkspace().tryGetPendingWidget(0) == null);
// Item deleted from db
- mCursor = mResolver.query(LauncherSettings.Favorites.getContentUri(item.id),
- null, null, null, null, null);
+ mCursor = queryItem();
assertEquals(0, mCursor.getCount());
}
@@ -215,32 +191,25 @@
public void testPendingWidget_notRestored_brokenInstall() {
// A widget which is was being installed once, even if its not being
// installed at the moment is not removed.
- LauncherAppWidgetInfo item = getInvalidWidgetInfo();
- item.restoreStatus = LauncherAppWidgetInfo.FLAG_ID_NOT_VALID
- | LauncherAppWidgetInfo.FLAG_RESTORE_STARTED
- | LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
-
- addItemToScreen(item);
+ addPendingItemToScreen(getInvalidWidgetInfo(),
+ FLAG_ID_NOT_VALID | FLAG_RESTORE_STARTED | FLAG_PROVIDER_NOT_READY);
verifyPendingWidgetPresent();
// Verify item still exists in db
- mCursor = mResolver.query(LauncherSettings.Favorites.getContentUri(item.id),
- null, null, null, null, null);
+ mCursor = queryItem();
assertEquals(1, mCursor.getCount());
// Widget still has an invalid id.
mCursor.moveToNext();
- assertEquals(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID,
+ assertEquals(FLAG_ID_NOT_VALID,
mCursor.getInt(mCursor.getColumnIndex(LauncherSettings.Favorites.RESTORED))
- & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID);
+ & FLAG_ID_NOT_VALID);
}
@Test
public void testPendingWidget_notRestored_activeInstall() throws Exception {
// A widget which is being installed is not removed
LauncherAppWidgetInfo item = getInvalidWidgetInfo();
- item.restoreStatus = LauncherAppWidgetInfo.FLAG_ID_NOT_VALID
- | LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
// Create an active installer session
SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
@@ -248,19 +217,18 @@
PackageInstaller installer = mTargetContext.getPackageManager().getPackageInstaller();
mSessionId = installer.createSession(params);
- addItemToScreen(item);
+ addPendingItemToScreen(item, FLAG_ID_NOT_VALID | FLAG_PROVIDER_NOT_READY);
verifyPendingWidgetPresent();
// Verify item still exists in db
- mCursor = mResolver.query(LauncherSettings.Favorites.getContentUri(item.id),
- null, null, null, null, null);
+ mCursor = queryItem();
assertEquals(1, mCursor.getCount());
// Widget still has an invalid id.
mCursor.moveToNext();
- assertEquals(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID,
+ assertEquals(FLAG_ID_NOT_VALID,
mCursor.getInt(mCursor.getColumnIndex(LauncherSettings.Favorites.RESTORED))
- & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID);
+ & FLAG_ID_NOT_VALID);
}
private void verifyWidgetPresent(LauncherAppWidgetProviderInfo info) {
@@ -275,6 +243,28 @@
widget != null);
}
+ private void addPendingItemToScreen(LauncherAppWidgetInfo item, int restoreStatus) {
+ item.restoreStatus = restoreStatus;
+ item.screenId = FIRST_SCREEN_ID;
+ new FavoriteItemsTransaction(mTargetContext)
+ .addItem(() -> item)
+ .commitAndLoadHome(mLauncher);
+ }
+
+ private LauncherAppWidgetProviderInfo addWidgetToScreen(boolean hasConfigureScreen,
+ boolean bindWidget, Consumer<LauncherAppWidgetInfo> itemOverride) {
+ LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(hasConfigureScreen);
+ new FavoriteItemsTransaction(mTargetContext)
+ .addItem(() -> {
+ LauncherAppWidgetInfo item = createWidgetInfo(info, mTargetContext, bindWidget);
+ item.screenId = FIRST_SCREEN_ID;
+ itemOverride.accept(item);
+ return item;
+ })
+ .commitAndLoadHome(mLauncher);
+ return info;
+ }
+
/**
* Returns a LauncherAppWidgetInfo with package name which is not present on the device
*/
@@ -312,4 +302,14 @@
item.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
return item;
}
+
+ private Cursor queryItem() {
+ try {
+ return MODEL_EXECUTOR.submit(() ->
+ mModel.getModelDbController().query(
+ TABLE_NAME, null, itemIdMatch(0), null, null)).get();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
index bf9eb5a..5c753f9 100644
--- a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
@@ -32,7 +32,9 @@
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.celllayout.FavoriteItemsTransaction;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -46,7 +48,6 @@
import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.Wait.Condition;
-import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.launcher3.util.rule.ShellCommandRule;
import org.junit.Before;
@@ -83,7 +84,6 @@
public void testEmpty() throws Throwable { /* needed while the broken tests are being fixed */ }
@Test
- @ScreenRecord // b/215673732
public void testPinWidgetNoConfig() throws Throwable {
runTest("pinWidgetNoConfig", true, (info, view) -> info instanceof LauncherAppWidgetInfo &&
((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId &&
@@ -92,7 +92,6 @@
}
@Test
- @ScreenRecord // b/215673732
public void testPinWidgetNoConfig_customPreview() throws Throwable {
// Command to set custom preview
Intent command = RequestPinItemActivity.getCommandIntent(
@@ -106,7 +105,6 @@
}
@Test
- @ScreenRecord // b/215673732
public void testPinWidgetWithConfig() throws Throwable {
runTest("pinWidgetWithConfig", true,
(info, view) -> info instanceof LauncherAppWidgetInfo &&
@@ -134,8 +132,7 @@
private void runTest(String activityMethod, boolean isWidget, ItemOperator itemMatcher,
Intent... commandIntents) throws Throwable {
- clearHomescreen();
- mDevice.pressHome();
+ new FavoriteItemsTransaction(mTargetContext).commitAndLoadHome(mLauncher);
// Open Pin item activity
BlockingBroadcastReceiver openMonitor = new BlockingBroadcastReceiver(
@@ -193,7 +190,10 @@
@Override
public boolean isTrue() throws Throwable {
- return mMainThreadExecutor.submit(mActivityMonitor.itemExists(mOp)).get();
+ return mMainThreadExecutor.submit(() -> {
+ Launcher l = Launcher.ACTIVITY_TRACKER.getCreatedActivity();
+ return l != null && l.getWorkspace().getFirstMatch(mOp) != null;
+ }).get();
}
}
}
diff --git a/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
index 7ba0b53..8e5e9cc 100644
--- a/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
@@ -147,9 +147,8 @@
for (int i = parent.getChildCount() - 1; i >= 0; i--) {
viewQueue.add(parent.getChildAt(i));
}
- } else if (view instanceof BubbleTextView) {
- BubbleTextView btv = (BubbleTextView) view;
- if (title.equals(btv.getText())) {
+ } else if (view instanceof BubbleTextView btv) {
+ if (title.equals(btv.getContentDescription().toString())) {
icon = btv;
break;
}
diff --git a/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java b/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java
index c4b6d43..62a8179 100644
--- a/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java
@@ -29,6 +29,7 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.tapl.Workspace;
import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.util.LauncherLayoutBuilder;
import com.android.launcher3.util.TestUtil;
@@ -177,14 +178,15 @@
public void testDragIconToPage3() {
Workspace workspace = mLauncher.getWorkspace();
- workspace.dragIcon(workspace.getHotseatAppIcon("Phone"), 3);
+ // b/299522368 sometimes the phone app is not present in the hotseat.
+ workspace.dragIcon(workspace.getHotseatAppIcon("Chrome"), 3);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 2, 3);
assertItemsOnPage(launcher, 0, "Play Store", "Maps");
assertPageEmpty(launcher, 1);
assertPageEmpty(launcher, 2);
- assertItemsOnPage(launcher, 3, "Phone");
+ assertItemsOnPage(launcher, 3, "Chrome");
});
}
diff --git a/tests/src/com/android/launcher3/util/DisplayControllerTest.kt b/tests/src/com/android/launcher3/util/DisplayControllerTest.kt
new file mode 100644
index 0000000..8e4e998
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/DisplayControllerTest.kt
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util
+
+import android.content.Context
+import android.content.res.Configuration
+import android.content.res.Resources
+import android.graphics.Point
+import android.graphics.Rect
+import android.hardware.display.DisplayManager
+import android.util.ArrayMap
+import android.util.DisplayMetrics
+import android.view.Display
+import android.view.Surface
+import androidx.test.annotation.UiThreadTest
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.LauncherPrefs
+import com.android.launcher3.util.DisplayController.CHANGE_DENSITY
+import com.android.launcher3.util.DisplayController.CHANGE_ROTATION
+import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener
+import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext
+import com.android.launcher3.util.window.CachedDisplayInfo
+import com.android.launcher3.util.window.WindowManagerProxy
+import kotlin.math.min
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.doNothing
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+import org.mockito.stubbing.Answer
+
+/** Unit tests for {@link DisplayController} */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DisplayControllerTest {
+
+ private val appContext: Context = ApplicationProvider.getApplicationContext()
+
+ @Mock private lateinit var context: SandboxContext
+ @Mock private lateinit var windowManagerProxy: WindowManagerProxy
+ @Mock private lateinit var launcherPrefs: LauncherPrefs
+ @Mock private lateinit var displayManager: DisplayManager
+ @Mock private lateinit var display: Display
+ @Mock private lateinit var resources: Resources
+ @Mock private lateinit var displayInfoChangeListener: DisplayInfoChangeListener
+
+ private lateinit var displayController: DisplayController
+
+ private val width = 2208
+ private val height = 1840
+ private val inset = 110
+ private val densityDpi = 420
+ private val density = densityDpi / DisplayMetrics.DENSITY_DEFAULT.toFloat()
+ private val bounds =
+ arrayOf(
+ WindowBounds(Rect(0, 0, width, height), Rect(0, inset, 0, 0), Surface.ROTATION_0),
+ WindowBounds(Rect(0, 0, height, width), Rect(0, inset, 0, 0), Surface.ROTATION_90),
+ WindowBounds(Rect(0, 0, width, height), Rect(0, inset, 0, 0), Surface.ROTATION_180),
+ WindowBounds(Rect(0, 0, height, width), Rect(0, inset, 0, 0), Surface.ROTATION_270)
+ )
+ private val configuration =
+ Configuration(appContext.resources.configuration).apply {
+ densityDpi = this@DisplayControllerTest.densityDpi
+ screenWidthDp = (bounds[0].bounds.width() / density).toInt()
+ screenHeightDp = (bounds[0].bounds.height() / density).toInt()
+ smallestScreenWidthDp = min(screenWidthDp, screenHeightDp)
+ }
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ whenever(context.getObject(eq(WindowManagerProxy.INSTANCE))).thenReturn(windowManagerProxy)
+ whenever(context.getObject(eq(LauncherPrefs.INSTANCE))).thenReturn(launcherPrefs)
+
+ // Mock WindowManagerProxy
+ val displayInfo =
+ CachedDisplayInfo(Point(width, height), Surface.ROTATION_0, Rect(0, 0, 0, 0))
+ whenever(windowManagerProxy.getDisplayInfo(any())).thenReturn(displayInfo)
+ whenever(windowManagerProxy.estimateInternalDisplayBounds(any()))
+ .thenAnswer(
+ Answer {
+ // Always create a new copy of bounds
+ val perDisplayBounds = ArrayMap<CachedDisplayInfo, List<WindowBounds>>()
+ perDisplayBounds[displayInfo] = bounds.toList()
+ return@Answer perDisplayBounds
+ }
+ )
+ whenever(windowManagerProxy.getRealBounds(any(), any())).thenAnswer { i ->
+ bounds[i.getArgument<CachedDisplayInfo>(1).rotation]
+ }
+
+ // Mock context
+ whenever(context.createWindowContext(any(), any(), nullable())).thenReturn(context)
+ whenever(context.getSystemService(eq(DisplayManager::class.java)))
+ .thenReturn(displayManager)
+ doNothing().`when`(context).registerComponentCallbacks(any())
+
+ // Mock display
+ whenever(display.rotation).thenReturn(displayInfo.rotation)
+ whenever(context.display).thenReturn(display)
+ whenever(displayManager.getDisplay(any())).thenReturn(display)
+
+ // Mock resources
+ whenever(resources.configuration).thenReturn(configuration)
+ whenever(context.resources).thenReturn(resources)
+
+ // Initialize DisplayController
+ displayController = DisplayController(context)
+ displayController.addChangeListener(displayInfoChangeListener)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testRotation() {
+ val displayInfo =
+ CachedDisplayInfo(Point(height, width), Surface.ROTATION_90, Rect(0, 0, 0, 0))
+ whenever(windowManagerProxy.getDisplayInfo(any())).thenReturn(displayInfo)
+ whenever(display.rotation).thenReturn(displayInfo.rotation)
+ val configuration =
+ Configuration(configuration).apply {
+ screenWidthDp = configuration.screenHeightDp
+ screenHeightDp = configuration.screenWidthDp
+ }
+ whenever(resources.configuration).thenReturn(configuration)
+
+ displayController.onConfigurationChanged(configuration)
+
+ verify(displayInfoChangeListener).onDisplayInfoChanged(any(), any(), eq(CHANGE_ROTATION))
+ }
+
+ @Test
+ @UiThreadTest
+ fun testFontScale() {
+ val configuration = Configuration(configuration).apply { fontScale = 1.2f }
+ whenever(resources.configuration).thenReturn(configuration)
+
+ displayController.onConfigurationChanged(configuration)
+
+ verify(displayInfoChangeListener).onDisplayInfoChanged(any(), any(), eq(CHANGE_DENSITY))
+ }
+}
diff --git a/tests/src/com/android/launcher3/util/IconSizeStepsTest.kt b/tests/src/com/android/launcher3/util/IconSizeStepsTest.kt
new file mode 100644
index 0000000..d9e3377
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/IconSizeStepsTest.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util
+
+import android.content.Context
+import android.content.res.Configuration
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.*
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class IconSizeStepsTest {
+ private var context: Context? = null
+ private val runningContext: Context = ApplicationProvider.getApplicationContext()
+ private lateinit var iconSizeSteps: IconSizeSteps
+
+ @Before
+ fun setup() {
+ // 160dp makes 1px = 1dp
+ val config =
+ Configuration(runningContext.resources.configuration).apply { this.densityDpi = 160 }
+ context = runningContext.createConfigurationContext(config)
+ iconSizeSteps = IconSizeSteps(context!!.resources)
+ }
+
+ @Test
+ fun minimumIconSize() {
+ assertThat(iconSizeSteps.minimumIconSize()).isEqualTo(52)
+ }
+
+ @Test
+ fun getNextLowerIconSize() {
+ assertThat(iconSizeSteps.getNextLowerIconSize(66)).isEqualTo(63)
+
+ // Assert that never goes below minimum
+ assertThat(iconSizeSteps.getNextLowerIconSize(52)).isEqualTo(52)
+ assertThat(iconSizeSteps.getNextLowerIconSize(30)).isEqualTo(52)
+ }
+
+ @Test
+ fun getIconSmallerThan() {
+ assertThat(iconSizeSteps.getIconSmallerThan(60)).isEqualTo(59)
+
+ // Assert that never goes below minimum
+ assertThat(iconSizeSteps.getIconSmallerThan(52)).isEqualTo(52)
+ assertThat(iconSizeSteps.getIconSmallerThan(30)).isEqualTo(52)
+ }
+}
diff --git a/tests/src/com/android/launcher3/util/LauncherModelHelper.java b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
index 976afcd..261436b 100644
--- a/tests/src/com/android/launcher3/util/LauncherModelHelper.java
+++ b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
@@ -15,34 +15,31 @@
*/
package com.android.launcher3.util;
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static android.content.pm.PackageInstaller.SessionParams.MODE_FULL_INSTALL;
+
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static com.android.launcher3.LauncherSettings.Favorites.CONTENT_URI;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.TestUtil.runOnExecutorSync;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageInstaller.SessionParams;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
-import android.content.res.Resources;
-import android.database.sqlite.SQLiteDatabase;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Color;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
-import android.os.Process;
import android.provider.Settings;
import android.test.mock.MockContentResolver;
import android.util.ArrayMap;
@@ -56,14 +53,10 @@
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherModel.ModelUpdateTask;
import com.android.launcher3.LauncherPrefs;
-import com.android.launcher3.LauncherProvider;
-import com.android.launcher3.LauncherSettings;
import com.android.launcher3.model.AllAppsList;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.model.ItemInstallQueue;
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.testing.TestInformationProvider;
@@ -72,37 +65,25 @@
import com.android.launcher3.util.window.WindowManagerProxy;
import com.android.launcher3.widget.custom.CustomWidgetManager;
-import org.mockito.ArgumentCaptor;
-
-import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
-import java.io.InputStreamReader;
+import java.io.IOException;
import java.io.OutputStreamWriter;
-import java.lang.reflect.Field;
-import java.util.HashMap;
-import java.util.List;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
-import java.util.function.Function;
/**
* Utility class to help manage Launcher Model and related objects for test.
*/
public class LauncherModelHelper {
- public static final int DESKTOP = LauncherSettings.Favorites.CONTAINER_DESKTOP;
- public static final int HOTSEAT = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
-
- public static final int APP_ICON = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
- public static final int SHORTCUT = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
- public static final int NO__ICON = -1;
-
- public static final String TEST_PACKAGE = testContext().getPackageName();
+ public static final String TEST_PACKAGE = getInstrumentation().getContext().getPackageName();
public static final String TEST_ACTIVITY = "com.android.launcher3.tests.Activity2";
+ public static final String TEST_ACTIVITY2 = "com.android.launcher3.tests.Activity3";
+ public static final String TEST_ACTIVITY3 = "com.android.launcher3.tests.Activity4";
// Authority for providing a test default-workspace-layout data.
private static final String TEST_PROVIDER_AUTHORITY =
@@ -110,39 +91,18 @@
private static final int DEFAULT_BITMAP_SIZE = 10;
private static final int DEFAULT_GRID_SIZE = 4;
- private final HashMap<Class, HashMap<String, Field>> mFieldCache = new HashMap<>();
- private final MockContentResolver mMockResolver = new MockContentResolver();
- public final TestLauncherProvider provider;
public final SandboxModelContext sandboxContext;
- public final long defaultProfileId;
+ private final RunnableList mDestroyTask = new RunnableList();
private BgDataModel mDataModel;
- private AllAppsList mAllAppsList;
public LauncherModelHelper() {
- Context context = getApplicationContext();
- // System settings cache content provider. Ensure that they are statically initialized
- Settings.Secure.getString(context.getContentResolver(), "test");
- Settings.System.getString(context.getContentResolver(), "test");
- Settings.Global.getString(context.getContentResolver(), "test");
-
- provider = new TestLauncherProvider();
sandboxContext = new SandboxModelContext();
- defaultProfileId = UserCache.INSTANCE.get(sandboxContext)
- .getSerialNumberForUser(Process.myUserHandle());
- setupProvider(LauncherProvider.AUTHORITY, provider);
}
public void setupProvider(String authority, ContentProvider provider) {
- ProviderInfo providerInfo = new ProviderInfo();
- providerInfo.authority = authority;
- providerInfo.applicationInfo = sandboxContext.getApplicationInfo();
- provider.attachInfo(sandboxContext, providerInfo);
- mMockResolver.addProvider(providerInfo.authority, provider);
- doReturn(providerInfo)
- .when(sandboxContext.mPm)
- .resolveContentProvider(eq(authority), anyInt());
+ sandboxContext.setupProvider(authority, provider);
}
public LauncherModel getModel() {
@@ -151,16 +111,35 @@
public synchronized BgDataModel getBgDataModel() {
if (mDataModel == null) {
- mDataModel = ReflectionHelpers.getField(getModel(), "mBgDataModel");
+ getModel().enqueueModelUpdateTask(new ModelUpdateTask() {
+ @Override
+ public void init(@NonNull LauncherAppState app, @NonNull LauncherModel model,
+ @NonNull BgDataModel dataModel, @NonNull AllAppsList allAppsList,
+ @NonNull Executor uiExecutor) {
+ mDataModel = dataModel;
+ }
+
+ @Override
+ public void run() { }
+ });
}
return mDataModel;
}
- public synchronized AllAppsList getAllAppsList() {
- if (mAllAppsList == null) {
- mAllAppsList = ReflectionHelpers.getField(getModel(), "mBgAllAppsList");
- }
- return mAllAppsList;
+ /**
+ * Creates a installer session for the provided package.
+ */
+ public int createInstallerSession(String pkg) throws IOException {
+ SessionParams sp = new SessionParams(MODE_FULL_INSTALL);
+ sp.setAppPackageName(pkg);
+ Bitmap icon = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+ icon.eraseColor(Color.RED);
+ sp.setAppIcon(icon);
+ sp.setAppLabel(pkg);
+ PackageInstaller pi = sandboxContext.getPackageManager().getPackageInstaller();
+ int sessionId = pi.createSession(sp);
+ mDestroyTask.add(() -> pi.abandonSession(sessionId));
+ return sessionId;
}
public void destroy() {
@@ -175,6 +154,8 @@
waitOrThrow(l1);
sandboxContext.onDestroy();
l2.countDown();
+
+ mDestroyTask.executeAllAndDestroy();
}
private void waitOrThrow(CountDownLatch latch) {
@@ -186,184 +167,6 @@
}
/**
- * Synchronously executes the task and returns all the UI callbacks posted.
- */
- public List<Runnable> executeTaskForTest(ModelUpdateTask task) throws Exception {
- LauncherModel model = getModel();
- if (!model.isModelLoaded()) {
- ReflectionHelpers.setField(model, "mModelLoaded", true);
- }
- Executor mockExecutor = mock(Executor.class);
- model.enqueueModelUpdateTask(new ModelUpdateTask() {
- @Override
- public void init(@NonNull final LauncherAppState app,
- @NonNull final LauncherModel model, @NonNull final BgDataModel dataModel,
- @NonNull final AllAppsList allAppsList, @NonNull final Executor uiExecutor) {
- task.init(app, model, dataModel, allAppsList, mockExecutor);
- }
-
- @Override
- public void run() {
- task.run();
- }
- });
- MODEL_EXECUTOR.submit(() -> null).get();
-
- ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
- verify(mockExecutor, atLeast(0)).execute(captor.capture());
- return captor.getAllValues();
- }
-
- /**
- * Synchronously executes a task on the model
- */
- public <T> T executeSimpleTask(Function<BgDataModel, T> task) throws Exception {
- BgDataModel dataModel = getBgDataModel();
- return MODEL_EXECUTOR.submit(() -> task.apply(dataModel)).get();
- }
-
- /**
- * Initializes mock data for the test.
- */
- public void initializeData(String resourceName) throws Exception {
- BgDataModel bgDataModel = getBgDataModel();
- AllAppsList allAppsList = getAllAppsList();
-
- MODEL_EXECUTOR.submit(() -> {
- // Copy apk from resources to a local file and install from there.
- Resources resources = testContext().getResources();
- int resId = resources.getIdentifier(
- resourceName, "raw", testContext().getPackageName());
- try (BufferedReader reader = new BufferedReader(new InputStreamReader(
- resources.openRawResource(resId)))) {
- String line;
- HashMap<String, Class> classMap = new HashMap<>();
- while ((line = reader.readLine()) != null) {
- line = line.trim();
- if (line.startsWith("#") || line.isEmpty()) {
- continue;
- }
- String[] commands = line.split(" ");
- switch (commands[0]) {
- case "classMap":
- classMap.put(commands[1], Class.forName(commands[2]));
- break;
- case "bgItem":
- bgDataModel.addItem(sandboxContext,
- (ItemInfo) initItem(classMap.get(commands[1]), commands, 2),
- false);
- break;
- case "allApps":
- allAppsList.add((AppInfo) initItem(AppInfo.class, commands, 1), null);
- break;
- }
- }
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }).get();
- }
-
- private Object initItem(Class clazz, String[] fieldDef, int startIndex) throws Exception {
- HashMap<String, Field> cache = mFieldCache.get(clazz);
- if (cache == null) {
- cache = new HashMap<>();
- Class c = clazz;
- while (c != null) {
- for (Field f : c.getDeclaredFields()) {
- f.setAccessible(true);
- cache.put(f.getName(), f);
- }
- c = c.getSuperclass();
- }
- mFieldCache.put(clazz, cache);
- }
-
- Object item = clazz.newInstance();
- for (int i = startIndex; i < fieldDef.length; i++) {
- String[] fieldData = fieldDef[i].split("=", 2);
- Field f = cache.get(fieldData[0]);
- Class type = f.getType();
- if (type == int.class || type == long.class) {
- f.set(item, Integer.parseInt(fieldData[1]));
- } else if (type == CharSequence.class || type == String.class) {
- f.set(item, fieldData[1]);
- } else if (type == Intent.class) {
- if (!fieldData[1].startsWith("#Intent")) {
- fieldData[1] = "#Intent;" + fieldData[1] + ";end";
- }
- f.set(item, Intent.parseUri(fieldData[1], 0));
- } else if (type == ComponentName.class) {
- f.set(item, ComponentName.unflattenFromString(fieldData[1]));
- } else {
- throw new Exception("Added parsing logic for "
- + f.getName() + " of type " + f.getType());
- }
- }
- return item;
- }
-
- public int addItem(int type, int screen, int container, int x, int y) {
- return addItem(type, screen, container, x, y, defaultProfileId, TEST_PACKAGE);
- }
-
- public int addItem(int type, int screen, int container, int x, int y, long profileId) {
- return addItem(type, screen, container, x, y, profileId, TEST_PACKAGE);
- }
-
- public int addItem(int type, int screen, int container, int x, int y, String packageName) {
- return addItem(type, screen, container, x, y, defaultProfileId, packageName);
- }
-
- public int addItem(int type, int screen, int container, int x, int y, String packageName,
- int id, Uri contentUri) {
- addItem(type, screen, container, x, y, defaultProfileId, packageName, id, contentUri);
- return id;
- }
-
- /**
- * Adds a mock item in the DB.
- * @param type {@link #APP_ICON} or {@link #SHORTCUT} or >= 2 for
- * folder (where the type represents the number of items in the folder).
- */
- public int addItem(int type, int screen, int container, int x, int y, long profileId,
- String packageName) {
- int id = LauncherSettings.Settings.call(sandboxContext.getContentResolver(),
- LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
- .getInt(LauncherSettings.Settings.EXTRA_VALUE);
- addItem(type, screen, container, x, y, profileId, packageName, id, CONTENT_URI);
- return id;
- }
-
- public void addItem(int type, int screen, int container, int x, int y, long profileId,
- String packageName, int id, Uri contentUri) {
- ContentValues values = new ContentValues();
- values.put(LauncherSettings.Favorites._ID, id);
- values.put(LauncherSettings.Favorites.CONTAINER, container);
- values.put(LauncherSettings.Favorites.SCREEN, screen);
- values.put(LauncherSettings.Favorites.CELLX, x);
- values.put(LauncherSettings.Favorites.CELLY, y);
- values.put(LauncherSettings.Favorites.SPANX, 1);
- values.put(LauncherSettings.Favorites.SPANY, 1);
- values.put(LauncherSettings.Favorites.PROFILE_ID, profileId);
-
- if (type == APP_ICON || type == SHORTCUT) {
- values.put(LauncherSettings.Favorites.ITEM_TYPE, type);
- values.put(LauncherSettings.Favorites.INTENT,
- new Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0));
- } else {
- values.put(LauncherSettings.Favorites.ITEM_TYPE,
- LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
- // Add folder items.
- for (int i = 0; i < type; i++) {
- addItem(APP_ICON, 0, id, 0, 0, profileId);
- }
- }
-
- sandboxContext.getContentResolver().insert(contentUri, values);
- }
-
- /**
* Sets up a mock provider to load the provided layout by default, next time the layout loads
*/
public LauncherModelHelper setupDefaultLayoutProvider(LauncherLayoutBuilder builder)
@@ -394,6 +197,9 @@
}
};
setupProvider(TEST_PROVIDER_AUTHORITY, cp);
+ mDestroyTask.add(() -> runOnExecutorSync(MODEL_EXECUTOR, () ->
+ UiDevice.getInstance(getInstrumentation()).executeShellCommand(
+ "settings delete secure launcher3.layout.provider")));
return this;
}
@@ -402,46 +208,16 @@
*/
public void loadModelSync() throws ExecutionException, InterruptedException {
Callbacks mockCb = new Callbacks() { };
- Executors.MAIN_EXECUTOR.submit(() -> getModel().addCallbacksAndLoad(mockCb)).get();
+ MAIN_EXECUTOR.submit(() -> getModel().addCallbacksAndLoad(mockCb)).get();
Executors.MODEL_EXECUTOR.submit(() -> { }).get();
- Executors.MAIN_EXECUTOR.submit(() -> { }).get();
- Executors.MAIN_EXECUTOR.submit(() -> getModel().removeCallbacks(mockCb)).get();
+ MAIN_EXECUTOR.submit(() -> { }).get();
+ MAIN_EXECUTOR.submit(() -> getModel().removeCallbacks(mockCb)).get();
}
- /**
- * An extension of LauncherProvider backed up by in-memory database.
- */
- public static class TestLauncherProvider extends LauncherProvider {
+ public static class SandboxModelContext extends SandboxContext {
- @Override
- public boolean onCreate() {
- return true;
- }
-
- public SQLiteDatabase getDb() {
- return getModelDbController().getDb();
- }
- }
-
- public static boolean deleteContents(File dir) {
- File[] files = dir.listFiles();
- boolean success = true;
- if (files != null) {
- for (File file : files) {
- if (file.isDirectory()) {
- success &= deleteContents(file);
- }
- if (!file.delete()) {
- success = false;
- }
- }
- }
- return success;
- }
-
- public class SandboxModelContext extends SandboxContext {
-
+ private final MockContentResolver mMockResolver = new MockContentResolver();
private final ArrayMap<String, Object> mSpiedServices = new ArrayMap<>();
private final PackageManager mPm;
private final File mDbDir;
@@ -451,12 +227,30 @@
UserCache.INSTANCE, InstallSessionHelper.INSTANCE, LauncherPrefs.INSTANCE,
LauncherAppState.INSTANCE, InvariantDeviceProfile.INSTANCE,
DisplayController.INSTANCE, CustomWidgetManager.INSTANCE,
- SettingsCache.INSTANCE, PluginManagerWrapper.INSTANCE, LockedUserState.INSTANCE,
+ SettingsCache.INSTANCE, PluginManagerWrapper.INSTANCE,
+ LockedUserState.INSTANCE, WallpaperColorHints.INSTANCE,
ItemInstallQueue.INSTANCE, WindowManagerProxy.INSTANCE);
+
+ // System settings cache content provider. Ensure that they are statically initialized
+ Settings.Secure.getString(
+ ApplicationProvider.getApplicationContext().getContentResolver(), "test");
+ Settings.System.getString(
+ ApplicationProvider.getApplicationContext().getContentResolver(), "test");
+ Settings.Global.getString(
+ ApplicationProvider.getApplicationContext().getContentResolver(), "test");
+
mPm = spy(getBaseContext().getPackageManager());
mDbDir = new File(getCacheDir(), UUID.randomUUID().toString());
}
+ @Override
+ protected <T> T createObject(MainThreadInitializedObject<T> object) {
+ if (object == LauncherAppState.INSTANCE) {
+ return (T) new LauncherAppState(this, null /* iconCacheFileName */);
+ }
+ return super.createObject(object);
+ }
+
public SandboxModelContext allow(MainThreadInitializedObject object) {
mAllowedObjects.add(object);
return this;
@@ -505,9 +299,30 @@
mSpiedServices.put(name, result);
return result;
}
- }
- private static Context testContext() {
- return getInstrumentation().getContext();
+ public void setupProvider(String authority, ContentProvider provider) {
+ ProviderInfo providerInfo = new ProviderInfo();
+ providerInfo.authority = authority;
+ providerInfo.applicationInfo = getApplicationInfo();
+ provider.attachInfo(this, providerInfo);
+ mMockResolver.addProvider(providerInfo.authority, provider);
+ doReturn(providerInfo).when(mPm).resolveContentProvider(eq(authority), anyInt());
+ }
+
+ private static boolean deleteContents(File dir) {
+ File[] files = dir.listFiles();
+ boolean success = true;
+ if (files != null) {
+ for (File file : files) {
+ if (file.isDirectory()) {
+ success &= deleteContents(file);
+ }
+ if (!file.delete()) {
+ success = false;
+ }
+ }
+ }
+ return success;
+ }
}
}
diff --git a/tests/src/com/android/launcher3/util/LockedUserStateTest.kt b/tests/src/com/android/launcher3/util/LockedUserStateTest.kt
index 84156e7..92ab2cb 100644
--- a/tests/src/com/android/launcher3/util/LockedUserStateTest.kt
+++ b/tests/src/com/android/launcher3/util/LockedUserStateTest.kt
@@ -32,7 +32,7 @@
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
-/** Unit tests for {@link LockedUserUtil} */
+/** Unit tests for {@link LockedUserState} */
@SmallTest
@RunWith(AndroidJUnit4::class)
class LockedUserStateTest {
@@ -49,40 +49,31 @@
@Test
fun runOnUserUnlocked_runs_action_immediately_if_already_unlocked() {
`when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(true)
- LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
val action: Runnable = mock()
-
- LockedUserState.get(context).runOnUserUnlocked(action)
+ LockedUserState(context).runOnUserUnlocked(action)
verify(action).run()
}
@Test
fun runOnUserUnlocked_waits_to_run_action_until_user_is_unlocked() {
`when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(false)
- LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
val action: Runnable = mock()
-
- LockedUserState.get(context).runOnUserUnlocked(action)
+ val state = LockedUserState(context)
+ state.runOnUserUnlocked(action)
verifyZeroInteractions(action)
-
- LockedUserState.get(context)
- .mUserUnlockedReceiver
- .onReceive(context, Intent(Intent.ACTION_USER_UNLOCKED))
-
+ state.mUserUnlockedReceiver.onReceive(context, Intent(Intent.ACTION_USER_UNLOCKED))
verify(action).run()
}
@Test
fun isUserUnlocked_returns_true_when_user_is_unlocked() {
`when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(true)
- LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
- assertThat(LockedUserState.get(context).isUserUnlocked).isTrue()
+ assertThat(LockedUserState(context).isUserUnlocked).isTrue()
}
@Test
fun isUserUnlocked_returns_false_when_user_is_locked() {
`when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(false)
- LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
- assertThat(LockedUserState.get(context).isUserUnlocked).isFalse()
+ assertThat(LockedUserState(context).isUserUnlocked).isFalse()
}
}
diff --git a/tests/src/com/android/launcher3/util/RaceConditionReproducer.java b/tests/src/com/android/launcher3/util/RaceConditionReproducer.java
deleted file mode 100644
index ed2ec7b..0000000
--- a/tests/src/com/android/launcher3/util/RaceConditionReproducer.java
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.util;
-
-import static com.android.launcher3.util.Executors.createAndStartNewLooper;
-
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.os.Handler;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Event processor for reliably reproducing multithreaded apps race conditions in tests.
- *
- * The app notifies us about “events” that happen in its threads. The race condition test runs the
- * test action multiple times (aka iterations), trying to generate all possible permutations of
- * these events. It keeps a set of all seen event sequences and steers the execution towards
- * executing events in previously unseen order. It does it by postponing execution of threads that
- * would lead to an already seen sequence.
- *
- * If an event A occurs before event B in the sequence, this is how execution order looks like:
- * Events: ... A ... B ...
- * Events and instructions, guaranteed order:
- * (instructions executed prior to A) A ... B (instructions executed after B)
- *
- * Each iteration has 3 parts (phases).
- * Phase 1. Picking a previously seen event subsequence that we believe can have previously unseen
- * continuations. Reproducing this sequence by pausing threads that would lead to other sequences.
- * Phase 2. Trying to generate previously unseen continuation of the sequence from Phase 1. We need
- * one new event after that sequence. All threads leading to seen continuations will be postponed
- * for some short period of time. The phase ends once the new event is registered, or after the
- * period of time ends (in which case we declare that the sequence can’t have new continuations).
- * Phase 3. Releasing all threads and letting the test iteration run till its end.
- *
- * The iterations end when all seen paths have been declared “uncontinuable”.
- *
- * When we register event XXX:enter, we hold all other events until we register XXX:exit.
- */
-public class RaceConditionReproducer {
- private static final String TAG = "RaceConditionReproducer";
-
- private static final boolean ENTER = true;
- private static final boolean EXIT = false;
- private static final String ENTER_POSTFIX = "enter";
- private static final String EXIT_POSTFIX = "exit";
-
- private static final long SHORT_TIMEOUT_MS = 2000;
- private static final long LONG_TIMEOUT_MS = 60000;
- // Handler used to resume postponed events.
- private static final Handler POSTPONED_EVENT_RESUME_HANDLER =
- new Handler(createAndStartNewLooper("RaceConditionEventResumer"));
-
- public static String enterExitEvt(String eventName, boolean isEnter) {
- return eventName + ":" + (isEnter ? ENTER_POSTFIX : EXIT_POSTFIX);
- }
-
- public static String enterEvt(String eventName) {
- return enterExitEvt(eventName, ENTER);
- }
-
- public static String exitEvt(String eventName) {
- return enterExitEvt(eventName, EXIT);
- }
-
- /**
- * Event in a particular sequence of events. A node in the prefix tree of all seen event
- * sequences.
- */
- private class EventNode {
- // Events that were seen just after this event.
- private final Map<String, EventNode> mNextEvents = new HashMap<>();
- // Whether we believe that further iterations will not be able to add more events to
- // mNextEvents.
- private boolean mStoppedAddingChildren = true;
-
- private void debugDump(StringBuilder sb, int indent, String name) {
- for (int i = 0; i < indent; ++i) sb.append('.');
- sb.append(!mStoppedAddingChildren ? "+" : "-");
- sb.append(" : ");
- sb.append(name);
- if (mLastRegisteredEvent == this) sb.append(" <");
- sb.append('\n');
-
- for (String key : mNextEvents.keySet()) {
- mNextEvents.get(key).debugDump(sb, indent + 2, key);
- }
- }
-
- /** Number of leaves in the subtree with this node as a root. */
- private int numberOfLeafNodes() {
- if (mNextEvents.isEmpty()) return 1;
-
- int leaves = 0;
- for (String event : mNextEvents.keySet()) {
- leaves += mNextEvents.get(event).numberOfLeafNodes();
- }
- return leaves;
- }
-
- /**
- * Whether we believe that further iterations will not be able add nodes to the subtree with
- * this node as a root.
- */
- private boolean stoppedAddingChildrenToTree() {
- if (!mStoppedAddingChildren) return false;
-
- for (String event : mNextEvents.keySet()) {
- if (!mNextEvents.get(event).stoppedAddingChildrenToTree()) return false;
- }
- return true;
- }
-
- /**
- * In the subtree with this node as a root, tries finding a node where we may have a
- * chance to add new children.
- * If succeeds, returns true and fills 'path' with the sequence of events to that node;
- * otherwise returns false.
- */
- private boolean populatePathToGrowthPoint(List<String> path) {
- for (String event : mNextEvents.keySet()) {
- if (mNextEvents.get(event).populatePathToGrowthPoint(path)) {
- path.add(0, event);
- return true;
- }
- }
- if (!mStoppedAddingChildren) {
- // Mark that we have finished adding children. It will remain true if no new
- // children are added, or will be set to false upon adding a new child.
- mStoppedAddingChildren = true;
- return true;
- }
- return false;
- }
- }
-
- // Starting point of all event sequences; the root of the prefix tree representation all
- // sequences generated by test iterations. A test iteration can add nodes int it.
- private EventNode mRoot = new EventNode();
- // During a test iteration, the last event that was registered.
- private EventNode mLastRegisteredEvent;
- // Length of the current sequence of registered events for the current test iteration.
- private int mRegisteredEventCount = 0;
- // During the first part of a test iteration, we go to a specific node under mRoot by
- // 'playing back' mSequenceToFollow. During this part, all events that don't belong to this
- // sequence get postponed.
- private List<String> mSequenceToFollow = new ArrayList<>();
- // Collection of events that got postponed, with corresponding wait objects used to let them go.
- private Map<String, Semaphore> mPostponedEvents = new HashMap<>();
- // Callback to run by POSTPONED_EVENT_RESUME_HANDLER, used to let go of all currently
- // postponed events.
- private Runnable mResumeAllEventsCallback;
- // String representation of the sequence of events registered so far for the current test
- // iteration. After registering any event, we output it to the log. The last output before
- // the test failure can be later played back to reliable reproduce the exact sequence of
- // events that broke the test.
- // Format: EV1|EV2|...\EVN
- private StringBuilder mCurrentSequence;
- // When not null, we are in a repro mode. We run only one test iteration, and are trying to
- // reproduce the event sequence represented by this string. The format is same as for
- // mCurrentSequence.
- private final String mReproString;
-
- /* Constructor for a normal test. */
- public RaceConditionReproducer() {
- mReproString = null;
- }
-
- /**
- * Constructor for reliably reproducing a race condition failure. The developer should find in
- * the log the latest "Repro sequence:" record and locally modify the test by passing that
- * string to the constructor. Running the test will have only one iteration that will reliably
- * "play back" that sequence.
- */
- public RaceConditionReproducer(String reproString) {
- mReproString = reproString;
- }
-
- public RaceConditionReproducer(String... reproSequence) {
- this(String.join("|", reproSequence));
- }
-
- public synchronized String getCurrentSequenceString() {
- return mCurrentSequence.toString();
- }
-
- /**
- * Starts a new test iteration. Events reported via RaceConditionTracker.onEvent before this
- * call will be ignored.
- */
- public synchronized void startIteration() {
- mLastRegisteredEvent = mRoot;
- mRegisteredEventCount = 0;
- mCurrentSequence = new StringBuilder();
- Log.d(TAG, "Repro sequence: " + mCurrentSequence);
- mSequenceToFollow = mReproString != null ?
- parseReproString(mReproString) : generateSequenceToFollowLocked();
- Log.e(TAG, "---- Start of iteration; state:\n" + dumpStateLocked());
- checkIfCompletedSequenceToFollowLocked();
-
- TraceHelperForTest.setRaceConditionReproducer(this);
- }
-
- /**
- * Ends a new test iteration. Events reported via RaceConditionTracker.onEvent after this call
- * will be ignored.
- * Returns whether we need more iterations.
- */
- public synchronized boolean finishIteration() {
- TraceHelperForTest.setRaceConditionReproducer(null);
-
- runResumeAllEventsCallbackLocked();
- assertTrue("Non-empty postponed events", mPostponedEvents.isEmpty());
- assertTrue("Last registered event is :enter", lastEventAsEnter() == null);
-
- // No events came after mLastRegisteredEvent. It doesn't make sense to come to it again
- // because we won't see new continuations.
- mLastRegisteredEvent.mStoppedAddingChildren = true;
- Log.e(TAG, "---- End of iteration; state:\n" + dumpStateLocked());
- if (mReproString != null) {
- assertTrue("Repro mode: failed to reproduce the sequence",
- mCurrentSequence.toString().startsWith(mReproString));
- }
- // If we are in a repro mode, we need only one iteration. Otherwise, continue if the tree
- // has prospective growth points.
- return mReproString == null && !mRoot.stoppedAddingChildrenToTree();
- }
-
- private static List<String> parseReproString(String reproString) {
- return Arrays.asList(reproString.split("\\|"));
- }
-
- /**
- * Called when the app issues an event.
- */
- public void onEvent(String event) {
- final Semaphore waitObject = tryRegisterEvent(event);
- if (waitObject != null) {
- waitUntilCanRegister(event, waitObject);
- }
- }
-
- /**
- * Returns whether the last event was not an XXX:enter, or this event is a matching XXX:exit.
- */
- private boolean canRegisterEventNowLocked(String event) {
- final String lastEventAsEnter = lastEventAsEnter();
- final String thisEventAsExit = eventAsExit(event);
-
- if (lastEventAsEnter != null) {
- if (!lastEventAsEnter.equals(thisEventAsExit)) {
- assertTrue("YYY:exit after XXX:enter", thisEventAsExit == null);
- // Last event was :enter, but this event is not :exit.
- return false;
- }
- } else {
- // Previous event was not :enter.
- assertTrue(":exit after a non-enter event", thisEventAsExit == null);
- }
- return true;
- }
-
- /**
- * Registers an event issued by the app and returns null or decides that the event must be
- * postponed, and returns an object to wait on.
- */
- private synchronized Semaphore tryRegisterEvent(String event) {
- Log.d(TAG, "Event issued by the app: " + event);
-
- if (!canRegisterEventNowLocked(event)) {
- return createWaitObjectForPostponedEventLocked(event);
- }
-
- if (mRegisteredEventCount < mSequenceToFollow.size()) {
- // We are in the first part of the iteration. We only register events that follow the
- // mSequenceToFollow and postponing all other events.
- if (event.equals(mSequenceToFollow.get(mRegisteredEventCount))) {
- // The event is the next one expected in the sequence. Register it.
- registerEventLocked(event);
-
- // If there are postponed events that could continue the sequence, register them.
- while (mRegisteredEventCount < mSequenceToFollow.size() &&
- mPostponedEvents.containsKey(
- mSequenceToFollow.get(mRegisteredEventCount))) {
- registerPostponedEventLocked(mSequenceToFollow.get(mRegisteredEventCount));
- }
-
- // Perhaps we just completed the required sequence...
- checkIfCompletedSequenceToFollowLocked();
- } else {
- // The event is not the next one in the sequence. Postpone it.
- return createWaitObjectForPostponedEventLocked(event);
- }
- } else if (mRegisteredEventCount == mSequenceToFollow.size()) {
- // The second phase of the iteration. We have just registered the whole
- // mSequenceToFollow, and want to add previously not seen continuations for the last
- // node in the sequence aka 'growth point'.
- if (!mLastRegisteredEvent.mNextEvents.containsKey(event) || mReproString != null) {
- // The event was never seen as a continuation for the current node.
- // Or we are in repro mode, in which case we are not in business of generating
- // new sequences after we've played back the required sequence.
- // Register it immediately.
- registerEventLocked(event);
- } else {
- // The event was seen as a continuation for the current node. Postpone it, hoping
- // that a new event will come from other threads.
- return createWaitObjectForPostponedEventLocked(event);
- }
- } else {
- // The third phase of the iteration. We are past the growth point and register
- // everything that comes.
- registerEventLocked(event);
- // Register events that may have been postponed while waiting for an :exit event
- // during the third phase. We don't do this if just registered event is :enter.
- if (eventAsEnter(event) == null && mRegisteredEventCount > mSequenceToFollow.size()) {
- registerPostponedEventsLocked(new HashSet<>(mPostponedEvents.keySet()));
- }
- }
- return null;
- }
-
- /** Called when there are chances that we just have registered the whole mSequenceToFollow. */
- private void checkIfCompletedSequenceToFollowLocked() {
- if (mRegisteredEventCount == mSequenceToFollow.size()) {
- // We just entered the second phase of the iteration. We have just registered the
- // whole mSequenceToFollow, and want to add previously not seen continuations for the
- // last node in the sequence aka 'growth point'. All seen continuations will be
- // postponed for SHORT_TIMEOUT_MS. At the end of this time period, we'll let them go.
- scheduleResumeAllEventsLocked();
-
- // Among the events that were postponed during the first stage, there may be an event
- // that wasn't seen after the current. If so, register it immediately because this
- // creates a new sequence.
- final Set<String> keys = new HashSet<>(mPostponedEvents.keySet());
- keys.removeAll(mLastRegisteredEvent.mNextEvents.keySet());
- if (!keys.isEmpty()) {
- registerPostponedEventLocked(keys.iterator().next());
- }
- }
- }
-
- private Semaphore createWaitObjectForPostponedEventLocked(String event) {
- final Semaphore waitObject = new Semaphore(0);
- assertTrue("Event already postponed: " + event, !mPostponedEvents.containsKey(event));
- mPostponedEvents.put(event, waitObject);
- return waitObject;
- }
-
- private void waitUntilCanRegister(String event, Semaphore waitObject) {
- try {
- assertTrue("Never registered event: " + event,
- waitObject.tryAcquire(LONG_TIMEOUT_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e) {
- fail("Wait was interrupted");
- }
- }
-
- /** Schedules resuming all postponed events after SHORT_TIMEOUT_MS */
- private void scheduleResumeAllEventsLocked() {
- assertTrue(mResumeAllEventsCallback == null);
- mResumeAllEventsCallback = this::allEventsResumeCallback;
- POSTPONED_EVENT_RESUME_HANDLER.postDelayed(mResumeAllEventsCallback, SHORT_TIMEOUT_MS);
- }
-
- private synchronized void allEventsResumeCallback() {
- assertTrue("In callback, but callback is not set", mResumeAllEventsCallback != null);
- mResumeAllEventsCallback = null;
- registerPostponedEventsLocked(new HashSet<>(mPostponedEvents.keySet()));
- }
-
- private void registerPostponedEventsLocked(Collection<String> events) {
- for (String event : events) {
- registerPostponedEventLocked(event);
- if (eventAsEnter(event) != null) {
- // Once :enter is registered, switch to waiting for :exit to come. Won't register
- // other postponed events.
- break;
- }
- }
- }
-
- private void registerPostponedEventLocked(String event) {
- mPostponedEvents.remove(event).release();
- registerEventLocked(event);
- }
-
- /**
- * If the last registered event was XXX:enter, returns XXX, otherwise, null.
- */
- private String lastEventAsEnter() {
- return eventAsEnter(mCurrentSequence.substring(mCurrentSequence.lastIndexOf("|") + 1));
- }
-
- /**
- * If the event is XXX:postfix, returns XXX, otherwise, null.
- */
- private static String prefixFromPostfixedEvent(String event, String postfix) {
- final int columnPos = event.indexOf(':');
- if (columnPos != -1 && postfix.equals(event.substring(columnPos + 1))) {
- return event.substring(0, columnPos);
- }
- return null;
- }
-
- /**
- * If the event is XXX:enter, returns XXX, otherwise, null.
- */
- private static String eventAsEnter(String event) {
- return prefixFromPostfixedEvent(event, ENTER_POSTFIX);
- }
-
- /**
- * If the event is XXX:exit, returns XXX, otherwise, null.
- */
- private static String eventAsExit(String event) {
- return prefixFromPostfixedEvent(event, EXIT_POSTFIX);
- }
-
- private void registerEventLocked(String event) {
- assertTrue(canRegisterEventNowLocked(event));
-
- Log.d(TAG, "Actually registering event: " + event);
- EventNode next = mLastRegisteredEvent.mNextEvents.get(event);
- if (next == null) {
- // This event wasn't seen after mLastRegisteredEvent.
- next = new EventNode();
- mLastRegisteredEvent.mNextEvents.put(event, next);
- // The fact that we've added a new event after the previous one means that the
- // previous event is still a growth point, unless this event is :exit, which means
- // that the previous event is :enter.
- mLastRegisteredEvent.mStoppedAddingChildren = eventAsExit(event) != null;
- }
-
- mLastRegisteredEvent = next;
- mRegisteredEventCount++;
-
- if (mCurrentSequence.length() > 0) mCurrentSequence.append("|");
- mCurrentSequence.append(event);
- Log.d(TAG, "Repro sequence: " + mCurrentSequence);
- }
-
- private void runResumeAllEventsCallbackLocked() {
- if (mResumeAllEventsCallback != null) {
- POSTPONED_EVENT_RESUME_HANDLER.removeCallbacks(mResumeAllEventsCallback);
- mResumeAllEventsCallback.run();
- }
- }
-
- private CharSequence dumpStateLocked() {
- StringBuilder sb = new StringBuilder();
-
- sb.append("Sequence to follow: ");
- for (String event : mSequenceToFollow) sb.append(" " + event);
- sb.append(".\n");
- sb.append("Registered event count: " + mRegisteredEventCount);
-
- sb.append("\nPostponed events: ");
- for (String event : mPostponedEvents.keySet()) sb.append(" " + event);
- sb.append(".");
-
- sb.append("\nNodes: \n");
- mRoot.debugDump(sb, 0, "");
- return sb;
- }
-
- public int numberOfLeafNodes() {
- return mRoot.numberOfLeafNodes();
- }
-
- private List<String> generateSequenceToFollowLocked() {
- ArrayList<String> sequence = new ArrayList<>();
- mRoot.populatePathToGrowthPoint(sequence);
- return sequence;
- }
-}
diff --git a/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java b/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java
deleted file mode 100644
index 59f2173..0000000
--- a/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.util;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import androidx.test.filters.LargeTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@LargeTest
-@RunWith(AndroidJUnit4.class)
-public class RaceConditionReproducerTest {
- private final static String SOME_VALID_SEQUENCE_3_3 = "B1|A1|A2|B2|A3|B3";
-
- private static int factorial(int n) {
- int res = 1;
- for (int i = 2; i <= n; ++i) res *= i;
- return res;
- }
-
- RaceConditionReproducer eventProcessor;
-
- @Before
- public void setup() {
- eventProcessor = new RaceConditionReproducer();
- }
-
- @After
- public void tearDown() {
- TraceHelperForTest.cleanup();
- }
-
- private void run3_3_TestAction() throws InterruptedException {
- Thread tb = new Thread(() -> {
- eventProcessor.onEvent("B1");
- eventProcessor.onEvent("B2");
- eventProcessor.onEvent("B3");
- });
- tb.start();
-
- eventProcessor.onEvent("A1");
- eventProcessor.onEvent("A2");
- eventProcessor.onEvent("A3");
-
- tb.join();
- }
-
- @Test
- @Ignore // The test is too long for continuous testing.
- // 2 threads, 3 events each.
- public void test3_3() throws Exception {
- boolean sawTheValidSequence = false;
-
- for (; ; ) {
- eventProcessor.startIteration();
- run3_3_TestAction();
- final boolean needMoreIterations = eventProcessor.finishIteration();
-
- sawTheValidSequence = sawTheValidSequence ||
- SOME_VALID_SEQUENCE_3_3.equals(eventProcessor.getCurrentSequenceString());
-
- if (!needMoreIterations) break;
- }
-
- assertEquals("Wrong number of leaf nodes",
- factorial(3 + 3) / (factorial(3) * factorial(3)),
- eventProcessor.numberOfLeafNodes());
- assertTrue(sawTheValidSequence);
- }
-
- @Test
- @Ignore // The test is too long for continuous testing.
- // 2 threads, 3 events, including enter-exit pairs each.
- public void test3_3_enter_exit() throws Exception {
- boolean sawTheValidSequence = false;
-
- for (; ; ) {
- eventProcessor.startIteration();
- Thread tb = new Thread(() -> {
- eventProcessor.onEvent("B1:enter");
- eventProcessor.onEvent("B1:exit");
- eventProcessor.onEvent("B2");
- eventProcessor.onEvent("B3:enter");
- eventProcessor.onEvent("B3:exit");
- });
- tb.start();
-
- eventProcessor.onEvent("A1");
- eventProcessor.onEvent("A2:enter");
- eventProcessor.onEvent("A2:exit");
- eventProcessor.onEvent("A3:enter");
- eventProcessor.onEvent("A3:exit");
-
- tb.join();
- final boolean needMoreIterations = eventProcessor.finishIteration();
-
- sawTheValidSequence = sawTheValidSequence ||
- "B1:enter|B1:exit|A1|A2:enter|A2:exit|B2|A3:enter|A3:exit|B3:enter|B3:exit".
- equals(eventProcessor.getCurrentSequenceString());
-
- if (!needMoreIterations) break;
- }
-
- assertEquals("Wrong number of leaf nodes",
- factorial(3 + 3) / (factorial(3) * factorial(3)),
- eventProcessor.numberOfLeafNodes());
- assertTrue(sawTheValidSequence);
- }
-
- @Test
- // 2 threads, 3 events each; reproducing a particular event sequence.
- public void test3_3_ReproMode() throws Exception {
- eventProcessor = new RaceConditionReproducer(SOME_VALID_SEQUENCE_3_3);
- eventProcessor.startIteration();
- run3_3_TestAction();
- assertTrue(!eventProcessor.finishIteration());
- assertEquals(SOME_VALID_SEQUENCE_3_3, eventProcessor.getCurrentSequenceString());
-
- assertEquals("Wrong number of leaf nodes", 1, eventProcessor.numberOfLeafNodes());
- }
-
- @Test
- @Ignore // The test is too long for continuous testing.
- // 2 threads with 2 events; 1 thread with 1 event.
- public void test2_1_2() throws Exception {
- for (; ; ) {
- eventProcessor.startIteration();
- Thread tb = new Thread(() -> {
- eventProcessor.onEvent("B1");
- eventProcessor.onEvent("B2");
- });
- tb.start();
-
- Thread tc = new Thread(() -> {
- eventProcessor.onEvent("C1");
- });
- tc.start();
-
- eventProcessor.onEvent("A1");
- eventProcessor.onEvent("A2");
-
- tb.join();
- tc.join();
-
- if (!eventProcessor.finishIteration()) break;
- }
-
- assertEquals("Wrong number of leaf nodes",
- factorial(2 + 2 + 1) / (factorial(2) * factorial(2) * factorial(1)),
- eventProcessor.numberOfLeafNodes());
- }
-
- @Test
- @Ignore // The test is too long for continuous testing.
- // 2 threads with 2 events; 1 thread with 1 event. Includes enter-exit pairs.
- public void test2_1_2_enter_exit() throws Exception {
- for (; ; ) {
- eventProcessor.startIteration();
- Thread tb = new Thread(() -> {
- eventProcessor.onEvent("B1:enter");
- eventProcessor.onEvent("B1:exit");
- eventProcessor.onEvent("B2:enter");
- eventProcessor.onEvent("B2:exit");
- });
- tb.start();
-
- Thread tc = new Thread(() -> {
- eventProcessor.onEvent("C1:enter");
- eventProcessor.onEvent("C1:exit");
- });
- tc.start();
-
- eventProcessor.onEvent("A1:enter");
- eventProcessor.onEvent("A1:exit");
- eventProcessor.onEvent("A2:enter");
- eventProcessor.onEvent("A2:exit");
-
- tb.join();
- tc.join();
-
- if (!eventProcessor.finishIteration()) break;
- }
-
- assertEquals("Wrong number of leaf nodes",
- factorial(2 + 2 + 1) / (factorial(2) * factorial(2) * factorial(1)),
- eventProcessor.numberOfLeafNodes());
- }
-}
diff --git a/tests/src/com/android/launcher3/util/TestResourceHelper.kt b/tests/src/com/android/launcher3/util/TestResourceHelper.kt
index fb03fe1..cf80ece 100644
--- a/tests/src/com/android/launcher3/util/TestResourceHelper.kt
+++ b/tests/src/com/android/launcher3/util/TestResourceHelper.kt
@@ -23,12 +23,18 @@
import com.android.launcher3.tests.R as TestR
import kotlin.IntArray
-class TestResourceHelper(private val context: Context, private val specsFileId: Int) :
+class TestResourceHelper(private val context: Context, specsFileId: Int) :
ResourceHelper(context, specsFileId) {
override fun obtainStyledAttributes(attrs: AttributeSet, styleId: IntArray): TypedArray {
- var clone = styleId.clone()
- if (styleId == R.styleable.SpecSize) clone = TestR.styleable.SpecSize
- else if (styleId == R.styleable.WorkspaceSpec) clone = TestR.styleable.WorkspaceSpec
+ val clone =
+ when {
+ styleId.contentEquals(R.styleable.SizeSpec) -> TestR.styleable.SizeSpec
+ styleId.contentEquals(R.styleable.WorkspaceSpec) -> TestR.styleable.WorkspaceSpec
+ styleId.contentEquals(R.styleable.FolderSpec) -> TestR.styleable.FolderSpec
+ styleId.contentEquals(R.styleable.AllAppsSpec) -> TestR.styleable.AllAppsSpec
+ else -> styleId.clone()
+ }
+
return context.obtainStyledAttributes(attrs, clone)
}
}
diff --git a/tests/src/com/android/launcher3/util/TestUtil.java b/tests/src/com/android/launcher3/util/TestUtil.java
index f8cd995..957bf95 100644
--- a/tests/src/com/android/launcher3/util/TestUtil.java
+++ b/tests/src/com/android/launcher3/util/TestUtil.java
@@ -18,32 +18,37 @@
import static android.util.Base64.NO_PADDING;
import static android.util.Base64.NO_WRAP;
-import static androidx.test.InstrumentationRegistry.getContext;
-import static androidx.test.InstrumentationRegistry.getInstrumentation;
-import static androidx.test.InstrumentationRegistry.getTargetContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_KEY;
import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_LABEL;
import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_TAG;
+import android.app.Instrumentation;
import android.app.blob.BlobHandle;
import android.app.blob.BlobStoreManager;
import android.content.Context;
import android.content.pm.LauncherApps;
import android.content.res.Resources;
+import android.graphics.Point;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
+import android.os.Process;
import android.os.UserHandle;
import android.provider.Settings;
+import android.system.OsConstants;
import android.util.Base64;
+import android.util.Log;
import androidx.test.uiautomator.UiDevice;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.config.FeatureFlags.BooleanFlag;
import com.android.launcher3.config.FeatureFlags.IntFlag;
+import com.android.launcher3.tapl.LauncherInstrumentation;
+import com.android.launcher3.tapl.Workspace;
import org.junit.Assert;
@@ -52,26 +57,36 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
+import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;
public class TestUtil {
+ private static final String TAG = "TestUtil";
+
public static final String DUMMY_PACKAGE = "com.example.android.aardwolf";
- public static final int DEFAULT_USER_ID = 0;
+ public static final String DUMMY_CLASS_NAME = "com.example.android.aardwolf.Activity1";
+ public static final long DEFAULT_UI_TIMEOUT = 10000;
public static void installDummyApp() throws IOException {
- installDummyAppForUser(DEFAULT_USER_ID);
+ final int defaultUserId = getMainUserId();
+ installDummyAppForUser(defaultUserId);
}
public static void installDummyAppForUser(int userId) throws IOException {
+ Instrumentation instrumentation = getInstrumentation();
// Copy apk from resources to a local file and install from there.
- final Resources resources = getContext().getResources();
+ final Resources resources = instrumentation.getContext().getResources();
final InputStream in = resources.openRawResource(
resources.getIdentifier("aardwolf_dummy_app",
- "raw", getContext().getPackageName()));
- final String apkFilename = getInstrumentation().getTargetContext().
- getFilesDir().getPath() + "/dummy_app.apk";
+ "raw", instrumentation.getContext().getPackageName()));
+ final String apkFilename = instrumentation.getTargetContext()
+ .getFilesDir().getPath() + "/dummy_app.apk";
try (PackageInstallCheck pic = new PackageInstallCheck()) {
final FileOutputStream out = new FileOutputStream(apkFilename);
@@ -84,7 +99,7 @@
in.close();
out.close();
- final String result = UiDevice.getInstance(getInstrumentation())
+ final String result = UiDevice.getInstance(instrumentation)
.executeShellCommand("pm install --user " + userId + " " + apkFilename);
Assert.assertTrue(
"Failed to install wellbeing test apk; make sure the device is rooted",
@@ -96,6 +111,38 @@
}
/**
+ * Returns the main user ID. NOTE: For headless system it is NOT 0. Returns 0 by default, if
+ * there is no main user.
+ *
+ * @return a main user ID
+ */
+ public static int getMainUserId() throws IOException {
+ Instrumentation instrumentation = getInstrumentation();
+ final String result = UiDevice.getInstance(instrumentation)
+ .executeShellCommand("cmd user get-main-user");
+ try {
+ return Integer.parseInt(result.trim());
+ } catch (NumberFormatException e) {
+ return 0;
+ }
+ }
+
+ /**
+ * @return Grid coordinates from the center and corners of the Workspace. Those are not pixels.
+ * See {@link Workspace#getIconGridDimensions()}
+ */
+ public static Point[] getCornersAndCenterPositions(LauncherInstrumentation launcher) {
+ final Point dimensions = launcher.getWorkspace().getIconGridDimensions();
+ return new Point[]{
+ new Point(0, 1),
+ new Point(0, dimensions.y - 2),
+ new Point(dimensions.x - 1, 1),
+ new Point(dimensions.x - 1, dimensions.y - 2),
+ new Point(dimensions.x / 2, dimensions.y / 2)
+ };
+ }
+
+ /**
* Utility class to override a boolean flag during test. Note that the returned SafeCloseable
* must be closed to restore the original state
*/
@@ -159,6 +206,50 @@
Settings.Secure.putString(context.getContentResolver(), LAYOUT_DIGEST_KEY, null);
}
+ /**
+ * Utility method to run a task synchronously which converts any exceptions to RuntimeException
+ */
+ public static void runOnExecutorSync(ExecutorService executor, UncheckedRunnable task) {
+ try {
+ executor.submit(() -> {
+ try {
+ task.run();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }).get();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Runs the callback on the UI thread and returns the result.
+ */
+ public static <T> T getOnUiThread(final Callable<T> callback) {
+ try {
+ FutureTask<T> task = new FutureTask<>(callback);
+ if (Looper.myLooper() == Looper.getMainLooper()) {
+ task.run();
+ } else {
+ new Handler(Looper.getMainLooper()).post(task);
+ }
+ return task.get(DEFAULT_UI_TIMEOUT, TimeUnit.MILLISECONDS);
+ } catch (TimeoutException e) {
+ Log.e(TAG, "Timeout in getOnUiThread, sending SIGABRT", e);
+ Process.sendSignal(Process.myPid(), OsConstants.SIGABRT);
+ throw new RuntimeException(e);
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Interface to indicate a runnable which can throw any exception. */
+ public interface UncheckedRunnable {
+ /** Method to run the task */
+ void run() throws Exception;
+ }
+
private static class PackageInstallCheck extends LauncherApps.Callback
implements AutoCloseable {
@@ -166,7 +257,8 @@
final LauncherApps mLauncherApps;
PackageInstallCheck() {
- mLauncherApps = getTargetContext().getSystemService(LauncherApps.class);
+ mLauncherApps = getInstrumentation().getTargetContext()
+ .getSystemService(LauncherApps.class);
mLauncherApps.registerCallback(this, new Handler(Looper.getMainLooper()));
}
diff --git a/tests/src/com/android/launcher3/util/TraceHelperForTest.java b/tests/src/com/android/launcher3/util/TraceHelperForTest.java
deleted file mode 100644
index f1c8a67..0000000
--- a/tests/src/com/android/launcher3/util/TraceHelperForTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.util;
-
-import java.util.LinkedList;
-import java.util.function.IntConsumer;
-
-public class TraceHelperForTest extends TraceHelper {
-
- private static final TraceHelperForTest INSTANCE_FOR_TEST = new TraceHelperForTest();
-
- private final ThreadLocal<LinkedList<TraceInfo>> mStack =
- ThreadLocal.withInitial(LinkedList::new);
-
- private RaceConditionReproducer mRaceConditionReproducer;
- private IntConsumer mFlagsChangeListener;
-
- public static void setRaceConditionReproducer(RaceConditionReproducer reproducer) {
- TraceHelper.INSTANCE = INSTANCE_FOR_TEST;
- INSTANCE_FOR_TEST.mRaceConditionReproducer = reproducer;
- }
-
- public static void cleanup() {
- INSTANCE_FOR_TEST.mRaceConditionReproducer = null;
- INSTANCE_FOR_TEST.mFlagsChangeListener = null;
- }
-
- public static void setFlagsChangeListener(IntConsumer listener) {
- TraceHelper.INSTANCE = INSTANCE_FOR_TEST;
- INSTANCE_FOR_TEST.mFlagsChangeListener = listener;
- }
-
- private TraceHelperForTest() { }
-
- @Override
- public Object beginSection(String sectionName, int flags) {
- LinkedList<TraceInfo> stack = mStack.get();
- TraceInfo info = new TraceInfo(sectionName, flags);
- stack.add(info);
-
- if ((flags & TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS) != 0
- && mRaceConditionReproducer != null) {
- mRaceConditionReproducer.onEvent(RaceConditionReproducer.enterEvt(sectionName));
- }
- updateBinderTracking(stack);
-
- super.beginSection(sectionName, flags);
- return info;
- }
-
- @Override
- public void endSection(Object token) {
- LinkedList<TraceInfo> stack = mStack.get();
- if (stack.size() == 0) {
- new Throwable().printStackTrace();
- }
- TraceInfo info = (TraceInfo) token;
- stack.remove(info);
- if ((info.flags & TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS) != 0
- && mRaceConditionReproducer != null) {
- mRaceConditionReproducer.onEvent(RaceConditionReproducer.exitEvt(info.sectionName));
- }
- updateBinderTracking(stack);
-
- super.endSection(token);
- }
-
- @Override
- public Object beginFlagsOverride(int flags) {
- LinkedList<TraceInfo> stack = mStack.get();
- TraceInfo info = new TraceInfo(null, flags);
- stack.add(info);
- updateBinderTracking(stack);
- super.beginFlagsOverride(flags);
- return info;
- }
-
- @Override
- public void endFlagsOverride(Object token) {
- super.endFlagsOverride(token);
- LinkedList<TraceInfo> stack = mStack.get();
- TraceInfo info = (TraceInfo) token;
- stack.remove(info);
- updateBinderTracking(stack);
- }
-
- private void updateBinderTracking(LinkedList<TraceInfo> stack) {
- if (mFlagsChangeListener != null) {
- mFlagsChangeListener.accept(stack.stream()
- .mapToInt(info -> info.flags).reduce(0, (a, b) -> a | b));
- }
- }
-
- private static class TraceInfo {
- public final String sectionName;
- public final int flags;
-
- TraceInfo(String sectionName, int flags) {
- this.sectionName = sectionName;
- this.flags = flags;
- }
- }
-}
diff --git a/tests/src/com/android/launcher3/util/WidgetUtils.java b/tests/src/com/android/launcher3/util/WidgetUtils.java
index b0df055..027a31a 100644
--- a/tests/src/com/android/launcher3/util/WidgetUtils.java
+++ b/tests/src/com/android/launcher3/util/WidgetUtils.java
@@ -18,18 +18,14 @@
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
-
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.os.Bundle;
import android.os.Process;
import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.LauncherWidgetHolder;
@@ -88,33 +84,6 @@
}
/**
- * Adds {@param item} on the homescreen on the 0th screen
- */
- public static void addItemToScreen(ItemInfo item, Context targetContext) {
- ContentResolver resolver = targetContext.getContentResolver();
- int screenId = FIRST_SCREEN_ID;
- // Update the screen id counter for the provider.
- LauncherSettings.Settings.call(resolver,
- LauncherSettings.Settings.METHOD_NEW_SCREEN_ID);
-
- if (screenId > FIRST_SCREEN_ID) {
- screenId = FIRST_SCREEN_ID;
- }
-
- // Insert the item
- ContentWriter writer = new ContentWriter(targetContext);
- item.id = LauncherSettings.Settings.call(
- resolver, LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
- .getInt(LauncherSettings.Settings.EXTRA_VALUE);
- item.screenId = screenId;
- item.onAddToDatabase(writer);
- writer.put(LauncherSettings.Favorites._ID, item.id);
- resolver.insert(LauncherSettings.Favorites.CONTENT_URI,
- writer.getValues(targetContext));
- }
-
-
- /**
* Creates a {@link AppWidgetProviderInfo} for the provided component name
*/
public static AppWidgetProviderInfo createAppWidgetProviderInfo(ComponentName cn) {
diff --git a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
index 7ca6a06..62d70ad 100644
--- a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
+++ b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
@@ -8,10 +8,9 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.test.core.app.ApplicationProvider;
import androidx.test.uiautomator.UiDevice;
-import com.android.app.viewcapture.ViewCapture;
+import com.android.app.viewcapture.data.ExportedData;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.ui.AbstractLauncherUiTest;
@@ -24,22 +23,21 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.function.Supplier;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class FailureWatcher extends TestWatcher {
private static final String TAG = "FailureWatcher";
private static boolean sSavedBugreport = false;
- final private UiDevice mDevice;
private final LauncherInstrumentation mLauncher;
@NonNull
- private final ViewCapture mViewCapture;
+ private final Supplier<ExportedData> mViewCaptureDataSupplier;
- public FailureWatcher(UiDevice device, LauncherInstrumentation launcher,
- @NonNull ViewCapture viewCapture) {
- mDevice = device;
+ public FailureWatcher(LauncherInstrumentation launcher,
+ @NonNull Supplier<ExportedData> viewCaptureDataSupplier) {
mLauncher = launcher;
- mViewCapture = viewCapture;
+ mViewCaptureDataSupplier = viewCaptureDataSupplier;
}
@Override
@@ -71,7 +69,7 @@
@Override
protected void failed(Throwable e, Description description) {
- onError(mLauncher, description, e, mViewCapture);
+ onError(mLauncher, description, e, mViewCaptureDataSupplier);
}
static File diagFile(Description description, String prefix, String ext) {
@@ -86,7 +84,7 @@
}
private static void onError(LauncherInstrumentation launcher, Description description,
- Throwable e, @Nullable ViewCapture viewCapture) {
+ Throwable e, @Nullable Supplier<ExportedData> viewCaptureDataSupplier) {
final File sceenshot = diagFile(description, "TestScreenshot", "png");
final File hierarchy = diagFile(description, "Hierarchy", "zip");
@@ -103,9 +101,10 @@
dumpCommand("cmd window dump-visible-window-views", out);
out.closeEntry();
- if (viewCapture != null) {
+ if (viewCaptureDataSupplier != null) {
out.putNextEntry(new ZipEntry("FS/data/misc/wmtrace/failed_test.vc"));
- viewCapture.dumpTo(out, ApplicationProvider.getApplicationContext());
+ final ExportedData exportedData = viewCaptureDataSupplier.get();
+ if (exportedData != null) exportedData.writeTo(out);
out.closeEntry();
}
} catch (Exception ignored) {
diff --git a/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java b/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java
deleted file mode 100644
index e9a52f8..0000000
--- a/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.android.launcher3.util.rule;
-
-import android.app.Activity;
-
-import com.android.launcher3.Launcher;
-import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
-
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-import java.util.concurrent.Callable;
-
-/**
- * Test rule to get the current Launcher activity.
- */
-public class LauncherActivityRule extends SimpleActivityRule<Launcher> {
-
- public LauncherActivityRule() {
- super(Launcher.class);
- }
-
- @Override
- public Statement apply(Statement base, Description description) {
-
- return new MyStatement(base) {
- @Override
- public void onActivityStarted(Activity activity) {
- if (activity instanceof Launcher) {
- ((Launcher) activity).getRotationHelper().forceAllowRotationForTesting(true);
- }
- }
- };
- }
-
- public Callable<Boolean> itemExists(final ItemOperator op) {
- return () -> {
- Launcher launcher = getActivity();
- if (launcher == null) {
- return false;
- }
- return launcher.getWorkspace().getFirstMatch(op) != null;
- };
- }
-}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/util/rule/SimpleActivityRule.java b/tests/src/com/android/launcher3/util/rule/SimpleActivityRule.java
deleted file mode 100644
index 2eedec3..0000000
--- a/tests/src/com/android/launcher3/util/rule/SimpleActivityRule.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.android.launcher3.util.rule;
-
-import android.app.Activity;
-import android.app.Application;
-import android.app.Application.ActivityLifecycleCallbacks;
-import android.os.Bundle;
-
-import androidx.test.InstrumentationRegistry;
-
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-/**
- * Test rule to get the current activity.
- */
-public class SimpleActivityRule<T extends Activity> implements TestRule {
-
- private final Class<T> mClass;
- private T mActivity;
-
- public SimpleActivityRule(Class<T> clazz) {
- mClass = clazz;
- }
-
- @Override
- public Statement apply(Statement base, Description description) {
- return new MyStatement(base);
- }
-
- public T getActivity() {
- return mActivity;
- }
-
- protected class MyStatement extends Statement implements ActivityLifecycleCallbacks {
-
- private final Statement mBase;
-
- public MyStatement(Statement base) {
- mBase = base;
- }
-
- @Override
- public void evaluate() throws Throwable {
- Application app = (Application)
- InstrumentationRegistry.getTargetContext().getApplicationContext();
- app.registerActivityLifecycleCallbacks(this);
- try {
- mBase.evaluate();
- } finally {
- app.unregisterActivityLifecycleCallbacks(this);
- mActivity = null;
- }
- }
-
- @Override
- public void onActivityCreated(Activity activity, Bundle bundle) {
- if (activity != null && mClass.isInstance(activity)) {
- mActivity = (T) activity;
- }
- }
-
- @Override
- public void onActivityStarted(Activity activity) {
- }
-
- @Override
- public void onActivityResumed(Activity activity) {
- }
-
- @Override
- public void onActivityPaused(Activity activity) {
- }
-
- @Override
- public void onActivityStopped(Activity activity) {
- }
-
- @Override
- public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
- }
-
- @Override
- public void onActivityDestroyed(Activity activity) {
- if (activity == mActivity) {
- mActivity = null;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/util/rule/StaticMockitoRule.java b/tests/src/com/android/launcher3/util/rule/StaticMockitoRule.java
new file mode 100644
index 0000000..6b91474
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/rule/StaticMockitoRule.java
@@ -0,0 +1,72 @@
+/*
+ * 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.util.rule;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+
+import com.android.dx.mockito.inline.extended.StaticMockitoSession;
+import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
+
+import org.junit.rules.MethodRule;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+import org.mockito.junit.MockitoRule;
+import org.mockito.quality.Strictness;
+
+/**
+ * Similar to {@link MockitoRule}, but uses {@link StaticMockitoSession}, which allows mocking
+ * static methods.
+ */
+public class StaticMockitoRule implements MethodRule {
+ private Class<?>[] mClasses;
+
+ public StaticMockitoRule(Class<?>... classes) {
+ mClasses = classes;
+ }
+
+ @Override
+ public Statement apply(Statement base, FrameworkMethod method, Object target) {
+ return new Statement() {
+ public void evaluate() throws Throwable {
+ StaticMockitoSessionBuilder builder =
+ mockitoSession()
+ .name(target.getClass().getSimpleName() + "." + method.getName())
+ .initMocks(target)
+ .strictness(Strictness.STRICT_STUBS);
+
+ for (Class<?> clazz : mClasses) {
+ builder.mockStatic(clazz);
+ }
+
+ StaticMockitoSession session = builder.startMocking();
+ Throwable testFailure = evaluateSafely(base);
+ session.finishMocking(testFailure);
+ if (testFailure != null) {
+ throw testFailure;
+ }
+ }
+
+ private Throwable evaluateSafely(Statement base) {
+ try {
+ base.evaluate();
+ return null;
+ } catch (Throwable throwable) {
+ return throwable;
+ }
+ }
+ };
+ }
+}
diff --git a/tests/src/com/android/launcher3/util/rule/TestIsolationRule.java b/tests/src/com/android/launcher3/util/rule/TestIsolationRule.java
new file mode 100644
index 0000000..592cc9b
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/rule/TestIsolationRule.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util.rule;
+
+import androidx.annotation.NonNull;
+
+import com.android.launcher3.tapl.LauncherInstrumentation;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Isolates tests from some of the state created by the previous test.
+ */
+public class TestIsolationRule implements TestRule {
+ final LauncherInstrumentation mLauncher;
+
+ public TestIsolationRule(LauncherInstrumentation launcher) {
+ mLauncher = launcher;
+ }
+
+ @NonNull
+ @Override
+ public Statement apply(@NonNull Statement base, @NonNull Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ base.evaluate();
+ // Make sure that Launcher workspace looks correct.
+ mLauncher.goHome();
+ AbstractLauncherUiTest.checkDetectedLeaks(mLauncher);
+ }
+ };
+ }
+}
diff --git a/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java b/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
index f33a50a..38de071 100644
--- a/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
+++ b/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
@@ -17,6 +17,8 @@
import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assume.assumeTrue;
+
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;
@@ -69,12 +71,9 @@
return new Statement() {
@Override
public void evaluate() throws Throwable {
- if ((stability.flavors() & getRunFlavor()) != 0) {
- Log.d(TAG, "Running " + description.getDisplayName());
- base.evaluate();
- } else {
- Log.d(TAG, "Skipping " + description.getDisplayName());
- }
+ assumeTrue("Ignoring the test due to @Stability annotation",
+ (stability.flavors() & getRunFlavor()) != 0);
+ base.evaluate();
}
};
} else {
diff --git a/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt b/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt
index 0c65539..ccbae4f 100644
--- a/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt
+++ b/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt
@@ -20,9 +20,21 @@
import android.media.permission.SafeCloseable
import android.os.Bundle
import androidx.test.core.app.ApplicationProvider
+import androidx.test.platform.app.InstrumentationRegistry
import com.android.app.viewcapture.SimpleViewCapture
import com.android.app.viewcapture.ViewCapture.MAIN_EXECUTOR
+import com.android.app.viewcapture.data.ExportedData
+import com.android.launcher3.tapl.TestHelpers
import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter
+import com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT
+import com.android.launcher3.util.viewcapture_analysis.ViewCaptureAnalyzer
+import java.io.BufferedOutputStream
+import java.io.FileOutputStream
+import java.io.IOException
+import java.io.OutputStreamWriter
+import java.util.function.Supplier
+import org.junit.Assert.assertTrue
+import org.junit.Assert.fail
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
@@ -33,28 +45,33 @@
*
* This rule will not work in OOP tests that don't have access to the activity under test.
*/
-class ViewCaptureRule : TestRule {
- val viewCapture = SimpleViewCapture("test-view-capture")
+class ViewCaptureRule(var alreadyOpenActivitySupplier: Supplier<Activity?>) : TestRule {
+ private val viewCapture = SimpleViewCapture("test-view-capture")
+ var viewCaptureData: ExportedData? = null
+ private set
override fun apply(base: Statement, description: Description): Statement {
+ // Skip view capture collection in Launcher3 tests to avoid hidden API check exception.
+ if (
+ "com.android.launcher3.tests" ==
+ InstrumentationRegistry.getInstrumentation().context.packageName
+ )
+ return base
+
return object : Statement() {
override fun evaluate() {
+ viewCaptureData = null
val windowListenerCloseables = mutableListOf<SafeCloseable>()
+ startCapturingExistingActivity(windowListenerCloseables)
+
val lifecycleCallbacks =
object : ActivityLifecycleCallbacksAdapter {
override fun onActivityCreated(activity: Activity, bundle: Bundle?) {
- super.onActivityCreated(activity, bundle)
- windowListenerCloseables.add(
- viewCapture.startCapture(
- activity.window.decorView,
- "${description.testClass?.simpleName}.${description.methodName}"
- )
- )
+ startCapture(windowListenerCloseables, activity)
}
override fun onActivityDestroyed(activity: Activity) {
- super.onActivityDestroyed(activity)
viewCapture.stopCapture(activity.window.decorView)
}
}
@@ -67,6 +84,9 @@
} finally {
application.unregisterActivityLifecycleCallbacks(lifecycleCallbacks)
+ viewCaptureData =
+ viewCapture.getExportedData(ApplicationProvider.getApplicationContext())
+
// Clean up ViewCapture references here rather than in onActivityDestroyed so
// test code can access view hierarchy capture. onActivityDestroyed would delete
// view capture data before FailureWatcher could output it as a test artifact.
@@ -74,7 +94,69 @@
// is removed while onDraw is running, resulting in an IllegalStateException.
MAIN_EXECUTOR.execute { windowListenerCloseables.onEach(SafeCloseable::close) }
}
+
+ analyzeViewCapture(description)
}
+
+ private fun startCapturingExistingActivity(
+ windowListenerCloseables: MutableCollection<SafeCloseable>
+ ) {
+ val alreadyOpenActivity = alreadyOpenActivitySupplier.get()
+ if (alreadyOpenActivity != null) {
+ startCapture(windowListenerCloseables, alreadyOpenActivity)
+ }
+ }
+
+ private fun startCapture(
+ windowListenerCloseables: MutableCollection<SafeCloseable>,
+ activity: Activity
+ ) {
+ windowListenerCloseables.add(
+ viewCapture.startCapture(
+ activity.window.decorView,
+ "${description.testClass?.simpleName}.${description.methodName}"
+ )
+ )
+ }
+ }
+ }
+
+ private fun analyzeViewCapture(description: Description) {
+ // OOP tests don't produce ViewCapture data
+ if (!TestHelpers.isInLauncherProcess()) return
+
+ // Due to flakiness of ViewCapture verifier, don't run the check in presubmit
+ if (TestStabilityRule.getRunFlavor() != PLATFORM_POSTSUBMIT) return
+
+ var frameCount = 0
+ for (i in 0 until viewCaptureData!!.windowDataCount) {
+ frameCount += viewCaptureData!!.getWindowData(i).frameDataCount
+ }
+ assertTrue("Empty ViewCapture data", frameCount > 0)
+
+ val anomalies: Map<String, String> = ViewCaptureAnalyzer.getAnomalies(viewCaptureData)
+ if (!anomalies.isEmpty()) {
+ val diagFile = FailureWatcher.diagFile(description, "ViewAnomalies", "txt")
+ try {
+ OutputStreamWriter(BufferedOutputStream(FileOutputStream(diagFile))).use { writer ->
+ writer.write("View animation anomalies detected.\r\n")
+ writer.write(
+ "To suppress an anomaly for a view, add its full path to the PATHS_TO_IGNORE list in the corresponding AnomalyDetector.\r\n"
+ )
+ writer.write("List of views with animation anomalies:\r\n")
+
+ for ((viewPath, message) in anomalies) {
+ writer.write("View: $viewPath\r\n $message\r\n")
+ }
+ }
+ } catch (ex: IOException) {
+ throw RuntimeException(ex)
+ }
+
+ val (viewPath, message) = anomalies.entries.first()
+ fail(
+ "${anomalies.size} view(s) had animation anomalies during the test, including view: $viewPath: $message\r\nSee ${diagFile.name} for details."
+ )
}
}
}
diff --git a/tests/src/com/android/launcher3/util/viewcapture_analysis/AlphaJumpDetector.java b/tests/src/com/android/launcher3/util/viewcapture_analysis/AlphaJumpDetector.java
new file mode 100644
index 0000000..4b65439
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/viewcapture_analysis/AlphaJumpDetector.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util.viewcapture_analysis;
+
+import com.android.launcher3.util.viewcapture_analysis.ViewCaptureAnalyzer.AnalysisNode;
+
+import java.util.List;
+
+/**
+ * Anomaly detector that triggers an error when alpha of a view changes too rapidly.
+ * Invisible views are treated as if they had zero alpha.
+ */
+final class AlphaJumpDetector extends AnomalyDetector {
+ // Commonly used parts of the paths to ignore.
+ private static final String CONTENT = "DecorView|LinearLayout|FrameLayout:id/content|";
+ private static final String DRAG_LAYER =
+ CONTENT + "LauncherRootView:id/launcher|DragLayer:id/drag_layer|";
+ private static final String RECENTS_DRAG_LAYER =
+ CONTENT + "LauncherRootView:id/launcher|RecentsDragLayer:id/drag_layer|";
+
+ private static final IgnoreNode IGNORED_NODES_ROOT = buildIgnoreNodesTree(List.of(
+ CONTENT
+ + "AddItemDragLayer:id/add_item_drag_layer|AddItemWidgetsBottomSheet:id"
+ + "/add_item_bottom_sheet|LinearLayout:id/add_item_bottom_sheet_content"
+ + "|ScrollView:id/widget_preview_scroll_view|WidgetCell:id/widget_cell"
+ + "|WidgetCellPreview:id/widget_preview_container|ImageView:id/widget_badge",
+ CONTENT
+ + "AddItemDragLayer:id/add_item_drag_layer|AddItemWidgetsBottomSheet:id"
+ + "/add_item_bottom_sheet|LinearLayout:id/add_item_bottom_sheet_content"
+ + "|ScrollView:id/widget_preview_scroll_view|WidgetCell:id/widget_cell"
+ + "|WidgetCellPreview:id/widget_preview_container|WidgetCell$1|FrameLayout"
+ + "|ImageView:id/icon",
+ CONTENT + "AddItemDragLayer:id/add_item_drag_layer|View",
+ DRAG_LAYER
+ + "AppWidgetResizeFrame|FrameLayout|ImageButton:id/widget_reconfigure_button",
+ DRAG_LAYER
+ + "AppWidgetResizeFrame|FrameLayout|ImageView:id/widget_resize_bottom_handle",
+ DRAG_LAYER + "AppWidgetResizeFrame|FrameLayout|ImageView:id/widget_resize_frame",
+ DRAG_LAYER + "AppWidgetResizeFrame|FrameLayout|ImageView:id/widget_resize_left_handle",
+ DRAG_LAYER + "AppWidgetResizeFrame|FrameLayout|ImageView:id/widget_resize_right_handle",
+ DRAG_LAYER + "AppWidgetResizeFrame|FrameLayout|ImageView:id/widget_resize_top_handle",
+ DRAG_LAYER + "FloatingTaskView|FloatingTaskThumbnailView:id/thumbnail",
+ DRAG_LAYER + "FloatingTaskView|SplitPlaceholderView:id/split_placeholder",
+ DRAG_LAYER + "Folder|FolderPagedView:id/folder_content",
+ DRAG_LAYER + "LauncherAllAppsContainerView:id/apps_view",
+ DRAG_LAYER + "LauncherDragView",
+ DRAG_LAYER + "LauncherRecentsView:id/overview_panel",
+ DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view|FrameLayout:id"
+ + "/select_mode_buttons|ImageButton:id/close",
+ DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view|LinearLayout:id"
+ + "/action_buttons|Button:id/action_screenshot",
+ DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view|LinearLayout:id"
+ + "/action_buttons|Button:id/action_select",
+ DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view|LinearLayout:id"
+ + "/action_buttons|Button:id/action_split",
+ DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view|LinearLayout:id"
+ + "/action_buttons|Space:id/action_split_space",
+ DRAG_LAYER
+ + "PopupContainerWithArrow:id/popup_container|LinearLayout:id"
+ + "/deep_shortcuts_container|DeepShortcutView:id/deep_shortcut_material"
+ + "|DeepShortcutTextView:id/bubble_text",
+ DRAG_LAYER
+ + "PopupContainerWithArrow:id/popup_container|LinearLayout:id"
+ + "/deep_shortcuts_container|DeepShortcutView:id/deep_shortcut_material|View"
+ + ":id/icon",
+ DRAG_LAYER
+ + "PopupContainerWithArrow:id/popup_container|LinearLayout:id"
+ + "/system_shortcuts_container|DeepShortcutView:id/system_shortcut"
+ + "|BubbleTextView:id/bubble_text",
+ DRAG_LAYER
+ + "PopupContainerWithArrow:id/popup_container|LinearLayout:id"
+ + "/system_shortcuts_container|DeepShortcutView:id/system_shortcut|View:id"
+ + "/icon",
+ DRAG_LAYER
+ + "PopupContainerWithArrow:id/popup_container|LinearLayout:id"
+ + "/system_shortcuts_container|ImageView",
+ DRAG_LAYER
+ + "PopupContainerWithArrow:id/popup_container|LinearLayout:id"
+ + "/widget_shortcut_container|DeepShortcutView:id/system_shortcut"
+ + "|BubbleTextView:id/bubble_text",
+ DRAG_LAYER
+ + "PopupContainerWithArrow:id/popup_container|LinearLayout:id"
+ + "/widget_shortcut_container|DeepShortcutView:id/system_shortcut|View:id/icon",
+ DRAG_LAYER + "SearchContainerView:id/apps_view",
+ DRAG_LAYER + "Snackbar|TextView:id/action",
+ DRAG_LAYER + "Snackbar|TextView:id/label",
+ DRAG_LAYER + "SplitInstructionsView|AppCompatTextView:id/split_instructions_text",
+ DRAG_LAYER + "TaskMenuView|LinearLayout:id/menu_option_layout",
+ DRAG_LAYER + "TaskMenuViewWithArrow|LinearLayout:id/menu_option_layout",
+ DRAG_LAYER + "TaskMenuView|TextView:id/task_name",
+ DRAG_LAYER + "View",
+ DRAG_LAYER + "WidgetsFullSheet|SpringRelativeLayout:id/container",
+ DRAG_LAYER + "WidgetsTwoPaneSheet|SpringRelativeLayout:id/container",
+ CONTENT + "LauncherRootView:id/launcher|FloatingIconView",
+ RECENTS_DRAG_LAYER + "ArrowTipView",
+ DRAG_LAYER + "ArrowTipView",
+ DRAG_LAYER + "FallbackRecentsView:id/overview_panel",
+ RECENTS_DRAG_LAYER + "FallbackRecentsView:id/overview_panel",
+ DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view"
+ + "|LinearLayout:id/action_buttons|Button:id/action_screenshot",
+ RECENTS_DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view"
+ + "|LinearLayout:id/action_buttons|Button:id/action_screenshot",
+ DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view"
+ + "|LinearLayout:id/action_buttons|Button:id/action_select",
+ RECENTS_DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view"
+ + "|LinearLayout:id/action_buttons|Button:id/action_select",
+ DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view"
+ + "|LinearLayout:id/action_buttons|Button:id/action_split",
+ RECENTS_DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view"
+ + "|LinearLayout:id/action_buttons|Button:id/action_split",
+ DRAG_LAYER + "IconView"
+ ));
+
+ // Minimal increase or decrease of view's alpha between frames that triggers the error.
+ private static final float ALPHA_JUMP_THRESHOLD = 1f;
+
+ // Per-AnalysisNode data that's specific to this detector.
+ private static class NodeData {
+ public boolean ignoreAlphaJumps;
+
+ // If ignoreNode is null, then this AnalysisNode node will be ignored if its parent is
+ // ignored.
+ // Otherwise, this AnalysisNode will be ignored if ignoreNode is a leaf i.e. has no
+ // children.
+ public IgnoreNode ignoreNode;
+ }
+
+ private NodeData getNodeData(AnalysisNode info) {
+ return (NodeData) info.detectorsData[detectorOrdinal];
+ }
+
+ @Override
+ void initializeNode(AnalysisNode info) {
+ final NodeData nodeData = new NodeData();
+ info.detectorsData[detectorOrdinal] = nodeData;
+
+ // If the parent view ignores alpha jumps, its descendants will too.
+ final boolean parentIgnoresAlphaJumps = info.parent != null && getNodeData(
+ info.parent).ignoreAlphaJumps;
+ if (parentIgnoresAlphaJumps) {
+ nodeData.ignoreAlphaJumps = true;
+ return;
+ }
+
+ // Parent view doesn't ignore alpha jumps.
+ // Initialize this AnalysisNode's ignore-node with the corresponding child of the
+ // ignore-node of the parent, if present.
+ final IgnoreNode parentIgnoreNode = info.parent != null
+ ? getNodeData(info.parent).ignoreNode
+ : IGNORED_NODES_ROOT;
+ nodeData.ignoreNode = parentIgnoreNode != null
+ ? parentIgnoreNode.children.get(info.nodeIdentity) : null;
+ // AnalysisNode will be ignored if the corresponding ignore-node is a leaf.
+ nodeData.ignoreAlphaJumps =
+ nodeData.ignoreNode != null && nodeData.ignoreNode.children.isEmpty();
+ }
+
+ @Override
+ String detectAnomalies(AnalysisNode oldInfo, AnalysisNode newInfo, int frameN, long timestamp,
+ int windowSizePx) {
+ // If the view was previously seen, proceed with analysis only if it was present in the
+ // view hierarchy in the previous frame.
+ if (oldInfo != null && oldInfo.frameN != frameN) return null;
+
+ final AnalysisNode latestInfo = newInfo != null ? newInfo : oldInfo;
+ final NodeData nodeData = getNodeData(latestInfo);
+ if (nodeData.ignoreAlphaJumps) return null;
+
+ final float oldAlpha = oldInfo != null ? oldInfo.alpha : 0;
+ final float newAlpha = newInfo != null ? newInfo.alpha : 0;
+ final float alphaDeltaAbs = Math.abs(newAlpha - oldAlpha);
+
+ if (alphaDeltaAbs >= ALPHA_JUMP_THRESHOLD) {
+ nodeData.ignoreAlphaJumps = true; // No need to report alpha jump in children.
+ return String.format(
+ "Alpha jump detected: alpha change: %s (%s -> %s), threshold: %s",
+ alphaDeltaAbs, oldAlpha, newAlpha, ALPHA_JUMP_THRESHOLD);
+ }
+ return null;
+ }
+}
diff --git a/tests/src/com/android/launcher3/util/viewcapture_analysis/AnomalyDetector.java b/tests/src/com/android/launcher3/util/viewcapture_analysis/AnomalyDetector.java
new file mode 100644
index 0000000..786791c
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/viewcapture_analysis/AnomalyDetector.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util.viewcapture_analysis;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Detector of one kind of anomaly.
+ */
+abstract class AnomalyDetector {
+ // Index of this detector in ViewCaptureAnalyzer.ANOMALY_DETECTORS
+ public int detectorOrdinal;
+
+ /**
+ * Element of the tree of ignored nodes.
+ * If the "children" map is empty, then this node should be ignored, i.e. the analysis shouldn't
+ * run for it.
+ * I.e. ignored nodes correspond to the leaves in the ignored nodes tree.
+ */
+ protected static class IgnoreNode {
+ // Map from child node identities to ignore-nodes for these children.
+ public final Map<String, IgnoreNode> children = new HashMap<>();
+ }
+
+ // Converts the list of full paths of nodes to ignore to a more efficient tree of ignore-nodes.
+ protected static IgnoreNode buildIgnoreNodesTree(Iterable<String> pathsToIgnore) {
+ final IgnoreNode root = new IgnoreNode();
+ for (String pathToIgnore : pathsToIgnore) {
+ // Scan the diag path of an ignored node and add its elements into the tree.
+ IgnoreNode currentIgnoreNode = root;
+ for (String part : pathToIgnore.split("\\|")) {
+ // Ensure that the child of the node is added to the tree.
+ IgnoreNode child = currentIgnoreNode.children.get(part);
+ if (child == null) {
+ currentIgnoreNode.children.put(part, child = new IgnoreNode());
+ }
+ currentIgnoreNode = child;
+ }
+ }
+ return root;
+ }
+
+ /**
+ * Initializes fields of the node that are specific to the anomaly detected by this
+ * detector.
+ */
+ abstract void initializeNode(@NonNull ViewCaptureAnalyzer.AnalysisNode info);
+
+ /**
+ * Detects anomalies by looking at the last occurrence of a view, and the current one.
+ * null value means that the view. 'oldInfo' and 'newInfo' cannot be both null.
+ * If an anomaly is detected, an exception will be thrown.
+ *
+ * @param oldInfo the view, as seen in the last frame that contained it in the view
+ * hierarchy before 'currentFrame'. 'null' means that the view is first seen
+ * in the 'currentFrame'.
+ * @param newInfo the view in the view hierarchy of the 'currentFrame'. 'null' means that
+ * the view is not present in the 'currentFrame', but was present in the
+ * previous frame.
+ * @param frameN number of the current frame.
+ * @param windowSizePx maximum of the window width and height, in pixels.
+ * @return Anomaly diagnostic message if an anomaly has been detected; null otherwise.
+ */
+ abstract String detectAnomalies(
+ @Nullable ViewCaptureAnalyzer.AnalysisNode oldInfo,
+ @Nullable ViewCaptureAnalyzer.AnalysisNode newInfo, int frameN,
+ long frameTimeNs, int windowSizePx);
+}
diff --git a/tests/src/com/android/launcher3/util/viewcapture_analysis/FlashDetector.java b/tests/src/com/android/launcher3/util/viewcapture_analysis/FlashDetector.java
new file mode 100644
index 0000000..8b88ace
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/viewcapture_analysis/FlashDetector.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util.viewcapture_analysis;
+
+import static org.junit.Assert.assertTrue;
+
+import com.android.launcher3.util.viewcapture_analysis.ViewCaptureAnalyzer.AnalysisNode;
+
+import java.util.List;
+
+/**
+ * Anomaly detector that triggers an error when a view flashes, i.e. appears or disappears for a too
+ * short period of time.
+ */
+final class FlashDetector extends AnomalyDetector {
+ // Maximum time period of a view visibility or invisibility that is recognized as a flash.
+ private static final int FLASH_DURATION_MS = 300;
+
+ // Commonly used parts of the paths to ignore.
+ private static final String CONTENT = "DecorView|LinearLayout|FrameLayout:id/content|";
+ private static final String DRAG_LAYER =
+ CONTENT + "LauncherRootView:id/launcher|DragLayer:id/drag_layer|";
+ private static final String RECENTS_DRAG_LAYER =
+ CONTENT + "LauncherRootView:id/launcher|RecentsDragLayer:id/drag_layer|";
+
+ private static final IgnoreNode IGNORED_NODES_ROOT = buildIgnoreNodesTree(List.of(
+ CONTENT + "LauncherRootView:id/launcher|FloatingIconView",
+ DRAG_LAYER + "LauncherRecentsView:id/overview_panel|TaskView|TextView",
+ DRAG_LAYER
+ + "LauncherAllAppsContainerView:id/apps_view|AllAppsRecyclerView:id"
+ + "/apps_list_view|BubbleTextView:id/icon",
+ CONTENT
+ + "AddItemDragLayer:id/add_item_drag_layer|AddItemWidgetsBottomSheet:id"
+ + "/add_item_bottom_sheet|LinearLayout:id/add_item_bottom_sheet_content"
+ + "|ScrollView:id/widget_preview_scroll_view|WidgetCell:id/widget_cell"
+ + "|WidgetCellPreview:id/widget_preview_container|WidgetImageView:id"
+ + "/widget_preview",
+ CONTENT
+ + "AddItemDragLayer:id/add_item_drag_layer|AddItemWidgetsBottomSheet:id"
+ + "/add_item_bottom_sheet|LinearLayout:id/add_item_bottom_sheet_content"
+ + "|ScrollView:id/widget_preview_scroll_view|WidgetCell:id/widget_cell"
+ + "|WidgetCellPreview:id/widget_preview_container|ImageView:id/widget_badge",
+ RECENTS_DRAG_LAYER + "FallbackRecentsView:id/overview_panel|TaskView|IconView:id/icon",
+ DRAG_LAYER + "SearchContainerView:id/apps_view",
+ DRAG_LAYER + "LauncherDragView",
+ DRAG_LAYER + "FloatingTaskView|FloatingTaskThumbnailView:id/thumbnail",
+ DRAG_LAYER
+ + "WidgetsFullSheet|SpringRelativeLayout:id/container|WidgetsRecyclerView:id"
+ + "/primary_widgets_list_view|WidgetsListHeader:id/widgets_list_header",
+ DRAG_LAYER
+ + "WidgetsTwoPaneSheet|SpringRelativeLayout:id/container|LinearLayout:id"
+ + "/linear_layout_container|FrameLayout:id/recycler_view_container"
+ + "|FrameLayout:id/widgets_two_pane_sheet_recyclerview|WidgetsRecyclerView:id"
+ + "/primary_widgets_list_view|WidgetsListHeader:id/widgets_list_header"
+ ));
+
+ // Per-AnalysisNode data that's specific to this detector.
+ private static class NodeData {
+ public boolean ignoreFlashes;
+
+ // If ignoreNode is null, then this AnalysisNode node will be ignored if its parent is
+ // ignored.
+ // Otherwise, this AnalysisNode will be ignored if ignoreNode is a leaf i.e. has no
+ // children.
+ public IgnoreNode ignoreNode;
+ }
+
+ private NodeData getNodeData(AnalysisNode info) {
+ return (NodeData) info.detectorsData[detectorOrdinal];
+ }
+
+ @Override
+ void initializeNode(AnalysisNode info) {
+ final NodeData nodeData = new NodeData();
+ info.detectorsData[detectorOrdinal] = nodeData;
+
+ // If the parent view ignores flashes, its descendants will too.
+ final boolean parentIgnoresFlashes = info.parent != null && getNodeData(
+ info.parent).ignoreFlashes;
+ if (parentIgnoresFlashes) {
+ nodeData.ignoreFlashes = true;
+ return;
+ }
+
+ // Parent view doesn't ignore flashes.
+ // Initialize this AnalysisNode's ignore-node with the corresponding child of the
+ // ignore-node of the parent, if present.
+ final IgnoreNode parentIgnoreNode = info.parent != null
+ ? getNodeData(info.parent).ignoreNode
+ : IGNORED_NODES_ROOT;
+ nodeData.ignoreNode = parentIgnoreNode != null
+ ? parentIgnoreNode.children.get(info.nodeIdentity) : null;
+ // AnalysisNode will be ignored if the corresponding ignore-node is a leaf.
+ nodeData.ignoreFlashes =
+ nodeData.ignoreNode != null && nodeData.ignoreNode.children.isEmpty();
+ }
+
+ @Override
+ String detectAnomalies(AnalysisNode oldInfo, AnalysisNode newInfo, int frameN,
+ long frameTimeNs, int windowSizePx) {
+ // Should we check when a view was visible for a short period, then its alpha became 0?
+ // Then 'lastVisible' time should be the last one still visible?
+ // Check only transitions of alpha between 0 and 1?
+
+ // If this is the first time ever when we see the view, there have been no flashes yet.
+ if (oldInfo == null) return null;
+
+ // A flash requires a view to go from the full visibility to no-visibility and then back,
+ // or vice versa.
+ // If the last time the view was seen before the current frame, it didn't have full
+ // visibility; no flash can possibly be detected at the current frame.
+ if (oldInfo.alpha < 1) return null;
+
+ final AnalysisNode latestInfo = newInfo != null ? newInfo : oldInfo;
+ final NodeData nodeData = getNodeData(latestInfo);
+ if (nodeData.ignoreFlashes) return null;
+
+ // Once the view becomes invisible, see for how long it was visible prior to that. If it
+ // was visible only for a short interval of time, it's a flash.
+ if (
+ // View is invisible in the current frame
+ newInfo == null
+ // When the view became visible last time, it was a transition from
+ // no-visibility to full visibility.
+ && oldInfo.timeBecameVisibleNs != -1) {
+ final long wasVisibleTimeMs = (frameTimeNs - oldInfo.timeBecameVisibleNs) / 1000000;
+
+ if (wasVisibleTimeMs <= FLASH_DURATION_MS) {
+ nodeData.ignoreFlashes = true; // No need to report flashes in children.
+ return
+ String.format(
+ "View was visible for a too short period of time %dms, which is a"
+ + " flash",
+ wasVisibleTimeMs
+ );
+ }
+ }
+
+ // Once a view becomes visible, see for how long it was invisible prior to that. If it
+ // was invisible only for a short interval of time, it's a flash.
+ if (
+ // The view is fully visible now
+ newInfo != null && newInfo.alpha >= 1
+ // The view wasn't visible in the previous frame
+ && frameN != oldInfo.frameN + 1) {
+ // We can assert the below condition because at this point, we know that
+ // oldInfo.alpha >= 1, i.e. it disappeared abruptly.
+ assertTrue("oldInfo.timeBecameInvisibleNs must not be -1",
+ oldInfo.timeBecameInvisibleNs != -1);
+
+ final long wasInvisibleTimeMs = (frameTimeNs - oldInfo.timeBecameInvisibleNs) / 1000000;
+ if (wasInvisibleTimeMs <= FLASH_DURATION_MS) {
+ nodeData.ignoreFlashes = true; // No need to report flashes in children.
+ return
+ String.format(
+ "View was invisible for a too short period of time %dms, which "
+ + "is a flash",
+ wasInvisibleTimeMs);
+ }
+ }
+ return null;
+ }
+}
diff --git a/tests/src/com/android/launcher3/util/viewcapture_analysis/PositionJumpDetector.java b/tests/src/com/android/launcher3/util/viewcapture_analysis/PositionJumpDetector.java
new file mode 100644
index 0000000..a1ddcb0
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/viewcapture_analysis/PositionJumpDetector.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util.viewcapture_analysis;
+
+import com.android.launcher3.util.viewcapture_analysis.ViewCaptureAnalyzer.AnalysisNode;
+
+import java.util.List;
+
+/**
+ * Anomaly detector that triggers an error when a view position jumps.
+ */
+final class PositionJumpDetector extends AnomalyDetector {
+ // Maximum allowed jump in "milliwindows", i.e. a 1/1000's of the maximum of the window
+ // dimensions.
+ private static final float JUMP_MIW = 250;
+
+ private static final String[] BORDER_NAMES = {"left", "top", "right", "bottom"};
+
+ // Commonly used parts of the paths to ignore.
+ private static final String CONTENT = "DecorView|LinearLayout|FrameLayout:id/content|";
+ private static final String DRAG_LAYER =
+ CONTENT + "LauncherRootView:id/launcher|DragLayer:id/drag_layer|";
+ private static final String RECENTS_DRAG_LAYER =
+ CONTENT + "LauncherRootView:id/launcher|RecentsDragLayer:id/drag_layer|";
+
+ private static final IgnoreNode IGNORED_NODES_ROOT = buildIgnoreNodesTree(List.of(
+ DRAG_LAYER + "SearchContainerView:id/apps_view",
+ DRAG_LAYER + "AppWidgetResizeFrame",
+ DRAG_LAYER + "LauncherAllAppsContainerView:id/apps_view",
+ CONTENT
+ + "AddItemDragLayer:id/add_item_drag_layer|AddItemWidgetsBottomSheet:id"
+ + "/add_item_bottom_sheet|LinearLayout:id/add_item_bottom_sheet_content",
+ DRAG_LAYER + "WidgetsTwoPaneSheet|SpringRelativeLayout:id/container",
+ DRAG_LAYER + "WidgetsFullSheet|SpringRelativeLayout:id/container",
+ DRAG_LAYER + "LauncherDragView",
+ RECENTS_DRAG_LAYER + "FallbackRecentsView:id/overview_panel|TaskView",
+ CONTENT + "LauncherRootView:id/launcher|FloatingIconView",
+ DRAG_LAYER + "FloatingTaskView",
+ DRAG_LAYER + "LauncherRecentsView:id/overview_panel"
+ ));
+
+ // Per-AnalysisNode data that's specific to this detector.
+ private static class NodeData {
+ public boolean ignoreJumps;
+
+ // If ignoreNode is null, then this AnalysisNode node will be ignored if its parent is
+ // ignored.
+ // Otherwise, this AnalysisNode will be ignored if ignoreNode is a leaf i.e. has no
+ // children.
+ public IgnoreNode ignoreNode;
+ }
+
+ private NodeData getNodeData(AnalysisNode info) {
+ return (NodeData) info.detectorsData[detectorOrdinal];
+ }
+
+ @Override
+ void initializeNode(AnalysisNode info) {
+ final NodeData nodeData = new NodeData();
+ info.detectorsData[detectorOrdinal] = nodeData;
+
+ // If the parent view ignores jumps, its descendants will too.
+ final boolean parentIgnoresJumps = info.parent != null && getNodeData(
+ info.parent).ignoreJumps;
+ if (parentIgnoresJumps) {
+ nodeData.ignoreJumps = true;
+ return;
+ }
+
+ // Parent view doesn't ignore jumps.
+ // Initialize this AnalysisNode's ignore-node with the corresponding child of the
+ // ignore-node of the parent, if present.
+ final IgnoreNode parentIgnoreNode = info.parent != null
+ ? getNodeData(info.parent).ignoreNode
+ : IGNORED_NODES_ROOT;
+ nodeData.ignoreNode = parentIgnoreNode != null
+ ? parentIgnoreNode.children.get(info.nodeIdentity) : null;
+ // AnalysisNode will be ignored if the corresponding ignore-node is a leaf.
+ nodeData.ignoreJumps =
+ nodeData.ignoreNode != null && nodeData.ignoreNode.children.isEmpty();
+ }
+
+ @Override
+ String detectAnomalies(AnalysisNode oldInfo, AnalysisNode newInfo, int frameN,
+ long frameTimeNs, int windowSizePx) {
+ // If the view is not present in the current frame, there can't be a jump detected in the
+ // current frame.
+ if (newInfo == null) return null;
+
+ // We only detect position jumps if the view was visible in the previous frame.
+ if (oldInfo == null || frameN != oldInfo.frameN + 1) return null;
+
+ final NodeData newNodeData = getNodeData(newInfo);
+ if (newNodeData.ignoreJumps) return null;
+
+ final float[] positionDiffs = {
+ newInfo.left - oldInfo.left,
+ newInfo.top - oldInfo.top,
+ newInfo.right - oldInfo.right,
+ newInfo.bottom - oldInfo.bottom
+ };
+
+ for (int i = 0; i < 4; ++i) {
+ final float positionDiffAbs = Math.abs(positionDiffs[i]);
+ if (positionDiffAbs * 1000 > JUMP_MIW * windowSizePx) {
+ newNodeData.ignoreJumps = true;
+ return String.format("Position jump: %s jumped by %s",
+ BORDER_NAMES[i], positionDiffAbs);
+ }
+ }
+ return null;
+ }
+}
diff --git a/tests/src/com/android/launcher3/util/viewcapture_analysis/ViewCaptureAnalyzer.java b/tests/src/com/android/launcher3/util/viewcapture_analysis/ViewCaptureAnalyzer.java
new file mode 100644
index 0000000..9459cc2
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/viewcapture_analysis/ViewCaptureAnalyzer.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util.viewcapture_analysis;
+
+import static android.view.View.VISIBLE;
+
+import com.android.app.viewcapture.data.ExportedData;
+import com.android.app.viewcapture.data.FrameData;
+import com.android.app.viewcapture.data.ViewNode;
+import com.android.app.viewcapture.data.WindowData;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Utility that analyzes ViewCapture data and finds anomalies such as views appearing or
+ * disappearing without alpha-fading.
+ */
+public class ViewCaptureAnalyzer {
+ private static final String SCRIM_VIEW_CLASS = "com.android.launcher3.views.ScrimView";
+
+ // All detectors. They will be invoked in the order listed here.
+ private static final AnomalyDetector[] ANOMALY_DETECTORS = {
+ new AlphaJumpDetector(),
+ new FlashDetector(),
+ new PositionJumpDetector()
+ };
+
+ static {
+ for (int i = 0; i < ANOMALY_DETECTORS.length; ++i) ANOMALY_DETECTORS[i].detectorOrdinal = i;
+ }
+
+ // A view from view capture data converted to a form that's convenient for detecting anomalies.
+ static class AnalysisNode {
+ public String className;
+ public String resourceId;
+ public AnalysisNode parent;
+
+ // Window coordinates of the view.
+ public float left;
+ public float top;
+ public float right;
+ public float bottom;
+
+ // Visible scale and alpha, build recursively from the ancestor list.
+ public float scaleX;
+ public float scaleY;
+ public float alpha; // Always > 0
+
+ public int frameN;
+
+ // Timestamp of the frame when this view became abruptly visible, i.e. its alpha became 1
+ // the next frame after it was 0 or the view wasn't visible.
+ // If the view is currently invisible or the last appearance wasn't abrupt, the value is -1.
+ public long timeBecameVisibleNs;
+
+ // Timestamp of the frame when this view became abruptly invisible last time, i.e. its
+ // alpha became 0, or view disappeared, after being 1 in the previous frame.
+ // If the view is currently visible or the last disappearance wasn't abrupt, the value is
+ // -1.
+ public long timeBecameInvisibleNs;
+
+ public ViewNode viewCaptureNode;
+
+ // Class name + resource id
+ public String nodeIdentity;
+
+ // Collection of detector-specific data for this node.
+ public final Object[] detectorsData = new Object[ANOMALY_DETECTORS.length];
+
+ @Override
+ public String toString() {
+ return String.format("view window coordinates: (%s, %s, %s, %s)",
+ left, top, right, bottom);
+ }
+ }
+
+ /**
+ * Scans a view capture record and searches for view animation anomalies. Can find anomalies for
+ * multiple views.
+ * Returns a map from the view path to the anomaly message for the view. Non-empty map means
+ * that anomalies were detected.
+ */
+ public static Map<String, String> getAnomalies(ExportedData viewCaptureData) {
+ final Map<String, String> anomalies = new HashMap<>();
+
+ final int scrimClassIndex = viewCaptureData.getClassnameList().indexOf(SCRIM_VIEW_CLASS);
+
+ final int windowDataCount = viewCaptureData.getWindowDataCount();
+ for (int i = 0; i < windowDataCount; ++i) {
+ analyzeWindowData(
+ viewCaptureData, viewCaptureData.getWindowData(i), scrimClassIndex, anomalies);
+ }
+ return anomalies;
+ }
+
+ private static void analyzeWindowData(ExportedData viewCaptureData, WindowData windowData,
+ int scrimClassIndex, Map<String, String> anomalies) {
+ // View hash code => Last seen node with this hash code.
+ // The view is added when we analyze the first frame where it's visible.
+ // After that, it gets updated for every frame where it's visible.
+ // As we go though frames, if a view becomes invisible, it stays in the map.
+ final Map<Integer, AnalysisNode> lastSeenNodes = new HashMap<>();
+
+ int windowWidthPx = -1;
+ int windowHeightPx = -1;
+
+ for (int frameN = 0; frameN < windowData.getFrameDataCount(); ++frameN) {
+ final FrameData frame = windowData.getFrameData(frameN);
+ final ViewNode rootNode = frame.getNode();
+
+ // If the rotation or window size has changed, reset the analyzer state.
+ final boolean isFirstFrame = windowWidthPx != rootNode.getWidth()
+ || windowHeightPx != rootNode.getHeight();
+ if (isFirstFrame) {
+ windowWidthPx = rootNode.getWidth();
+ windowHeightPx = rootNode.getHeight();
+ lastSeenNodes.clear();
+ }
+
+ final int windowSizePx = Math.max(rootNode.getWidth(), rootNode.getHeight());
+
+ analyzeFrame(frameN, isFirstFrame, frame, viewCaptureData, lastSeenNodes,
+ scrimClassIndex, anomalies, windowSizePx);
+ }
+ }
+
+ private static void analyzeFrame(int frameN, boolean isFirstFrame, FrameData frame,
+ ExportedData viewCaptureData,
+ Map<Integer, AnalysisNode> lastSeenNodes, int scrimClassIndex,
+ Map<String, String> anomalies, int windowSizePx) {
+ // Analyze the node tree starting from the root.
+ long frameTimeNs = frame.getTimestamp();
+ analyzeView(
+ frameTimeNs,
+ frame.getNode(),
+ /* parent = */ null,
+ frameN,
+ isFirstFrame,
+ /* leftShift = */ 0,
+ /* topShift = */ 0,
+ viewCaptureData,
+ lastSeenNodes,
+ scrimClassIndex,
+ anomalies,
+ windowSizePx);
+
+ // Analyze transitions when a view visible in the previous frame became invisible in the
+ // current one.
+ for (AnalysisNode info : lastSeenNodes.values()) {
+ if (info.frameN == frameN - 1) {
+ if (!info.viewCaptureNode.getWillNotDraw()) {
+ Arrays.stream(ANOMALY_DETECTORS).forEach(
+ detector ->
+ detectAnomaly(
+ detector,
+ frameN,
+ /* oldInfo = */ info,
+ /* newInfo = */ null,
+ anomalies,
+ frameTimeNs,
+ windowSizePx)
+ );
+ }
+ info.timeBecameInvisibleNs = info.alpha == 1 ? frameTimeNs : -1;
+ info.timeBecameVisibleNs = -1;
+ }
+ }
+ }
+
+ private static void analyzeView(long frameTimeNs, ViewNode viewCaptureNode, AnalysisNode parent,
+ int frameN,
+ boolean isFirstFrame, float leftShift, float topShift, ExportedData viewCaptureData,
+ Map<Integer, AnalysisNode> lastSeenNodes, int scrimClassIndex,
+ Map<String, String> anomalies, int windowSizePx) {
+ // Skip analysis of invisible views
+ final float parentAlpha = parent != null ? parent.alpha : 1;
+ final float alpha = getVisibleAlpha(viewCaptureNode, parentAlpha);
+ if (alpha <= 0.0) return;
+
+ // Calculate analysis node parameters
+ final int hashcode = viewCaptureNode.getHashcode();
+ final int classIndex = viewCaptureNode.getClassnameIndex();
+
+ final float parentScaleX = parent != null ? parent.scaleX : 1;
+ final float parentScaleY = parent != null ? parent.scaleY : 1;
+ final float scaleX = parentScaleX * viewCaptureNode.getScaleX();
+ final float scaleY = parentScaleY * viewCaptureNode.getScaleY();
+
+ final float left = leftShift
+ + (viewCaptureNode.getLeft() + viewCaptureNode.getTranslationX()) * parentScaleX
+ + viewCaptureNode.getWidth() * (parentScaleX - scaleX) / 2;
+ final float top = topShift
+ + (viewCaptureNode.getTop() + viewCaptureNode.getTranslationY()) * parentScaleY
+ + viewCaptureNode.getHeight() * (parentScaleY - scaleY) / 2;
+ final float width = viewCaptureNode.getWidth() * scaleX;
+ final float height = viewCaptureNode.getHeight() * scaleY;
+
+ // Initialize new analysis node
+ final AnalysisNode newAnalysisNode = new AnalysisNode();
+ newAnalysisNode.className = viewCaptureData.getClassname(classIndex);
+ newAnalysisNode.resourceId = viewCaptureNode.getId();
+ newAnalysisNode.nodeIdentity =
+ getNodeIdentity(newAnalysisNode.className, newAnalysisNode.resourceId);
+ newAnalysisNode.parent = parent;
+ newAnalysisNode.left = left;
+ newAnalysisNode.top = top;
+ newAnalysisNode.right = left + width;
+ newAnalysisNode.bottom = top + height;
+ newAnalysisNode.scaleX = scaleX;
+ newAnalysisNode.scaleY = scaleY;
+ newAnalysisNode.alpha = alpha;
+ newAnalysisNode.frameN = frameN;
+ newAnalysisNode.timeBecameInvisibleNs = -1;
+ newAnalysisNode.viewCaptureNode = viewCaptureNode;
+ Arrays.stream(ANOMALY_DETECTORS).forEach(
+ detector -> detector.initializeNode(newAnalysisNode));
+
+ final AnalysisNode oldAnalysisNode = lastSeenNodes.get(hashcode); // may be null
+
+ if (oldAnalysisNode != null && oldAnalysisNode.frameN + 1 == frameN) {
+ // If this view was present in the previous frame, keep the time when it became visible.
+ newAnalysisNode.timeBecameVisibleNs = oldAnalysisNode.timeBecameVisibleNs;
+ } else {
+ // If the view is becoming visible after being invisible, initialize the time when it
+ // became visible with a new value.
+ // If the view became visible abruptly, i.e. alpha jumped from 0 to 1 between the
+ // previous and the current frames, then initialize with the time of the current
+ // frame. Otherwise, use -1.
+ newAnalysisNode.timeBecameVisibleNs = newAnalysisNode.alpha >= 1 ? frameTimeNs : -1;
+ }
+
+ // Detect anomalies for the view.
+ if (!isFirstFrame && !viewCaptureNode.getWillNotDraw()) {
+ Arrays.stream(ANOMALY_DETECTORS).forEach(
+ detector ->
+ detectAnomaly(detector, frameN, oldAnalysisNode, newAnalysisNode,
+ anomalies, frameTimeNs, windowSizePx)
+ );
+ }
+ lastSeenNodes.put(hashcode, newAnalysisNode);
+
+ // Enumerate children starting from the topmost one. Stop at ScrimView, if present.
+ final float leftShiftForChildren = left - viewCaptureNode.getScrollX();
+ final float topShiftForChildren = top - viewCaptureNode.getScrollY();
+ for (int i = viewCaptureNode.getChildrenCount() - 1; i >= 0; --i) {
+ final ViewNode child = viewCaptureNode.getChildren(i);
+
+ // Don't analyze anything under scrim view because we don't know whether it's
+ // transparent.
+ if (child.getClassnameIndex() == scrimClassIndex) break;
+
+ analyzeView(frameTimeNs, child, newAnalysisNode, frameN, isFirstFrame,
+ leftShiftForChildren,
+ topShiftForChildren,
+ viewCaptureData, lastSeenNodes, scrimClassIndex, anomalies, windowSizePx);
+ }
+ }
+
+ private static void detectAnomaly(AnomalyDetector detector, int frameN,
+ AnalysisNode oldAnalysisNode, AnalysisNode newAnalysisNode,
+ Map<String, String> anomalies, long frameTimeNs, int windowSizePx) {
+ final String maybeAnomaly =
+ detector.detectAnomalies(oldAnalysisNode, newAnalysisNode, frameN, frameTimeNs,
+ windowSizePx);
+ if (maybeAnomaly != null) {
+ AnalysisNode latestInfo = newAnalysisNode != null ? newAnalysisNode : oldAnalysisNode;
+ final String viewDiagPath = diagPathFromRoot(latestInfo);
+ if (!anomalies.containsKey(viewDiagPath)) {
+ anomalies.put(viewDiagPath, String.format("%s, %s", maybeAnomaly, latestInfo));
+ }
+ }
+ }
+
+ private static float getVisibleAlpha(ViewNode node, float parenVisibleAlpha) {
+ return node.getVisibility() == VISIBLE
+ ? parenVisibleAlpha * Math.max(0, Math.min(node.getAlpha(), 1))
+ : 0f;
+ }
+
+ private static String classNameToSimpleName(String className) {
+ return className.substring(className.lastIndexOf(".") + 1);
+ }
+
+ private static String diagPathFromRoot(AnalysisNode analysisNode) {
+ final StringBuilder path = new StringBuilder(analysisNode.nodeIdentity);
+ for (AnalysisNode ancestor = analysisNode.parent;
+ ancestor != null;
+ ancestor = ancestor.parent) {
+ path.insert(0, ancestor.nodeIdentity + "|");
+ }
+ return path.toString();
+ }
+
+ private static String getNodeIdentity(String className, String resourceId) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(classNameToSimpleName(className));
+ if (!"NO_ID".equals(resourceId)) sb.append(":" + resourceId);
+ return sb.toString();
+ }
+}
diff --git a/tests/src/com/android/launcher3/workspace/WorkspaceSpecsTest.kt b/tests/src/com/android/launcher3/workspace/WorkspaceSpecsTest.kt
deleted file mode 100644
index 9cd0a2e..0000000
--- a/tests/src/com/android/launcher3/workspace/WorkspaceSpecsTest.kt
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.workspace
-
-import android.content.Context
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.launcher3.AbstractDeviceProfileTest
-import com.android.launcher3.tests.R as TestR
-import com.android.launcher3.util.TestResourceHelper
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class WorkspaceSpecsTest : AbstractDeviceProfileTest() {
- override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context
-
- @Before
- fun setup() {
- initializeVarsForPhone(deviceSpecs["phone"]!!)
- }
-
- @Test
- fun parseValidFile() {
- val workspaceSpecs =
- WorkspaceSpecs(TestResourceHelper(context!!, TestR.xml.valid_workspace_file))
- assertThat(workspaceSpecs.workspaceHeightSpecList.size).isEqualTo(3)
- assertThat(workspaceSpecs.workspaceHeightSpecList[0].toString())
- .isEqualTo(
- "WorkspaceSpec(" +
- "maxAvailableSize=1533, " +
- "specType=HEIGHT, " +
- "startPadding=SizeSpec(fixedSize=0.0, " +
- "ofAvailableSpace=0.0, " +
- "ofRemainderSpace=0.0), " +
- "endPadding=SizeSpec(fixedSize=84.0, " +
- "ofAvailableSpace=0.0, " +
- "ofRemainderSpace=0.0), " +
- "gutter=SizeSpec(fixedSize=42.0, " +
- "ofAvailableSpace=0.0, " +
- "ofRemainderSpace=0.0), " +
- "cellSize=SizeSpec(fixedSize=0.0, " +
- "ofAvailableSpace=0.15808, " +
- "ofRemainderSpace=0.0)" +
- ")"
- )
- assertThat(workspaceSpecs.workspaceHeightSpecList[1].toString())
- .isEqualTo(
- "WorkspaceSpec(" +
- "maxAvailableSize=1607, " +
- "specType=HEIGHT, " +
- "startPadding=SizeSpec(fixedSize=0.0, " +
- "ofAvailableSpace=0.0, " +
- "ofRemainderSpace=0.0), " +
- "endPadding=SizeSpec(fixedSize=0.0, " +
- "ofAvailableSpace=0.0, " +
- "ofRemainderSpace=1.0), " +
- "gutter=SizeSpec(fixedSize=42.0, " +
- "ofAvailableSpace=0.0, " +
- "ofRemainderSpace=0.0), " +
- "cellSize=SizeSpec(fixedSize=273.0, " +
- "ofAvailableSpace=0.0, " +
- "ofRemainderSpace=0.0)" +
- ")"
- )
- assertThat(workspaceSpecs.workspaceHeightSpecList[2].toString())
- .isEqualTo(
- "WorkspaceSpec(" +
- "maxAvailableSize=26247, " +
- "specType=HEIGHT, " +
- "startPadding=SizeSpec(fixedSize=21.0, " +
- "ofAvailableSpace=0.0, " +
- "ofRemainderSpace=0.0), " +
- "endPadding=SizeSpec(fixedSize=0.0, " +
- "ofAvailableSpace=0.0, " +
- "ofRemainderSpace=1.0), " +
- "gutter=SizeSpec(fixedSize=42.0, " +
- "ofAvailableSpace=0.0, " +
- "ofRemainderSpace=0.0), " +
- "cellSize=SizeSpec(fixedSize=273.0, " +
- "ofAvailableSpace=0.0, " +
- "ofRemainderSpace=0.0)" +
- ")"
- )
- assertThat(workspaceSpecs.workspaceWidthSpecList.size).isEqualTo(1)
- assertThat(workspaceSpecs.workspaceWidthSpecList[0].toString())
- .isEqualTo(
- "WorkspaceSpec(" +
- "maxAvailableSize=26247, " +
- "specType=WIDTH, " +
- "startPadding=SizeSpec(fixedSize=58.0, " +
- "ofAvailableSpace=0.0, " +
- "ofRemainderSpace=0.0), " +
- "endPadding=SizeSpec(fixedSize=58.0, " +
- "ofAvailableSpace=0.0, " +
- "ofRemainderSpace=0.0), " +
- "gutter=SizeSpec(fixedSize=42.0, " +
- "ofAvailableSpace=0.0, " +
- "ofRemainderSpace=0.0), " +
- "cellSize=SizeSpec(fixedSize=0.0, " +
- "ofAvailableSpace=0.0, " +
- "ofRemainderSpace=0.25)" +
- ")"
- )
- }
-
- @Test(expected = IllegalStateException::class)
- fun parseInvalidFile_missingTag_throwsError() {
- WorkspaceSpecs(TestResourceHelper(context!!, TestR.xml.invalid_workspace_file_case_1))
- }
-
- @Test(expected = IllegalStateException::class)
- fun parseInvalidFile_moreThanOneValuePerTag_throwsError() {
- WorkspaceSpecs(TestResourceHelper(context!!, TestR.xml.invalid_workspace_file_case_2))
- }
-
- @Test(expected = IllegalStateException::class)
- fun parseInvalidFile_valueBiggerThan1_throwsError() {
- WorkspaceSpecs(TestResourceHelper(context!!, TestR.xml.invalid_workspace_file_case_3))
- }
-}
diff --git a/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java b/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java
index 10afe13..425c3c0 100644
--- a/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java
+++ b/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java
@@ -45,8 +45,8 @@
mLauncher.clickObject(
mLauncher.waitForObjectInContainer(
mWidgetCell.getParent().getParent().getParent().getParent(),
- By.text(ADD_AUTOMATICALLY)),
- LauncherInstrumentation.GestureScope.OUTSIDE_WITHOUT_PILFER);
+ By.text(ADD_AUTOMATICALLY))
+ );
mLauncher.waitUntilLauncherObjectGone(getSelector());
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index 399abc7..44875d5 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -48,6 +48,8 @@
private static final int MAX_SCROLL_ATTEMPTS = 40;
+ private static final String BOTTOM_SHEET_RES_ID = "bottom_sheet_background";
+
private final int mHeight;
private final int mIconHeight;
@@ -210,6 +212,9 @@
public AppIcon getAppIcon(String appName) {
AppIcon appIcon = tryGetAppIcon(appName);
mLauncher.assertNotNull("Unable to scroll to a clickable icon: " + appName, appIcon);
+ // appIcon.getAppName() checks for content description, so it is possible that it can have
+ // trailing words. So check if the content description contains the appName.
+ mLauncher.assertTrue("Wrong app icon name.", appIcon.getAppName().contains(appName));
return appIcon;
}
@@ -333,4 +338,33 @@
final Bundle testInfo = mLauncher.getTestInfo(TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS);
return testInfo == null ? 0 : testInfo.getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
+
+ /**
+ * Taps outside bottom sheet to dismiss it. Available on tablets only.
+ * @param tapRight Tap on the right of bottom sheet if true, or left otherwise.
+ */
+ public void dismissByTappingOutsideForTablet(boolean tapRight) {
+ mLauncher.assertTrue("Device must be a tablet", mLauncher.isTablet());
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to tap outside AllApps bottom sheet on the "
+ + (tapRight ? "right" : "left"))) {
+ final UiObject2 allAppsBottomSheet =
+ mLauncher.waitForLauncherObject(BOTTOM_SHEET_RES_ID);
+ mLauncher.touchOutsideContainer(allAppsBottomSheet, tapRight);
+ try (LauncherInstrumentation.Closable tapped = mLauncher.addContextLayer(
+ "tapped outside AllApps bottom sheet")) {
+ verifyVisibleContainerOnDismiss();
+ }
+ }
+ }
+
+ protected abstract void verifyVisibleContainerOnDismiss();
+
+ /**
+ * Return the QSB UI object on the AllApps screen.
+ * @return the QSB UI object.
+ */
+ @NonNull
+ public abstract Qsb getQsb();
}
\ No newline at end of file
diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsQsb.java b/tests/tapl/com/android/launcher3/tapl/AllAppsQsb.java
index 0931cd4..1692351 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllAppsQsb.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllAppsQsb.java
@@ -22,16 +22,7 @@
*/
class AllAppsQsb extends Qsb {
- private final UiObject2 mAllAppsContainer;
-
AllAppsQsb(LauncherInstrumentation launcher, UiObject2 allAppsContainer) {
- super(launcher);
- mAllAppsContainer = allAppsContainer;
- waitForQsbObject();
- }
-
- @Override
- protected UiObject2 waitForQsbObject() {
- return mLauncher.waitForObjectInContainer(mAllAppsContainer, "search_container_all_apps");
+ super(launcher, allAppsContainer, "search_container_all_apps");
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIcon.java b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
index 0a0cf07..85098c8 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIcon.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
@@ -37,10 +37,14 @@
}
static BySelector getAppIconSelector(String appName, LauncherInstrumentation launcher) {
- return By.clazz(TextView.class).textContains(appName)
+ return By.clazz(TextView.class).desc(makeMultilinePattern(appName))
.pkg(launcher.getLauncherPackageName());
}
+ static BySelector getMenuItemSelector(String text, LauncherInstrumentation launcher) {
+ return By.clazz(TextView.class).text(text).pkg(launcher.getLauncherPackageName());
+ }
+
static BySelector getAnyAppIconSelector() {
return By.clazz(TextView.class);
}
@@ -94,4 +98,24 @@
public String getIconName() {
return getObject().getText();
}
+
+ /**
+ * Return the app name of a icon by the content description. This should be used when trying to
+ * get the name of an app where the text of it is multiline.
+ */
+ @NonNull
+ String getAppName() {
+ return getObject().getContentDescription();
+ }
+
+ /**
+ * Create a regular expression pattern that matches strings starting with the app name, where
+ * spaces in the app name are replaced with zero or more occurrences of the "\s" character
+ * (which represents a whitespace character in regular expressions), followed by any characters
+ * after the app name.
+ */
+ static Pattern makeMultilinePattern(String appName) {
+ return Pattern.compile(appName.replaceAll("\\s+", "\\\\s*") + ".*",
+ Pattern.DOTALL);
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java b/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
index 667290f..bbcc6a8 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
@@ -50,7 +50,7 @@
*/
public AppIconMenuItem getMenuItem(String shortcutText) {
final UiObject2 menuItem = mLauncher.waitForObjectInContainer(mDeepShortcutsContainer,
- AppIcon.getAppIconSelector(shortcutText, mLauncher));
+ AppIcon.getMenuItemSelector(shortcutText, mLauncher));
return createMenuItem(menuItem);
}
@@ -59,7 +59,7 @@
*/
public SplitScreenMenuItem getSplitScreenMenuItem() {
final UiObject2 menuItem = mLauncher.waitForObjectInContainer(mDeepShortcutsContainer,
- AppIcon.getAppIconSelector("Split screen", mLauncher));
+ AppIcon.getMenuItemSelector("Split screen", mLauncher));
return new SplitScreenMenuItem(mLauncher, menuItem);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 5a96d95..677f204 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -28,6 +28,8 @@
import androidx.annotation.NonNull;
import androidx.test.uiautomator.UiObject2;
+import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel;
+import com.android.launcher3.tapl.LauncherInstrumentation.TrackpadGestureType;
import com.android.launcher3.testing.shared.TestProtocol;
import java.util.List;
@@ -64,85 +66,71 @@
}
- protected boolean zeroButtonToOverviewGestureStartsInLauncher() {
- return mLauncher.isTablet();
- }
-
protected boolean zeroButtonToOverviewGestureStateTransitionWhileHolding() {
return false;
}
protected void goToOverviewUnchecked() {
- switch (mLauncher.getNavigationModel()) {
- case ZERO_BUTTON: {
- final long downTime = SystemClock.uptimeMillis();
- sendDownPointerToEnterOverviewToLauncher(downTime);
- String swipeAndHoldToEnterOverviewActionName =
- "swiping and holding to enter overview";
- // If swiping from an app (e.g. Overview is in Background), we pause and hold on
- // swipe up to make overview appear, or else swiping without holding would take
- // us to the Home state. If swiping up from Home (e.g. Overview in Home or
- // Workspace state where the below condition is true), there is no need to pause,
- // and we will not test for an intermediate carousel as one will not exist.
- if (zeroButtonToOverviewGestureStateTransitionWhileHolding()) {
- mLauncher.runToState(
- () -> sendSwipeUpAndHoldToEnterOverviewGestureToLauncher(downTime),
- OVERVIEW_STATE_ORDINAL, swipeAndHoldToEnterOverviewActionName);
- sendUpPointerToEnterOverviewToLauncher(downTime);
- } else {
- // If swiping up from an app to overview, pause on intermediate carousel
- // until snapshots are visible. No intermediate carousel when swiping from
- // Home. The task swiped up is not a snapshot but the TaskViewSimulator. If
- // only a single task exists, no snapshots will be available during swipe up.
- mLauncher.executeAndWaitForLauncherEvent(
- () -> sendSwipeUpAndHoldToEnterOverviewGestureToLauncher(downTime),
- event -> TestProtocol.PAUSE_DETECTED_MESSAGE.equals(
- event.getClassName().toString()),
- () -> "Pause wasn't detected",
- swipeAndHoldToEnterOverviewActionName);
- try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "paused on swipe up to overview")) {
- if (mLauncher.getRecentTasks().size() > 1) {
- // When swiping up to grid-overview for tablets, the swiped tab will be
- // in the middle of the screen (TaskViewSimulator, not a snapshot), and
- // all remaining snapshots will be to the left of that task. In
- // non-tablet overview, snapshots can be on either side of the swiped
- // task, but we still check that they become visible after swiping and
- // pausing.
- mLauncher.waitForOverviewObject("snapshot");
- if (mLauncher.isTablet()) {
- List<UiObject2> tasks = mLauncher.getDevice().findObjects(
- mLauncher.getOverviewObjectSelector("snapshot"));
- final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
- mLauncher.assertTrue(
- "All tasks not to the left of the swiped task",
- tasks.stream()
- .allMatch(
- t -> t.getVisibleBounds().right < centerX));
- }
-
- }
- String upPointerToEnterOverviewActionName =
- "sending UP pointer to enter overview";
- mLauncher.runToState(() -> sendUpPointerToEnterOverviewToLauncher(downTime),
- OVERVIEW_STATE_ORDINAL, upPointerToEnterOverviewActionName);
- }
- }
- break;
- }
-
- case THREE_BUTTON:
- if (mLauncher.isTablet()) {
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
- LauncherInstrumentation.EVENT_TOUCH_DOWN);
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
- LauncherInstrumentation.EVENT_TOUCH_UP);
- }
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
+ if (mLauncher.getNavigationModel() == NavigationModel.ZERO_BUTTON
+ || mLauncher.getTrackpadGestureType() == TrackpadGestureType.THREE_FINGER) {
+ final long downTime = SystemClock.uptimeMillis();
+ sendDownPointerToEnterOverviewToLauncher(downTime);
+ String swipeAndHoldToEnterOverviewActionName =
+ "swiping and holding to enter overview";
+ // If swiping from an app (e.g. Overview is in Background), we pause and hold on
+ // swipe up to make overview appear, or else swiping without holding would take
+ // us to the Home state. If swiping up from Home (e.g. Overview in Home or
+ // Workspace state where the below condition is true), there is no need to pause,
+ // and we will not test for an intermediate carousel as one will not exist.
+ if (zeroButtonToOverviewGestureStateTransitionWhileHolding()) {
mLauncher.runToState(
- () -> mLauncher.waitForNavigationUiObject("recent_apps").click(),
- OVERVIEW_STATE_ORDINAL, "clicking Recents button");
- break;
+ () -> sendSwipeUpAndHoldToEnterOverviewGestureToLauncher(downTime),
+ OVERVIEW_STATE_ORDINAL, swipeAndHoldToEnterOverviewActionName);
+ sendUpPointerToEnterOverviewToLauncher(downTime);
+ } else {
+ // If swiping up from an app to overview, pause on intermediate carousel
+ // until snapshots are visible. No intermediate carousel when swiping from
+ // Home. The task swiped up is not a snapshot but the TaskViewSimulator. If
+ // only a single task exists, no snapshots will be available during swipe up.
+ mLauncher.executeAndWaitForLauncherEvent(
+ () -> sendSwipeUpAndHoldToEnterOverviewGestureToLauncher(downTime),
+ event -> TestProtocol.PAUSE_DETECTED_MESSAGE.equals(
+ event.getClassName().toString()),
+ () -> "Pause wasn't detected",
+ swipeAndHoldToEnterOverviewActionName);
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "paused on swipe up to overview")) {
+ if (mLauncher.getRecentTasks().size() > 1) {
+ // When swiping up to grid-overview for tablets, the swiped tab will be
+ // in the middle of the screen (TaskViewSimulator, not a snapshot), and
+ // all remaining snapshots will be to the left of that task. In
+ // non-tablet overview, snapshots can be on either side of the swiped
+ // task, but we still check that they become visible after swiping and
+ // pausing.
+ mLauncher.waitForOverviewObject("snapshot");
+ if (mLauncher.isTablet()) {
+ List<UiObject2> tasks = mLauncher.getDevice().findObjects(
+ mLauncher.getOverviewObjectSelector("snapshot"));
+ final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
+ mLauncher.assertTrue(
+ "All tasks not to the left of the swiped task",
+ tasks.stream()
+ .allMatch(
+ t -> t.getVisibleBounds().right < centerX));
+ }
+
+ }
+ String upPointerToEnterOverviewActionName =
+ "sending UP pointer to enter overview";
+ mLauncher.runToState(() -> sendUpPointerToEnterOverviewToLauncher(downTime),
+ OVERVIEW_STATE_ORDINAL, upPointerToEnterOverviewActionName);
+ }
+ }
+ } else {
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
+ mLauncher.runToState(
+ () -> mLauncher.waitForNavigationUiObject("recent_apps").click(),
+ OVERVIEW_STATE_ORDINAL, "clicking Recents button");
}
expectSwitchToOverviewEvents();
}
@@ -154,12 +142,9 @@
final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
final int startY = getSwipeStartY();
final Point start = new Point(centerX, startY);
- final LauncherInstrumentation.GestureScope gestureScope =
- zeroButtonToOverviewGestureStartsInLauncher()
- ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
- : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER;
- mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start, gestureScope);
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start,
+ LauncherInstrumentation.GestureScope.EXPECT_PILFER);
if (!mLauncher.isLauncher3()) {
mLauncher.expectEvent(TestProtocol.SEQUENCE_PILFER,
@@ -175,10 +160,6 @@
final Point start = new Point(centerX, startY);
final Point end =
new Point(centerX, startY - swipeHeight - mLauncher.getTouchSlop());
- final LauncherInstrumentation.GestureScope gestureScope =
- zeroButtonToOverviewGestureStartsInLauncher()
- ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
- : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER;
mLauncher.movePointer(
downTime,
@@ -186,7 +167,7 @@
ZERO_BUTTON_SWIPE_UP_GESTURE_DURATION,
start,
end,
- gestureScope);
+ LauncherInstrumentation.GestureScope.EXPECT_PILFER);
}
private void sendUpPointerToEnterOverviewToLauncher(long downTime) {
@@ -197,13 +178,9 @@
final Point end =
new Point(centerX, startY - swipeHeight - mLauncher.getTouchSlop());
- final LauncherInstrumentation.GestureScope gestureScope =
- zeroButtonToOverviewGestureStartsInLauncher()
- ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER
- : LauncherInstrumentation.GestureScope.OUTSIDE_WITHOUT_PILFER;
-
mLauncher.sendPointer(downTime, SystemClock.uptimeMillis(),
- MotionEvent.ACTION_UP, end, gestureScope);
+ MotionEvent.ACTION_UP, end,
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
}
/**
@@ -235,71 +212,48 @@
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to quick switch to the previous app")) {
verifyActiveContainer();
- final boolean launcherWasVisible = mLauncher.isLauncherVisible();
- switch (mLauncher.getNavigationModel()) {
- case ZERO_BUTTON: {
- final int startX;
- final int startY;
- final int endX;
- final int endY;
- final int cornerRadius = (int) Math.ceil(mLauncher.getWindowCornerRadius());
- if (toRight) {
- // Swipe from the bottom left to the bottom right of the screen.
- startX = cornerRadius;
- startY = getSwipeStartY();
- endX = mLauncher.getDevice().getDisplayWidth() - cornerRadius;
- endY = startY;
- } else {
- // Swipe from the bottom right to the bottom left of the screen.
- startX = mLauncher.getDevice().getDisplayWidth() - cornerRadius;
- startY = getSwipeStartY();
- endX = cornerRadius;
- endY = startY;
- }
-
- final boolean isZeroButton = mLauncher.getNavigationModel()
- == LauncherInstrumentation.NavigationModel.ZERO_BUTTON;
- LauncherInstrumentation.GestureScope gestureScope =
- launcherWasVisible && isZeroButton
- ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
- : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER;
- mLauncher.executeAndWaitForEvent(
- () -> mLauncher.linearGesture(
- startX, startY, endX, endY, 20, false, gestureScope),
- event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
- () -> "Quick switch gesture didn't change window state", "swiping");
- break;
+ if (mLauncher.getNavigationModel() == NavigationModel.ZERO_BUTTON
+ || mLauncher.getTrackpadGestureType() == TrackpadGestureType.FOUR_FINGER) {
+ final int startX;
+ final int startY;
+ final int endX;
+ final int endY;
+ final int cornerRadius = (int) Math.ceil(mLauncher.getWindowCornerRadius());
+ if (toRight) {
+ // Swipe from the bottom left to the bottom right of the screen.
+ startX = cornerRadius;
+ startY = getSwipeStartY();
+ endX = mLauncher.getDevice().getDisplayWidth() - cornerRadius;
+ endY = startY;
+ } else {
+ // Swipe from the bottom right to the bottom left of the screen.
+ startX = mLauncher.getDevice().getDisplayWidth() - cornerRadius;
+ startY = getSwipeStartY();
+ endX = cornerRadius;
+ endY = startY;
}
- case THREE_BUTTON:
- // Double press the recents button.
- UiObject2 recentsButton = mLauncher.waitForNavigationUiObject("recent_apps");
- if (mLauncher.isTablet()) {
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
- LauncherInstrumentation.EVENT_TOUCH_DOWN);
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
- LauncherInstrumentation.EVENT_TOUCH_UP);
- }
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
- mLauncher.runToState(() -> recentsButton.click(), OVERVIEW_STATE_ORDINAL,
- "clicking Recents button for the first time");
- mLauncher.getOverview();
- if (mLauncher.isTablet()) {
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
- LauncherInstrumentation.EVENT_TOUCH_DOWN);
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
- LauncherInstrumentation.EVENT_TOUCH_UP);
- }
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
- mLauncher.executeAndWaitForEvent(
- () -> recentsButton.click(),
- event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
- () -> "Pressing recents button didn't change window state",
- "clicking Recents button for the second time");
- break;
+ mLauncher.executeAndWaitForEvent(
+ () -> mLauncher.linearGesture(
+ startX, startY, endX, endY, 20, false,
+ LauncherInstrumentation.GestureScope.EXPECT_PILFER),
+ event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
+ () -> "Quick switch gesture didn't change window state", "swiping");
+ } else {
+ // Double press the recents button.
+ UiObject2 recentsButton = mLauncher.waitForNavigationUiObject("recent_apps");
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
+ mLauncher.runToState(() -> recentsButton.click(), OVERVIEW_STATE_ORDINAL,
+ "clicking Recents button for the first time");
+ mLauncher.getOverview();
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
+ mLauncher.executeAndWaitForEvent(
+ () -> recentsButton.click(),
+ event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
+ () -> "Pressing recents button didn't change window state",
+ "clicking Recents button for the second time");
}
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, TASK_START_EVENT);
- return;
}
}
@@ -312,6 +266,8 @@
}
protected int getSwipeStartY() {
- return mLauncher.getRealDisplaySize().y - 1;
+ return mLauncher.getTrackpadGestureType() == TrackpadGestureType.THREE_FINGER
+ ? mLauncher.getDevice().getDisplayHeight() * 3 / 4
+ : mLauncher.getRealDisplaySize().y - 1;
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index 2c3c028..aa5c770 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -324,13 +324,16 @@
if (!hasTasks() || isClearAllVisible()) {
return false;
}
- OverviewTask task = mLauncher.isTablet() ? getFocusedTaskForTablet() : getCurrentTask();
+ boolean isTablet = mLauncher.isTablet();
+ if (isTablet && mLauncher.isGridOnlyOverviewEnabled()) {
+ return false;
+ }
+ OverviewTask task = isTablet ? getFocusedTaskForTablet() : getCurrentTask();
if (task == null) {
return false;
}
// In tablets, if focused task is not in center, overview actions aren't visible.
- if (mLauncher.isTablet()
- && Math.abs(task.getExactCenterX() - mLauncher.getExactScreenCenterX()) >= 1) {
+ if (isTablet && Math.abs(task.getExactCenterX() - mLauncher.getExactScreenCenterX()) >= 1) {
return false;
}
// Overview actions aren't visible for split screen tasks.
diff --git a/tests/tapl/com/android/launcher3/tapl/Home.java b/tests/tapl/com/android/launcher3/tapl/Home.java
index ee9dd1a..252435b 100644
--- a/tests/tapl/com/android/launcher3/tapl/Home.java
+++ b/tests/tapl/com/android/launcher3/tapl/Home.java
@@ -59,11 +59,6 @@
}
@Override
- protected boolean zeroButtonToOverviewGestureStartsInLauncher() {
- return true;
- }
-
- @Override
protected boolean zeroButtonToOverviewGestureStateTransitionWhileHolding() {
return true;
}
diff --git a/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java
index 1239d7a..8542f91 100644
--- a/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java
@@ -23,30 +23,34 @@
import com.android.launcher3.testing.shared.TestProtocol;
public class HomeAllApps extends AllApps {
- private static final String BOTTOM_SHEET_RES_ID = "bottom_sheet_background";
HomeAllApps(LauncherInstrumentation launcher) {
super(launcher);
}
/**
- * Swipes down to Workspace.
+ * Swipes up or down to dismiss to Workspace.
+ * @param swipeDown Swipe all apps down to dismiss, otherwise swipe up to dismiss by going home.
*
* @return the Workspace object.
*/
@NonNull
- public Workspace switchToWorkspace() {
+ public Workspace switchToWorkspace(boolean swipeDown) {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c =
mLauncher.addContextLayer("want to switch from all apps to workspace")) {
UiObject2 allAppsContainer = verifyActiveContainer();
final int startX = allAppsContainer.getVisibleCenter().x;
- final int startY = getTopVisibleIconBounds(allAppsContainer).centerY();
- final int endY = mLauncher.getDevice().getDisplayHeight();
+ final int startY = swipeDown ? getTopVisibleIconBounds(allAppsContainer).centerY()
+ : mLauncher.getDevice().getDisplayHeight();
+ final int endY =
+ swipeDown ? mLauncher.getDevice().getDisplayHeight() : getTopVisibleIconBounds(
+ allAppsContainer).centerY();
LauncherInstrumentation.log(
"switchToWorkspace: startY = " + startY + ", endY = " + endY
- + ", slop = " + mLauncher.getTouchSlop());
+ + ", slop = " + mLauncher.getTouchSlop()
+ + ", swipeDown = " + swipeDown);
mLauncher.swipeToState(
startX,
@@ -54,7 +58,9 @@
startX,
endY,
5 /* steps */,
- NORMAL_STATE_ORDINAL, LauncherInstrumentation.GestureScope.INSIDE);
+ NORMAL_STATE_ORDINAL,
+ swipeDown ? LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER
+ : LauncherInstrumentation.GestureScope.EXPECT_PILFER);
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
"swiped to workspace")) {
@@ -91,30 +97,8 @@
.getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
- /**
- * Taps outside bottom sheet to dismiss and return to workspace. Available on tablets only.
- * @param tapRight Tap on the right of bottom sheet if true, or left otherwise.
- */
- public Workspace dismissByTappingOutsideForTablet(boolean tapRight) {
- try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
- LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "want to tap outside AllApps bottom sheet on the "
- + (tapRight ? "right" : "left"))) {
- final UiObject2 allAppsBottomSheet =
- mLauncher.waitForLauncherObject(BOTTOM_SHEET_RES_ID);
- mLauncher.touchOutsideContainer(allAppsBottomSheet, tapRight);
- try (LauncherInstrumentation.Closable tapped = mLauncher.addContextLayer(
- "tapped outside AllApps bottom sheet")) {
- return mLauncher.getWorkspace();
- }
- }
- }
-
- /**
- * Return the QSB UI object on the AllApps screen.
- * @return the QSB UI object.
- */
@NonNull
+ @Override
public Qsb getQsb() {
return new AllAppsQsb(mLauncher, verifyActiveContainer());
}
@@ -124,4 +108,9 @@
return mLauncher.getTestInfo(TestProtocol.REQUEST_APPS_LIST_SCROLL_Y)
.getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
+
+ @Override
+ protected void verifyVisibleContainerOnDismiss() {
+ mLauncher.getWorkspace();
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/HomeQsb.java b/tests/tapl/com/android/launcher3/tapl/HomeQsb.java
index 20d09a1..5385c65 100644
--- a/tests/tapl/com/android/launcher3/tapl/HomeQsb.java
+++ b/tests/tapl/com/android/launcher3/tapl/HomeQsb.java
@@ -22,16 +22,7 @@
*/
class HomeQsb extends Qsb {
- private final UiObject2 mHotSeat;
-
HomeQsb(LauncherInstrumentation launcher, UiObject2 hotseat) {
- super(launcher);
- mHotSeat = hotseat;
- waitForQsbObject();
- }
-
- @Override
- protected UiObject2 waitForQsbObject() {
- return mLauncher.waitForObjectInContainer(mHotSeat, "search_container_hotseat");
+ super(launcher, hotseat, "search_container_hotseat");
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 48e327f..3450ea7 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -16,10 +16,14 @@
package com.android.launcher3.tapl;
+import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
+
import static com.android.launcher3.testing.shared.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
+import android.app.UiAutomation;
import android.graphics.Point;
import android.view.MotionEvent;
+import android.view.accessibility.AccessibilityEvent;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
@@ -83,12 +87,18 @@
* fired when the click is executed.
*/
public LaunchedAppState launchIntoSplitScreen() {
- try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
- "want to launch split tasks from " + launchableType())) {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "want to launch split tasks from " + launchableType())) {
LauncherInstrumentation.log("Launchable.launch before click "
- + mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
-
- mLauncher.clickLauncherObject(mObject);
+ + mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(
+ mObject));
+ mLauncher.executeAndWaitForLauncherEvent(
+ () -> mLauncher.clickLauncherObject(mObject),
+ accessibilityEvent ->
+ accessibilityEvent.getEventType() == TYPE_WINDOW_STATE_CHANGED,
+ () -> "Unable to click object to launch split",
+ "Click launcher object to launch split");
try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, OverviewTask.SPLIT_START_EVENT);
@@ -152,7 +162,7 @@
downTime,
MotionEvent.ACTION_DOWN,
iconCenter,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
LauncherInstrumentation.log("movePointerForStartDrag: sent down");
expectLongClickEvents.run();
waitForLongPressConfirmation();
@@ -165,7 +175,7 @@
downTime,
downTime,
/* slowDown= */ true,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
}
private int getStartDragThreshold() {
diff --git a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
index a59eff7..30417c0 100644
--- a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
+++ b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
@@ -30,6 +30,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.os.SystemClock;
+import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
@@ -37,6 +38,7 @@
import androidx.test.uiautomator.Condition;
import androidx.test.uiautomator.UiDevice;
+import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.testing.shared.TestProtocol;
/**
@@ -50,6 +52,8 @@
// UNSTASHED_TASKBAR_HANDLE_HINT_SCALE value from TaskbarStashController.
private static final float UNSTASHED_TASKBAR_HANDLE_HINT_SCALE = 1.1f;
+ private static final int STASHED_TASKBAR_BOTTOM_EDGE_DP = 1;
+
private final Condition<UiDevice, Boolean> mStashedTaskbarHintScaleCondition =
device -> mLauncher.getTestInfo(REQUEST_STASHED_TASKBAR_SCALE).getFloat(
TestProtocol.TEST_INFO_RESPONSE_FIELD) - UNSTASHED_TASKBAR_HANDLE_HINT_SCALE
@@ -124,13 +128,13 @@
mLauncher.getRealDisplaySize().x / 2, unstashTargetY);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, unstashTarget,
- LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
+ LauncherInstrumentation.GestureScope.EXPECT_PILFER);
LauncherInstrumentation.log("showTaskbar: sent down");
try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("pressed down")) {
mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, unstashTarget,
- LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
+ LauncherInstrumentation.GestureScope.EXPECT_PILFER);
return new Taskbar(mLauncher);
}
@@ -179,7 +183,7 @@
downTime,
SystemClock.uptimeMillis(),
/* slowDown= */ false,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
try (LauncherInstrumentation.Closable c3 = launcher.addContextLayer(
"moved pointer to drop point")) {
@@ -190,7 +194,7 @@
SystemClock.uptimeMillis(),
MotionEvent.ACTION_UP,
endPoint,
- LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: "
+ "after drop");
@@ -209,7 +213,7 @@
*
* <p>This unstashing occurs when not actively hovering the taskbar.
*/
- public void hoverScreenBottomEdgeToUnstashTaskbar() {
+ public Taskbar hoverScreenBottomEdgeToUnstashTaskbar() {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"cursor hover entering screen edge to unstash taskbar")) {
@@ -220,19 +224,23 @@
int leftEdge = 10;
Point taskbarUnstashArea = new Point(leftEdge, mLauncher.getRealDisplaySize().y - 1);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER,
- new Point(taskbarUnstashArea.x, taskbarUnstashArea.y), null);
+ new Point(taskbarUnstashArea.x, taskbarUnstashArea.y), null,
+ InputDevice.SOURCE_MOUSE);
mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_EXIT,
- new Point(taskbarUnstashArea.x, taskbarUnstashArea.y), null);
+ new Point(taskbarUnstashArea.x, taskbarUnstashArea.y), null,
+ InputDevice.SOURCE_MOUSE);
+
+ return new Taskbar(mLauncher);
}
}
/**
* Emulate the cursor hovering the taskbar to get unstash hint, then hovering below to unstash.
*/
- public void hoverBelowHintedTaskbarToUnstash() {
+ public Taskbar hoverBelowHintedTaskbarToUnstash() {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"cursor hover entering stashed taskbar")) {
@@ -240,7 +248,8 @@
Point stashedTaskbarHintArea = new Point(mLauncher.getRealDisplaySize().x / 2,
mLauncher.getRealDisplaySize().y - 1);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER,
- new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y), null);
+ new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y), null,
+ InputDevice.SOURCE_MOUSE);
mLauncher.getDevice().wait(mStashedTaskbarHintScaleCondition,
LauncherInstrumentation.WAIT_TIME_MS);
@@ -251,9 +260,11 @@
Point taskbarUnstashArea = new Point(mLauncher.getRealDisplaySize().x / 2,
mLauncher.getRealDisplaySize().y - 1);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_EXIT,
- new Point(taskbarUnstashArea.x, taskbarUnstashArea.y), null);
+ new Point(taskbarUnstashArea.x, taskbarUnstashArea.y), null,
+ InputDevice.SOURCE_MOUSE);
mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID);
+ return new Taskbar(mLauncher);
}
}
}
@@ -288,4 +299,48 @@
}
}
}
+
+ /**
+ * Emulate the cursor clicking the stashed taskbar to go home.
+ */
+ public Workspace clickStashedTaskbarToGoHome() {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "cursor hover entering stashed taskbar")) {
+ long downTime = SystemClock.uptimeMillis();
+ int stashedTaskbarBottomEdge = ResourceUtils.pxFromDp(STASHED_TASKBAR_BOTTOM_EDGE_DP,
+ mLauncher.getResources().getDisplayMetrics());
+ Point stashedTaskbarHintArea = new Point(mLauncher.getRealDisplaySize().x / 2,
+ mLauncher.getRealDisplaySize().y - stashedTaskbarBottomEdge - 1);
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER,
+ new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y), null,
+ InputDevice.SOURCE_MOUSE);
+
+ mLauncher.getDevice().wait(mStashedTaskbarHintScaleCondition,
+ LauncherInstrumentation.WAIT_TIME_MS);
+
+ try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "cursor clicking stashed taskbar to go home")) {
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_EXIT,
+ new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y),
+ null, InputDevice.SOURCE_MOUSE);
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN,
+ new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y),
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER,
+ InputDevice.SOURCE_MOUSE);
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_BUTTON_PRESS,
+ new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y),
+ null, InputDevice.SOURCE_MOUSE);
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_BUTTON_RELEASE,
+ new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y),
+ null, InputDevice.SOURCE_MOUSE);
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP,
+ new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y),
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER,
+ InputDevice.SOURCE_MOUSE);
+
+ return mLauncher.getWorkspace();
+ }
+ }
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index c4f5da5..71ca77f 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -20,7 +20,7 @@
import static android.content.pm.PackageManager.DONT_KILL_APP;
import static android.content.pm.PackageManager.MATCH_ALL;
import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
-
+import static android.view.MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT;
import static com.android.launcher3.tapl.Folder.FOLDER_CONTENT_RES_ID;
import static com.android.launcher3.tapl.TestHelpers.getOverviewPackageName;
import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
@@ -28,12 +28,14 @@
import android.app.ActivityManager;
import android.app.Instrumentation;
import android.app.UiAutomation;
+import android.app.UiModeManager;
import android.content.ComponentName;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.Point;
@@ -98,18 +100,9 @@
private static final int ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME = 15;
private static final int GESTURE_STEP_MS = 16;
- static final Pattern EVENT_TOUCH_DOWN = getTouchEventPattern("ACTION_DOWN");
- static final Pattern EVENT_TOUCH_UP = getTouchEventPattern("ACTION_UP");
- private static final Pattern EVENT_TOUCH_CANCEL = getTouchEventPattern("ACTION_CANCEL");
static final Pattern EVENT_PILFER_POINTERS = Pattern.compile("pilferPointers");
static final Pattern EVENT_START = Pattern.compile("start:");
- static final Pattern EVENT_TOUCH_DOWN_TIS = getTouchEventPatternTIS("ACTION_DOWN");
- static final Pattern EVENT_TOUCH_UP_TIS = getTouchEventPatternTIS("ACTION_UP");
- static final Pattern EVENT_TOUCH_CANCEL_TIS = getTouchEventPatternTIS("ACTION_CANCEL");
- static final Pattern EVENT_HOVER_ENTER_TIS = getTouchEventPatternTIS("ACTION_HOVER_ENTER");
- static final Pattern EVENT_HOVER_EXIT_TIS = getTouchEventPatternTIS("ACTION_HOVER_EXIT");
-
private static final Pattern EVENT_KEY_BACK_DOWN =
getKeyEventPattern("ACTION_DOWN", "KEYCODE_BACK");
private static final Pattern EVENT_KEY_BACK_UP =
@@ -129,26 +122,19 @@
public enum NavigationModel {ZERO_BUTTON, THREE_BUTTON}
- // Where the gesture happens: outside of Launcher, inside or from inside to outside and
- // whether the gesture recognition triggers pilfer.
+ // Defines whether the gesture recognition triggers pilfer.
public enum GestureScope {
- OUTSIDE_WITHOUT_PILFER, OUTSIDE_WITH_PILFER, INSIDE, INSIDE_TO_OUTSIDE,
- INSIDE_TO_OUTSIDE_WITHOUT_PILFER,
- INSIDE_TO_OUTSIDE_WITH_KEYCODE, // For gestures that will trigger a keycode from TIS.
- OUTSIDE_WITH_KEYCODE,
+ DONT_EXPECT_PILFER,
+ EXPECT_PILFER,
}
- /**
- * Represents a point in the code at which a callback can run.
- */
- public enum CALLBACK_RUN_POINT {
- CALLBACK_HOLD_BEFORE_DROP,
- CALLBACK_HOVER_ENTER,
- CALLBACK_HOVER_EXIT,
+ public enum TrackpadGestureType {
+ NONE,
+ TWO_FINGER,
+ THREE_FINGER,
+ FOUR_FINGER
}
- private Consumer<CALLBACK_RUN_POINT> mCallbackAtRunPoint = null;
-
// Base class for launcher containers.
abstract static class VisibleContainer {
protected final LauncherInstrumentation mLauncher;
@@ -176,7 +162,7 @@
void close();
}
- private static final String WORKSPACE_RES_ID = "workspace";
+ static final String WORKSPACE_RES_ID = "workspace";
private static final String APPS_RES_ID = "apps_view";
private static final String OVERVIEW_RES_ID = "overview_panel";
private static final String WIDGETS_RES_ID = "primary_widgets_list_view";
@@ -188,6 +174,8 @@
static final long DEFAULT_POLL_INTERVAL = 1000;
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
private static final String ANDROID_PACKAGE = "android";
+ private static final String ASSISTANT_PACKAGE = "com.google.android.googlequicksearchbox";
+ private static final String ASSISTANT_GO_HOME_RES_ID = "home_icon";
private static WeakReference<VisibleContainer> sActiveContainer = new WeakReference<>(null);
@@ -208,20 +196,8 @@
private boolean mCheckEventsForSuccessfulGestures = false;
private Runnable mOnLauncherCrashed;
- private static Pattern getTouchEventPattern(String prefix, String action) {
- // The pattern includes checks that we don't get a multi-touch events or other surprises.
- return Pattern.compile(
- prefix + ": MotionEvent.*?action=" + action + ".*?id\\[0\\]=0"
- + ".*?toolType\\[0\\]=TOOL_TYPE_FINGER.*?buttonState=0.*?pointerCount=1");
- }
-
- private static Pattern getTouchEventPattern(String action) {
- return getTouchEventPattern("Touch event", action);
- }
-
- private static Pattern getTouchEventPatternTIS(String action) {
- return getTouchEventPattern("TouchInteractionService.onInputEvent", action);
- }
+ private TrackpadGestureType mTrackpadGestureType = TrackpadGestureType.NONE;
+ private int mPointerCount = 0;
private static Pattern getKeyEventPattern(String action, String keyCode) {
return Pattern.compile("Key event: KeyEvent.*action=" + action + ".*keyCode=" + keyCode);
@@ -365,6 +341,11 @@
.getParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
+ Insets getImeInsets() {
+ return getTestInfo(TestProtocol.REQUEST_IME_INSETS)
+ .getParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD);
+ }
+
public boolean isTablet() {
return getTestInfo(TestProtocol.REQUEST_IS_TABLET)
.getBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD);
@@ -715,6 +696,19 @@
}
/**
+ * Set the trackpad gesture type of the interaction.
+ * @param trackpadGestureType whether it's not from trackpad, two-finger, three-finger, or
+ * four-finger gesture.
+ */
+ public void setTrackpadGestureType(TrackpadGestureType trackpadGestureType) {
+ mTrackpadGestureType = trackpadGestureType;
+ }
+
+ TrackpadGestureType getTrackpadGestureType() {
+ return mTrackpadGestureType;
+ }
+
+ /**
* Sets expected rotation.
* TAPL periodically checks that Launcher didn't suddenly change the rotation to unexpected one.
* Null parameter disables checks. The initial state is "no checks".
@@ -727,6 +721,10 @@
mExpectedRotationCheckEnabled = expectedRotationCheckEnabled;
}
+ public boolean getExpectedRotationCheckEnabled() {
+ return mExpectedRotationCheckEnabled;
+ }
+
public String getNavigationModeMismatchError(boolean waitForCorrectState) {
final int waitTime = waitForCorrectState ? WAIT_TIME_MS : 0;
final NavigationModel navigationModel = getNavigationModel();
@@ -957,8 +955,8 @@
GestureScope gestureScope = gestureStartFromLauncher
// Without the navigation bar layer, the gesture scope on tablets remains inside the
// launcher process.
- ? (isTablet() ? GestureScope.INSIDE : GestureScope.INSIDE_TO_OUTSIDE)
- : GestureScope.OUTSIDE_WITH_PILFER;
+ ? (isTablet() ? GestureScope.DONT_EXPECT_PILFER : GestureScope.EXPECT_PILFER)
+ : GestureScope.EXPECT_PILFER;
linearGesture(
displaySize.x / 2, displaySize.y - 1,
displaySize.x / 2, 0,
@@ -1003,8 +1001,11 @@
// We need waiting for any accessibility event generated after pressing Home because
// otherwise waitForIdle may return immediately in case when there was a big enough
// pause in accessibility events prior to pressing Home.
+ boolean isThreeFingerTrackpadGesture =
+ mTrackpadGestureType == TrackpadGestureType.THREE_FINGER;
final String action;
- if (getNavigationModel() == NavigationModel.ZERO_BUTTON) {
+ if (getNavigationModel() == NavigationModel.ZERO_BUTTON
+ || isThreeFingerTrackpadGesture) {
checkForAnomaly(false, true);
final Point displaySize = getRealDisplaySize();
@@ -1020,24 +1021,22 @@
} else {
action = "swiping up to home";
+ int startY = isThreeFingerTrackpadGesture ? displaySize.y * 3 / 4
+ : displaySize.y - 1;
+ int endY = isThreeFingerTrackpadGesture ? displaySize.y / 4 : displaySize.y / 2;
swipeToState(
- displaySize.x / 2, displaySize.y - 1,
- displaySize.x / 2, displaySize.y / 2,
+ displaySize.x / 2, startY,
+ displaySize.x / 2, endY,
ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME, NORMAL_STATE_ORDINAL,
- gestureStartFromLauncher ? GestureScope.INSIDE_TO_OUTSIDE
- : GestureScope.OUTSIDE_WITH_PILFER);
+ GestureScope.EXPECT_PILFER);
}
} else {
log("Hierarchy before clicking home:");
dumpViewHierarchy();
action = "clicking home button";
- if (isTablet()) {
- expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
- expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_UP);
- }
runToState(
- waitForNavigationUiObject("home")::click,
+ getHomeButton()::click,
NORMAL_STATE_ORDINAL,
!hasLauncherObject(WORKSPACE_RES_ID)
&& (hasLauncherObject(APPS_RES_ID)
@@ -1059,21 +1058,19 @@
waitForLauncherInitialized();
final boolean launcherVisible =
isTablet() ? isLauncherContainerVisible() : isLauncherVisible();
- if (getNavigationModel() == NavigationModel.ZERO_BUTTON) {
+ boolean isThreeFingerTrackpadGesture =
+ mTrackpadGestureType == TrackpadGestureType.THREE_FINGER;
+ if (getNavigationModel() == NavigationModel.ZERO_BUTTON
+ || isThreeFingerTrackpadGesture) {
final Point displaySize = getRealDisplaySize();
- final GestureScope gestureScope =
- launcherVisible ? GestureScope.INSIDE_TO_OUTSIDE_WITH_KEYCODE
- : GestureScope.OUTSIDE_WITH_KEYCODE;
// TODO(b/225505986): change startY and endY back to displaySize.y / 2 once the
// issue is solved.
- linearGesture(0, displaySize.y / 4, displaySize.x / 2, displaySize.y / 4,
- 10, false, gestureScope);
+ int startX = isThreeFingerTrackpadGesture ? displaySize.x / 4 : 0;
+ int endX = isThreeFingerTrackpadGesture ? displaySize.x * 3 / 4 : displaySize.x / 2;
+ linearGesture(startX, displaySize.y / 4, endX, displaySize.y / 4,
+ 10, false, GestureScope.DONT_EXPECT_PILFER);
} else {
waitForNavigationUiObject("back").click();
- if (isTablet()) {
- expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
- expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_UP);
- }
}
if (launcherVisible) {
if (getContext().getApplicationInfo().isOnBackInvokedCallbackEnabled()) {
@@ -1220,6 +1217,28 @@
}
@NonNull
+ private UiObject2 getHomeButton() {
+ UiModeManager uiManager =
+ (UiModeManager) getContext().getSystemService(Context.UI_MODE_SERVICE);
+ if (uiManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR) {
+ return waitForAssistantHomeButton();
+ } else {
+ return waitForNavigationUiObject("home");
+ }
+ }
+
+ /* Assistant Home button is present when system is in car mode. */
+ @NonNull
+ UiObject2 waitForAssistantHomeButton() {
+ final UiObject2 object = mDevice.wait(
+ Until.findObject(By.res(ASSISTANT_PACKAGE, ASSISTANT_GO_HOME_RES_ID)),
+ WAIT_TIME_MS);
+ assertNotNull(
+ "Can't find an assistant UI object with id: " + ASSISTANT_GO_HOME_RES_ID, object);
+ return object;
+ }
+
+ @NonNull
UiObject2 waitForNavigationUiObject(String resId) {
String resPackage = getNavigationButtonResPackage();
final UiObject2 object = mDevice.wait(
@@ -1481,15 +1500,17 @@
* animations because in some scenarios there is a playing animations when the click is
* attempted.
*/
- void clickObject(UiObject2 uiObject, GestureScope gestureScope) {
+ void clickObject(UiObject2 uiObject) {
final long clickTime = SystemClock.uptimeMillis();
final Point center = uiObject.getVisibleCenter();
- sendPointer(clickTime, clickTime, MotionEvent.ACTION_DOWN, center, gestureScope);
- sendPointer(clickTime, clickTime, MotionEvent.ACTION_UP, center, gestureScope);
+ sendPointer(clickTime, clickTime, MotionEvent.ACTION_DOWN, center,
+ GestureScope.DONT_EXPECT_PILFER);
+ sendPointer(clickTime, clickTime, MotionEvent.ACTION_UP, center,
+ GestureScope.DONT_EXPECT_PILFER);
}
void clickLauncherObject(UiObject2 object) {
- clickObject(object, GestureScope.INSIDE);
+ clickObject(object);
}
void scrollToLastVisibleRow(
@@ -1582,7 +1603,8 @@
executeAndWaitForLauncherEvent(
() -> linearGesture(
- startX, startY, endX, endY, steps, slowDown, GestureScope.INSIDE),
+ startX, startY, endX, endY, steps, slowDown,
+ GestureScope.DONT_EXPECT_PILFER),
event -> TestProtocol.SCROLL_FINISHED_MESSAGE.equals(event.getClassName()),
() -> "Didn't receive a scroll end message: " + startX + ", " + startY
+ ", " + endX + ", " + endY,
@@ -1592,18 +1614,43 @@
// Inject a swipe gesture. Inject exactly 'steps' motion points, incrementing event time by a
// fixed interval each time.
public void linearGesture(int startX, int startY, int endX, int endY, int steps,
- boolean slowDown,
- GestureScope gestureScope) {
+ boolean slowDown, GestureScope gestureScope) {
log("linearGesture: " + startX + ", " + startY + " -> " + endX + ", " + endY);
final long downTime = SystemClock.uptimeMillis();
final Point start = new Point(startX, startY);
final Point end = new Point(endX, endY);
sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start, gestureScope);
+ if (mTrackpadGestureType != TrackpadGestureType.NONE) {
+ sendPointer(downTime, downTime, getPointerAction(MotionEvent.ACTION_POINTER_DOWN, 1),
+ start, gestureScope);
+ if (mTrackpadGestureType == TrackpadGestureType.THREE_FINGER
+ || mTrackpadGestureType == TrackpadGestureType.FOUR_FINGER) {
+ sendPointer(downTime, downTime,
+ getPointerAction(MotionEvent.ACTION_POINTER_DOWN, 2),
+ start, gestureScope);
+ if (mTrackpadGestureType == TrackpadGestureType.FOUR_FINGER) {
+ sendPointer(downTime, downTime,
+ getPointerAction(MotionEvent.ACTION_POINTER_DOWN, 3),
+ start, gestureScope);
+ }
+ }
+ }
final long endTime = movePointer(
start, end, steps, false, downTime, downTime, slowDown, gestureScope);
+ if (mTrackpadGestureType != TrackpadGestureType.NONE) {
+ for (int i = mPointerCount; i >= 2; i--) {
+ sendPointer(downTime, downTime,
+ getPointerAction(MotionEvent.ACTION_POINTER_UP, i - 1),
+ start, gestureScope);
+ }
+ }
sendPointer(downTime, endTime, MotionEvent.ACTION_UP, end, gestureScope);
}
+ private static int getPointerAction(int action, int index) {
+ return action + (index << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
+ }
+
long movePointer(Point start, Point end, int steps, boolean isDecelerating, long downTime,
long startTime, boolean slowDown, GestureScope gestureScope) {
long endTime = movePointer(downTime, startTime, steps * GESTURE_STEP_MS,
@@ -1627,74 +1674,104 @@
return getContext().getResources();
}
- private static MotionEvent getMotionEvent(long downTime, long eventTime, int action,
- float x, float y) {
- MotionEvent.PointerProperties properties = new MotionEvent.PointerProperties();
- properties.id = 0;
- properties.toolType = Configurator.getInstance().getToolType();
+ private static MotionEvent getTrackpadMotionEvent(long downTime, long eventTime,
+ int action, float x, float y, int pointerCount, TrackpadGestureType gestureType) {
+ MotionEvent.PointerProperties[] pointerProperties =
+ new MotionEvent.PointerProperties[pointerCount];
+ MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[pointerCount];
+ boolean isMultiFingerGesture = gestureType != TrackpadGestureType.TWO_FINGER;
+ for (int i = 0; i < pointerCount; i++) {
+ pointerProperties[i] = getPointerProperties(i);
+ pointerCoords[i] = getPointerCoords(x, y);
+ if (isMultiFingerGesture) {
+ pointerCoords[i].setAxisValue(AXIS_GESTURE_SWIPE_FINGER_COUNT,
+ gestureType == TrackpadGestureType.THREE_FINGER ? 3 : 4);
+ }
+ }
+ return MotionEvent.obtain(downTime, eventTime, action, pointerCount, pointerProperties,
+ pointerCoords, 0, 0, 1.0f, 1.0f, 0, 0,
+ InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_CLASS_POINTER, 0, 0,
+ isMultiFingerGesture ? MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE
+ : MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE);
+ }
+ private static MotionEvent getMotionEvent(long downTime, long eventTime, int action,
+ float x, float y, int source) {
+ return MotionEvent.obtain(downTime, eventTime, action, 1,
+ new MotionEvent.PointerProperties[]{getPointerProperties(0)},
+ new MotionEvent.PointerCoords[]{getPointerCoords(x, y)},
+ 0, 0, 1.0f, 1.0f, 0, 0, source, 0);
+ }
+
+ private static MotionEvent.PointerProperties getPointerProperties(int pointerId) {
+ MotionEvent.PointerProperties properties = new MotionEvent.PointerProperties();
+ properties.id = pointerId;
+ properties.toolType = Configurator.getInstance().getToolType();
+ return properties;
+ }
+
+ private static MotionEvent.PointerCoords getPointerCoords(float x, float y) {
MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
coords.pressure = 1;
coords.size = 1;
coords.x = x;
coords.y = y;
-
- return MotionEvent.obtain(downTime, eventTime, action, 1,
- new MotionEvent.PointerProperties[]{properties},
- new MotionEvent.PointerCoords[]{coords},
- 0, 0, 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
+ return coords;
}
private boolean hasTIS() {
- return getTestInfo(TestProtocol.REQUEST_HAS_TIS).getBoolean(TestProtocol.REQUEST_HAS_TIS);
+ return getTestInfo(TestProtocol.REQUEST_HAS_TIS).getBoolean(
+ TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
+ boolean isGridOnlyOverviewEnabled() {
+ return getTestInfo(TestProtocol.REQUEST_FLAG_ENABLE_GRID_ONLY_OVERVIEW).getBoolean(
+ TestProtocol.TEST_INFO_RESPONSE_FIELD);
+ }
public void sendPointer(long downTime, long currentTime, int action, Point point,
GestureScope gestureScope) {
+ sendPointer(downTime, currentTime, action, point, gestureScope,
+ InputDevice.SOURCE_TOUCHSCREEN);
+ }
+
+ public void sendPointer(long downTime, long currentTime, int action, Point point,
+ GestureScope gestureScope, int source) {
final boolean hasTIS = hasTIS();
- switch (action) {
+ int pointerCount = mPointerCount;
+
+ boolean isTrackpadGesture = mTrackpadGestureType != TrackpadGestureType.NONE;
+ switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
- if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
- && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
- && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE) {
- expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
- }
- if (hasTIS && getNavigationModel() != NavigationModel.THREE_BUTTON) {
- expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
+ if (isTrackpadGesture) {
+ mPointerCount = 1;
+ pointerCount = mPointerCount;
}
break;
case MotionEvent.ACTION_UP:
- if (hasTIS && gestureScope != GestureScope.INSIDE
- && gestureScope != GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER
- && (gestureScope == GestureScope.OUTSIDE_WITH_PILFER
- || gestureScope == GestureScope.INSIDE_TO_OUTSIDE)) {
+ if (hasTIS && gestureScope == GestureScope.EXPECT_PILFER) {
expectEvent(TestProtocol.SEQUENCE_PILFER, EVENT_PILFER_POINTERS);
}
- if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
- && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
- && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE) {
- expectEvent(TestProtocol.SEQUENCE_MAIN,
- gestureScope == GestureScope.INSIDE
- || gestureScope == GestureScope.OUTSIDE_WITHOUT_PILFER
- ? EVENT_TOUCH_UP : EVENT_TOUCH_CANCEL);
- }
- if (hasTIS && getNavigationModel() != NavigationModel.THREE_BUTTON) {
- expectEvent(TestProtocol.SEQUENCE_TIS,
- gestureScope == GestureScope.INSIDE_TO_OUTSIDE_WITH_KEYCODE
- || gestureScope == GestureScope.OUTSIDE_WITH_KEYCODE
- ? EVENT_TOUCH_CANCEL_TIS : EVENT_TOUCH_UP_TIS);
- }
break;
- case MotionEvent.ACTION_HOVER_ENTER:
- expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_HOVER_ENTER_TIS);
+ case MotionEvent.ACTION_POINTER_DOWN:
+ mPointerCount++;
+ pointerCount = mPointerCount;
break;
- case MotionEvent.ACTION_HOVER_EXIT:
- expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_HOVER_EXIT_TIS);
+ case MotionEvent.ACTION_POINTER_UP:
+ // When the gesture is handled outside, it's cancelled within launcher.
+ mPointerCount--;
break;
}
- final MotionEvent event = getMotionEvent(downTime, currentTime, action, point.x, point.y);
+ final MotionEvent event = isTrackpadGesture
+ ? getTrackpadMotionEvent(
+ downTime, currentTime, action, point.x, point.y, pointerCount,
+ mTrackpadGestureType)
+ : getMotionEvent(downTime, currentTime, action, point.x, point.y, source);
+ if (action == MotionEvent.ACTION_BUTTON_PRESS
+ || action == MotionEvent.ACTION_BUTTON_RELEASE) {
+ event.setActionButton(MotionEvent.BUTTON_PRIMARY);
+ }
assertTrue("injectInputEvent failed",
mInstrumentation.getUiAutomation().injectInputEvent(event, true, false));
event.recycle();
@@ -1702,8 +1779,7 @@
public long movePointer(long downTime, long startTime, long duration, Point from, Point to,
GestureScope gestureScope) {
- return movePointer(
- downTime, startTime, duration, false, from, to, gestureScope);
+ return movePointer(downTime, startTime, duration, false, from, to, gestureScope);
}
public long movePointer(long downTime, long startTime, long duration, boolean isDecelerating,
@@ -1763,11 +1839,12 @@
@NonNull final UiObject2 target, @NonNull String resName, Pattern longClickEvent) {
final Point targetCenter = target.getVisibleCenter();
final long downTime = SystemClock.uptimeMillis();
- sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, targetCenter, GestureScope.INSIDE);
+ sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, targetCenter,
+ GestureScope.DONT_EXPECT_PILFER);
expectEvent(TestProtocol.SEQUENCE_MAIN, longClickEvent);
final UiObject2 result = waitForLauncherObject(resName);
sendPointer(downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, targetCenter,
- GestureScope.INSIDE);
+ GestureScope.DONT_EXPECT_PILFER);
return result;
}
@@ -1851,6 +1928,12 @@
return tasks;
}
+ /** Reinitializes the workspace to its default layout. */
+ public void reinitializeLauncherData() {
+ getTestInfo(TestProtocol.REQUEST_REINITIALIZE_DATA);
+ }
+
+ /** Clears the workspace, leaving it empty. */
public void clearLauncherData() {
getTestInfo(TestProtocol.REQUEST_CLEAR_DATA);
}
@@ -2037,30 +2120,18 @@
? containerBounds.right + 1
: containerBounds.left - 1;
}
- int y = containerBounds.top + containerBounds.height() / 2;
+ // If IME is visible and overlaps the container bounds, touch above it.
+ int bottomBound = Math.min(
+ containerBounds.bottom,
+ getRealDisplaySize().y - getImeInsets().bottom);
+ int y = (bottomBound - containerBounds.top) / 2;
final long downTime = SystemClock.uptimeMillis();
final Point tapTarget = new Point(x, y);
sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, tapTarget,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
sendPointer(downTime, downTime, MotionEvent.ACTION_UP, tapTarget,
- LauncherInstrumentation.GestureScope.INSIDE);
- }
- }
-
- /**
- * Sets the consumer to run callbacks at all run-points.
- */
- public void setRunPointCallback(Consumer<CALLBACK_RUN_POINT> callback) {
- mCallbackAtRunPoint = callback;
- }
-
- /**
- * Runs the callback at the specified point if it exists.
- */
- void runCallbackIfActive(CALLBACK_RUN_POINT runPoint) {
- if (mCallbackAtRunPoint != null) {
- mCallbackAtRunPoint.accept(runPoint);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
index 386deac..bd2c9c1 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
@@ -19,8 +19,6 @@
import androidx.annotation.NonNull;
import androidx.test.uiautomator.UiObject2;
-import com.android.launcher3.testing.shared.TestProtocol;
-
/**
* View containing overview actions
*/
@@ -51,13 +49,6 @@
"clicked screenshot button")) {
UiObject2 closeScreenshot = mLauncher.waitForSystemUiObject(
"screenshot_dismiss_image");
- if (mLauncher.getNavigationModel()
- != LauncherInstrumentation.NavigationModel.THREE_BUTTON) {
- mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS,
- LauncherInstrumentation.EVENT_TOUCH_DOWN_TIS);
- mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS,
- LauncherInstrumentation.EVENT_TOUCH_UP_TIS);
- }
closeScreenshot.click();
try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer(
"dismissed screenshot")) {
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
index 39b93b4..e4cfc52 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -124,7 +124,7 @@
final int centerY = taskBounds.centerY();
mLauncher.executeAndWaitForLauncherEvent(
() -> mLauncher.linearGesture(centerX, centerY, centerX, 0, 10, false,
- LauncherInstrumentation.GestureScope.INSIDE),
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER),
event -> TestProtocol.DISMISS_ANIMATION_ENDS_MESSAGE.equals(event.getClassName()),
() -> "Didn't receive a dismiss animation ends message: " + centerX + ", "
+ centerY, "swiping to dismiss");
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java b/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java
index e349620..859e504 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java
@@ -16,6 +16,8 @@
package com.android.launcher3.tapl;
+import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
+
import androidx.annotation.NonNull;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiObject2;
@@ -50,6 +52,32 @@
}
}
+ /**
+ * Taps the app info item from the overview task menu and returns the LaunchedAppState
+ * representing the App info settings page.
+ */
+ @NonNull
+ public LaunchedAppState tapAppInfoMenuItem() {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "before tapping the app info menu item")) {
+
+ mLauncher.executeAndWaitForLauncherEvent(
+ () -> mLauncher.clickLauncherObject(
+ mLauncher.findObjectInContainer(mMenu, By.text("App info"))),
+ accessibilityEvent ->
+ accessibilityEvent.getEventType() == TYPE_WINDOW_STATE_CHANGED,
+ () -> "Unable to start Settings by clicking App Info",
+ "Tap the app info menu item");
+
+ try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "tapped app info menu item")) {
+ mLauncher.waitUntilSystemLauncherObjectGone("overview_panel");
+ return new LaunchedAppState(mLauncher);
+ }
+ }
+ }
+
/** Returns true if an item matching the given string is present in the menu. */
public boolean hasMenuItem(String expectedMenuItemText) {
UiObject2 menuItem = mLauncher.findObjectInContainer(mMenu, By.text(expectedMenuItemText));
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenuItem.java b/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenuItem.java
index b2cc92d..e3035bf 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenuItem.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenuItem.java
@@ -15,13 +15,7 @@
*/
package com.android.launcher3.tapl;
-import static com.android.launcher3.tapl.LauncherInstrumentation.CALLBACK_RUN_POINT.CALLBACK_HOVER_ENTER;
-import static com.android.launcher3.tapl.LauncherInstrumentation.CALLBACK_RUN_POINT.CALLBACK_HOVER_EXIT;
-
-import android.graphics.Point;
import android.graphics.Rect;
-import android.os.SystemClock;
-import android.view.MotionEvent;
import androidx.test.uiautomator.UiObject2;
@@ -42,28 +36,4 @@
public Rect getVisibleBounds() {
return mMenuItem.getVisibleBounds();
}
-
- /**
- * Emulate the cursor entering and exiting a hover over this menu item.
- */
- public void hoverCursor() {
- try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
- LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "cursor hover entering menu item")) {
- long downTime = SystemClock.uptimeMillis();
- mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER,
- new Point(mMenuItem.getVisibleCenter().x, mMenuItem.getVisibleCenter().y),
- null);
- mLauncher.runCallbackIfActive(CALLBACK_HOVER_ENTER);
-
- try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
- "cursor hover exiting menu item")) {
- downTime = SystemClock.uptimeMillis();
- mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_EXIT,
- new Point(mMenuItem.getVisibleCenter().x, mMenuItem.getVisibleCenter().y),
- null);
- mLauncher.runCallbackIfActive(CALLBACK_HOVER_EXIT);
- }
- }
- }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Qsb.java b/tests/tapl/com/android/launcher3/tapl/Qsb.java
index 6bc4f21..0f2aff8 100644
--- a/tests/tapl/com/android/launcher3/tapl/Qsb.java
+++ b/tests/tapl/com/android/launcher3/tapl/Qsb.java
@@ -29,14 +29,24 @@
private static final String ASSISTANT_APP_PACKAGE = "com.google.android.googlequicksearchbox";
private static final String ASSISTANT_ICON_RES_ID = "mic_icon";
+ private static final String LENS_ICON_RES_ID = "lens_icon";
+ private static final String LENS_APP_TEXT_RES_ID = "lens_camera_cutout_text";
protected final LauncherInstrumentation mLauncher;
+ private final UiObject2 mContainer;
+ private final String mQsbResName;
- protected Qsb(LauncherInstrumentation launcher) {
+ protected Qsb(LauncherInstrumentation launcher, UiObject2 container, String qsbResName) {
mLauncher = launcher;
+ mContainer = container;
+ mQsbResName = qsbResName;
+ waitForQsbObject();
}
// Waits for the quick search box.
- protected abstract UiObject2 waitForQsbObject();
+ private UiObject2 waitForQsbObject() {
+ return mLauncher.waitForObjectInContainer(mContainer, mQsbResName);
+ }
+
/**
* Launch assistant app by tapping mic icon on qsb.
*/
@@ -68,6 +78,37 @@
}
/**
+ * Launches lens app by tapping lens icon on qsb.
+ */
+ @NonNull
+ public LaunchedAppState launchLens() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to click lens icon button");
+ LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
+ UiObject2 lensIcon = mLauncher.waitForLauncherObject(LENS_ICON_RES_ID);
+
+ LauncherInstrumentation.log("Qsb.launchLens before click "
+ + lensIcon.getVisibleCenter() + " in "
+ + mLauncher.getVisibleBounds(lensIcon));
+
+ mLauncher.clickLauncherObject(lensIcon);
+
+ try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
+ // Package name is not enough to check if the app is launched, because many
+ // elements are having googlequicksearchbox as package name. So it checks if the
+ // corresponding text resource is displayed
+ BySelector selector = By.res(ASSISTANT_APP_PACKAGE, LENS_APP_TEXT_RES_ID);
+ mLauncher.assertTrue(
+ "Lens app didn't start: (" + selector + ")",
+ mLauncher.getDevice().wait(Until.hasObject(selector),
+ LauncherInstrumentation.WAIT_TIME_MS)
+ );
+ return new LaunchedAppState(mLauncher);
+ }
+ }
+ }
+
+ /**
* Show search result page from tapping qsb.
*/
public SearchResultFromQsb showSearchResult() {
@@ -79,8 +120,12 @@
mLauncher.waitForIdle();
try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer(
"clicked qsb to open search result page")) {
- return new SearchResultFromQsb(mLauncher);
+ return createSearchResult();
}
}
}
+
+ protected SearchResultFromQsb createSearchResult() {
+ return new SearchResultFromQsb(mLauncher);
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
index 80176e9..513d6bb 100644
--- a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
+++ b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
@@ -20,6 +20,8 @@
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiObject2;
+import com.android.launcher3.testing.shared.TestProtocol;
+
import java.util.ArrayList;
/**
@@ -32,7 +34,7 @@
// This particular ID change should happen with caution
private static final String SEARCH_CONTAINER_RES_ID = "search_results_list_view";
- private final LauncherInstrumentation mLauncher;
+ protected final LauncherInstrumentation mLauncher;
SearchResultFromQsb(LauncherInstrumentation launcher) {
mLauncher = launcher;
@@ -43,33 +45,42 @@
public void searchForInput(String input) {
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to search for result with an input");
- LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
- mLauncher.waitForLauncherObject(INPUT_RES).setText(input);
+ LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
+ mLauncher.executeAndWaitForLauncherEvent(
+ () -> mLauncher.waitForLauncherObject(INPUT_RES).setText(input),
+ event -> TestProtocol.SEARCH_RESULT_COMPLETE.equals(event.getClassName()),
+ () -> "Didn't receive a search result completed message", "searching");
}
}
/** Find the app from search results with app name. */
- public Launchable findAppIcon(String appName) {
+ public AppIcon findAppIcon(String appName) {
UiObject2 icon = mLauncher.waitForLauncherObject(By.clazz(TextView.class).text(appName));
+ return createAppIcon(icon);
+ }
+
+ protected AppIcon createAppIcon(UiObject2 icon) {
return new AllAppsAppIcon(mLauncher, icon);
}
/** Find the web suggestion from search suggestion's title text */
- public void verifyWebSuggestIsPresent(String text) {
- ArrayList<UiObject2> goldenGateResults =
+ public SearchWebSuggestion findWebSuggestion(String text) {
+ ArrayList<UiObject2> webSuggestions =
new ArrayList<>(mLauncher.waitForObjectsInContainer(
mLauncher.waitForSystemLauncherObject(SEARCH_CONTAINER_RES_ID),
By.clazz(TextView.class)));
- boolean found = false;
- for(UiObject2 uiObject: goldenGateResults) {
+ for (UiObject2 uiObject: webSuggestions) {
String currentString = uiObject.getText();
if (currentString.equals(text)) {
- found = true;
+ return createWebSuggestion(uiObject);
}
}
- if (!found) {
- throw new IllegalStateException("Web suggestion title: " + text + " not found");
- }
+ mLauncher.fail("Web suggestion title: " + text + " not found");
+ return null;
+ }
+
+ protected SearchWebSuggestion createWebSuggestion(UiObject2 webSuggestion) {
+ return new SearchWebSuggestion(mLauncher, webSuggestion);
}
/** Find the total amount of views being displayed and return the size */
@@ -85,7 +96,7 @@
* Taps outside bottom sheet to dismiss and return to workspace. Available on tablets only.
* @param tapRight Tap on the right of bottom sheet if true, or left otherwise.
*/
- public Workspace dismissByTappingOutsideForTablet(boolean tapRight) {
+ public void dismissByTappingOutsideForTablet(boolean tapRight) {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to tap outside AllApps bottom sheet on the "
@@ -95,8 +106,12 @@
mLauncher.touchOutsideContainer(allAppsBottomSheet, tapRight);
try (LauncherInstrumentation.Closable tapped = mLauncher.addContextLayer(
"tapped outside AllApps bottom sheet")) {
- return mLauncher.getWorkspace();
+ verifyVisibleContainerOnDismiss();
}
}
}
+
+ protected void verifyVisibleContainerOnDismiss() {
+ mLauncher.getWorkspace();
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/SearchResultFromTaskbarQsb.java b/tests/tapl/com/android/launcher3/tapl/SearchResultFromTaskbarQsb.java
new file mode 100644
index 0000000..00291a3
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/SearchResultFromTaskbarQsb.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * Operations on search result page opened from Taskbar qsb.
+ */
+public class SearchResultFromTaskbarQsb extends SearchResultFromQsb {
+
+ SearchResultFromTaskbarQsb(LauncherInstrumentation launcher) {
+ super(launcher);
+ }
+
+ @Override
+ public TaskbarAppIcon findAppIcon(String appName) {
+ return (TaskbarAppIcon) super.findAppIcon(appName);
+ }
+
+ @Override
+ protected TaskbarAppIcon createAppIcon(UiObject2 icon) {
+ return new TaskbarAppIcon(mLauncher, icon);
+ }
+
+ @Override
+ public TaskbarSearchWebSuggestion findWebSuggestion(String text) {
+ return (TaskbarSearchWebSuggestion) super.findWebSuggestion(text);
+ }
+
+ @Override
+ protected TaskbarSearchWebSuggestion createWebSuggestion(UiObject2 webSuggestion) {
+ return new TaskbarSearchWebSuggestion(mLauncher, webSuggestion);
+ }
+
+ @Override
+ protected void verifyVisibleContainerOnDismiss() {
+ mLauncher.getLaunchedAppState().assertTaskbarVisible();
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/SearchWebSuggestion.java b/tests/tapl/com/android/launcher3/tapl/SearchWebSuggestion.java
new file mode 100644
index 0000000..e4dec98
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/SearchWebSuggestion.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+import com.android.launcher3.testing.shared.TestProtocol;
+
+import java.util.regex.Pattern;
+
+/**
+ * Operations on a search web suggestion from a qsb.
+ */
+public class SearchWebSuggestion extends Launchable {
+
+ private static final Pattern LONG_CLICK_EVENT = Pattern.compile("onAllAppsItemLongClick");
+
+ SearchWebSuggestion(LauncherInstrumentation launcher, UiObject2 object) {
+ super(launcher, object);
+ }
+
+ @Override
+ protected void expectActivityStartEvents() {
+ }
+
+ @Override
+ protected String launchableType() {
+ return "search web suggestion";
+ }
+
+ @Override
+ protected void waitForLongPressConfirmation() {
+ mLauncher.waitForLauncherObject("popup_container");
+ }
+
+ @Override
+ protected void addExpectedEventsForLongClick() {
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, getLongClickEvent());
+ }
+
+ protected Pattern getLongClickEvent() {
+ return LONG_CLICK_EVENT;
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/Taskbar.java b/tests/tapl/com/android/launcher3/tapl/Taskbar.java
index 051630e..4293ee8 100644
--- a/tests/tapl/com/android/launcher3/tapl/Taskbar.java
+++ b/tests/tapl/com/android/launcher3/tapl/Taskbar.java
@@ -76,13 +76,13 @@
mLauncher.getRealDisplaySize().x - 1, mLauncher.getRealDisplaySize().y - 1);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, stashTarget,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
LauncherInstrumentation.log("hideTaskbar: sent down");
try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("pressed down")) {
mLauncher.waitUntilSystemLauncherObjectGone(TASKBAR_RES_ID);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, stashTarget,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
}
} finally {
mLauncher.getTestInfo(REQUEST_DISABLE_MANUAL_TASKBAR_STASHING);
@@ -92,7 +92,7 @@
/**
* Opens the Taskbar all apps page.
*/
- public AllAppsFromTaskbar openAllApps() {
+ public TaskbarAllApps openAllApps() {
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to open taskbar all apps");
LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
@@ -101,7 +101,15 @@
mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID),
getAllAppsButtonSelector()));
- return new AllAppsFromTaskbar(mLauncher);
+ return getAllApps();
+ }
+ }
+
+ /** Returns {@link TaskbarAllApps} if it is open, otherwise fails. */
+ public TaskbarAllApps getAllApps() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to get taskbar all apps object")) {
+ return new TaskbarAllApps(mLauncher);
}
}
@@ -147,9 +155,9 @@
mLauncher.getRealDisplaySize().y - 1);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, tapTarget,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, tapTarget,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
}
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java b/tests/tapl/com/android/launcher3/tapl/TaskbarAllApps.java
similarity index 82%
rename from tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java
rename to tests/tapl/com/android/launcher3/tapl/TaskbarAllApps.java
index c4744a1..c1234fe 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java
+++ b/tests/tapl/com/android/launcher3/tapl/TaskbarAllApps.java
@@ -23,9 +23,9 @@
/**
* Operations on AllApps opened from the Taskbar.
*/
-public class AllAppsFromTaskbar extends AllApps {
+public class TaskbarAllApps extends AllApps {
- AllAppsFromTaskbar(LauncherInstrumentation launcher) {
+ TaskbarAllApps(LauncherInstrumentation launcher) {
super(launcher);
}
@@ -62,4 +62,15 @@
return mLauncher.getTestInfo(TestProtocol.REQUEST_TASKBAR_APPS_LIST_SCROLL_Y)
.getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
+
+ @NonNull
+ @Override
+ public TaskbarAllAppsQsb getQsb() {
+ return new TaskbarAllAppsQsb(mLauncher, verifyActiveContainer());
+ }
+
+ @Override
+ protected void verifyVisibleContainerOnDismiss() {
+ mLauncher.getLaunchedAppState().assertTaskbarVisible();
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/TaskbarAllAppsQsb.java b/tests/tapl/com/android/launcher3/tapl/TaskbarAllAppsQsb.java
new file mode 100644
index 0000000..7cecd3e
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/TaskbarAllAppsQsb.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * Operations on Taskbar AllApp screen qsb.
+ */
+public class TaskbarAllAppsQsb extends Qsb {
+
+ TaskbarAllAppsQsb(LauncherInstrumentation launcher, UiObject2 allAppsContainer) {
+ super(launcher, allAppsContainer, "search_container_all_apps");
+ }
+
+ @Override
+ public SearchResultFromTaskbarQsb showSearchResult() {
+ return (SearchResultFromTaskbarQsb) super.showSearchResult();
+ }
+
+ @Override
+ protected SearchResultFromTaskbarQsb createSearchResult() {
+ return new SearchResultFromTaskbarQsb(mLauncher);
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/TaskbarSearchWebSuggestion.java b/tests/tapl/com/android/launcher3/tapl/TaskbarSearchWebSuggestion.java
new file mode 100644
index 0000000..cd8ce42
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/TaskbarSearchWebSuggestion.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+import java.util.regex.Pattern;
+
+/**
+ * Operations on a search web suggestion from the Taskbar qsb.
+ */
+public class TaskbarSearchWebSuggestion extends SearchWebSuggestion implements
+ SplitscreenDragSource {
+
+ private static final Pattern LONG_CLICK_EVENT = Pattern.compile("onTaskbarItemLongClick");
+
+ TaskbarSearchWebSuggestion(LauncherInstrumentation launcher,
+ UiObject2 object) {
+ super(launcher, object);
+ }
+
+ @Override
+ protected Pattern getLongClickEvent() {
+ return LONG_CLICK_EVENT;
+ }
+
+ /** This method requires public access, however should not be called in tests. */
+ @Override
+ public Launchable getLaunchable() {
+ return this;
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/WidgetResizeFrame.java b/tests/tapl/com/android/launcher3/tapl/WidgetResizeFrame.java
index 8f51d04..ec1cbd8 100644
--- a/tests/tapl/com/android/launcher3/tapl/WidgetResizeFrame.java
+++ b/tests/tapl/com/android/launcher3/tapl/WidgetResizeFrame.java
@@ -15,6 +15,16 @@
*/
package com.android.launcher3.tapl;
+import static com.android.launcher3.tapl.Launchable.DEFAULT_DRAG_STEPS;
+import static org.junit.Assert.assertTrue;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.view.MotionEvent;
+
+import androidx.test.uiautomator.UiObject2;
+
/** The resize frame that is shown for a widget on the workspace. */
public class WidgetResizeFrame {
@@ -34,4 +44,36 @@
mLauncher.getDevice().pressHome();
}
}
+
+ /** Resizes the widget to double its height, and returns the resize frame. */
+ public WidgetResizeFrame resize() {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to resize the widget frame.")) {
+ UiObject2 widget = mLauncher.waitForLauncherObject("widget_resize_frame");
+ UiObject2 bottomResizeHandle =
+ mLauncher.waitForLauncherObject("widget_resize_bottom_handle");
+ Rect originalWidgetSize = widget.getVisibleBounds();
+ Point targetStart = bottomResizeHandle.getVisibleCenter();
+ Point targetDest = bottomResizeHandle.getVisibleCenter();
+ targetDest.offset(0, originalWidgetSize.height());
+
+ final long downTime = SystemClock.uptimeMillis();
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, targetStart,
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
+ mLauncher.movePointer(targetStart, targetDest, DEFAULT_DRAG_STEPS,
+ true, downTime, downTime, true,
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, targetDest,
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
+
+ try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer(
+ "want to return resized widget resize frame")) {
+ float newHeight = mLauncher.waitForLauncherObject(
+ "widget_resize_frame").getVisibleBounds().height();
+ assertTrue("Widget not resized.", newHeight >= originalWidgetSize.height() * 2);
+ return this;
+ }
+ }
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 7bb02cb..cf48ebc 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -18,7 +18,6 @@
import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_SCROLLED;
-import static com.android.launcher3.tapl.LauncherInstrumentation.CALLBACK_RUN_POINT.CALLBACK_HOLD_BEFORE_DROP;
import static com.android.launcher3.testing.shared.TestProtocol.ALL_APPS_STATE_ORDINAL;
import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
@@ -28,6 +27,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.os.SystemClock;
+import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -105,7 +105,8 @@
windowCornerRadius,
startY - swipeHeight - mLauncher.getTouchSlop(),
12,
- ALL_APPS_STATE_ORDINAL, LauncherInstrumentation.GestureScope.INSIDE);
+ ALL_APPS_STATE_ORDINAL,
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
"swiped to all apps")) {
@@ -286,6 +287,10 @@
final UiObject2 workspace = verifyActiveContainer();
List<UiObject2> workspaceIcons =
mLauncher.waitForObjectsInContainer(workspace, AppIcon.getAnyAppIconSelector());
+ Log.d("b/288944469", "List size = " + workspaceIcons.size());
+ for (int i = 0; i < workspaceIcons.size(); i++) {
+ Log.d("b/288944469", "index = " + i + " tesxt = " + workspaceIcons.get(i).getText());
+ }
return workspaceIcons.stream()
.collect(
Collectors.toMap(
@@ -387,7 +392,7 @@
Until.hasObject(installerAlert), LauncherInstrumentation.WAIT_TIME_MS));
final UiObject2 ok = device.findObject(By.text("OK"));
assertNotNull("OK button is not shown", ok);
- launcher.clickObject(ok, LauncherInstrumentation.GestureScope.OUTSIDE_WITHOUT_PILFER);
+ launcher.clickObject(ok);
assertTrue("Uninstall alert is not dismissed after clicking OK", device.wait(
Until.gone(installerAlert), LauncherInstrumentation.WAIT_TIME_MS));
@@ -454,7 +459,7 @@
launcher.runToState(
() -> launcher.sendPointer(
downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, dest,
- LauncherInstrumentation.GestureScope.INSIDE),
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER),
NORMAL_STATE_ORDINAL,
"sending UP event");
if (expectedEvents != null) {
@@ -543,7 +548,7 @@
executeAndWaitForPageScroll(launcher,
() -> launcher.movePointer(finalDragStart, screenEdge, DEFAULT_DRAG_STEPS,
true, downTime, downTime, true,
- LauncherInstrumentation.GestureScope.INSIDE));
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER));
targetDest.x += displayX * (targetDest.x > 0 ? -1 : 1);
dragStart = screenEdge;
}
@@ -552,8 +557,7 @@
// we just have to put move the icon to the destination and drop it
launcher.movePointer(dragStart, targetDest, DEFAULT_DRAG_STEPS, isDecelerating,
downTime, SystemClock.uptimeMillis(), false,
- LauncherInstrumentation.GestureScope.INSIDE);
- launcher.runCallbackIfActive(CALLBACK_HOLD_BEFORE_DROP);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
dropDraggedIcon(launcher, targetDest, downTime, expectDropEvents);
}
}
@@ -586,8 +590,7 @@
// we just have to put move the icon to the destination and drop it
launcher.movePointer(dragStart, targetDest, DEFAULT_DRAG_STEPS, isDecelerating,
downTime, SystemClock.uptimeMillis(), false,
- LauncherInstrumentation.GestureScope.INSIDE);
- launcher.runCallbackIfActive(CALLBACK_HOLD_BEFORE_DROP);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
dropDraggedIcon(launcher, targetDest, downTime, expectDropEvents);
}
}
@@ -624,7 +627,7 @@
executeAndWaitForPageScroll(launcher,
() -> launcher.movePointer(finalDragStart, screenEdge, DEFAULT_DRAG_STEPS,
true, downTime, downTime, true,
- LauncherInstrumentation.GestureScope.INSIDE));
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER));
currentPage = Workspace.geCurrentPage(launcher);
currentPosition = screenEdge;
}
@@ -653,7 +656,7 @@
launcher.movePointer(dragStart, targetDest, DEFAULT_DRAG_STEPS, true,
downTime, SystemClock.uptimeMillis(), false,
- LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
dropDraggedIcon(launcher, targetDest, downTime, expectDropEvents);
}