Prevent falling into OtherActivityInputConsumer when over lockscreen am: f6d75c98a9
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/21050546
Change-Id: I3cdb8010e623e1fb2309b2657730d4fb7032a98a
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index bab994a..0a55675 100644
--- a/Android.bp
+++ b/Android.bp
@@ -13,24 +13,12 @@
// limitations under the License.
package {
- default_applicable_licenses: ["packages_apps_Launcher3_license"],
+ // See: http://go/android-license-faq
+ default_applicable_licenses: ["Android-Apache-2.0"],
}
min_launcher3_sdk_version = "26"
-// Added automatically by a large-scale-change
-// See: http://go/android-license-faq
-license {
- name: "packages_apps_Launcher3_license",
- visibility: [":__subpackages__"],
- license_kinds: [
- "SPDX-license-identifier-Apache-2.0",
- ],
- license_text: [
- "NOTICE",
- ],
-}
-
android_library {
name: "launcher-aosp-tapl",
libs: [
@@ -43,11 +31,13 @@
"androidx.test.uiautomator_uiautomator",
"androidx.preference_preference",
"SystemUISharedLib",
+ "SystemUIAnimationLib",
],
srcs: [
"tests/tapl/**/*.java",
"src/com/android/launcher3/ResourceUtils.java",
"src/com/android/launcher3/testing/TestProtocol.java",
+ "src/com/android/launcher3/testing/*Request.java",
],
resource_dirs: [ ],
manifest: "tests/tapl/AndroidManifest.xml",
@@ -207,6 +197,7 @@
"lottie",
"SystemUISharedLib",
"SystemUI-statsd",
+ "SystemUIAnimationLib",
],
manifest: "quickstep/AndroidManifest.xml",
min_sdk_version: "current",
@@ -219,6 +210,8 @@
srcs: [
"ext_tests/src/**/*.java",
"ext_tests/src/**/*.kt",
+ "quickstep/ext_tests/src/**/*.java",
+ "quickstep/ext_tests/src/**/*.kt",
],
}
@@ -235,6 +228,19 @@
],
}
+// Common source files used to build go launcher except go/src files
+filegroup {
+ name: "launcher-go-src-no-build-config",
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ "quickstep/src/**/*.java",
+ "quickstep/src/**/*.kt",
+ "go/quickstep/src/**/*.java",
+ "go/quickstep/src/**/*.kt",
+ ],
+}
+
// Proguard files for Launcher3
filegroup {
name: "launcher-proguard-rules",
@@ -265,7 +271,9 @@
static_libs: [
"Launcher3CommonDepsLib",
"QuickstepResLib",
+ "androidx.room_room-runtime",
],
+ plugins: ["androidx.room_room-compiler-plugin"],
manifest: "quickstep/AndroidManifest-launcher.xml",
additional_manifests: [
"go/AndroidManifest.xml",
@@ -296,6 +304,7 @@
"SystemUISharedLib",
"Launcher3CommonDepsLib",
"QuickstepResLib",
+ "SystemUIAnimationLib",
],
manifest: "quickstep/AndroidManifest.xml",
platform_apis: true,
diff --git a/Android.mk b/Android.mk
index ceaaf13..1bc8b28 100644
--- a/Android.mk
+++ b/Android.mk
@@ -49,7 +49,8 @@
LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.launcher3.*
LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
+LOCAL_LICENSE_PACKAGE_NAME := Android Launcher3
+LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
include $(BUILD_PACKAGE)
#
@@ -85,7 +86,8 @@
LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
+LOCAL_LICENSE_PACKAGE_NAME := Android Launcher3
+LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
include $(BUILD_PACKAGE)
@@ -136,7 +138,8 @@
LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.launcher3.*
LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
+LOCAL_LICENSE_PACKAGE_NAME := Android Launcher3
+LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
include $(BUILD_PACKAGE)
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index eee6db5..02b83fe 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -19,6 +19,7 @@
-->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
package="com.android.launcher3">
<!--
@@ -41,6 +42,7 @@
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<!-- for rotating surface by arbitrary degree -->
<uses-permission android:name="android.permission.ROTATE_SURFACE_FLINGER" />
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!--
Permissions required for read/write access to the workspace data. These permission name
@@ -49,13 +51,11 @@
-->
<permission
android:name="${packageName}.permission.READ_SETTINGS"
- android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="signatureOrSystem"
android:label="@string/permlab_read_settings"
android:description="@string/permdesc_read_settings"/>
<permission
android:name="${packageName}.permission.WRITE_SETTINGS"
- android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="signatureOrSystem"
android:label="@string/permlab_write_settings"
android:description="@string/permdesc_write_settings"/>
@@ -175,5 +175,11 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
+
+ <!-- [b/197780098] Disable eager initialization of Jetpack libraries. -->
+ <provider
+ android:name="androidx.startup.InitializationProvider"
+ android:authorities="${applicationId}.androidx-startup"
+ tools:node="remove" />
</application>
</manifest>
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index b838a51..4f580e0 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -20,7 +20,7 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher3">
- <uses-sdk android:targetSdkVersion="29" android:minSdkVersion="26"/>
+ <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.
@@ -58,6 +58,7 @@
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
+ <action android:name="android.intent.action.SHOW_WORK_APPS" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY"/>
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index c5b1efa..0000000
--- a/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
- Copyright (c) 2005-2008, 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.
-
- 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.
-
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
diff --git a/OWNERS b/OWNERS
index 05fa502..7f98ea6 100644
--- a/OWNERS
+++ b/OWNERS
@@ -39,6 +39,7 @@
xuqiu@google.com
sreyasr@google.com
thiruram@google.com
+brianji@google.com
per-file FeatureFlags.java, globs = set noparent
per-file FeatureFlags.java = sunnygoyal@google.com, winsonc@google.com, zakcohen@google.com, mrcasey@google.com, adamcohen@google.com, hyunyoungs@google.com
diff --git a/build.gradle b/build.gradle
index 683a4cf..68ed73d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -20,8 +20,8 @@
buildToolsVersion BUILD_TOOLS_VERSION
defaultConfig {
- minSdkVersion 25
- targetSdkVersion 28
+ minSdkVersion 26
+ targetSdkVersion 30
versionCode 1
versionName "1.0"
@@ -170,7 +170,7 @@
protobuf {
// Configure the protoc executable
protoc {
- artifact = "com.google.protobuf:protoc:${protocVersion}"
+ artifact = "com.google.protobuf:protoc:${protocVersion}${PROTO_ARCH_SUFFIX}"
}
generateProtoTasks {
all().each { task ->
diff --git a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
index 0f61d14..d16e12c 100644
--- a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
+++ b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
@@ -27,9 +27,12 @@
import android.view.View;
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.ShortcutAndWidgetContainer;
import java.util.ArrayList;
import java.util.Collection;
@@ -124,7 +127,7 @@
}
@Override
- public Bundle call(String method, String arg) {
+ public Bundle call(String method, String arg, @Nullable Bundle extras) {
final Bundle response = new Bundle();
switch (method) {
case TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS: {
@@ -204,6 +207,32 @@
}
}
+ case TestProtocol.REQUEST_USE_TEST_WORKSPACE_LAYOUT: {
+ useTestWorkspaceLayout(true);
+ return response;
+ }
+
+ case TestProtocol.REQUEST_USE_DEFAULT_WORKSPACE_LAYOUT: {
+ useTestWorkspaceLayout(false);
+ return response;
+ }
+
+ case TestProtocol.REQUEST_HOTSEAT_ICON_NAMES: {
+ return getLauncherUIProperty(Bundle::putStringArrayList, l -> {
+ ShortcutAndWidgetContainer hotseatIconsContainer =
+ l.getHotseat().getShortcutsAndWidgets();
+ ArrayList<String> hotseatIconNames = new ArrayList<>();
+
+ for (int i = 0; i < hotseatIconsContainer.getChildCount(); i++) {
+ // Use unchecked cast to catch changes in hotseat layout
+ BubbleTextView icon = (BubbleTextView) hotseatIconsContainer.getChildAt(i);
+ hotseatIconNames.add((String) icon.getText());
+ }
+
+ return hotseatIconNames;
+ });
+ }
+
case TestProtocol.REQUEST_GET_ACTIVITIES_CREATED_COUNT: {
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, sActivitiesCreatedCount);
return response;
@@ -219,7 +248,18 @@
}
default:
- return super.call(method, arg);
+ return super.call(method, arg, extras);
+ }
+ }
+
+ private void useTestWorkspaceLayout(boolean useTestWorkspaceLayout) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ LauncherSettings.Settings.call(mContext.getContentResolver(), useTestWorkspaceLayout
+ ? LauncherSettings.Settings.METHOD_SET_USE_TEST_WORKSPACE_LAYOUT_FLAG
+ : LauncherSettings.Settings.METHOD_CLEAR_USE_TEST_WORKSPACE_LAYOUT_FLAG);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
}
}
diff --git a/fill_screens.py b/fill_screens.py
deleted file mode 100755
index a887792..0000000
--- a/fill_screens.py
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/usr/bin/env python2.5
-
-import cgi
-import os
-import shutil
-import sys
-import sqlite3
-
-SCREENS = 5
-COLUMNS = 4
-ROWS = 4
-CELL_SIZE = 110
-
-DIR = "db_files"
-AUTO_FILE = "launcher.db"
-
-APPLICATION_COMPONENTS = [
- "com.android.calculator2/com.android.calculator2.Calculator",
- "com.android.providers.downloads.ui/com.android.providers.downloads.ui.DownloadList",
- "com.android.settings/com.android.settings.Settings",
- "com.android.mms/com.android.mms.ui.ConversationList",
- "com.android.contacts/com.android.contacts.activities.PeopleActivity",
- "com.android.dialer/com.android.dialer.DialtactsActivity"
-]
-
-def usage():
- print "usage: fill_screens.py -- fills up the launcher db"
-
-
-def make_dir():
- shutil.rmtree(DIR, True)
- os.makedirs(DIR)
-
-def pull_file(fn):
- print "pull_file: " + fn
- rv = os.system("adb pull"
- + " /data/data/com.android.launcher/databases/launcher.db"
- + " " + fn);
- if rv != 0:
- print "adb pull failed"
- sys.exit(1)
-
-def push_file(fn):
- print "push_file: " + fn
- rv = os.system("adb push"
- + " " + fn
- + " /data/data/com.android.launcher/databases/launcher.db")
- if rv != 0:
- print "adb push failed"
- sys.exit(1)
-
-def process_file(fn):
- print "process_file: " + fn
- conn = sqlite3.connect(fn)
- c = conn.cursor()
- c.execute("DELETE FROM favorites")
-
- intentFormat = "#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=%s;end"
-
- id = 0;
- for s in range(SCREENS):
- for x in range(ROWS):
- for y in range(COLUMNS):
- id += 1
- insert = "INSERT into favorites (_id, title, intent, container, screen, cellX, cellY, spanX, spanY, itemType, appWidgetId, iconType) VALUES (%d, '%s', '%s', %d, %d, %d, %d, %d, %d, %d, %d, %d)"
- insert = insert % (id, "title", "", -100, s, x, y, 1, 1, 2, -1, 0)
- c.execute(insert)
- folder_id = id
-
- for z in range(15):
- id += 1
- intent = intentFormat % (APPLICATION_COMPONENTS[id % len(APPLICATION_COMPONENTS)])
- insert = "INSERT into favorites (_id, title, intent, container, screen, cellX, cellY, spanX, spanY, itemType, appWidgetId, iconType) VALUES (%d, '%s', '%s', %d, %d, %d, %d, %d, %d, %d, %d, %d)"
- insert = insert % (id, "title", intent, folder_id, 0, 0, 0, 1, 1, 0, -1, 0)
- c.execute(insert)
-
- conn.commit()
- c.close()
-
-def main(argv):
- if len(argv) == 1:
- make_dir()
- pull_file(AUTO_FILE)
- process_file(AUTO_FILE)
- push_file(AUTO_FILE)
- else:
- usage()
-
-if __name__=="__main__":
- main(sys.argv)
diff --git a/go/AndroidManifest.xml b/go/AndroidManifest.xml
index 2671604..728b326 100644
--- a/go/AndroidManifest.xml
+++ b/go/AndroidManifest.xml
@@ -54,6 +54,10 @@
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
android:enabled="false"
tools:node="replace" />
+
+ <service
+ android:name="com.android.launcher3.model.AppShareabilityJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE" />
</application>
</manifest>
diff --git a/go/quickstep/res/values-af/strings.xml b/go/quickstep/res/values-af/strings.xml
index 363eff5..501d297 100644
--- a/go/quickstep/res/values-af/strings.xml
+++ b/go/quickstep/res/values-af/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Verander jou digitalebystandprogram in Instellings om na teks op jou skerm te luister of dit te vertaal"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Tik hier om na teks op hierdie skerm te luister"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Tik hier om teks op hierdie skerm te vertaal"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Hierdie program kan nie gedeel word nie"</string>
</resources>
diff --git a/go/quickstep/res/values-am/strings.xml b/go/quickstep/res/values-am/strings.xml
index 5d8a766..ed34797 100644
--- a/go/quickstep/res/values-am/strings.xml
+++ b/go/quickstep/res/values-am/strings.xml
@@ -9,11 +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-ar/strings.xml b/go/quickstep/res/values-ar/strings.xml
index 323e7b0..7d98184 100644
--- a/go/quickstep/res/values-ar/strings.xml
+++ b/go/quickstep/res/values-ar/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-as/strings.xml b/go/quickstep/res/values-as/strings.xml
index cd123b5..8bf83ef 100644
--- a/go/quickstep/res/values-as/strings.xml
+++ b/go/quickstep/res/values-as/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-az/strings.xml b/go/quickstep/res/values-az/strings.xml
index f097ad3..2b03b16 100644
--- a/go/quickstep/res/values-az/strings.xml
+++ b/go/quickstep/res/values-az/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Ekrandakı mətni dinləmək və ya tərcümə etmək üçün Ayarlarda rəqəmsal assistent tətbiqini dəyişin"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Bu ekrandakı mətni dinləmək üçün buraya toxunun"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Bu ekrandakı mətni tərcümə etmək üçün buraya toxunun"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Bu tətbiqi paylaşmaq mümkün deyil"</string>
</resources>
diff --git a/go/quickstep/res/values-b+sr+Latn/strings.xml b/go/quickstep/res/values-b+sr+Latn/strings.xml
index 8663c81..263f011 100644
--- a/go/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/go/quickstep/res/values-b+sr+Latn/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Da biste čuli tekst sa ekrana ili ga preveli, promenite aplikaciju digitalnog pomoćnika u Podešavanjima"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Dodirnite ovde da biste čuli tekst sa ovog ekrana"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Dodirnite ovde da biste preveli tekst sa ovog ekrana"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Ova aplikacija ne može da se deli"</string>
</resources>
diff --git a/go/quickstep/res/values-be/strings.xml b/go/quickstep/res/values-be/strings.xml
index d4600cc..83374bb 100644
--- a/go/quickstep/res/values-be/strings.xml
+++ b/go/quickstep/res/values-be/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-bg/strings.xml b/go/quickstep/res/values-bg/strings.xml
index 3741646..5941898 100644
--- a/go/quickstep/res/values-bg/strings.xml
+++ b/go/quickstep/res/values-bg/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-bn/strings.xml b/go/quickstep/res/values-bn/strings.xml
index 5485d6b..8c27e63 100644
--- a/go/quickstep/res/values-bn/strings.xml
+++ b/go/quickstep/res/values-bn/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-bs/strings.xml b/go/quickstep/res/values-bs/strings.xml
index 675e5b8..7db34ae 100644
--- a/go/quickstep/res/values-bs/strings.xml
+++ b/go/quickstep/res/values-bs/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Da slušate ili prevedete tekst na ekranu, promijenite aplikaciju digitalnog asistenta u Postavkama"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Dodirnite ovdje da slušate tekst na ovom ekranu"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Dodirnite ovdje da prevedete tekst na ovom ekranu"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Nije moguće dijeliti ovu aplikaciju"</string>
</resources>
diff --git a/go/quickstep/res/values-ca/strings.xml b/go/quickstep/res/values-ca/strings.xml
index 212df28..889f50e 100644
--- a/go/quickstep/res/values-ca/strings.xml
+++ b/go/quickstep/res/values-ca/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Per escoltar o traduir text en pantalla, canvia l\'aplicació d\'assistent digital a Configuració"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Toca aquí per escoltar text en pantalla"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Toca aquí per traduir text en pantalla"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Aquesta aplicació o es pot compartir"</string>
</resources>
diff --git a/go/quickstep/res/values-cs/strings.xml b/go/quickstep/res/values-cs/strings.xml
index 886b5c2..b569dfc 100644
--- a/go/quickstep/res/values-cs/strings.xml
+++ b/go/quickstep/res/values-cs/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Pokud si chcete poslechnout nebo přeložit text na obrazovce, v Nastavení změňte aplikaci digitálního asistenta"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Klepnutím sem si poslechnete text na této obrazovce"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Klepnutím sem přeložíte text na této obrazovce"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Tuto aplikaci nelze sdílet"</string>
</resources>
diff --git a/go/quickstep/res/values-da/strings.xml b/go/quickstep/res/values-da/strings.xml
index 2bc179c..8f2055b 100644
--- a/go/quickstep/res/values-da/strings.xml
+++ b/go/quickstep/res/values-da/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Hvis du vil høre eller oversætte tekst på din skærm, skal du ændre din digitale assistent i Indstillinger"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Tryk her for at høre teksten på denne skærm"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Tryk her for at oversætte teksten på denne skærm"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Denne app kan ikke deles"</string>
</resources>
diff --git a/go/quickstep/res/values-de/strings.xml b/go/quickstep/res/values-de/strings.xml
index 3825b9d..efc11c9 100644
--- a/go/quickstep/res/values-de/strings.xml
+++ b/go/quickstep/res/values-de/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Wenn du dir auf deinem Display Text anhören oder übersetzen lassen möchtest, ändere in den Einstellungen deine App für den digitalen Assistenten"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Hier tippen, um dir Text auf diesem Display anzuhören"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Hier tippen, um dir Text auf diesem Display übersetzen zu lassen"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Diese App kann nicht gemeinsam genutzt werden"</string>
</resources>
diff --git a/go/quickstep/res/values-el/strings.xml b/go/quickstep/res/values-el/strings.xml
index bfa6279..9a67420 100644
--- a/go/quickstep/res/values-el/strings.xml
+++ b/go/quickstep/res/values-el/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-en-rAU/strings.xml b/go/quickstep/res/values-en-rAU/strings.xml
index f1d43a8..676ac43 100644
--- a/go/quickstep/res/values-en-rAU/strings.xml
+++ b/go/quickstep/res/values-en-rAU/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"To listen to or translate text on your screen, change your digital assistant app in settings"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Tap here to listen to text on this screen"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Tap here to translate text on this screen"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"This app can’t be shared"</string>
</resources>
diff --git a/go/quickstep/res/values-en-rCA/strings.xml b/go/quickstep/res/values-en-rCA/strings.xml
index f1d43a8..676ac43 100644
--- a/go/quickstep/res/values-en-rCA/strings.xml
+++ b/go/quickstep/res/values-en-rCA/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"To listen to or translate text on your screen, change your digital assistant app in settings"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Tap here to listen to text on this screen"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Tap here to translate text on this screen"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"This app can’t be shared"</string>
</resources>
diff --git a/go/quickstep/res/values-en-rGB/strings.xml b/go/quickstep/res/values-en-rGB/strings.xml
index f1d43a8..676ac43 100644
--- a/go/quickstep/res/values-en-rGB/strings.xml
+++ b/go/quickstep/res/values-en-rGB/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"To listen to or translate text on your screen, change your digital assistant app in settings"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Tap here to listen to text on this screen"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Tap here to translate text on this screen"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"This app can’t be shared"</string>
</resources>
diff --git a/go/quickstep/res/values-en-rIN/strings.xml b/go/quickstep/res/values-en-rIN/strings.xml
index f1d43a8..676ac43 100644
--- a/go/quickstep/res/values-en-rIN/strings.xml
+++ b/go/quickstep/res/values-en-rIN/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"To listen to or translate text on your screen, change your digital assistant app in settings"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Tap here to listen to text on this screen"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Tap here to translate text on this screen"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"This app can’t be shared"</string>
</resources>
diff --git a/go/quickstep/res/values-en-rXC/strings.xml b/go/quickstep/res/values-en-rXC/strings.xml
index c729cd8..b6a4021 100644
--- a/go/quickstep/res/values-en-rXC/strings.xml
+++ b/go/quickstep/res/values-en-rXC/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"To listen to or translate text on your screen, change your digital assistant app in Settings"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Tap here to listen to text on this screen"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Tap here to translate text on this screen"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"This app can’t be shared"</string>
</resources>
diff --git a/go/quickstep/res/values-es-rUS/strings.xml b/go/quickstep/res/values-es-rUS/strings.xml
index cde1cd7..0f53967 100644
--- a/go/quickstep/res/values-es-rUS/strings.xml
+++ b/go/quickstep/res/values-es-rUS/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Para escuchar o traducir texto en la pantalla, cambia la app de asistente digital en Configuración"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Presiona aquí para escuchar texto en esta pantalla"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Presiona aquí para traducir texto en esta pantalla"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"No se puede compartir esta app"</string>
</resources>
diff --git a/go/quickstep/res/values-es/strings.xml b/go/quickstep/res/values-es/strings.xml
index 0049443..fcd0fb8 100644
--- a/go/quickstep/res/values-es/strings.xml
+++ b/go/quickstep/res/values-es/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Para escuchar o traducir texto que haya en tu pantalla, cambia tu aplicación de asistente digital en Ajustes"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Toca aquí para escuchar el texto que hay en esta pantalla"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Toca aquí para traducir el texto que hay en esta pantalla"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Esta aplicación no se puede compartir"</string>
</resources>
diff --git a/go/quickstep/res/values-et/strings.xml b/go/quickstep/res/values-et/strings.xml
index 9a7c118..2fffdd8 100644
--- a/go/quickstep/res/values-et/strings.xml
+++ b/go/quickstep/res/values-et/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Ekraanil kuvatud teksti kuulamiseks või tõlkimiseks vahetage seadetes digitaalse assistendi rakendust"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Puudutage siin, et ekraanil kuvatud teksti kuulda"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Puudutage siin, et ekraanil kuvatud tekst tõlkida"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Seda rakendust ei saa jagada"</string>
</resources>
diff --git a/go/quickstep/res/values-eu/strings.xml b/go/quickstep/res/values-eu/strings.xml
index 79b1acb..75ddb46 100644
--- a/go/quickstep/res/values-eu/strings.xml
+++ b/go/quickstep/res/values-eu/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Pantailako testua entzun edo itzultzeko, aldatu laguntzaile digitalaren aplikazioa Ezarpenak atalean"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Sakatu hau pantailako testua entzuteko"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Sakatu hau pantailako testua itzultzeko"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Ezin da partekatu aplikazioa"</string>
</resources>
diff --git a/go/quickstep/res/values-fa/strings.xml b/go/quickstep/res/values-fa/strings.xml
index c86fddb..47786e9 100644
--- a/go/quickstep/res/values-fa/strings.xml
+++ b/go/quickstep/res/values-fa/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-fi/strings.xml b/go/quickstep/res/values-fi/strings.xml
index c13a92c..bab635f 100644
--- a/go/quickstep/res/values-fi/strings.xml
+++ b/go/quickstep/res/values-fi/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Jos haluat kuunnella tai kääntää näytöllä näkyvää tekstiä, vaihda digiavustajasovellus asetuksista"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Kuuntele näytöllä näkyvä teksti napauttamalla tästä"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Käännä näytöllä näkyvä teksti napauttamalla tästä"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Tätä sovellusta ei voi jakaa"</string>
</resources>
diff --git a/go/quickstep/res/values-fr-rCA/strings.xml b/go/quickstep/res/values-fr-rCA/strings.xml
index d04abd8..2cc9d8f 100644
--- a/go/quickstep/res/values-fr-rCA/strings.xml
+++ b/go/quickstep/res/values-fr-rCA/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Pour écouter ou traduire le texte affiché sur votre écran, modifiez l\'application de votre assistant numérique dans les paramètres"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Touchez ce bouton pour écouter le texte affiché sur cet écran"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Touchez ce bouton pour traduire le texte affiché sur cet écran"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Cette application ne peut pas être partagée"</string>
</resources>
diff --git a/go/quickstep/res/values-fr/strings.xml b/go/quickstep/res/values-fr/strings.xml
index 045a8a0..fded0af 100644
--- a/go/quickstep/res/values-fr/strings.xml
+++ b/go/quickstep/res/values-fr/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Pour écouter ou traduire le texte à l\'écran, modifiez l\'appli d\'assistant numérique dans \"Paramètres\""</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Appuyez ici pour écouter le texte à l\'écran"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Appuyez ici pour traduire le texte à l\'écran"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Impossible de partager cette appli"</string>
</resources>
diff --git a/go/quickstep/res/values-gl/strings.xml b/go/quickstep/res/values-gl/strings.xml
index 0c01317..86c6a57 100644
--- a/go/quickstep/res/values-gl/strings.xml
+++ b/go/quickstep/res/values-gl/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Para escoitar ou traducir o texto da pantalla, cambia a aplicación de asistente dixital en Configuración"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Tocar aquí para escoitar o texto desta pantalla"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Tocar aquí para traducir o texto desta pantalla"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Non se pode compartir esta aplicación"</string>
</resources>
diff --git a/go/quickstep/res/values-gu/strings.xml b/go/quickstep/res/values-gu/strings.xml
index 9cd1101..80d9e2e 100644
--- a/go/quickstep/res/values-gu/strings.xml
+++ b/go/quickstep/res/values-gu/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-hi/strings.xml b/go/quickstep/res/values-hi/strings.xml
index 95a8dd8..ecf0cfb 100644
--- a/go/quickstep/res/values-hi/strings.xml
+++ b/go/quickstep/res/values-hi/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-hr/strings.xml b/go/quickstep/res/values-hr/strings.xml
index bef6b71..137472d 100644
--- a/go/quickstep/res/values-hr/strings.xml
+++ b/go/quickstep/res/values-hr/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Da biste poslušali ili preveli tekst na zaslonu, promijenite aplikaciju digitalnog asistenta u postavkama"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Dodirnite ovdje da biste poslušali tekst na ovom zaslonu"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Dodirnite ovdje da biste preveli tekst na ovom zaslonu"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Ovu aplikaciju ne možete dijeliti"</string>
</resources>
diff --git a/go/quickstep/res/values-hu/strings.xml b/go/quickstep/res/values-hu/strings.xml
index f2cd089..d94e6b7 100644
--- a/go/quickstep/res/values-hu/strings.xml
+++ b/go/quickstep/res/values-hu/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"A képernyőn megjelenő szöveg meghallgatásához vagy lefordításához módosítsa a digitálisasszisztens-alkalmazást a Beállítások menüben"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Koppintson ide a jelenleg képernyőn lévő szöveg meghallgatásához"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Koppintson ide a jelenleg képernyőn lévő szöveg lefordításához"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Ezt az alkalmazást nem lehet megosztani"</string>
</resources>
diff --git a/go/quickstep/res/values-hy/strings.xml b/go/quickstep/res/values-hy/strings.xml
index b238a92..c6352c9 100644
--- a/go/quickstep/res/values-hy/strings.xml
+++ b/go/quickstep/res/values-hy/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-in/strings.xml b/go/quickstep/res/values-in/strings.xml
index 7e240e8..692bedc 100644
--- a/go/quickstep/res/values-in/strings.xml
+++ b/go/quickstep/res/values-in/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Untuk mendengarkan atau menerjemahkan teks di layar, ubah aplikasi asisten digital Anda di Setelan"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Ketuk di sini untuk mendengarkan teks di layar ini"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Ketuk di sini untuk menerjemahkan teks di layar ini"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Aplikasi ini tidak dapat dibagikan"</string>
</resources>
diff --git a/go/quickstep/res/values-is/strings.xml b/go/quickstep/res/values-is/strings.xml
index c882c99..25a96dd 100644
--- a/go/quickstep/res/values-is/strings.xml
+++ b/go/quickstep/res/values-is/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Breyttu forriti stafræna hjálparans í stillingum til að hlusta á eða þýða texta"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Ýttu hér til að hlusta á texta á þessum skjá"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Ýttu hér til að þýða texta á þessum skjá"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Ekki er hægt að deila þessu forriti"</string>
</resources>
diff --git a/go/quickstep/res/values-it/strings.xml b/go/quickstep/res/values-it/strings.xml
index 75afcbb..ebdea20 100644
--- a/go/quickstep/res/values-it/strings.xml
+++ b/go/quickstep/res/values-it/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Per ascoltare o tradurre il testo mostrato sullo schermo, cambia l\'app dell\'assistente digitale nelle Impostazioni"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Tocca qui per ascoltare il testo mostrato in questa schermata"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Tocca qui per tradurre il testo mostrato in questa schermata"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Impossibile condividere questa app"</string>
</resources>
diff --git a/go/quickstep/res/values-iw/strings.xml b/go/quickstep/res/values-iw/strings.xml
index fd3747e..ddb8ddd 100644
--- a/go/quickstep/res/values-iw/strings.xml
+++ b/go/quickstep/res/values-iw/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-ja/strings.xml b/go/quickstep/res/values-ja/strings.xml
index cfbfeca..3ce87f7 100644
--- a/go/quickstep/res/values-ja/strings.xml
+++ b/go/quickstep/res/values-ja/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-ka/strings.xml b/go/quickstep/res/values-ka/strings.xml
index 3280a7e..0f73810 100644
--- a/go/quickstep/res/values-ka/strings.xml
+++ b/go/quickstep/res/values-ka/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-kk/strings.xml b/go/quickstep/res/values-kk/strings.xml
index 9720e2a..2a2f96d 100644
--- a/go/quickstep/res/values-kk/strings.xml
+++ b/go/quickstep/res/values-kk/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-km/strings.xml b/go/quickstep/res/values-km/strings.xml
index b44ff0a..cec7646 100644
--- a/go/quickstep/res/values-km/strings.xml
+++ b/go/quickstep/res/values-km/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-kn/strings.xml b/go/quickstep/res/values-kn/strings.xml
index ef19541..28ba66b 100644
--- a/go/quickstep/res/values-kn/strings.xml
+++ b/go/quickstep/res/values-kn/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-ko/strings.xml b/go/quickstep/res/values-ko/strings.xml
index 7b298e9..97ccfef 100644
--- a/go/quickstep/res/values-ko/strings.xml
+++ b/go/quickstep/res/values-ko/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-ky/strings.xml b/go/quickstep/res/values-ky/strings.xml
index 66fb264..e4a2474 100644
--- a/go/quickstep/res/values-ky/strings.xml
+++ b/go/quickstep/res/values-ky/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-lo/strings.xml b/go/quickstep/res/values-lo/strings.xml
index f2c6ffa..b6f7b07 100644
--- a/go/quickstep/res/values-lo/strings.xml
+++ b/go/quickstep/res/values-lo/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-lt/strings.xml b/go/quickstep/res/values-lt/strings.xml
index e47d2bb..dffe34f 100644
--- a/go/quickstep/res/values-lt/strings.xml
+++ b/go/quickstep/res/values-lt/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Jei norite klausyti teksto ekrane ar jį išversti, pakeiskite skaitmeninio pagelbiklio programą „Nustatymų“ skiltyje"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Palieskite čia, jei norite klausyti teksto šiame ekrane"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Palieskite čia, jei norite išversti tekstą šiame ekrane"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Šios programos negalima bendrinti"</string>
</resources>
diff --git a/go/quickstep/res/values-lv/strings.xml b/go/quickstep/res/values-lv/strings.xml
index 831486a..faf3274 100644
--- a/go/quickstep/res/values-lv/strings.xml
+++ b/go/quickstep/res/values-lv/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Lai klausītos vai tulkotu ekrānā parādīto tekstu, iestatījumos mainiet digitālā asistenta lietotni"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Lai klausītos ekrānā parādīto tekstu, pieskarieties šeit"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Lai tulkotu ekrānā parādīto tekstu, pieskarieties šeit"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Šo lietotni nevar kopīgot."</string>
</resources>
diff --git a/go/quickstep/res/values-mk/strings.xml b/go/quickstep/res/values-mk/strings.xml
index 93d582c..7e8cecf 100644
--- a/go/quickstep/res/values-mk/strings.xml
+++ b/go/quickstep/res/values-mk/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-ml/strings.xml b/go/quickstep/res/values-ml/strings.xml
index d34a5f1..ed57395 100644
--- a/go/quickstep/res/values-ml/strings.xml
+++ b/go/quickstep/res/values-ml/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-mn/strings.xml b/go/quickstep/res/values-mn/strings.xml
index d1144ee..d03b2d2 100644
--- a/go/quickstep/res/values-mn/strings.xml
+++ b/go/quickstep/res/values-mn/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-mr/strings.xml b/go/quickstep/res/values-mr/strings.xml
index e190359..d3dff92 100644
--- a/go/quickstep/res/values-mr/strings.xml
+++ b/go/quickstep/res/values-mr/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-ms/strings.xml b/go/quickstep/res/values-ms/strings.xml
index 9ecbe99..3b0a7fb 100644
--- a/go/quickstep/res/values-ms/strings.xml
+++ b/go/quickstep/res/values-ms/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Untuk mendengar atau menterjemahkan teks pada skrin anda, tukar apl pembantu digital anda dalam Tetapan"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Ketik di sini untuk mendengar teks pada skrin ini"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Ketik di sini untuk menterjemahkan teks pada skrin ini"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Apl ini tidak boleh dikongsi"</string>
</resources>
diff --git a/go/quickstep/res/values-my/strings.xml b/go/quickstep/res/values-my/strings.xml
index e318314..0ca0e9c 100644
--- a/go/quickstep/res/values-my/strings.xml
+++ b/go/quickstep/res/values-my/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"ဖန်သားပြင်ပေါ်ရှိ စာသားကို နားထောင်ရန် (သို့) ဘာသာပြန်ဆိုရန် ‘ဆက်တင်များ’ တွင် ဒစ်ဂျစ်တယ် assistant အက်ပ်ကို ပြောင်းပါ"</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-nb/strings.xml b/go/quickstep/res/values-nb/strings.xml
index ec3ef59..662b544 100644
--- a/go/quickstep/res/values-nb/strings.xml
+++ b/go/quickstep/res/values-nb/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"For å høre eller oversette tekst på skjermen, endre digital assistent-appen i innstillingene"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Trykk her for å høre teksten på denne skjermen"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Trykk her for å oversette teksten på denne skjermen"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Denne appen kan ikke deles"</string>
</resources>
diff --git a/go/quickstep/res/values-ne/strings.xml b/go/quickstep/res/values-ne/strings.xml
index cd1ee06..11a70dd 100644
--- a/go/quickstep/res/values-ne/strings.xml
+++ b/go/quickstep/res/values-ne/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-nl/strings.xml b/go/quickstep/res/values-nl/strings.xml
index 82a8519..2d4c6e2 100644
--- a/go/quickstep/res/values-nl/strings.xml
+++ b/go/quickstep/res/values-nl/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Als je tekst op je scherm wilt beluisteren of vertalen, wijzig je de digitale-assistent-app in Instellingen"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Tik hier om tekst op dit scherm te beluisteren"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Tik hier om tekst op dit scherm te vertalen"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Deze app kan niet worden gedeeld"</string>
</resources>
diff --git a/go/quickstep/res/values-or/strings.xml b/go/quickstep/res/values-or/strings.xml
index db328ec..6a3c5dc 100644
--- a/go/quickstep/res/values-or/strings.xml
+++ b/go/quickstep/res/values-or/strings.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_share_drop_target_label" msgid="5804774105974539508">"ଆପ୍ ସେୟାର୍ କରନ୍ତୁ"</string>
+ <string name="app_share_drop_target_label" msgid="5804774105974539508">"ଆପ ସେୟାର କରନ୍ତୁ"</string>
<string name="action_listen" msgid="2370304050784689486">"ଶୁଣନ୍ତୁ"</string>
<string name="action_translate" msgid="8028378961867277746">"ଅନୁବାଦ କରନ୍ତୁ"</string>
<string name="action_search" msgid="6269564710943755464">"Lens"</string>
<string name="dialog_acknowledge" msgid="2804025517675853172">"ବୁଝିଗଲି"</string>
- <string name="dialog_cancel" msgid="6464336969134856366">"ବାତିଲ୍ କରନ୍ତୁ"</string>
+ <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>"ସେଟିଂସ > ଆପ୍ସ > ଡିଫଲ୍ଟ ଆପ୍ସ > Digital assistant ଆପ"</b>"କୁ ଯାଆନ୍ତୁ।"</string>
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଥିବା ଟେକ୍ସଟକୁ ଶୁଣିବା କିମ୍ବା ଅନୁବାଦ କରିବା ପାଇଁ, ସେଟିଂସରେ ଆପଣଙ୍କ Digital assistant ଆପକୁ ବଦଳାନ୍ତୁ"</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-pa/strings.xml b/go/quickstep/res/values-pa/strings.xml
index c3bc875..8549b58 100644
--- a/go/quickstep/res/values-pa/strings.xml
+++ b/go/quickstep/res/values-pa/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-pl/strings.xml b/go/quickstep/res/values-pl/strings.xml
index a03e05e..5dc66f5 100644
--- a/go/quickstep/res/values-pl/strings.xml
+++ b/go/quickstep/res/values-pl/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Aby odsłuchać lub przetłumaczyć tekst widoczny na ekranie, zmień w Ustawieniach aplikację asystenta cyfrowego"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Kliknij tutaj, aby odsłuchać tekst widoczny na ekranie"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Kliknij tutaj, aby przetłumaczyć tekst widoczny na ekranie"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Tej aplikacji nie można udostępnić"</string>
</resources>
diff --git a/go/quickstep/res/values-pt-rPT/strings.xml b/go/quickstep/res/values-pt-rPT/strings.xml
index 311cac1..e64f520 100644
--- a/go/quickstep/res/values-pt-rPT/strings.xml
+++ b/go/quickstep/res/values-pt-rPT/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Para ouvir ou traduzir o texto no ecrã, mude de app de assistente digital nas Definições"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Toque aqui para ouvir o texto neste ecrã"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Toque aqui para traduzir o texto neste ecrã"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Não é possível partilhar esta app"</string>
</resources>
diff --git a/go/quickstep/res/values-pt/strings.xml b/go/quickstep/res/values-pt/strings.xml
index 0a0da37..ba59231 100644
--- a/go/quickstep/res/values-pt/strings.xml
+++ b/go/quickstep/res/values-pt/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Para ouvir ou traduzir o texto exibido na tela, mude seu app assistente digital nas Configurações"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Toque aqui para ouvir o texto exibido na tela"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Toque aqui para traduzir o texto exibido na tela"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Não é possível compartilhar o app"</string>
</resources>
diff --git a/go/quickstep/res/values-ro/strings.xml b/go/quickstep/res/values-ro/strings.xml
index 37cf48d..3d6f0d8 100644
--- a/go/quickstep/res/values-ro/strings.xml
+++ b/go/quickstep/res/values-ro/strings.xml
@@ -1,19 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_share_drop_target_label" msgid="5804774105974539508">"Trimiteți aplicația"</string>
- <string name="action_listen" msgid="2370304050784689486">"Ascultați"</string>
- <string name="action_translate" msgid="8028378961867277746">"Traduceți"</string>
+ <string name="app_share_drop_target_label" msgid="5804774105974539508">"Trimite aplicația"</string>
+ <string name="action_listen" msgid="2370304050784689486">"Ascultă"</string>
+ <string name="action_translate" msgid="8028378961867277746">"Tradu"</string>
<string name="action_search" msgid="6269564710943755464">"Lens"</string>
<string name="dialog_acknowledge" msgid="2804025517675853172">"OK"</string>
- <string name="dialog_cancel" msgid="6464336969134856366">"ANULAȚI"</string>
+ <string name="dialog_cancel" msgid="6464336969134856366">"ANULEAZĂ"</string>
<string name="dialog_settings" msgid="6564397136021186148">"SETĂRI"</string>
- <string name="niu_actions_confirmation_title" msgid="3863451714863526143">"Traduceți sau ascultați textul de pe ecran"</string>
- <string name="niu_actions_confirmation_text" msgid="2105271481950866089">"Informații precum textul de pe ecran, adresele web și capturile de ecran pot fi trimise la Google.\n\nCa să schimbați informațiile trimise, accesați "<b>"Setări > Aplicații > Aplicații prestabilite > Aplicația asistent digital"</b>"."</string>
- <string name="assistant_not_selected_title" msgid="5017072974603345228">"Alegeți un asistent pentru a folosi această funcție"</string>
- <string name="assistant_not_selected_text" msgid="3244613673884359276">"Pentru a asculta sau a traduce text de pe ecran, alegeți o aplicație asistent digital în Setări"</string>
- <string name="assistant_not_supported_title" msgid="1675788067597484142">"Schimbați asistentul pentru a folosi această funcție"</string>
- <string name="assistant_not_supported_text" msgid="1708031078549268884">"Pentru a asculta sau a traduce text de pe ecran, schimbați aplicația asistent digital în Setări"</string>
- <string name="tooltip_listen" msgid="7634466447860989102">"Atingeți aici pentru a asculta text de pe ecran"</string>
- <string name="tooltip_translate" msgid="4184845868901542567">"Atingeți aici pentru a traduce text de pe ecran"</string>
+ <string name="niu_actions_confirmation_title" msgid="3863451714863526143">"Tradu sau ascultă textul de pe ecran"</string>
+ <string name="niu_actions_confirmation_text" msgid="2105271481950866089">"Informații precum textul de pe ecran, adresele web și capturile de ecran pot fi trimise la Google.\n\nCa să schimbi informațiile trimise, accesează "<b>"Setări > Aplicații > Aplicații prestabilite > Aplicația asistent digital"</b>"."</string>
+ <string name="assistant_not_selected_title" msgid="5017072974603345228">"Alege un asistent pentru a folosi această funcție"</string>
+ <string name="assistant_not_selected_text" msgid="3244613673884359276">"Pentru a asculta sau a traduce text de pe ecran, alege o aplicație asistent digital în Setări"</string>
+ <string name="assistant_not_supported_title" msgid="1675788067597484142">"Schimbă asistentul pentru a folosi această funcție"</string>
+ <string name="assistant_not_supported_text" msgid="1708031078549268884">"Pentru a asculta sau a traduce text de pe ecran, schimbă aplicația asistent digital în Setări"</string>
+ <string name="tooltip_listen" msgid="7634466447860989102">"Atinge aici pentru a asculta text de pe ecran"</string>
+ <string name="tooltip_translate" msgid="4184845868901542567">"Atinge aici pentru a traduce text de pe ecran"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Aplicația nu poate fi distribuită"</string>
</resources>
diff --git a/go/quickstep/res/values-ru/strings.xml b/go/quickstep/res/values-ru/strings.xml
index d31c42a..d845c35 100644
--- a/go/quickstep/res/values-ru/strings.xml
+++ b/go/quickstep/res/values-ru/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-si/strings.xml b/go/quickstep/res/values-si/strings.xml
index cd6060c..52718f2 100644
--- a/go/quickstep/res/values-si/strings.xml
+++ b/go/quickstep/res/values-si/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-sk/strings.xml b/go/quickstep/res/values-sk/strings.xml
index 880d8ad..89291af 100644
--- a/go/quickstep/res/values-sk/strings.xml
+++ b/go/quickstep/res/values-sk/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Ak si chcete vypočuť alebo nechať preložiť text na obrazovke, zmeňte v Nastaveniach aplikáciu digitálneho asistenta"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Klepnutím tu si vypočujte text na tejto obrazovke"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Klepnutím tu si nechajte preložiť text na tejto obrazovke"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Táto aplikácia sa nedá zdieľať"</string>
</resources>
diff --git a/go/quickstep/res/values-sl/strings.xml b/go/quickstep/res/values-sl/strings.xml
index 31fcffc..afa674e 100644
--- a/go/quickstep/res/values-sl/strings.xml
+++ b/go/quickstep/res/values-sl/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Za poslušanje ali prevod besedila na zaslonu v nastavitvah izberite drugega digitalnega pomočnika."</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Dotaknite se tukaj za poslušanje besedila na zaslonu."</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Dotaknite se tukaj za prevod besedila na zaslonu."</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Te aplikacije ni mogoče deliti z drugimi."</string>
</resources>
diff --git a/go/quickstep/res/values-sq/strings.xml b/go/quickstep/res/values-sq/strings.xml
index bc9c429..123ca39 100644
--- a/go/quickstep/res/values-sq/strings.xml
+++ b/go/quickstep/res/values-sq/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Për të dëgjuar ose përkthyer tekstin në ekran, ndrysho aplikacionin e asistentit dixhital te \"Cilësimet\""</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Trokit këtu për të dëgjuar tekstin në këtë ekran"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Trokit këtu për të përkthyer tekstin në këtë ekran"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Ky aplikacion nuk mund të ndahet"</string>
</resources>
diff --git a/go/quickstep/res/values-sr/strings.xml b/go/quickstep/res/values-sr/strings.xml
index 9c9a332..749fc0e 100644
--- a/go/quickstep/res/values-sr/strings.xml
+++ b/go/quickstep/res/values-sr/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-sv/strings.xml b/go/quickstep/res/values-sv/strings.xml
index cb70a58..e76fe7f 100644
--- a/go/quickstep/res/values-sv/strings.xml
+++ b/go/quickstep/res/values-sv/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Byt digital assistentapp i Inställningar om du vill lyssna på eller översätta text på skärmen"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Tryck här för att lyssna på texten på skärmen"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Tryck här för att översätta texten på skärmen"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Den här appen kan inte delas"</string>
</resources>
diff --git a/go/quickstep/res/values-sw/strings.xml b/go/quickstep/res/values-sw/strings.xml
index a78980a..5a25702 100644
--- a/go/quickstep/res/values-sw/strings.xml
+++ b/go/quickstep/res/values-sw/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Ili usikilize au utafsiri maandishi kwenye skrini yako, badilisha programu yako ya mratibu dijitali katika Mipangilio"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Gusa hapa ili usikilize maandishi kwenye skrini hii"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Gusa hapa ili utafsiri maandishi kwenye skrini hii"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Huwezi kushiriki programu hii"</string>
</resources>
diff --git a/go/quickstep/res/values-ta/strings.xml b/go/quickstep/res/values-ta/strings.xml
index 89848d5..cd97aa3 100644
--- a/go/quickstep/res/values-ta/strings.xml
+++ b/go/quickstep/res/values-ta/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-te/strings.xml b/go/quickstep/res/values-te/strings.xml
index cb481d0..656adf6 100644
--- a/go/quickstep/res/values-te/strings.xml
+++ b/go/quickstep/res/values-te/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-th/strings.xml b/go/quickstep/res/values-th/strings.xml
index f19cb2a..8ce2ffc 100644
--- a/go/quickstep/res/values-th/strings.xml
+++ b/go/quickstep/res/values-th/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-tl/strings.xml b/go/quickstep/res/values-tl/strings.xml
index 1810c4c..2da5f59 100644
--- a/go/quickstep/res/values-tl/strings.xml
+++ b/go/quickstep/res/values-tl/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Para pakinggan o isalin ang text sa iyong screen, palitan ang iyong app ng digital na assistant sa Mga Setting"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Mag-tap dito para pakinggan ang text sa screen na ito"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Mag-tap dito para isalin ang text sa screen na ito"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Hindi maibabahagi ang app na ito"</string>
</resources>
diff --git a/go/quickstep/res/values-tr/strings.xml b/go/quickstep/res/values-tr/strings.xml
index 0854dec..dd2e907 100644
--- a/go/quickstep/res/values-tr/strings.xml
+++ b/go/quickstep/res/values-tr/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Ekranınızdaki metni dinlemek veya çevirmek için Ayarlar\'dan dijital asistan uygulamanızı değiştirin"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Bu ekrandaki metni dinlemek için buraya dokunun"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Bu ekrandaki metni çevirmek için buraya dokunun"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Bu uygulama paylaşılamaz"</string>
</resources>
diff --git a/go/quickstep/res/values-uk/strings.xml b/go/quickstep/res/values-uk/strings.xml
index 475ff20..c59b3bf 100644
--- a/go/quickstep/res/values-uk/strings.xml
+++ b/go/quickstep/res/values-uk/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-ur/strings.xml b/go/quickstep/res/values-ur/strings.xml
index 6393127..dd6c2cc 100644
--- a/go/quickstep/res/values-ur/strings.xml
+++ b/go/quickstep/res/values-ur/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-uz/strings.xml b/go/quickstep/res/values-uz/strings.xml
index 5228cfe..cb6b9e0 100644
--- a/go/quickstep/res/values-uz/strings.xml
+++ b/go/quickstep/res/values-uz/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Ekrandagi matnni eshittirish yoki tarjima qilish uchun Sozlamalar orqali raqamli assistent ilovasini almashtiring"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Ekrandagi matnni eshittirish uchun bosing"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Ekrandagi matnni tarjima qilish uchun bosing"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Bu ilova ulashilmaydi"</string>
</resources>
diff --git a/go/quickstep/res/values-vi/strings.xml b/go/quickstep/res/values-vi/strings.xml
index cebb934..0bca168 100644
--- a/go/quickstep/res/values-vi/strings.xml
+++ b/go/quickstep/res/values-vi/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Để nghe hoặc dịch văn bản trên màn hình, hãy thay đổi ứng dụng trợ lý kỹ thuật số trong phần Cài đặt"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Nhấn vào đây để nghe văn bản trên màn hình này"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Nhấn vào đây để dịch văn bản trên màn hình này"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Bạn không thể chia sẻ ứng dụng này"</string>
</resources>
diff --git a/go/quickstep/res/values-zh-rCN/strings.xml b/go/quickstep/res/values-zh-rCN/strings.xml
index 9a71dd7..27bde29 100644
--- a/go/quickstep/res/values-zh-rCN/strings.xml
+++ b/go/quickstep/res/values-zh-rCN/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-zh-rHK/strings.xml b/go/quickstep/res/values-zh-rHK/strings.xml
index 29402d8..07cc125 100644
--- a/go/quickstep/res/values-zh-rHK/strings.xml
+++ b/go/quickstep/res/values-zh-rHK/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-zh-rTW/strings.xml b/go/quickstep/res/values-zh-rTW/strings.xml
index 86d78c6..41fd8b1 100644
--- a/go/quickstep/res/values-zh-rTW/strings.xml
+++ b/go/quickstep/res/values-zh-rTW/strings.xml
@@ -16,4 +16,5 @@
<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>
</resources>
diff --git a/go/quickstep/res/values-zu/strings.xml b/go/quickstep/res/values-zu/strings.xml
index 20b7894..1be7898 100644
--- a/go/quickstep/res/values-zu/strings.xml
+++ b/go/quickstep/res/values-zu/strings.xml
@@ -16,4 +16,5 @@
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Ukuze ulalele noma uhumushe umbhalo kusikrini sakho, shintsha i-app yomsizi wakho odijithali kokuthi Amasethingi"</string>
<string name="tooltip_listen" msgid="7634466447860989102">"Thepha lapha ukuze ulalele umbhalo kusikrini"</string>
<string name="tooltip_translate" msgid="4184845868901542567">"Thepha lapha ukuze uhumushe umbhalo kulesi sikrini"</string>
+ <string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Le app ayikwazi ukwabiwa"</string>
</resources>
diff --git a/go/quickstep/res/values/integers.xml b/go/quickstep/res/values/integers.xml
new file mode 100644
index 0000000..e6e8111
--- /dev/null
+++ b/go/quickstep/res/values/integers.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources>
+ <!-- Job IDs must be integers unique within their package -->
+ <integer name="app_shareability_job_id">200</integer>
+</resources>
\ No newline at end of file
diff --git a/go/quickstep/res/values/strings.xml b/go/quickstep/res/values/strings.xml
index 8429f6a..42f4702 100644
--- a/go/quickstep/res/values/strings.xml
+++ b/go/quickstep/res/values/strings.xml
@@ -41,4 +41,8 @@
<string name="tooltip_listen">Tap here to listen to text on this screen</string>
<!-- Tooltip to highlight and explain the Translate button -->
<string name="tooltip_translate">Tap here to translate text on this screen</string>
+
+ <!-- ******* Toast Messages ******* -->
+ <!-- Toast to indicate that an app cannot be shared -->
+ <string name="toast_p2p_app_not_shareable">This app can’t be shared</string>
</resources>
diff --git a/go/quickstep/res/values/styles.xml b/go/quickstep/res/values/styles.xml
index 442c413..c659331 100644
--- a/go/quickstep/res/values/styles.xml
+++ b/go/quickstep/res/values/styles.xml
@@ -73,7 +73,7 @@
<style name="ModalDialogText">
<item name="android:fontFamily">sans-serif-medium</item>
<item name="android:textSize">16sp</item>
- <item name="android:textColor">?android:attr/textColorSecondary</item>
+ <item name="android:textColor">?android:attr/textColorTertiary</item>
<item name="android:lineHeight">24dp</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
diff --git a/go/quickstep/src/com/android/launcher3/AppSharing.java b/go/quickstep/src/com/android/launcher3/AppSharing.java
index b72e71c..cb1f1c7 100644
--- a/go/quickstep/src/com/android/launcher3/AppSharing.java
+++ b/go/quickstep/src/com/android/launcher3/AppSharing.java
@@ -16,20 +16,32 @@
package com.android.launcher3;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_APP_SHARE_TAP;
+
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
+import android.os.Process;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
+import android.widget.Toast;
import androidx.core.content.FileProvider;
+import com.android.launcher3.model.AppShareabilityChecker;
+import com.android.launcher3.model.AppShareabilityJobService;
+import com.android.launcher3.model.AppShareabilityManager;
+import com.android.launcher3.model.AppShareabilityManager.ShareabilityStatus;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.popup.SystemShortcut;
+import com.android.launcher3.views.ActivityContext;
import java.io.File;
@@ -44,6 +56,11 @@
* because it is unique to Go and not toggleable at runtime.
*/
public static final boolean ENABLE_APP_SHARING = true;
+ /**
+ * With this flag enabled, the Share App button will be dynamically enabled/disabled based
+ * on each app's shareability status.
+ */
+ public static final boolean ENABLE_SHAREABILITY_CHECK = true;
private static final String TAG = "AppSharing";
private static final String FILE_PROVIDER_SUFFIX = ".overview.fileprovider";
@@ -51,46 +68,70 @@
private static final String APP_MIME_TYPE = "application/application";
private final String mSharingComponent;
+ private AppShareabilityManager mShareabilityMgr;
private AppSharing(Launcher launcher) {
mSharingComponent = launcher.getText(R.string.app_sharing_component).toString();
}
- private boolean canShare(ItemInfo info) {
- /**
- * TODO: Implement once b/168831749 has been resolved
- * The implementation should check the validity of the app.
- * It should also check whether the app is free or paid, returning false in the latter case.
- * For now, all checks occur in the sharing app.
- * So, we simply check whether the sharing app is defined.
- */
- return !TextUtils.isEmpty(mSharingComponent);
- }
-
private Uri getShareableUri(Context context, String path, String displayName) {
String authority = BuildConfig.APPLICATION_ID + FILE_PROVIDER_SUFFIX;
File pathFile = new File(path);
return FileProvider.getUriForFile(context, authority, pathFile, displayName);
}
- private SystemShortcut<Launcher> getShortcut(Launcher launcher, ItemInfo info) {
- if (!canShare(info)) {
+ private SystemShortcut<Launcher> getShortcut(Launcher launcher, ItemInfo info,
+ View originalView) {
+ if (TextUtils.isEmpty(mSharingComponent)) {
return null;
}
+ return new Share(launcher, info, originalView);
+ }
- return new Share(launcher, info);
+ /**
+ * Instantiates AppShareabilityManager, which then reads app shareability data from disk
+ * Also schedules a job to update those data
+ * @param context The application context
+ * @param checker An implementation of AppShareabilityChecker to perform the actual checks
+ * when updating the data
+ */
+ public static void setUpShareabilityCache(Context context, AppShareabilityChecker checker) {
+ AppShareabilityManager shareMgr = AppShareabilityManager.INSTANCE.get(context);
+ shareMgr.setShareabilityChecker(checker);
+ AppShareabilityJobService.schedule(context);
}
/**
* The Share App system shortcut, used to initiate p2p sharing of a given app
*/
public final class Share extends SystemShortcut<Launcher> {
- public Share(Launcher target, ItemInfo itemInfo) {
- super(R.drawable.ic_share, R.string.app_share_drop_target_label, target, itemInfo);
+ private final PopupDataProvider mPopupDataProvider;
+ private final boolean mSharingEnabledForUser;
+
+ public Share(Launcher target, ItemInfo itemInfo, View originalView) {
+ super(R.drawable.ic_share, R.string.app_share_drop_target_label, target, itemInfo,
+ originalView);
+ mPopupDataProvider = target.getPopupDataProvider();
+
+ mSharingEnabledForUser = bluetoothSharingEnabled(target);
+ if (!mSharingEnabledForUser) {
+ setEnabled(false);
+ } else if (ENABLE_SHAREABILITY_CHECK) {
+ mShareabilityMgr =
+ AppShareabilityManager.INSTANCE.get(target.getApplicationContext());
+ checkShareability(/* requestUpdateIfUnknown */ true);
+ }
}
@Override
public void onClick(View view) {
+ ActivityContext.lookupContext(view.getContext())
+ .getStatsLogManager().logger().log(LAUNCHER_SYSTEM_SHORTCUT_APP_SHARE_TAP);
+ if (!isEnabled()) {
+ showCannotShareToast(view.getContext());
+ return;
+ }
+
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
@@ -118,15 +159,60 @@
sendIntent.setType(APP_MIME_TYPE);
sendIntent.setComponent(ComponentName.unflattenFromString(mSharingComponent));
- mTarget.startActivitySafely(view, sendIntent, mItemInfo);
+ UserHandle user = mItemInfo.user;
+ if (user != null && !user.equals(Process.myUserHandle())) {
+ mTarget.startActivityAsUser(sendIntent, user);
+ } else {
+ mTarget.startActivitySafely(view, sendIntent, mItemInfo);
+ }
AbstractFloatingView.closeAllOpenViews(mTarget);
}
+
+ private void onStatusUpdated(boolean success) {
+ if (!success) {
+ // Something went wrong. Specific error logged in AppShareabilityManager.
+ return;
+ }
+ checkShareability(/* requestUpdateIfUnknown */ false);
+ mTarget.runOnUiThread(() -> {
+ mPopupDataProvider.redrawSystemShortcuts();
+ });
+ }
+
+ private void checkShareability(boolean requestUpdateIfUnknown) {
+ String packageName = mItemInfo.getTargetComponent().getPackageName();
+ @ShareabilityStatus int status = mShareabilityMgr.getStatus(packageName);
+ setEnabled(status == ShareabilityStatus.SHAREABLE);
+
+ if (requestUpdateIfUnknown && status == ShareabilityStatus.UNKNOWN) {
+ mShareabilityMgr.requestAppStatusUpdate(packageName, this::onStatusUpdated);
+ }
+ }
+
+ private boolean bluetoothSharingEnabled(Context context) {
+ return !context.getSystemService(UserManager.class)
+ .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH_SHARING, mItemInfo.user);
+ }
+
+ private void showCannotShareToast(Context context) {
+ ActivityContext activityContext = ActivityContext.lookupContext(context);
+ String blockedByMessage = activityContext.getStringCache() != null
+ ? activityContext.getStringCache().disabledByAdminMessage
+ : context.getString(R.string.blocked_by_policy);
+
+ CharSequence text = (mSharingEnabledForUser)
+ ? context.getText(R.string.toast_p2p_app_not_shareable)
+ : blockedByMessage;
+ int duration = Toast.LENGTH_SHORT;
+ Toast.makeText(context, text, duration).show();
+ }
}
/**
* Shortcut factory for generating the Share App button
*/
- public static final SystemShortcut.Factory<Launcher> SHORTCUT_FACTORY = (launcher, itemInfo) ->
- (new AppSharing(launcher)).getShortcut(launcher, itemInfo);
+ public static final SystemShortcut.Factory<Launcher> SHORTCUT_FACTORY =
+ (launcher, itemInfo, originalView) ->
+ (new AppSharing(launcher)).getShortcut(launcher, itemInfo, originalView);
}
diff --git a/go/quickstep/src/com/android/launcher3/model/AppShareabilityChecker.java b/go/quickstep/src/com/android/launcher3/model/AppShareabilityChecker.java
new file mode 100644
index 0000000..0a82904
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/model/AppShareabilityChecker.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.model;
+
+import androidx.annotation.Nullable;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * Interface for checking apps' shareability. Implementations need to be able to determine whether
+ * apps are shareable given their package names.
+ */
+public interface AppShareabilityChecker {
+ /**
+ * Checks the shareability of the provided apps. Once the check is complete, updates the
+ * provided manager with the results and calls the (optionally) provided callback.
+ * @param packageNames The apps to check
+ * @param shareMgr The manager to receive the results
+ * @param callback Optional callback to be invoked when the check is finished
+ */
+ void checkApps(List<String> packageNames, AppShareabilityManager shareMgr,
+ @Nullable Consumer<Boolean> callback);
+}
diff --git a/go/quickstep/src/com/android/launcher3/model/AppShareabilityDatabase.java b/go/quickstep/src/com/android/launcher3/model/AppShareabilityDatabase.java
new file mode 100644
index 0000000..03eed7e
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/model/AppShareabilityDatabase.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.model;
+
+import androidx.room.Dao;
+import androidx.room.Database;
+import androidx.room.Insert;
+import androidx.room.OnConflictStrategy;
+import androidx.room.Query;
+import androidx.room.RoomDatabase;
+import androidx.room.Update;
+
+import java.util.List;
+
+/**
+ * This database maintains a collection of AppShareabilityStatus items
+ * In its intended use case, there will be one entry for each app installed on the device
+ */
+@Database(entities = {AppShareabilityStatus.class}, exportSchema = false, version = 1)
+public abstract class AppShareabilityDatabase extends RoomDatabase {
+ /**
+ * Data Access Object for this database
+ */
+ @Dao
+ public interface ShareabilityDao {
+ /** Add an AppShareabilityStatus to the database */
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ void insertAppStatus(AppShareabilityStatus status);
+
+ /** Add a collection of AppShareabilityStatus objects to the database */
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ void insertAppStatuses(AppShareabilityStatus... statuses);
+
+ /**
+ * Update an AppShareabilityStatus in the database
+ * @return The number of entries successfully updated
+ */
+ @Update
+ int updateAppStatus(AppShareabilityStatus status);
+
+ /** Retrieve all entries from the database */
+ @Query("SELECT * FROM AppShareabilityStatus")
+ List<AppShareabilityStatus> getAllEntries();
+ }
+
+ protected abstract ShareabilityDao shareabilityDao();
+}
diff --git a/go/quickstep/src/com/android/launcher3/model/AppShareabilityJobService.java b/go/quickstep/src/com/android/launcher3/model/AppShareabilityJobService.java
new file mode 100644
index 0000000..60bea53
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/model/AppShareabilityJobService.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.model;
+
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.content.ComponentName;
+import android.content.Context;
+import android.util.Log;
+
+import com.android.launcher3.R;
+
+/**
+ * A job to request AppShareabilityManager to update its shareability data
+ * The shareability status of an app is not expected to change often, so this job is only
+ * run periodically.
+ */
+public final class AppShareabilityJobService extends JobService {
+
+ private static final String TAG = "AppShareabilityJobService";
+ // Run this job once a week
+ private static final int RECURRENCE_INTERVAL_MILLIS = 604800000;
+
+ @Override
+ public boolean onStartJob(final JobParameters params) {
+ Context context = getApplicationContext();
+ AppShareabilityManager.INSTANCE.get(context).requestFullUpdate();
+ return false; // Job is finished
+ }
+
+ @Override
+ public boolean onStopJob(final JobParameters params) {
+ Log.d(TAG, "App shareability data update job stopped; id=" + params.getJobId()
+ + ", reason="
+ + JobParameters.getInternalReasonCodeDescription(params.getStopReason()));
+ return true; // Reschedule the job
+ }
+
+ /**
+ * Creates and schedules the job.
+ * Does not schedule a duplicate job if one is already pending.
+ * @param context The application context
+ */
+ public static void schedule(Context context) {
+ final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
+
+ final JobInfo pendingJob = jobScheduler.getPendingJob(R.integer.app_shareability_job_id);
+ if (pendingJob != null) {
+ // Don't schedule duplicate jobs
+ return;
+ }
+
+ final JobInfo newJob = new JobInfo.Builder(R.integer.app_shareability_job_id,
+ new ComponentName(context, AppShareabilityJobService.class))
+ .setPeriodic(RECURRENCE_INTERVAL_MILLIS)
+ .setPersisted(true)
+ .setRequiresBatteryNotLow(true)
+ .build();
+ jobScheduler.schedule(newJob);
+ }
+}
diff --git a/go/quickstep/src/com/android/launcher3/model/AppShareabilityManager.java b/go/quickstep/src/com/android/launcher3/model/AppShareabilityManager.java
new file mode 100644
index 0000000..0d0f700
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/model/AppShareabilityManager.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.model;
+
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.content.Context;
+import android.content.pm.LauncherActivityInfo;
+import android.content.pm.LauncherApps;
+import android.os.Process;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
+import androidx.room.Room;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.launcher3.model.AppShareabilityDatabase.ShareabilityDao;
+import com.android.launcher3.util.MainThreadInitializedObject;
+
+import java.lang.annotation.Retention;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+
+/**
+ * This class maintains the shareability status of installed apps.
+ * Each app's status is retrieved from the Play Store's API. Statuses are cached in order
+ * to limit extraneous calls to that API (which can be time-consuming).
+ */
+public class AppShareabilityManager {
+ @Retention(SOURCE)
+ @IntDef({
+ ShareabilityStatus.UNKNOWN,
+ ShareabilityStatus.NOT_SHAREABLE,
+ ShareabilityStatus.SHAREABLE
+ })
+ public @interface ShareabilityStatus {
+ int UNKNOWN = 0;
+ int NOT_SHAREABLE = 1;
+ int SHAREABLE = 2;
+ }
+
+ private static final String TAG = "AppShareabilityManager";
+ private static final String DB_NAME = "shareabilityDatabase";
+ public static MainThreadInitializedObject<AppShareabilityManager> INSTANCE =
+ new MainThreadInitializedObject<>(AppShareabilityManager::new);
+
+ private final Context mContext;
+ // Local map to store the data in memory for quick access
+ private final Map<String, Integer> mDataMap;
+ // Database to persist the data across reboots
+ private AppShareabilityDatabase mDatabase;
+ // Data Access Object for the database
+ private ShareabilityDao mDao;
+ // Class to perform shareability checks
+ private AppShareabilityChecker mShareChecker;
+
+ private AppShareabilityManager(Context context) {
+ mContext = context;
+ mDataMap = new ArrayMap<>();
+ mDatabase = Room.databaseBuilder(mContext, AppShareabilityDatabase.class, DB_NAME).build();
+ mDao = mDatabase.shareabilityDao();
+ MODEL_EXECUTOR.post(this::readFromDB);
+ }
+
+ /**
+ * Set the shareability checker. The checker determines whether given apps are shareable.
+ * This must be set before the manager can update its data.
+ * @param checker Implementation of AppShareabilityChecker to perform the checks
+ */
+ public void setShareabilityChecker(AppShareabilityChecker checker) {
+ mShareChecker = checker;
+ }
+
+ /**
+ * Retrieve the ShareabilityStatus of an app from the local map
+ * This does not interact with the saved database
+ * @param packageName The app's package name
+ * @return The status as a ShareabilityStatus integer
+ */
+ public synchronized @ShareabilityStatus int getStatus(String packageName) {
+ @ShareabilityStatus int status = ShareabilityStatus.UNKNOWN;
+ if (mDataMap.containsKey(packageName)) {
+ status = mDataMap.get(packageName);
+ }
+ return status;
+ }
+
+ /**
+ * Set the status of a given app. This updates the local map as well as the saved database.
+ */
+ public synchronized void setStatus(String packageName, @ShareabilityStatus int status) {
+ mDataMap.put(packageName, status);
+
+ // Write to the database on a separate thread
+ MODEL_EXECUTOR.post(() ->
+ mDao.insertAppStatus(new AppShareabilityStatus(packageName, status)));
+ }
+
+ /**
+ * Set the statuses of given apps. This updates the local map as well as the saved database.
+ */
+ public synchronized void setStatuses(List<AppShareabilityStatus> statuses) {
+ for (int i = 0, size = statuses.size(); i < size; i++) {
+ AppShareabilityStatus entry = statuses.get(i);
+ mDataMap.put(entry.packageName, entry.status);
+ }
+
+ // Write to the database on a separate thread
+ MODEL_EXECUTOR.post(() ->
+ mDao.insertAppStatuses(statuses.toArray(new AppShareabilityStatus[0])));
+ }
+
+ /**
+ * Request a status update for a specific app
+ * @param packageName The app's package name
+ * @param callback Optional callback to be called when the update is complete. The received
+ * Boolean denotes whether the update was successful.
+ */
+ public void requestAppStatusUpdate(String packageName, @Nullable Consumer<Boolean> callback) {
+ MODEL_EXECUTOR.post(() -> updateCache(packageName, callback));
+ }
+
+ /**
+ * Request a status update for all apps
+ */
+ public void requestFullUpdate() {
+ MODEL_EXECUTOR.post(this::updateCache);
+ }
+
+ /**
+ * Update the cached shareability data for all installed apps
+ */
+ @WorkerThread
+ private void updateCache() {
+ updateCache(/* packageName */ null, /* callback */ null);
+ }
+
+ /**
+ * Update the cached shareability data
+ * @param packageName A specific package to update. If null, all installed apps will be updated.
+ * @param callback Optional callback to be called when the update is complete. The received
+ * Boolean denotes whether the update was successful.
+ */
+ @WorkerThread
+ private void updateCache(@Nullable String packageName, @Nullable Consumer<Boolean> callback) {
+ if (mShareChecker == null) {
+ Log.e(TAG, "AppShareabilityChecker not set");
+ return;
+ }
+
+ List<String> packageNames = new ArrayList<>();
+ if (packageName != null) {
+ packageNames.add(packageName);
+ } else {
+ LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class);
+ List<LauncherActivityInfo> installedApps =
+ launcherApps.getActivityList(/* packageName */ null, Process.myUserHandle());
+ for (int i = 0, size = installedApps.size(); i < size; i++) {
+ packageNames.add(installedApps.get(i).getApplicationInfo().packageName);
+ }
+ }
+
+ mShareChecker.checkApps(packageNames, this, callback);
+ }
+
+ @WorkerThread
+ private synchronized void readFromDB() {
+ mDataMap.clear();
+ List<AppShareabilityStatus> entries = mDao.getAllEntries();
+ for (int i = 0, size = entries.size(); i < size; i++) {
+ AppShareabilityStatus entry = entries.get(i);
+ mDataMap.put(entry.packageName, entry.status);
+ }
+ }
+
+ /**
+ * Provides a testable instance of this class
+ * This instance allows database queries on the main thread
+ * @hide */
+ @VisibleForTesting
+ public static AppShareabilityManager getTestInstance(Context context) {
+ AppShareabilityManager manager = new AppShareabilityManager(context);
+ manager.mDatabase.close();
+ manager.mDatabase = Room.inMemoryDatabaseBuilder(context, AppShareabilityDatabase.class)
+ .allowMainThreadQueries()
+ .build();
+ manager.mDao = manager.mDatabase.shareabilityDao();
+ return manager;
+ }
+}
diff --git a/go/quickstep/src/com/android/launcher3/model/AppShareabilityStatus.java b/go/quickstep/src/com/android/launcher3/model/AppShareabilityStatus.java
new file mode 100644
index 0000000..61018c6
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/model/AppShareabilityStatus.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.model;
+
+import androidx.annotation.NonNull;
+import androidx.room.Entity;
+import androidx.room.PrimaryKey;
+
+import com.android.launcher3.model.AppShareabilityManager.ShareabilityStatus;
+
+/**
+ * Database entry to hold the shareability status of a single app
+ */
+@Entity
+public class AppShareabilityStatus {
+ @PrimaryKey
+ @NonNull
+ public String packageName;
+
+ public @ShareabilityStatus int status;
+
+ public AppShareabilityStatus(@NonNull String packageName, @ShareabilityStatus int status) {
+ this.packageName = packageName;
+ this.status = status;
+ }
+}
diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
index 91cab3c..c997e52 100644
--- a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
+++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
@@ -50,9 +50,9 @@
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.BaseActivity;
-import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.views.ArrowTipView;
import com.android.quickstep.util.AssistContentRequester;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.views.GoOverviewActionsView;
@@ -75,7 +75,7 @@
public static final String ACTIONS_ERROR_CODE = "niu_actions_app_error_code";
public static final int ERROR_PERMISSIONS_STRUCTURE = 1;
public static final int ERROR_PERMISSIONS_SCREENSHOT = 2;
- private static final String NIU_ACTIONS_CONFIRMED = "launcher_go.niu_actions_confirmed";
+ public static final String NIU_ACTIONS_CONFIRMED = "launcher_go.niu_actions_confirmed";
private static final String ASSIST_SETTINGS_ARGS_BUNDLE = ":settings:show_fragment_args";
private static final String ASSIST_SETTINGS_ARGS_KEY = ":settings:fragment_args_key";
private static final String ASSIST_SETTINGS_PREFERENCE_KEY = "default_assist";
@@ -86,10 +86,11 @@
@Retention(SOURCE)
@IntDef({PRIVACY_CONFIRMATION, ASSISTANT_NOT_SELECTED, ASSISTANT_NOT_SUPPORTED})
- private @interface DialogType{}
- private static final int PRIVACY_CONFIRMATION = 0;
- private static final int ASSISTANT_NOT_SELECTED = 1;
- private static final int ASSISTANT_NOT_SUPPORTED = 2;
+ @VisibleForTesting
+ public @interface DialogType{}
+ public static final int PRIVACY_CONFIRMATION = 0;
+ public static final int ASSISTANT_NOT_SELECTED = 1;
+ public static final int ASSISTANT_NOT_SUPPORTED = 2;
private AssistContentRequester mContentRequester;
@@ -117,6 +118,7 @@
private AssistContentRequester mFactoryContentRequester;
private SharedPreferences mSharedPreferences;
private OverlayDialogGo mDialog;
+ private ArrowTipView mArrowTipView;
private TaskOverlayGo(TaskThumbnailView taskThumbnailView,
AssistContentRequester assistContentRequester) {
@@ -184,6 +186,9 @@
public void reset() {
super.reset();
mWebUrl = null;
+ if (mDialog != null && mDialog.isShowing()) {
+ mDialog.dismiss();
+ }
}
@Override
@@ -209,7 +214,8 @@
Intent intent = createNIUIntent(actionType);
// Only add and send the image if the appropriate permissions are held
if (mAssistStructurePermitted && mAssistScreenshotPermitted) {
- mImageApi.shareAsDataWithExplicitIntent(/* crop */ null, intent);
+ mImageApi.shareAsDataWithExplicitIntent(/* crop */ null, intent,
+ () -> showDialog(actionType, ASSISTANT_NOT_SUPPORTED));
} else {
// If both permissions are disabled, the structure error code takes priority
// The user must enable that one before they can enable screenshots
@@ -253,7 +259,11 @@
String assistantPackage =
Settings.Secure.getString(contentResolver, Settings.Secure.ASSISTANT);
- mNIUPackageName = assistantPackage.split("/", 2)[0];
+ if (!TextUtils.isEmpty(assistantPackage)) {
+ mNIUPackageName = assistantPackage.split("/", 2)[0];
+ } else {
+ mNIUPackageName = "";
+ }
}
protected class OverlayUICallbacksGoImpl extends OverlayUICallbacksImpl
@@ -295,7 +305,6 @@
mImageApi = imageActionsApi;
}
- // TODO (b/192406446): Test that these dialogs are shown at the appropriate times
private void showDialog(String action, @DialogType int type) {
switch (type) {
case PRIVACY_CONFIRMATION:
@@ -328,7 +337,7 @@
int bodyTextID, int button1TextID,
View.OnClickListener button1Callback, int button2TextID,
View.OnClickListener button2Callback) {
- BaseDraggingActivity activity = BaseActivity.fromContext(getActionsView().getContext());
+ BaseActivity activity = BaseActivity.fromContext(getActionsView().getContext());
LayoutInflater inflater = LayoutInflater.from(activity);
View view = inflater.inflate(R.layout.niu_actions_dialog, /* root */ null);
@@ -362,6 +371,11 @@
mDialog.cancel();
}
+ @VisibleForTesting
+ public OverlayDialogGo getDialog() {
+ return mDialog;
+ }
+
private void onDialogClickSettings(View v) {
mDialog.dismiss();
@@ -382,17 +396,24 @@
* Order of tooltips are translate and then listen
*/
private void showTooltipsIfUnseen() {
+ if (mArrowTipView != null && mArrowTipView.isOpen()) {
+ return;
+ }
if (!mSharedPreferences.getBoolean(TRANSLATE_TOOL_TIP_SEEN, false)) {
- ((GoOverviewActionsView) getActionsView()).showTranslateToolTip();
+ mArrowTipView = ((GoOverviewActionsView) getActionsView()).showTranslateToolTip();
mSharedPreferences.edit().putBoolean(TRANSLATE_TOOL_TIP_SEEN, true).apply();
} else if (!mSharedPreferences.getBoolean(LISTEN_TOOL_TIP_SEEN, false)) {
- ((GoOverviewActionsView) getActionsView()).showListenToolTip();
+ mArrowTipView = ((GoOverviewActionsView) getActionsView()).showListenToolTip();
mSharedPreferences.edit().putBoolean(LISTEN_TOOL_TIP_SEEN, true).apply();
}
}
}
- private static final class OverlayDialogGo extends AlertDialog {
+ /**
+ * Basic modal dialog for various user prompts
+ */
+ @VisibleForTesting
+ public static final class OverlayDialogGo extends AlertDialog {
private final String mAction;
private final @DialogType int mType;
diff --git a/go/quickstep/src/com/android/quickstep/views/GoOverviewActionsView.java b/go/quickstep/src/com/android/quickstep/views/GoOverviewActionsView.java
index d4eca2f..4e0aec3 100644
--- a/go/quickstep/src/com/android/quickstep/views/GoOverviewActionsView.java
+++ b/go/quickstep/src/com/android/quickstep/views/GoOverviewActionsView.java
@@ -85,31 +85,33 @@
/**
* Shows Tooltip for action icons
*/
- private void showToolTip(int viewId, int textResourceId) {
+ private ArrowTipView showToolTip(int viewId, int textResourceId) {
int[] location = new int[2];
@Px int topMargin = getResources().getDimensionPixelSize(R.dimen.tooltip_top_margin);
findViewById(viewId).getLocationOnScreen(location);
mArrowTipView = new ArrowTipView(getContext(), /* isPointingUp= */ false)
.showAtLocation(getResources().getString(textResourceId),
/* arrowXCoord= */ location[0] + findViewById(viewId).getWidth() / 2,
- /* yCoord= */ location[1] - topMargin);
+ /* yCoord= */ location[1] - topMargin,
+ /* shouldAutoClose= */ false);
mArrowTipView.bringToFront();
+ return mArrowTipView;
}
/**
* Shows Tooltip for listen action icon
*/
- public void showListenToolTip() {
- showToolTip(/* viewId= */ R.id.action_listen,
+ public ArrowTipView showListenToolTip() {
+ return showToolTip(/* viewId= */ R.id.action_listen,
/* textResourceId= */ R.string.tooltip_listen);
}
/**
* Shows Tooltip for translate action icon
*/
- public void showTranslateToolTip() {
- showToolTip(/* viewId= */ R.id.action_translate,
+ public ArrowTipView showTranslateToolTip() {
+ return showToolTip(/* viewId= */ R.id.action_translate,
/* textResourceId= */ R.string.tooltip_translate);
}
diff --git a/go/res/xml/device_profiles.xml b/go/res/xml/device_profiles.xml
index 0c7eba3..7c3a160 100644
--- a/go/res/xml/device_profiles.xml
+++ b/go/res/xml/device_profiles.xml
@@ -33,6 +33,8 @@
launcher:minHeightDps="491.33"
launcher:iconImageSize="60"
launcher:iconTextSize="14.0"
+ launcher:allAppsBorderSpace="16"
+ launcher:allAppsCellHeight="104"
launcher:canBeDefault="true" />
</grid-option>
diff --git a/go/src/com/android/launcher3/util/AbsGridOccupancy.java b/go/src/com/android/launcher3/util/AbsGridOccupancy.java
new file mode 100644
index 0000000..4a46bd1
--- /dev/null
+++ b/go/src/com/android/launcher3/util/AbsGridOccupancy.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+/**
+ * Defines method to find the next vacant cell on a grid.
+ * This uses the default top-down, left-right approach and can be over-written through
+ * code swaps in different launchers.
+ */
+public abstract class AbsGridOccupancy {
+
+ /**
+ * Find the first vacant cell, if there is one.
+ *
+ * @param vacantOut Holds the x and y coordinate of the vacant cell
+ * @param spanX Horizontal cell span.
+ * @param spanY Vertical cell span.
+ *
+ * @return true if a vacant cell was found
+ */
+ protected boolean findVacantCell(int[] vacantOut, boolean[][] cells, int countX, int countY,
+ int spanX, int spanY) {
+ for (int y = 0; (y + spanY) <= countY; y++) {
+ for (int x = 0; (x + spanX) <= countX; x++) {
+ boolean available = !cells[x][y];
+ out:
+ for (int i = x; i < x + spanX; i++) {
+ for (int j = y; j < y + spanY; j++) {
+ available = available && !cells[i][j];
+ if (!available) break out;
+ }
+ }
+ if (available) {
+ vacantOut[0] = x;
+ vacantOut[1] = y;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/lint-baseline-launcher3.xml b/lint-baseline-launcher3.xml
index 94345a6..107a346 100644
--- a/lint-baseline-launcher3.xml
+++ b/lint-baseline-launcher3.xml
@@ -3,6 +3,17 @@
<issue
id="NewApi"
+ message="Call requires API level 28 (current min is 26): `android.os.UserManager#requestQuietModeEnabled`"
+ errorLine1=" showConfirm |= !userManager.requestQuietModeEnabled(!toState, userProfile);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/apps/Launcher3/src/com/android/launcher3/allapps/WorkModeSwitch.java"
+ line="110"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="NewApi"
message="Call requires API level R (current min is 26): `android.view.View#getWindowInsetsController`"
errorLine1=" getWindowInsetsController().hide(WindowInsets.Type.ime());"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index c559988..10eedc8 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -23,6 +23,8 @@
//
// ItemInfos
message ItemInfo {
+ reserved 8;
+
oneof Item {
Application application = 1;
Task task = 2;
@@ -42,7 +44,14 @@
optional ContainerInfo container_info = 7;
// Stores the origin of the Item
- optional Attribute attribute = 8;
+ repeated Attribute item_attributes = 12;
+}
+
+message LauncherAttributes{
+
+ // Integer value of item attribute enum
+ // (e.g. SUGGESTED_LABEL, ALL_APPS_SEARCH_RESULT_SETTING etc)
+ repeated int32 item_attributes = 1;
}
// Represents various launcher surface where items are placed.
@@ -67,6 +76,9 @@
// Represents the apps list sorted alphabetically inside the all-apps view.
message AllAppsContainer {
+ oneof ParentContainer {
+ TaskBarContainer taskbar_container = 1;
+ }
}
message WidgetsContainer {
@@ -74,6 +86,9 @@
// Represents the predicted apps row(top row) in the all-apps view.
message PredictionContainer {
+ oneof ParentContainer {
+ TaskBarContainer taskbar_container = 1;
+ }
}
// Represents the apps container within search results.
@@ -112,6 +127,7 @@
optional int32 cardinality = 2;
}
+// Next value 40
enum Attribute {
UNKNOWN = 0;
DEFAULT_LAYOUT = 1; // icon automatically placed in workspace, folder, hotseat
@@ -156,6 +172,18 @@
ALL_APPS_SEARCH_RESULT_LEGACY_SHORTCUT = 30;
ALL_APPS_SEARCH_RESULT_ASSISTANT_MEMORY = 31;
+ // Web suggestions provided by AGA
+ ALL_APPS_SEARCH_RESULT_WEB_SUGGEST = 39;
+
+ // Suggestion Type provided by AGA
+ WEB_SEARCH_RESULT_QUERY = 32;
+ WEB_SEARCH_RESULT_TRENDING = 33;
+ WEB_SEARCH_RESULT_ENTITY = 34;
+ WEB_SEARCH_RESULT_ANSWER = 35;
+ WEB_SEARCH_RESULT_PERSONAL = 36;
+ WEB_SEARCH_RESULT_CALCULATOR = 37;
+ WEB_SEARCH_RESULT_URL = 38;
+
WIDGETS_BOTTOM_TRAY = 28;
WIDGETS_TRAY_PREDICTION = 29;
}
diff --git a/quickstep/Android.bp b/quickstep/Android.bp
index 7b3e6c4..70b1438 100644
--- a/quickstep/Android.bp
+++ b/quickstep/Android.bp
@@ -14,11 +14,7 @@
package {
// See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "packages_apps_Launcher3_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["packages_apps_Launcher3_license"],
+ default_applicable_licenses: ["Android-Apache-2.0"],
}
filegroup {
diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml
index 53910e3..7d7054f 100644
--- a/quickstep/AndroidManifest-launcher.xml
+++ b/quickstep/AndroidManifest-launcher.xml
@@ -20,7 +20,7 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher3">
- <uses-sdk android:targetSdkVersion="29" android:minSdkVersion="25"/>
+ <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.
@@ -57,6 +57,7 @@
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
+ <action android:name="android.intent.action.SHOW_WORK_APPS" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY"/>
diff --git a/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java b/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java
new file mode 100644
index 0000000..e5f0295
--- /dev/null
+++ b/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.BaseQuickstepLauncher;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.taskbar.LauncherTaskbarUIController;
+import com.android.launcher3.testing.DebugTestInformationHandler;
+import com.android.launcher3.testing.TestProtocol;
+
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Class to handle requests from tests, including debug ones, to Quickstep Launcher builds.
+ */
+public abstract class DebugQuickstepTestInformationHandler extends QuickstepTestInformationHandler {
+
+ private final DebugTestInformationHandler mDebugTestInformationHandler;
+
+ public DebugQuickstepTestInformationHandler(Context context) {
+ super(context);
+ mDebugTestInformationHandler = new DebugTestInformationHandler(context);
+ }
+
+ @Override
+ public Bundle call(String method, String arg, @Nullable Bundle extras) {
+ Bundle response = new Bundle();
+ switch (method) {
+ case TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING:
+ runOnUIThread(l -> {
+ enableManualTaskbarStashing(l, true);
+ });
+ return response;
+
+ case TestProtocol.REQUEST_DISABLE_MANUAL_TASKBAR_STASHING:
+ runOnUIThread(l -> {
+ enableManualTaskbarStashing(l, false);
+ });
+ return response;
+
+ case TestProtocol.REQUEST_UNSTASH_TASKBAR_IF_STASHED:
+ runOnUIThread(l -> {
+ enableManualTaskbarStashing(l, true);
+
+ BaseQuickstepLauncher quickstepLauncher = (BaseQuickstepLauncher) l;
+ LauncherTaskbarUIController taskbarUIController =
+ quickstepLauncher.getTaskbarUIController();
+
+ // Allow null-pointer to catch illegal states.
+ taskbarUIController.unstashTaskbarIfStashed();
+
+ enableManualTaskbarStashing(l, false);
+ });
+ return response;
+
+ case TestProtocol.REQUEST_STASHED_TASKBAR_HEIGHT: {
+ final Resources resources = mContext.getResources();
+ response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD,
+ resources.getDimensionPixelSize(R.dimen.taskbar_stashed_size));
+ return response;
+ }
+
+ default:
+ response = super.call(method, arg, extras);
+ if (response != null) return response;
+ return mDebugTestInformationHandler.call(method, arg, extras);
+ }
+ }
+
+ private void enableManualTaskbarStashing(Launcher launcher, boolean enable) {
+ BaseQuickstepLauncher quickstepLauncher = (BaseQuickstepLauncher) launcher;
+ LauncherTaskbarUIController taskbarUIController =
+ quickstepLauncher.getTaskbarUIController();
+
+ // Allow null-pointer to catch illegal states.
+ taskbarUIController.enableManualStashingForTests(enable);
+ }
+
+ /**
+ * Runs the given command on the UI thread.
+ */
+ private static void runOnUIThread(UIThreadCommand command) {
+ try {
+ MAIN_EXECUTOR.submit(() -> {
+ command.execute(Launcher.ACTIVITY_TRACKER.getCreatedActivity());
+ return null;
+ }).get();
+ } catch (ExecutionException | InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private interface UIThreadCommand {
+
+ void execute(Launcher launcher);
+ }
+}
+
diff --git a/quickstep/protos_overrides/launcher_atom_extension.proto b/quickstep/protos_overrides/launcher_atom_extension.proto
index d2dc0cb..f5a277b 100644
--- a/quickstep/protos_overrides/launcher_atom_extension.proto
+++ b/quickstep/protos_overrides/launcher_atom_extension.proto
@@ -22,21 +22,45 @@
// Wrapper message for containers used at the quickstep level.
// Message name should match with launcher_atom_extension.proto message at
// the AOSP level.
+// Next ID = 3
message ExtendedContainers {
+ reserved 2; // Deleted fields
oneof Container{
DeviceSearchResultContainer device_search_result_container = 1;
- CorrectedDeviceSearchResultContainer corrected_device_search_result_container = 2;
}
}
// Represents on-device search result container.
+// Next ID = 4
message DeviceSearchResultContainer{
optional int32 query_length = 1;
-}
+ optional SearchAttributes search_attributes = 2;
+ // [0, m], m varies based on the display density and resolution
+ // To indicate the location of the tapped on-device search result.
+ // For application, it will be the column number in the apps row.
+ optional int32 grid_x = 3;
-// Represents on-device search result container with results from spell-corrected query.
-message CorrectedDeviceSearchResultContainer{
- optional int32 query_length = 1;
-}
+ // Next ID = 4
+ message SearchAttributes{
+ // True if results are based on spell corrected query
+ optional bool corrected_query = 1;
+
+ // True if the item's title/content is a direct match to the search query, false otherwise.
+ optional bool direct_match = 2;
+
+ // Entry point for this on-device search session
+ optional EntryState entry_state = 3;
+
+ enum EntryState{
+ ENTRY_STATE_UNKNOWN = 0;
+
+ // User entered using swipe-up gesture from homescreen and searchbox in AllApps drawer.
+ ALL_APPS = 1;
+
+ // User entered by tapping on QSB bar on homescreen.
+ QSB = 2;
+ }
+ }
+}
diff --git a/quickstep/res/drawable-v28/gesture_tutorial_action_button_background.xml b/quickstep/res/drawable-v28/gesture_tutorial_action_button_background.xml
index 57423c2..710482f 100644
--- a/quickstep/res/drawable-v28/gesture_tutorial_action_button_background.xml
+++ b/quickstep/res/drawable-v28/gesture_tutorial_action_button_background.xml
@@ -16,5 +16,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="?android:attr/dialogCornerRadius"/>
- <solid android:color="@color/gesture_tutorial_primary_color"/>
+ <solid android:color="?android:attr/colorAccent"/>
</shape>
\ No newline at end of file
diff --git a/quickstep/res/drawable/bg_sandbox_feedback.xml b/quickstep/res/drawable/bg_sandbox_feedback.xml
index 83a3dea..83d7e43 100644
--- a/quickstep/res/drawable/bg_sandbox_feedback.xml
+++ b/quickstep/res/drawable/bg_sandbox_feedback.xml
@@ -14,7 +14,8 @@
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="28dp"/>
- <solid android:color="?android:attr/colorBackgroundFloating"/>
+ <solid android:color="?androidprv:attr/colorSurface"/>
</shape>
diff --git a/quickstep/res/drawable/gesture_tutorial_action_button_background.xml b/quickstep/res/drawable/gesture_tutorial_action_button_background.xml
index ac6a52a..98dc1a5 100644
--- a/quickstep/res/drawable/gesture_tutorial_action_button_background.xml
+++ b/quickstep/res/drawable/gesture_tutorial_action_button_background.xml
@@ -25,7 +25,7 @@
<shape
android:shape="rectangle">
<corners android:radius="50dp"/>
- <solid android:color="@color/gesture_tutorial_primary_color"/>
+ <solid android:color="?android:attr/colorAccent"/>
</shape>
</item>
</layer-list>
\ No newline at end of file
diff --git a/quickstep/res/drawable/gesture_tutorial_cancel_button_background.xml b/quickstep/res/drawable/gesture_tutorial_cancel_button_background.xml
index 0a34af6..7762615 100644
--- a/quickstep/res/drawable/gesture_tutorial_cancel_button_background.xml
+++ b/quickstep/res/drawable/gesture_tutorial_cancel_button_background.xml
@@ -17,5 +17,5 @@
android:shape="rectangle">
<corners android:radius="50dp"/>
<solid android:color="@android:color/transparent"/>
- <stroke android:width="1dp" android:color="@color/gesture_tutorial_primary_color"/>
+ <stroke android:width="1dp" android:color="?android:attr/colorAccent"/>
</shape>
\ No newline at end of file
diff --git a/quickstep/res/drawable/gesture_tutorial_finger_dot.xml b/quickstep/res/drawable/gesture_tutorial_finger_dot.xml
index 5f8aafd..cbb2612 100644
--- a/quickstep/res/drawable/gesture_tutorial_finger_dot.xml
+++ b/quickstep/res/drawable/gesture_tutorial_finger_dot.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
- <solid android:color="@color/gesture_tutorial_primary_color" />
+ <solid android:color="?android:attr/colorAccent" />
<size android:width="92dp" android:height="92dp"/>
</shape>
\ No newline at end of file
diff --git a/quickstep/res/drawable/gesture_tutorial_loop_back.xml b/quickstep/res/drawable/gesture_tutorial_loop_back.xml
index d2909ff..ae47709 100644
--- a/quickstep/res/drawable/gesture_tutorial_loop_back.xml
+++ b/quickstep/res/drawable/gesture_tutorial_loop_back.xml
@@ -85,7 +85,7 @@
<path
android:name="_R_G_L_0_G_D_0_P_0"
android:fillAlpha="0.25"
- android:fillColor="@color/gesture_tutorial_primary_color"
+ android:fillColor="?android:attr/colorAccent"
android:fillType="nonZero"
android:pathData=" M12.5 -446 C12.5,-446 12.5,446 12.5,446 C12.5,446 -12.5,446 -12.5,446 C-12.5,446 -12.5,-446 -12.5,-446 C-12.5,-446 12.5,-446 12.5,-446c " />
</group>
diff --git a/quickstep/res/drawable/gesture_tutorial_loop_home.xml b/quickstep/res/drawable/gesture_tutorial_loop_home.xml
index 931f8c0..bed35dd 100644
--- a/quickstep/res/drawable/gesture_tutorial_loop_home.xml
+++ b/quickstep/res/drawable/gesture_tutorial_loop_home.xml
@@ -81,7 +81,7 @@
<path
android:name="_R_G_L_1_G_D_0_P_0"
android:fillAlpha="0.25"
- android:fillColor="@color/gesture_tutorial_primary_color"
+ android:fillColor="?android:attr/colorAccent"
android:fillType="nonZero"
android:pathData=" M206 -12.5 C206,-12.5 206,12.5 206,12.5 C206,12.5 -206,12.5 -206,12.5 C-206,12.5 -206,-12.5 -206,-12.5 C-206,-12.5 206,-12.5 206,-12.5c " />
</group>
diff --git a/quickstep/res/drawable/gesture_tutorial_loop_overview.xml b/quickstep/res/drawable/gesture_tutorial_loop_overview.xml
index a4c532b..53e8b5f 100644
--- a/quickstep/res/drawable/gesture_tutorial_loop_overview.xml
+++ b/quickstep/res/drawable/gesture_tutorial_loop_overview.xml
@@ -81,7 +81,7 @@
<path
android:name="_R_G_L_1_G_D_0_P_0"
android:fillAlpha="0.25"
- android:fillColor="@color/gesture_tutorial_primary_color"
+ android:fillColor="?android:attr/colorAccent"
android:fillType="nonZero"
android:pathData=" M206 -12.5 C206,-12.5 206,12.5 206,12.5 C206,12.5 -206,12.5 -206,12.5 C-206,12.5 -206,-12.5 -206,-12.5 C-206,-12.5 206,-12.5 206,-12.5c " />
</group>
diff --git a/quickstep/res/drawable/ic_sysbar_back_kids.xml b/quickstep/res/drawable/ic_sysbar_back_kids.xml
new file mode 100644
index 0000000..ac6d49b
--- /dev/null
+++ b/quickstep/res/drawable/ic_sysbar_back_kids.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M21,11.4v1c0,1 -0.8,1.8 -1.8,1.8l0,0h-8.8l2.7,2.7c0.7,0.7 0.7,1.8 0,2.5c0,0 0,0 0,0l-0.7,0.7c-0.7,0.7 -1.8,0.7 -2.5,0c0,0 0,0 0,0l-5.9,-5.9C2.6,13 2.6,11 3.9,9.7l5.9,-5.9c0.7,-0.7 1.8,-0.7 2.5,0c0,0 0,0 0,0l0.7,0.7c0.7,0.7 0.7,1.8 0,2.5c0,0 0,0 0,0l-2.6,2.6h8.7C20.2,9.6 21,10.5 21,11.4z"/>
+</vector>
diff --git a/quickstep/res/drawable/ic_sysbar_home_kids.xml b/quickstep/res/drawable/ic_sysbar_home_kids.xml
new file mode 100644
index 0000000..2397e70
--- /dev/null
+++ b/quickstep/res/drawable/ic_sysbar_home_kids.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22.7,11l-7.9,-7c-1.6,-1.4 -3.9,-1.4 -5.5,0L7.4,5.7V4.1C7.4,3.5 6.9,3 6.3,3H5.2C4.5,3 4,3.5 4,4.1c0,0 0,0 0,0v4.6L1.4,11c-0.5,0.4 -0.5,1.1 -0.1,1.5c0,0 0,0 0,0c0.2,0.2 0.5,0.4 0.8,0.4H4v5c0,1.3 1,2.3 2.3,2.3c0,0 0,0 0,0h11.4c1.3,0 2.3,-1 2.3,-2.3v-5h2c0.6,0 1.1,-0.5 1.1,-1.1C23,11.5 22.9,11.2 22.7,11L22.7,11zM14.3,15.6c0,0.6 -0.5,1.1 -1.1,1.2h-2.3c-0.6,0 -1.1,-0.5 -1.1,-1.1v-1.3c0,-0.6 0.5,-1.1 1.1,-1.1c0,0 0,0 0,0h2.3c0.6,0 1.1,0.5 1.1,1.1c0,0 0,0 0,0L14.3,15.6z"/>
+</vector>
diff --git a/quickstep/res/drawable/ic_sysbar_notifications.xml b/quickstep/res/drawable/ic_sysbar_notifications.xml
new file mode 100644
index 0000000..21fcf90
--- /dev/null
+++ b/quickstep/res/drawable/ic_sysbar_notifications.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18,17v-6c0,-3.07 -1.63,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.64,5.36 6,7.92 6,11v6L4,17v2h16v-2h-2zM16,17L8,17v-6c0,-2.48 1.51,-4.5 4,-4.5s4,2.02 4,4.5v6zM12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.9,2 2,2z"/>
+</vector>
diff --git a/quickstep/res/drawable/ic_sysbar_quick_settings.xml b/quickstep/res/drawable/ic_sysbar_quick_settings.xml
new file mode 100644
index 0000000..958284d
--- /dev/null
+++ b/quickstep/res/drawable/ic_sysbar_quick_settings.xml
@@ -0,0 +1,13 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M13.85,22.25h-3.7c-0.74,0 -1.36,-0.54 -1.45,-1.27l-0.27,-1.89c-0.27,-0.14 -0.53,-0.29 -0.79,-0.46l-1.8,0.72c-0.7,0.26 -1.47,-0.03 -1.81,-0.65L2.2,15.53c-0.35,-0.66 -0.2,-1.44 0.36,-1.88l1.53,-1.19c-0.01,-0.15 -0.02,-0.3 -0.02,-0.46 0,-0.15 0.01,-0.31 0.02,-0.46l-1.52,-1.19c-0.59,-0.45 -0.74,-1.26 -0.37,-1.88l1.85,-3.19c0.34,-0.62 1.11,-0.9 1.79,-0.63l1.81,0.73c0.26,-0.17 0.52,-0.32 0.78,-0.46l0.27,-1.91c0.09,-0.7 0.71,-1.25 1.44,-1.25h3.7c0.74,0 1.36,0.54 1.45,1.27l0.27,1.89c0.27,0.14 0.53,0.29 0.79,0.46l1.8,-0.72c0.71,-0.26 1.48,0.03 1.82,0.65l1.84,3.18c0.36,0.66 0.2,1.44 -0.36,1.88l-1.52,1.19c0.01,0.15 0.02,0.3 0.02,0.46s-0.01,0.31 -0.02,0.46l1.52,1.19c0.56,0.45 0.72,1.23 0.37,1.86l-1.86,3.22c-0.34,0.62 -1.11,0.9 -1.8,0.63l-1.8,-0.72c-0.26,0.17 -0.52,0.32 -0.78,0.46l-0.27,1.91c-0.1,0.68 -0.72,1.22 -1.46,1.22zM10.62,20.25h2.76l0.37,-2.55 0.53,-0.22c0.44,-0.18 0.88,-0.44 1.34,-0.78l0.45,-0.34 2.38,0.96 1.38,-2.4 -2.03,-1.58 0.07,-0.56c0.03,-0.26 0.06,-0.51 0.06,-0.78s-0.03,-0.53 -0.06,-0.78l-0.07,-0.56 2.03,-1.58 -1.39,-2.4 -2.39,0.96 -0.45,-0.35c-0.42,-0.32 -0.87,-0.58 -1.33,-0.77l-0.52,-0.22 -0.37,-2.55h-2.76l-0.37,2.55 -0.53,0.21c-0.44,0.19 -0.88,0.44 -1.34,0.79l-0.45,0.33 -2.38,-0.95 -1.39,2.39 2.03,1.58 -0.07,0.56c-0.03,0.26 -0.06,0.53 -0.06,0.79s0.02,0.53 0.06,0.78l0.07,0.56 -2.03,1.58 1.38,2.4 2.39,-0.96 0.45,0.35c0.43,0.33 0.86,0.58 1.33,0.77l0.53,0.22 0.38,2.55z"/>
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,12m-3.5,0a3.5,3.5 0,1 1,7 0a3.5,3.5 0,1 1,-7 0"/>
+</vector>
diff --git a/quickstep/res/layout-land/gesture_tutorial_mock_hotseat.xml b/quickstep/res/layout-land/gesture_tutorial_mock_hotseat.xml
new file mode 100644
index 0000000..20d2ecc
--- /dev/null
+++ b/quickstep/res/layout-land/gesture_tutorial_mock_hotseat.xml
@@ -0,0 +1,80 @@
+<?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.
+-->
+<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="wrap_content"
+ android:layout_height="match_parent"
+ android:paddingTop="26dp"
+ android:paddingBottom="26dp"
+ android:paddingStart="56dp"
+ android:paddingEnd="56dp">
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_1"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_1"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintVertical_chainStyle="spread_inside"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/hotseat_icon_2"
+ app:layout_constraintStart_toStartOf="parent"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_2"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_2"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toBottomOf="@id/hotseat_icon_1"
+ app:layout_constraintBottom_toTopOf="@id/hotseat_icon_3"
+ app:layout_constraintStart_toStartOf="parent"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_3"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_3"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toBottomOf="@id/hotseat_icon_2"
+ app:layout_constraintBottom_toTopOf="@id/hotseat_icon_4"
+ app:layout_constraintStart_toStartOf="parent"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_4"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_4"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toBottomOf="@id/hotseat_icon_3"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout-land/gesture_tutorial_tablet_mock_hotseat.xml b/quickstep/res/layout-land/gesture_tutorial_tablet_mock_hotseat.xml
new file mode 100644
index 0000000..6877b89
--- /dev/null
+++ b/quickstep/res/layout-land/gesture_tutorial_tablet_mock_hotseat.xml
@@ -0,0 +1,123 @@
+<?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.
+-->
+<androidx.constraintlayout.widget.ConstraintLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="32dp"
+ android:paddingStart="@dimen/gesture_tutorial_hotseat_padding_start_end"
+ android:paddingEnd="@dimen/gesture_tutorial_hotseat_padding_start_end">
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_search_bar"
+ android:layout_width="200dp"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_search_height"
+
+ app:layout_constraintHorizontal_chainStyle="spread_inside"
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_search_corner_radius"
+ app:cardBackgroundColor="@color/mock_search_bar"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/hotseat_icon_1"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_1"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_1"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/hotseat_search_bar"
+ app:layout_constraintEnd_toStartOf="@id/hotseat_icon_2"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_2"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_2"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/hotseat_icon_1"
+ app:layout_constraintEnd_toStartOf="@id/hotseat_icon_3"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_3"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_3"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/hotseat_icon_2"
+ app:layout_constraintEnd_toStartOf="@id/hotseat_icon_4"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_4"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_1"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/hotseat_icon_3"
+ app:layout_constraintEnd_toStartOf="@id/hotseat_icon_5"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_5"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_4"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/hotseat_icon_4"
+ app:layout_constraintEnd_toStartOf="@id/hotseat_icon_6"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_6"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_2"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/hotseat_icon_5"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/activity_allset.xml b/quickstep/res/layout/activity_allset.xml
index 9ad10dc..0cae733 100644
--- a/quickstep/res/layout/activity_allset.xml
+++ b/quickstep/res/layout/activity_allset.xml
@@ -60,7 +60,7 @@
<TextView
android:id="@+id/title"
- style="@style/TextAppearance.GestureTutorial.Feedback.Title"
+ style="@style/TextAppearance.GestureTutorial.Feedback.Title.AllSet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/allset_title_margin_top"
@@ -71,15 +71,13 @@
<TextView
android:id="@+id/subtitle"
- style="@style/TextAppearance.GestureTutorial.Feedback.Subtitle"
- android:layout_width="0dp"
+ style="@style/TextAppearance.GestureTutorial.Feedback.Subtitle.AllSet"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/allset_subtitle_margin_top"
app:layout_constraintTop_toBottomOf="@id/title"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintWidth_max="@dimen/allset_subtitle_width_max"
- android:gravity="start"
- android:text="@string/allset_description"/>
+ android:gravity="start"/>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/navigation_settings_guideline_bottom"
diff --git a/quickstep/res/layout/gesture_tutorial_foldable_mock_hotseat.xml b/quickstep/res/layout/gesture_tutorial_foldable_mock_hotseat.xml
index 5612666..027e4a0 100644
--- a/quickstep/res/layout/gesture_tutorial_foldable_mock_hotseat.xml
+++ b/quickstep/res/layout/gesture_tutorial_foldable_mock_hotseat.xml
@@ -1,12 +1,26 @@
<?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.
+-->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="32dp"
- android:paddingStart="170dp"
- android:paddingEnd="170dp">
+ android:paddingStart="@dimen/gesture_tutorial_hotseat_padding_start_end"
+ android:paddingEnd="@dimen/gesture_tutorial_hotseat_padding_start_end">
<androidx.cardview.widget.CardView
android:id="@+id/hotseat_search_bar"
diff --git a/quickstep/res/layout/gesture_tutorial_fragment.xml b/quickstep/res/layout/gesture_tutorial_fragment.xml
index 08e6178..b3ca297 100644
--- a/quickstep/res/layout/gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/gesture_tutorial_fragment.xml
@@ -27,10 +27,8 @@
<FrameLayout
android:id="@+id/gesture_tutorial_fake_hotseat_view"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:layout_alignParentBottom="true"/>
+ android:layout_width="@dimen/gesture_tutorial_hotseat_width"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_height"/>
</RelativeLayout>
@@ -102,7 +100,7 @@
android:background="@drawable/gesture_tutorial_ripple"/>
<include
- layout="@layout/gesture_tutorial_foldable_mock_taskbar"
+ layout="@layout/gesture_tutorial_tablet_mock_taskbar"
android:id="@+id/gesture_tutorial_fake_taskbar_view"
android:layout_width="match_parent"
android:layout_height="@dimen/gesture_tutorial_mock_taskbar_height"
@@ -121,33 +119,23 @@
android:scaleType="fitXY"
android:visibility="gone"/>
- <ImageView
- android:id="@+id/gesture_tutorial_finger_dot"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/gesture_tutorial_finger_dot"
- android:layout_centerHorizontal="true"
- android:layout_centerVertical="true"
- android:visibility="gone"/>
-
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/gesture_tutorial_fragment_feedback_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
- android:layout_marginTop="24dp"
android:paddingTop="24dp"
android:paddingBottom="16dp"
+ android:paddingStart="24dp"
+ android:paddingEnd="24dp"
android:background="@drawable/bg_sandbox_feedback">
<TextView
android:id="@+id/gesture_tutorial_fragment_feedback_title"
style="@style/TextAppearance.GestureTutorial.Feedback.Title"
- android:layout_width="0dp"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="24dp"
- android:layout_marginEnd="24dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@@ -158,9 +146,7 @@
style="@style/TextAppearance.GestureTutorial.Feedback.Subtitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_marginTop="24dp"
- android:layout_marginStart="24dp"
- android:layout_marginEnd="24dp"
+ android:layout_marginTop="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@@ -182,7 +168,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
- android:layout_marginEnd="16dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingStart="26dp"
@@ -201,11 +186,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
- android:layout_marginEnd="16dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
- android:paddingStart="26dp"
- android:paddingEnd="26dp"
android:text="@string/gesture_tutorial_action_button_label_skip"
android:background="?android:attr/selectableItemBackgroundBorderless"
@@ -214,4 +196,13 @@
</androidx.constraintlayout.widget.ConstraintLayout>
+ <ImageView
+ android:id="@+id/gesture_tutorial_finger_dot"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/gesture_tutorial_finger_dot"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:visibility="gone"/>
+
</com.android.quickstep.interaction.RootSandboxLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/gesture_tutorial_mock_conversation.xml b/quickstep/res/layout/gesture_tutorial_mock_conversation.xml
index e8d5d79..5550389 100644
--- a/quickstep/res/layout/gesture_tutorial_mock_conversation.xml
+++ b/quickstep/res/layout/gesture_tutorial_mock_conversation.xml
@@ -34,8 +34,8 @@
android:layout_height="0dp"
android:layout_marginTop="43dp"
android:layout_marginBottom="22dp"
- android:layout_marginStart="34dp"
- android:layout_marginEnd="211dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_top_bar_margin_start"
+ android:layout_marginEnd="@dimen/gesture_tutorial_top_bar_margin_end"
app:cardElevation="0dp"
app:cardCornerRadius="4dp"
@@ -84,7 +84,7 @@
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="@color/mock_conversation_background"
- android:paddingBottom="66dp"
+ android:paddingBottom="@dimen/gesture_tutorial_conversation_bottom_padding"
app:layout_constraintTop_toBottomOf="@id/top_bar"
app:layout_constraintBottom_toBottomOf="parent"
@@ -108,6 +108,7 @@
android:layout_marginBottom="@dimen/gesture_tutorial_message_large_margin_bottom"
android:layout_marginStart="124dp"
android:layout_marginEnd="@dimen/gesture_tutorial_message_padding_end"
+ android:visibility="@integer/gesture_tutorial_extra_messages_visibility"
app:cardElevation="0dp"
app:cardCornerRadius="18dp"
@@ -122,6 +123,7 @@
android:layout_height="@dimen/gesture_tutorial_message_icon_size"
android:layout_marginBottom="@dimen/gesture_tutorial_message_large_margin_bottom"
android:layout_marginStart="@dimen/gesture_tutorial_message_padding_start"
+ android:visibility="@integer/gesture_tutorial_extra_messages_visibility"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/gesture_tutorial_message_icon_corner_radius"
@@ -135,6 +137,7 @@
android:layout_height="36dp"
android:layout_marginStart="17dp"
android:layout_marginEnd="112dp"
+ android:visibility="@integer/gesture_tutorial_extra_messages_visibility"
app:cardElevation="0dp"
app:cardCornerRadius="18dp"
@@ -151,6 +154,7 @@
android:layout_marginBottom="@dimen/gesture_tutorial_message_small_margin_bottom"
android:layout_marginStart="280dp"
android:layout_marginEnd="@dimen/gesture_tutorial_message_padding_end"
+ android:visibility="@integer/gesture_tutorial_extra_messages_visibility"
app:cardElevation="0dp"
app:cardCornerRadius="18dp"
@@ -164,7 +168,7 @@
android:layout_width="0dp"
android:layout_height="74dp"
android:layout_marginBottom="@dimen/gesture_tutorial_message_large_margin_bottom"
- android:layout_marginStart="124dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_message_margin_start"
android:layout_marginEnd="@dimen/gesture_tutorial_message_padding_end"
app:cardElevation="0dp"
@@ -192,7 +196,7 @@
android:layout_width="0dp"
android:layout_height="36dp"
android:layout_marginStart="17dp"
- android:layout_marginEnd="144dp"
+ android:layout_marginEnd="@dimen/gesture_tutorial_reply_margin_end"
app:cardElevation="0dp"
app:cardCornerRadius="18dp"
@@ -206,7 +210,7 @@
android:id="@+id/message_4"
android:layout_width="0dp"
android:layout_height="74dp"
- android:layout_marginStart="124dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_message_margin_start"
android:layout_marginEnd="@dimen/gesture_tutorial_message_padding_end"
app:cardElevation="0dp"
diff --git a/quickstep/res/layout/gesture_tutorial_mock_conversation_list.xml b/quickstep/res/layout/gesture_tutorial_mock_conversation_list.xml
index 364ad6d..a172ad3 100644
--- a/quickstep/res/layout/gesture_tutorial_mock_conversation_list.xml
+++ b/quickstep/res/layout/gesture_tutorial_mock_conversation_list.xml
@@ -35,7 +35,7 @@
android:layout_marginTop="43dp"
android:layout_marginBottom="22dp"
android:layout_marginStart="34dp"
- android:layout_marginEnd="35dp"
+ android:layout_marginEnd="34dp"
app:cardElevation="0dp"
app:cardCornerRadius="4dp"
@@ -51,337 +51,336 @@
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="@color/mock_list_background"
- android:paddingBottom="66dp"
+ android:paddingTop="@dimen/gesture_tutorial_conversation_list_padding_top"
+ android:paddingStart="26dp"
app:layout_constraintTop_toBottomOf="@id/top_bar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
- <androidx.constraintlayout.widget.ConstraintLayout
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:paddingTop="@dimen/gesture_tutorial_conversation_list_padding_top"
- android:paddingStart="26dp"
- android:paddingBottom="14dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_icon_1"
+ android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_list_profile_icon"
app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@id/mock_button">
+ app:layout_constraintStart_toStartOf="parent"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_icon_1"
- android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
- android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_line_1"
+ android:layout_width="0dp"
+ android:layout_height="18dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+ android:layout_marginEnd="@dimen/gesture_tutorial_conversation_line_1_margin_end"
- app:cardElevation="0dp"
- app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
- app:cardBackgroundColor="@color/mock_list_profile_icon"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintStart_toStartOf="parent"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="4dp"
+ app:cardBackgroundColor="@color/mock_list_preview_message"
+ app:layout_constraintVertical_chainStyle="packed"
+ app:layout_constraintTop_toTopOf="@id/conversation_icon_1"
+ app:layout_constraintStart_toEndOf="@id/conversation_icon_1"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/conversation_line_2"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_line_1"
- android:layout_width="0dp"
- android:layout_height="18dp"
- android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="217dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_line_2"
+ android:layout_width="0dp"
+ android:layout_height="16dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+ android:layout_marginEnd="@dimen/gesture_tutorial_conversation_line_2_margin_end"
+ android:layout_marginTop="4dp"
- app:cardElevation="0dp"
- app:cardCornerRadius="4dp"
- app:cardBackgroundColor="@color/mock_list_preview_message"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintTop_toTopOf="@id/conversation_icon_1"
- app:layout_constraintStart_toEndOf="@id/conversation_icon_1"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toTopOf="@id/conversation_line_2"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="4dp"
+ app:cardBackgroundColor="@color/mock_list_preview_message"
+ app:layout_constraintTop_toBottomOf="@id/conversation_line_1"
+ app:layout_constraintStart_toEndOf="@id/conversation_icon_1"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toBottomOf="@id/conversation_icon_1"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_line_2"
- android:layout_width="0dp"
- android:layout_height="16dp"
- android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="142dp"
- android:layout_marginTop="4dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_icon_2"
+ android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
+ android:layout_marginTop="32dp"
- app:cardElevation="0dp"
- app:cardCornerRadius="4dp"
- app:cardBackgroundColor="@color/mock_list_preview_message"
- app:layout_constraintTop_toBottomOf="@id/conversation_line_1"
- app:layout_constraintStart_toEndOf="@id/conversation_icon_1"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toBottomOf="@id/conversation_icon_1"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_list_profile_icon"
+ app:layout_constraintTop_toBottomOf="@id/conversation_icon_1"
+ app:layout_constraintStart_toStartOf="parent"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_icon_2"
- android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
- android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
- android:layout_marginTop="32dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_line_3"
+ android:layout_width="0dp"
+ android:layout_height="18dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+ android:layout_marginEnd="@dimen/gesture_tutorial_conversation_line_3_margin_end"
- app:cardElevation="0dp"
- app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
- app:cardBackgroundColor="@color/mock_list_profile_icon"
- app:layout_constraintTop_toBottomOf="@id/conversation_icon_1"
- app:layout_constraintStart_toStartOf="parent"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="4dp"
+ app:cardBackgroundColor="@color/mock_list_preview_message"
+ app:layout_constraintVertical_chainStyle="packed"
+ app:layout_constraintTop_toTopOf="@id/conversation_icon_2"
+ app:layout_constraintStart_toEndOf="@id/conversation_icon_2"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/conversation_line_4"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_line_3"
- android:layout_width="0dp"
- android:layout_height="18dp"
- android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="190dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_line_4"
+ android:layout_width="0dp"
+ android:layout_height="16dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+ android:layout_marginEnd="@dimen/gesture_tutorial_conversation_line_4_margin_end"
+ android:layout_marginTop="4dp"
- app:cardElevation="0dp"
- app:cardCornerRadius="4dp"
- app:cardBackgroundColor="@color/mock_list_preview_message"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintTop_toTopOf="@id/conversation_icon_2"
- app:layout_constraintStart_toEndOf="@id/conversation_icon_2"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toTopOf="@id/conversation_line_4"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="4dp"
+ app:cardBackgroundColor="@color/mock_list_preview_message"
+ app:layout_constraintTop_toBottomOf="@id/conversation_line_3"
+ app:layout_constraintStart_toEndOf="@id/conversation_icon_2"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toBottomOf="@id/conversation_icon_2"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_line_4"
- android:layout_width="0dp"
- android:layout_height="16dp"
- android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="171dp"
- android:layout_marginTop="4dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_icon_3"
+ android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
+ android:layout_marginTop="32dp"
- app:cardElevation="0dp"
- app:cardCornerRadius="4dp"
- app:cardBackgroundColor="@color/mock_list_preview_message"
- app:layout_constraintTop_toBottomOf="@id/conversation_line_3"
- app:layout_constraintStart_toEndOf="@id/conversation_icon_2"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toBottomOf="@id/conversation_icon_2"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_list_profile_icon"
+ app:layout_constraintTop_toBottomOf="@id/conversation_icon_2"
+ app:layout_constraintStart_toStartOf="parent"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_icon_3"
- android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
- android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
- android:layout_marginTop="32dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_line_5"
+ android:layout_width="0dp"
+ android:layout_height="18dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+ android:layout_marginEnd="@dimen/gesture_tutorial_conversation_line_5_margin_end"
- app:cardElevation="0dp"
- app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
- app:cardBackgroundColor="@color/mock_list_profile_icon"
- app:layout_constraintTop_toBottomOf="@id/conversation_icon_2"
- app:layout_constraintStart_toStartOf="parent"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="4dp"
+ app:cardBackgroundColor="@color/mock_list_preview_message"
+ app:layout_constraintVertical_chainStyle="packed"
+ app:layout_constraintTop_toTopOf="@id/conversation_icon_3"
+ app:layout_constraintStart_toEndOf="@id/conversation_icon_3"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/conversation_line_6"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_line_5"
- android:layout_width="0dp"
- android:layout_height="18dp"
- android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="198dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_line_6"
+ android:layout_width="0dp"
+ android:layout_height="16dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+ android:layout_marginEnd="@dimen/gesture_tutorial_conversation_line_6_margin_end"
+ android:layout_marginTop="4dp"
- app:cardElevation="0dp"
- app:cardCornerRadius="4dp"
- app:cardBackgroundColor="@color/mock_list_preview_message"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintTop_toTopOf="@id/conversation_icon_3"
- app:layout_constraintStart_toEndOf="@id/conversation_icon_3"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toTopOf="@id/conversation_line_6"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="4dp"
+ app:cardBackgroundColor="@color/mock_list_preview_message"
+ app:layout_constraintTop_toBottomOf="@id/conversation_line_5"
+ app:layout_constraintStart_toEndOf="@id/conversation_icon_3"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toBottomOf="@id/conversation_icon_3"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_line_6"
- android:layout_width="0dp"
- android:layout_height="16dp"
- android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="79dp"
- android:layout_marginTop="4dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_icon_4"
+ android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
+ android:layout_marginTop="32dp"
- app:cardElevation="0dp"
- app:cardCornerRadius="4dp"
- app:cardBackgroundColor="@color/mock_list_preview_message"
- app:layout_constraintTop_toBottomOf="@id/conversation_line_5"
- app:layout_constraintStart_toEndOf="@id/conversation_icon_3"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toBottomOf="@id/conversation_icon_3"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_list_profile_icon"
+ app:layout_constraintTop_toBottomOf="@id/conversation_icon_3"
+ app:layout_constraintStart_toStartOf="parent"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_icon_4"
- android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
- android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
- android:layout_marginTop="32dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_line_7"
+ android:layout_width="0dp"
+ android:layout_height="18dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+ android:layout_marginEnd="@dimen/gesture_tutorial_conversation_line_7_margin_end"
- app:cardElevation="0dp"
- app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
- app:cardBackgroundColor="@color/mock_list_profile_icon"
- app:layout_constraintTop_toBottomOf="@id/conversation_icon_3"
- app:layout_constraintStart_toStartOf="parent"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="4dp"
+ app:cardBackgroundColor="@color/mock_list_preview_message"
+ app:layout_constraintVertical_chainStyle="packed"
+ app:layout_constraintTop_toTopOf="@id/conversation_icon_4"
+ app:layout_constraintStart_toEndOf="@id/conversation_icon_4"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/conversation_line_8"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_line_7"
- android:layout_width="0dp"
- android:layout_height="18dp"
- android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="174dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_line_8"
+ android:layout_width="0dp"
+ android:layout_height="16dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+ android:layout_marginEnd="@dimen/gesture_tutorial_conversation_line_8_margin_end"
+ android:layout_marginTop="4dp"
- app:cardElevation="0dp"
- app:cardCornerRadius="4dp"
- app:cardBackgroundColor="@color/mock_list_preview_message"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintTop_toTopOf="@id/conversation_icon_4"
- app:layout_constraintStart_toEndOf="@id/conversation_icon_4"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toTopOf="@id/conversation_line_8"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="4dp"
+ app:cardBackgroundColor="@color/mock_list_preview_message"
+ app:layout_constraintTop_toBottomOf="@id/conversation_line_7"
+ app:layout_constraintStart_toEndOf="@id/conversation_icon_4"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toBottomOf="@id/conversation_icon_4"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_line_8"
- android:layout_width="0dp"
- android:layout_height="16dp"
- android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="117dp"
- android:layout_marginTop="4dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_icon_5"
+ android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
+ android:layout_marginTop="32dp"
+ android:visibility="@integer/gesture_tutorial_extra_conversations_visibility"
- app:cardElevation="0dp"
- app:cardCornerRadius="4dp"
- app:cardBackgroundColor="@color/mock_list_preview_message"
- app:layout_constraintTop_toBottomOf="@id/conversation_line_7"
- app:layout_constraintStart_toEndOf="@id/conversation_icon_4"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toBottomOf="@id/conversation_icon_4"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_list_profile_icon"
+ app:layout_constraintTop_toBottomOf="@id/conversation_icon_4"
+ app:layout_constraintStart_toStartOf="parent"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_icon_5"
- android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
- android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
- android:layout_marginTop="32dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_line_9"
+ android:layout_width="0dp"
+ android:layout_height="18dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+ android:layout_marginEnd="244dp"
+ android:visibility="@integer/gesture_tutorial_extra_conversations_visibility"
- app:cardElevation="0dp"
- app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
- app:cardBackgroundColor="@color/mock_list_profile_icon"
- app:layout_constraintTop_toBottomOf="@id/conversation_icon_4"
- app:layout_constraintStart_toStartOf="parent"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="4dp"
+ app:cardBackgroundColor="@color/mock_list_preview_message"
+ app:layout_constraintVertical_chainStyle="packed"
+ app:layout_constraintTop_toTopOf="@id/conversation_icon_5"
+ app:layout_constraintStart_toEndOf="@id/conversation_icon_5"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/conversation_line_10"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_line_9"
- android:layout_width="0dp"
- android:layout_height="18dp"
- android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="244dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_line_10"
+ android:layout_width="0dp"
+ android:layout_height="16dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+ android:layout_marginEnd="143dp"
+ android:layout_marginTop="4dp"
+ android:visibility="@integer/gesture_tutorial_extra_conversations_visibility"
- app:cardElevation="0dp"
- app:cardCornerRadius="4dp"
- app:cardBackgroundColor="@color/mock_list_preview_message"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintTop_toTopOf="@id/conversation_icon_5"
- app:layout_constraintStart_toEndOf="@id/conversation_icon_5"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toTopOf="@id/conversation_line_10"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="4dp"
+ app:cardBackgroundColor="@color/mock_list_preview_message"
+ app:layout_constraintTop_toBottomOf="@id/conversation_line_9"
+ app:layout_constraintStart_toEndOf="@id/conversation_icon_5"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toBottomOf="@id/conversation_icon_5"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_line_10"
- android:layout_width="0dp"
- android:layout_height="16dp"
- android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="143dp"
- android:layout_marginTop="4dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_icon_6"
+ android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
+ android:layout_marginTop="32dp"
+ android:visibility="@integer/gesture_tutorial_extra_conversations_visibility"
- app:cardElevation="0dp"
- app:cardCornerRadius="4dp"
- app:cardBackgroundColor="@color/mock_list_preview_message"
- app:layout_constraintTop_toBottomOf="@id/conversation_line_9"
- app:layout_constraintStart_toEndOf="@id/conversation_icon_5"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toBottomOf="@id/conversation_icon_5"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_list_profile_icon"
+ app:layout_constraintTop_toBottomOf="@id/conversation_icon_5"
+ app:layout_constraintStart_toStartOf="parent"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_icon_6"
- android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
- android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
- android:layout_marginTop="32dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_line_11"
+ android:layout_width="0dp"
+ android:layout_height="18dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+ android:layout_marginEnd="177dp"
+ android:visibility="@integer/gesture_tutorial_extra_conversations_visibility"
- app:cardElevation="0dp"
- app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
- app:cardBackgroundColor="@color/mock_list_profile_icon"
- app:layout_constraintTop_toBottomOf="@id/conversation_icon_5"
- app:layout_constraintStart_toStartOf="parent"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="4dp"
+ app:cardBackgroundColor="@color/mock_list_preview_message"
+ app:layout_constraintVertical_chainStyle="packed"
+ app:layout_constraintTop_toTopOf="@id/conversation_icon_6"
+ app:layout_constraintStart_toEndOf="@id/conversation_icon_6"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/conversation_line_12"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_line_11"
- android:layout_width="0dp"
- android:layout_height="18dp"
- android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="177dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_line_12"
+ android:layout_width="0dp"
+ android:layout_height="16dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+ android:layout_marginEnd="117dp"
+ android:layout_marginTop="4dp"
+ android:visibility="@integer/gesture_tutorial_extra_conversations_visibility"
- app:cardElevation="0dp"
- app:cardCornerRadius="4dp"
- app:cardBackgroundColor="@color/mock_list_preview_message"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintTop_toTopOf="@id/conversation_icon_6"
- app:layout_constraintStart_toEndOf="@id/conversation_icon_6"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toTopOf="@id/conversation_line_12"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="4dp"
+ app:cardBackgroundColor="@color/mock_list_preview_message"
+ app:layout_constraintTop_toBottomOf="@id/conversation_line_11"
+ app:layout_constraintStart_toEndOf="@id/conversation_icon_6"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toBottomOf="@id/conversation_icon_6"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_line_12"
- android:layout_width="0dp"
- android:layout_height="16dp"
- android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="117dp"
- android:layout_marginTop="4dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_icon_7"
+ android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
+ android:layout_marginTop="32dp"
+ android:visibility="@integer/gesture_tutorial_extra_conversations_visibility"
- app:cardElevation="0dp"
- app:cardCornerRadius="4dp"
- app:cardBackgroundColor="@color/mock_list_preview_message"
- app:layout_constraintTop_toBottomOf="@id/conversation_line_11"
- app:layout_constraintStart_toEndOf="@id/conversation_icon_6"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toBottomOf="@id/conversation_icon_6"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_list_profile_icon"
+ app:layout_constraintTop_toBottomOf="@id/conversation_icon_6"
+ app:layout_constraintStart_toStartOf="parent"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_icon_7"
- android:layout_width="@dimen/gesture_tutorial_conversation_icon_size"
- android:layout_height="@dimen/gesture_tutorial_conversation_icon_size"
- android:layout_marginTop="32dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_line_13"
+ android:layout_width="0dp"
+ android:layout_height="18dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+ android:layout_marginEnd="189dp"
+ android:visibility="@integer/gesture_tutorial_extra_conversations_visibility"
- app:cardElevation="0dp"
- app:cardCornerRadius="@dimen/gesture_tutorial_conversation_icon_corner_radius"
- app:cardBackgroundColor="@color/mock_list_profile_icon"
- app:layout_constraintTop_toBottomOf="@id/conversation_icon_6"
- app:layout_constraintStart_toStartOf="parent"/>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="4dp"
+ app:cardBackgroundColor="@color/mock_list_preview_message"
+ app:layout_constraintVertical_chainStyle="packed"
+ app:layout_constraintTop_toTopOf="@id/conversation_icon_7"
+ app:layout_constraintStart_toEndOf="@id/conversation_icon_7"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/conversation_line_14"/>
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_line_13"
- android:layout_width="0dp"
- android:layout_height="18dp"
- android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="189dp"
+ <androidx.cardview.widget.CardView
+ android:id="@+id/conversation_line_14"
+ android:layout_width="0dp"
+ android:layout_height="16dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
+ android:layout_marginEnd="166dp"
+ android:layout_marginTop="4dp"
+ android:visibility="@integer/gesture_tutorial_extra_conversations_visibility"
- app:cardElevation="0dp"
- app:cardCornerRadius="4dp"
- app:cardBackgroundColor="@color/mock_list_preview_message"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintTop_toTopOf="@id/conversation_icon_7"
- app:layout_constraintStart_toEndOf="@id/conversation_icon_7"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toTopOf="@id/conversation_line_14"/>
-
- <androidx.cardview.widget.CardView
- android:id="@+id/conversation_line_14"
- android:layout_width="0dp"
- android:layout_height="16dp"
- android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="166dp"
- android:layout_marginTop="4dp"
-
- app:cardElevation="0dp"
- app:cardCornerRadius="4dp"
- app:cardBackgroundColor="@color/mock_list_preview_message"
- app:layout_constraintTop_toBottomOf="@id/conversation_line_13"
- app:layout_constraintStart_toEndOf="@id/conversation_icon_7"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toBottomOf="@id/conversation_icon_7"/>
-
- </androidx.constraintlayout.widget.ConstraintLayout>
+ app:cardElevation="0dp"
+ app:cardCornerRadius="4dp"
+ app:cardBackgroundColor="@color/mock_list_preview_message"
+ app:layout_constraintTop_toBottomOf="@id/conversation_line_13"
+ app:layout_constraintStart_toEndOf="@id/conversation_icon_7"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toBottomOf="@id/conversation_icon_7"/>
<androidx.cardview.widget.CardView
android:id="@+id/mock_button"
android:layout_width="149dp"
android:layout_height="56dp"
- android:layout_marginEnd="24dp"
+ android:layout_marginEnd="@dimen/gesture_tutorial_mock_button_margin_end"
+ android:layout_marginBottom="@dimen/gesture_tutorial_mock_button_margin_bottom"
app:cardElevation="0dp"
app:cardCornerRadius="164dp"
diff --git a/quickstep/res/layout/gesture_tutorial_mock_webpage.xml b/quickstep/res/layout/gesture_tutorial_mock_webpage.xml
index bb20968..0b1b40d 100644
--- a/quickstep/res/layout/gesture_tutorial_mock_webpage.xml
+++ b/quickstep/res/layout/gesture_tutorial_mock_webpage.xml
@@ -34,8 +34,8 @@
android:layout_height="0dp"
android:layout_marginTop="48dp"
android:layout_marginBottom="16dp"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="16dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_webpage_url_margin_start_end"
+ android:layout_marginEnd="@dimen/gesture_tutorial_webpage_url_margin_start_end"
app:cardElevation="0dp"
app:cardCornerRadius="100dp"
@@ -63,7 +63,7 @@
android:layout_height="0dp"
android:layout_marginTop="22dp"
android:layout_marginBottom="22dp"
- android:layout_marginStart="24dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_webpage_top_bar_button_margin_start"
app:cardElevation="0dp"
app:cardCornerRadius="8dp"
@@ -78,8 +78,8 @@
android:layout_height="0dp"
android:layout_marginTop="28dp"
android:layout_marginBottom="28dp"
- android:layout_marginStart="97dp"
- android:layout_marginEnd="97dp"
+ android:layout_marginStart="@dimen/gesture_tutorial_webpage_top_bar_margin_start"
+ android:layout_marginEnd="@dimen/gesture_tutorial_webpage_top_bar_margin_end"
app:cardElevation="0dp"
app:cardCornerRadius="2dp"
@@ -107,7 +107,7 @@
android:id="@+id/mock_line_1"
android:layout_width="0dp"
android:layout_height="@dimen/gesture_tutorial_webpage_large_line_height"
- android:layout_marginEnd="126dp"
+ android:layout_marginEnd="@dimen/gesture_tutorial_webpage_line_1_margin_end"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/gesture_tutorial_webpage_small_corner_radius"
@@ -121,7 +121,7 @@
android:layout_width="0dp"
android:layout_height="@dimen/gesture_tutorial_webpage_large_line_height"
android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
- android:layout_marginEnd="64dp"
+ android:layout_marginEnd="@dimen/gesture_tutorial_webpage_line_2_margin_end"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/gesture_tutorial_webpage_small_corner_radius"
@@ -135,7 +135,7 @@
android:layout_width="0dp"
android:layout_height="@dimen/gesture_tutorial_webpage_large_line_height"
android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
- android:layout_marginEnd="151dp"
+ android:layout_marginEnd="@dimen/gesture_tutorial_webpage_line_3_margin_end"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/gesture_tutorial_webpage_small_corner_radius"
@@ -174,7 +174,7 @@
android:layout_width="0dp"
android:layout_height="240dp"
android:layout_marginTop="@dimen/gesture_tutorial_webpage_large_margin_top"
- android:layout_marginEnd="24dp"
+ android:layout_marginEnd="@dimen/gesture_tutorial_webpage_block_margin_end"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/gesture_tutorial_webpage_large_corner_radius"
@@ -189,6 +189,7 @@
android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
android:layout_marginTop="@dimen/gesture_tutorial_webpage_large_margin_top"
android:layout_marginEnd="52dp"
+ android:visibility="@integer/gesture_tutorial_webpage_extra_lines_visibility"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
@@ -203,6 +204,7 @@
android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
android:layout_marginEnd="41dp"
+ android:visibility="@integer/gesture_tutorial_webpage_extra_lines_visibility"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
@@ -217,6 +219,7 @@
android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
android:layout_marginEnd="71dp"
+ android:visibility="@integer/gesture_tutorial_webpage_extra_lines_visibility"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
@@ -231,6 +234,7 @@
android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
android:layout_marginEnd="198dp"
+ android:visibility="@integer/gesture_tutorial_webpage_extra_lines_visibility"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
@@ -245,6 +249,7 @@
android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
android:layout_marginTop="@dimen/gesture_tutorial_webpage_large_margin_top"
android:layout_marginEnd="64dp"
+ android:visibility="@integer/gesture_tutorial_webpage_extra_lines_visibility"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
@@ -258,6 +263,7 @@
android:layout_height="@dimen/gesture_tutorial_webpage_small_line_height"
android:layout_marginTop="@dimen/gesture_tutorial_webpage_small_margin_top"
android:layout_marginEnd="71dp"
+ android:visibility="@integer/gesture_tutorial_webpage_extra_lines_visibility"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/gesture_tutorial_webpage_medium_corner_radius"
diff --git a/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation.xml b/quickstep/res/layout/gesture_tutorial_tablet_mock_conversation.xml
similarity index 93%
rename from quickstep/res/layout/gesture_tutorial_foldable_mock_conversation.xml
rename to quickstep/res/layout/gesture_tutorial_tablet_mock_conversation.xml
index b0cc00b..c8cf8c3 100644
--- a/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation.xml
+++ b/quickstep/res/layout/gesture_tutorial_tablet_mock_conversation.xml
@@ -106,8 +106,8 @@
android:layout_width="0dp"
android:layout_height="112dp"
android:layout_marginBottom="@dimen/gesture_tutorial_message_large_margin_bottom"
- android:layout_marginStart="445dp"
- android:layout_marginEnd="@dimen/gesture_tutorial_foldable_message_padding_start_end"
+ android:layout_marginStart="@dimen/gesture_tutorial_tablet_message_1_margin"
+ android:layout_marginEnd="@dimen/gesture_tutorial_tablet_message_padding_start_end"
app:cardElevation="0dp"
app:cardCornerRadius="18dp"
@@ -121,7 +121,7 @@
android:layout_width="@dimen/gesture_tutorial_message_icon_size"
android:layout_height="@dimen/gesture_tutorial_message_icon_size"
android:layout_marginBottom="@dimen/gesture_tutorial_message_large_margin_bottom"
- android:layout_marginStart="@dimen/gesture_tutorial_foldable_message_padding_start_end"
+ android:layout_marginStart="@dimen/gesture_tutorial_tablet_message_padding_start_end"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/gesture_tutorial_message_icon_corner_radius"
@@ -134,7 +134,7 @@
android:layout_width="0dp"
android:layout_height="36dp"
android:layout_marginStart="17dp"
- android:layout_marginEnd="441dp"
+ android:layout_marginEnd="@dimen/gesture_tutorial_tablet_reply_1_margin"
app:cardElevation="0dp"
app:cardCornerRadius="18dp"
@@ -149,8 +149,8 @@
android:layout_width="0dp"
android:layout_height="36dp"
android:layout_marginBottom="@dimen/gesture_tutorial_message_small_margin_bottom"
- android:layout_marginStart="601dp"
- android:layout_marginEnd="@dimen/gesture_tutorial_foldable_message_padding_start_end"
+ android:layout_marginStart="@dimen/gesture_tutorial_tablet_message_2_margin"
+ android:layout_marginEnd="@dimen/gesture_tutorial_tablet_message_padding_start_end"
app:cardElevation="0dp"
app:cardCornerRadius="18dp"
@@ -164,8 +164,8 @@
android:layout_width="0dp"
android:layout_height="74dp"
android:layout_marginBottom="@dimen/gesture_tutorial_message_large_margin_bottom"
- android:layout_marginStart="445dp"
- android:layout_marginEnd="@dimen/gesture_tutorial_foldable_message_padding_start_end"
+ android:layout_marginStart="@dimen/gesture_tutorial_tablet_message_3_margin"
+ android:layout_marginEnd="@dimen/gesture_tutorial_tablet_message_padding_start_end"
app:cardElevation="0dp"
app:cardCornerRadius="18dp"
@@ -179,7 +179,7 @@
android:layout_width="@dimen/gesture_tutorial_message_icon_size"
android:layout_height="@dimen/gesture_tutorial_message_icon_size"
android:layout_marginBottom="32dp"
- android:layout_marginStart="@dimen/gesture_tutorial_foldable_message_padding_start_end"
+ android:layout_marginStart="@dimen/gesture_tutorial_tablet_message_padding_start_end"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/gesture_tutorial_message_icon_corner_radius"
@@ -192,7 +192,7 @@
android:layout_width="0dp"
android:layout_height="36dp"
android:layout_marginStart="17dp"
- android:layout_marginEnd="473dp"
+ android:layout_marginEnd="@dimen/gesture_tutorial_tablet_reply_2_margin"
app:cardElevation="0dp"
app:cardCornerRadius="18dp"
@@ -206,8 +206,8 @@
android:id="@+id/message_4"
android:layout_width="0dp"
android:layout_height="74dp"
- android:layout_marginStart="445dp"
- android:layout_marginEnd="@dimen/gesture_tutorial_foldable_message_padding_start_end"
+ android:layout_marginStart="345dp"
+ android:layout_marginEnd="@dimen/gesture_tutorial_tablet_message_padding_start_end"
app:cardElevation="0dp"
app:cardCornerRadius="18dp"
diff --git a/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation_list.xml b/quickstep/res/layout/gesture_tutorial_tablet_mock_conversation_list.xml
similarity index 95%
rename from quickstep/res/layout/gesture_tutorial_foldable_mock_conversation_list.xml
rename to quickstep/res/layout/gesture_tutorial_tablet_mock_conversation_list.xml
index e5cd9bc..0fb0677 100644
--- a/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation_list.xml
+++ b/quickstep/res/layout/gesture_tutorial_tablet_mock_conversation_list.xml
@@ -67,7 +67,7 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toStartOf="@id/mock_button">
+ app:layout_constraintEnd_toEndOf="parent">
<androidx.cardview.widget.CardView
android:id="@+id/conversation_icon_1"
@@ -189,7 +189,7 @@
android:layout_width="0dp"
android:layout_height="16dp"
android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="15dp"
+ android:layout_marginEnd="@dimen/gesture_tutorial_tablet_conversation_line_6_margin_end"
android:layout_marginTop="4dp"
app:cardElevation="0dp"
@@ -233,7 +233,7 @@
android:layout_width="0dp"
android:layout_height="16dp"
android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="72dp"
+ android:layout_marginEnd="@dimen/gesture_tutorial_tablet_conversation_line_8_margin_end"
android:layout_marginTop="4dp"
app:cardElevation="0dp"
@@ -277,7 +277,7 @@
android:layout_width="0dp"
android:layout_height="16dp"
android:layout_marginStart="@dimen/gesture_tutorial_conversation_line_padding_start"
- android:layout_marginEnd="111dp"
+ android:layout_marginEnd="@dimen/gesture_tutorial_tablet_conversation_line_10_margin_end"
android:layout_marginTop="4dp"
app:cardElevation="0dp"
@@ -376,21 +376,21 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="@id/conversation_icon_7"/>
+ <androidx.cardview.widget.CardView
+ android:id="@+id/mock_button"
+ android:layout_width="149dp"
+ android:layout_height="56dp"
+ android:layout_marginEnd="126dp"
+ android:layout_marginBottom="24dp"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="164dp"
+ app:cardBackgroundColor="@color/mock_list_button"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
</androidx.constraintlayout.widget.ConstraintLayout>
- <androidx.cardview.widget.CardView
- android:id="@+id/mock_button"
- android:layout_width="149dp"
- android:layout_height="56dp"
- android:layout_marginEnd="126dp"
- android:layout_marginBottom="24dp"
-
- app:cardElevation="0dp"
- app:cardCornerRadius="164dp"
- app:cardBackgroundColor="@color/mock_list_button"
- app:layout_constraintBottom_toBottomOf="parent"
- 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_tablet_mock_hotseat.xml b/quickstep/res/layout/gesture_tutorial_tablet_mock_hotseat.xml
new file mode 100644
index 0000000..027e4a0
--- /dev/null
+++ b/quickstep/res/layout/gesture_tutorial_tablet_mock_hotseat.xml
@@ -0,0 +1,122 @@
+<?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.
+-->
+<androidx.constraintlayout.widget.ConstraintLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="32dp"
+ android:paddingStart="@dimen/gesture_tutorial_hotseat_padding_start_end"
+ android:paddingEnd="@dimen/gesture_tutorial_hotseat_padding_start_end">
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_search_bar"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_search_height"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_search_corner_radius"
+ app:cardBackgroundColor="@color/mock_search_bar"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_1"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_marginTop="@dimen/gesture_tutorial_hotseat_icon_search_margin"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_1"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintHorizontal_chainStyle="spread_inside"
+ app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/hotseat_icon_2"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_2"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_marginTop="@dimen/gesture_tutorial_hotseat_icon_search_margin"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_2"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
+ app:layout_constraintStart_toEndOf="@id/hotseat_icon_1"
+ app:layout_constraintEnd_toStartOf="@id/hotseat_icon_3"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_3"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_marginTop="@dimen/gesture_tutorial_hotseat_icon_search_margin"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_3"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
+ app:layout_constraintStart_toEndOf="@id/hotseat_icon_2"
+ app:layout_constraintEnd_toStartOf="@id/hotseat_icon_4"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_4"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_marginTop="@dimen/gesture_tutorial_hotseat_icon_search_margin"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_1"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
+ app:layout_constraintStart_toEndOf="@id/hotseat_icon_3"
+ app:layout_constraintEnd_toStartOf="@id/hotseat_icon_5"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_5"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_marginTop="@dimen/gesture_tutorial_hotseat_icon_search_margin"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_4"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
+ app:layout_constraintStart_toEndOf="@id/hotseat_icon_4"
+ app:layout_constraintEnd_toStartOf="@id/hotseat_icon_6"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/hotseat_icon_6"
+ android:layout_width="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_hotseat_icon_size"
+ android:layout_marginTop="@dimen/gesture_tutorial_hotseat_icon_search_margin"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_hotseat_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_2"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toBottomOf="@id/hotseat_search_bar"
+ app:layout_constraintStart_toEndOf="@id/hotseat_icon_5"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/gesture_tutorial_foldable_mock_taskbar.xml b/quickstep/res/layout/gesture_tutorial_tablet_mock_taskbar.xml
similarity index 100%
rename from quickstep/res/layout/gesture_tutorial_foldable_mock_taskbar.xml
rename to quickstep/res/layout/gesture_tutorial_tablet_mock_taskbar.xml
diff --git a/quickstep/res/layout/gesture_tutorial_foldable_mock_webpage.xml b/quickstep/res/layout/gesture_tutorial_tablet_mock_webpage.xml
similarity index 100%
rename from quickstep/res/layout/gesture_tutorial_foldable_mock_webpage.xml
rename to quickstep/res/layout/gesture_tutorial_tablet_mock_webpage.xml
diff --git a/quickstep/res/layout/predicted_hotseat_edu.xml b/quickstep/res/layout/predicted_hotseat_edu.xml
index e4e3956..f0c12f1 100644
--- a/quickstep/res/layout/predicted_hotseat_edu.xml
+++ b/quickstep/res/layout/predicted_hotseat_edu.xml
@@ -42,6 +42,7 @@
android:paddingLeft="@dimen/bottom_sheet_edu_padding"
android:paddingRight="@dimen/bottom_sheet_edu_padding"
android:text="@string/hotseat_edu_title_migrate"
+ android:fontFamily="google-sans"
android:textAlignment="center"
android:textColor="@android:color/white"
android:textSize="20sp" />
diff --git a/quickstep/res/layout/taskbar_all_apps.xml b/quickstep/res/layout/taskbar_all_apps.xml
new file mode 100644
index 0000000..34d4b23
--- /dev/null
+++ b/quickstep/res/layout/taskbar_all_apps.xml
@@ -0,0 +1,66 @@
+<?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.
+-->
+<com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <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"
+ android:theme="?attr/allAppsTheme">
+
+ <include
+ layout="@layout/all_apps_bottom_sheet_background"
+ android:visibility="gone" />
+
+ <include
+ layout="@layout/search_results_rv_layout"
+ android:visibility="gone" />
+
+ <include
+ layout="@layout/all_apps_rv_layout"
+ android:visibility="gone" />
+
+ <com.android.launcher3.allapps.FloatingHeaderView
+ android:id="@+id/all_apps_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/search_container_all_apps"
+ android:clipToPadding="false"
+ android:paddingTop="@dimen/all_apps_header_top_padding"
+ android:orientation="vertical">
+
+ <include layout="@layout/floating_header_content" />
+
+ <include layout="@layout/all_apps_personal_work_tabs" />
+ </com.android.launcher3.allapps.FloatingHeaderView>
+
+ <com.android.launcher3.taskbar.allapps.TaskbarAllAppsFallbackSearchContainer
+ android:id="@+id/search_container_all_apps"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:visibility="gone" />
+
+ <include layout="@layout/all_apps_fast_scroller" />
+ </com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView>
+</com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView>
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index a842d3c..e834157 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Jy het die \"wissel tussen programme\"-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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Gereed!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Swiep op om na die tuisskerm toe te gaan"</string>
<string name="allset_description" msgid="6350320429953234580">"Jy is gereed om jou foon te begin gebruik"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Jy is gereed om jou tablet te begin gebruik"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Stelselnavigasie-instellings"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Deel"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Skermkiekie"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Toeganklikheid"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Terug"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME-wisselaar"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Onlangs"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Kennisgewings"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Kitsinstellings"</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>
</resources>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index ce14b54..342bbe2 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"የወደ መነሻ ሂድ ምልክትን አጠናቀዋል።"</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"መተግበሪያዎችን የመቀያየር ምልክትን አጠናቀዋል።"</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"ሁሉም ዝግጁ!"</string>
<string name="allset_hint" msgid="2384632994739392447">"ወደ መነሻ ለመሄድ በጣት ወደ ላይ ማንሸራተት"</string>
<string name="allset_description" msgid="6350320429953234580">"ስልክዎን መጠቀም ለመጀመር ዝግጁ ነዎት"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"ጡባዊዎን መጠቀም ለመጀመር ዝግጁ ነዎት"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"የስርዓት አሰሳ ቅንብሮች"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"አጋራ"</string>
<string name="action_screenshot" msgid="8171125848358142917">"ቅጽበታዊ ገጽ እይታ"</string>
@@ -97,4 +101,13 @@
<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_back" msgid="8558862226461164514">"ተመለስ"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"አይኤምኢ መቀየሪያ"</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="move_drop_target_top_or_left" msgid="2988702185049595807">"ወደ ላይ/ግራ ይውሰዱ"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ወደ ታች/ቀኝ ይውሰዱ"</string>
</resources>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index afe2156..f15fcd4 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"أكملت التدريب على إيماءة الانتقال إلى الشاشة الرئيسية."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"أكملت التدريب على إيماءة التبديل بين التطبيقات."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"اكتملت عملية الإعداد"</string>
<string name="allset_hint" msgid="2384632994739392447">"مرِّر سريعًا للأعلى للانتقال إلى الشاشة الرئيسية."</string>
<string name="allset_description" msgid="6350320429953234580">"يمكنك الآن بدء استخدام هاتفك."</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"يمكنك الآن بدء استخدام جهازك اللوحي."</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"إعدادات التنقّل داخل النظام"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"مشاركة"</string>
<string name="action_screenshot" msgid="8171125848358142917">"لقطة شاشة"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"الانتقال إلى يمين الشاشة أو أعلاها"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"الانتقال إلى يسار الشاشة أو أسفلها"</string>
</resources>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index 62c472e..b33abed 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"আপুনি গৃহ স্ক্ৰীনলৈ যোৱাৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে।"</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"আপুনি এপ্ সলনি কৰাৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে।"</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"সকলো সাজু!"</string>
<string name="allset_hint" msgid="2384632994739392447">"গৃহ স্ক্ৰীনলৈ যাবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string>
<string name="allset_description" msgid="6350320429953234580">"আপুনি আপোনাৰ ফ’নটো ব্যৱহাৰ কৰিবলৈ সাজু"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"আপুনি আপোনাৰ টেবলেটটো ব্যৱহাৰ কৰিবলৈ সাজু"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"ছিষ্টেম নেভিগেশ্বনৰ ছেটিং"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"শ্বেয়াৰ কৰক"</string>
<string name="action_screenshot" msgid="8171125848358142917">"স্ক্ৰীনশ্বট"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"ওপৰৰ বাঁওফাললৈ নিয়ক"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"তলৰ সোঁফাললৈ নিয়ক"</string>
</resources>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index 91d09f5..07e29bb 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Əsas səhifəyə keçmə 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="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>
@@ -67,6 +69,7 @@
<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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Hər şey hazırdır!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Əsas səhifəyə keçmək üçün yuxarı çəkin"</string>
<string name="allset_description" msgid="6350320429953234580">"Telefondan istifadəyə başlamağa hazırsınız"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Planşetdən istifadəyə başlamağa hazırsınız"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Sistem naviqasiya ayarları"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Paylaşın"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Skrinşot"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Əlçatımlılıq"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Geriyə"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME keçiricisi"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Sonuncular"</string>
+ <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="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>
</resources>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index 92fd21d..42023d3 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Gotovo!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Prevucite nagore da biste otvorili početni ekran"</string>
<string name="allset_description" msgid="6350320429953234580">"Spremni ste da počnete da koristite telefon"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Spremni ste da počnete da koristite tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Podešavanja kretanja kroz sistem"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Deli"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Snimak ekrana"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Pristupačnost"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Nazad"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME prebacivač"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Nedavno"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Obaveštenja"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Brza podešavanja"</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>
</resources>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index 2bdea32..dc4dc65 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Вы навучыліся рабіць жэст пераходу на галоўны экран."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Вы навучыліся рабіць жэст пераключэння паміж праграмамі."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Гатова!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Каб перайсці на галоўны экран, правядзіце пальцам уверх"</string>
<string name="allset_description" msgid="6350320429953234580">"Вы можаце пачаць карыстанне тэлефонам"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Вы можаце пачаць карыстанне планшэтам"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Налады навігацыі ў сістэме"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Абагуліць"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Здымак экрана"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"Перамясціць уверх/улева"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Перамясціць уніз/управа"</string>
</resources>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index fd9a3cd..560a03b 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Изпълнихте жеста за преминаване към началния екран."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Изпълнихте жеста за превключване между приложения."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Готово!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Прекарайте пръст нагоре, за да отворите началния екран"</string>
<string name="allset_description" msgid="6350320429953234580">"Можете да започнете да използвате телефона си"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Можете да започнете да използвате таблета си"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Настройки за навигиране в системата"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Споделяне"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Екранна снимка"</string>
@@ -97,4 +101,13 @@
<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_back" msgid="8558862226461164514">"Назад"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Редактор за метода на въвежд.: Превключвател"</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="move_drop_target_top_or_left" msgid="2988702185049595807">"Преместване горе/вляво"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Преместване долу/вдясно"</string>
</resources>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index 799fe0b..d4774a7 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"আপনি হোম স্ক্রিনে যাওয়ার জেসচার সম্পর্কে জেনেছেন।"</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"আপনি একটি অ্যাপ থেকে অন্য অ্যাপে যাওয়ার জেসচার সম্পর্কে জেনেছেন।"</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"সব রেডি!"</string>
<string name="allset_hint" msgid="2384632994739392447">"হোম স্ক্রিনে যেতে উপরের দিকে সোয়াইপ করুন"</string>
<string name="allset_description" msgid="6350320429953234580">"এবারে আপনি ফোন ব্যবহার করতে পারবেন"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"এবারে আপনি ট্যাবলেট ব্যবহার করতে পারবেন"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"সিস্টেম নেভিগেশন সেটিংস"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"শেয়ার করুন"</string>
<string name="action_screenshot" msgid="8171125848358142917">"স্ক্রিনশট নিন"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"উপরে/বাঁদিকে সরান"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"নিচে/ডানদিকে সরান"</string>
</resources>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index bb6c415..3743e24 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -53,6 +53,7 @@
<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_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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Sve je spremno!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Prevucite prema gore da odete na početni ekran"</string>
<string name="allset_description" msgid="6350320429953234580">"Sve je spremno da počnete koristiti telefon"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Sve je spremno da počnete koristiti tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Postavke navigiranja sistemom"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Dijeli"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Snimak ekrana"</string>
@@ -97,4 +101,13 @@
<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">"Dom"</string>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Pristupačnost"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Nazad"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME prebacivač"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Nedavno"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Obavještenja"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Brze postavke"</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>
</resources>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index 2e57be3..9400fba 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<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="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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Tot a punt!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Llisca cap amunt per anar a la pàgina d\'inici"</string>
<string name="allset_description" msgid="6350320429953234580">"Ja pots començar a utilitzar el telèfon"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Ja pots començar a utilitzar la tauleta"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Configuració de navegació del sistema"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Comparteix"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Captura de pantalla"</string>
@@ -97,4 +101,13 @@
<string name="taskbar_edu_previous" msgid="459202320127201702">"Enrere"</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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Accessibilitat"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Enrere"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Selector d\'IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Recents"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notificacions"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Config. ràpida"</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>
</resources>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index 749ebce..cb49a35 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -53,6 +53,7 @@
<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_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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Hotovo!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Přejetím nahoru se vrátíte na plochu"</string>
<string name="allset_description" msgid="6350320429953234580">"Jste připraveni začít používat telefon"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Jste připraveni začít používat tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Nastavení navigace v systému"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Sdílet"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Snímek obrazovky"</string>
@@ -97,4 +101,13 @@
<string name="taskbar_edu_previous" msgid="459202320127201702">"Zpět"</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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Přístupnost"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Zpět"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Přepínač IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Poslední"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Oznámení"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Rychlé nastavení"</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>
</resources>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index 2747cc0..621006b 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<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="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="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>
@@ -67,6 +69,7 @@
<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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Alt er parat!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Stryg opad for at gå til startsiden"</string>
<string name="allset_description" msgid="6350320429953234580">"Du er klar til at bruge din telefon"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Du er klar til at bruge din tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Indstillinger for systemnavigation"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Del"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Hjælpefunktioner"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Tilbage"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME-vælger"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Seneste"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifikationer"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Kvikmenu"</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>
</resources>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 7a203a1..d19c23b 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<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="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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Du hast 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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Fertig!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Nach oben wischen, um den Startbildschirm aufzurufen"</string>
<string name="allset_description" msgid="6350320429953234580">"Du kannst dein Smartphone jetzt verwenden"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Du kannst dein Tablet jetzt verwenden"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Einstellungen der Systemsteuerung"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Teilen"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Bedienungshilfen"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Zurück"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME-Wechsler"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Letzte Apps"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Benachrichtigungen"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Schnelleinstellungen"</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>
</resources>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index e1f709d..2c6702b 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Ολοκληρώσατε την κίνηση μετάβασης στην αρχική οθόνη."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Ολοκληρώσατε την κίνηση εναλλαγής εφαρμογών."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Όλα έτοιμα!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Σύρετε προς τα πάνω για μετάβαση στην αρχική οθόνη."</string>
<string name="allset_description" msgid="6350320429953234580">"Είστε έτοιμοι να ξεκινήσετε να χρησιμοποιείτε το τηλέφωνό σας"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Είστε έτοιμοι να ξεκινήσετε να χρησιμοποιείτε το tablet."</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Ρυθμίσεις πλοήγησης συστήματος"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Κοινοποίηση"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Στιγμιότυπο οθόνης"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"Μετακίνηση επάνω/αριστερά"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Μετακίνηση κάτω/δεξιά"</string>
</resources>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index 487ea72..7b297af 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"You completed the go home gesture."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Swipe to go home"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Swipe up from the bottom of your screen. This gesture always takes you to the home screen."</string>
+ <string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Swipe up with two fingers from the bottom of the screen. This gesture always takes you to the home screen."</string>
<string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Make sure that you swipe up from the bottom edge of the screen."</string>
<string name="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"You completed the switch apps gesture."</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Swipe to switch apps"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"To switch between apps, swipe up from the bottom of your screen, hold, then release."</string>
+ <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"To switch between apps, swipe up with two fingers from the bottom of your screen, hold, then release."</string>
<string name="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Ready!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Swipe up to go home"</string>
<string name="allset_description" msgid="6350320429953234580">"You’re ready to start using your phone"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"You’re ready to start using your tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"System navigation settings"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Share"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Accessibility"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Back"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME switcher"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Recents"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifications"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</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>
</resources>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index 8c98e3c..4013a71 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"You completed the go home gesture."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Swipe to go home"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Swipe up from the bottom of your screen. This gesture always takes you to the home screen."</string>
+ <string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Swipe up with two fingers from the bottom of the screen. This gesture always takes you to the home screen."</string>
<string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Make sure that you swipe up from the bottom edge of the screen."</string>
<string name="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"You completed the switch apps gesture."</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Swipe to switch apps"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"To switch between apps, swipe up from the bottom of your screen, hold, then release."</string>
+ <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"To switch between apps, swipe up with two fingers from the bottom of your screen, hold, then release."</string>
<string name="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Ready!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Swipe up to go home"</string>
<string name="allset_description" msgid="6350320429953234580">"You’re ready to start using your phone"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"You’re ready to start using your tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"System navigation settings"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Share"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Accessibility"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Back"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME switcher"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Recents"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifications"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</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>
</resources>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index 487ea72..7b297af 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"You completed the go home gesture."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Swipe to go home"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Swipe up from the bottom of your screen. This gesture always takes you to the home screen."</string>
+ <string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Swipe up with two fingers from the bottom of the screen. This gesture always takes you to the home screen."</string>
<string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Make sure that you swipe up from the bottom edge of the screen."</string>
<string name="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"You completed the switch apps gesture."</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Swipe to switch apps"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"To switch between apps, swipe up from the bottom of your screen, hold, then release."</string>
+ <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"To switch between apps, swipe up with two fingers from the bottom of your screen, hold, then release."</string>
<string name="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Ready!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Swipe up to go home"</string>
<string name="allset_description" msgid="6350320429953234580">"You’re ready to start using your phone"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"You’re ready to start using your tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"System navigation settings"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Share"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Accessibility"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Back"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME switcher"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Recents"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifications"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</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>
</resources>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index 487ea72..7b297af 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"You completed the go home gesture."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Swipe to go home"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Swipe up from the bottom of your screen. This gesture always takes you to the home screen."</string>
+ <string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Swipe up with two fingers from the bottom of the screen. This gesture always takes you to the home screen."</string>
<string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Make sure that you swipe up from the bottom edge of the screen."</string>
<string name="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"You completed the switch apps gesture."</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Swipe to switch apps"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"To switch between apps, swipe up from the bottom of your screen, hold, then release."</string>
+ <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"To switch between apps, swipe up with two fingers from the bottom of your screen, hold, then release."</string>
<string name="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Ready!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Swipe up to go home"</string>
<string name="allset_description" msgid="6350320429953234580">"You’re ready to start using your phone"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"You’re ready to start using your tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"System navigation settings"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Share"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Accessibility"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Back"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME switcher"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Recents"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifications"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</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>
</resources>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index fa9e467..bd2a024 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"You completed the go Home gesture."</string>
<string name="home_gesture_intro_title" msgid="836590312858441830">"Swipe to go home"</string>
<string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Swipe up from the bottom of your screen. This gesture always takes you to the Home screen."</string>
+ <string name="home_gesture_spoken_intro_subtitle" msgid="1030987707382031750">"Swipe up with 2 fingers from the bottom of the screen. This gesture always takes you to the Home screen."</string>
<string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Make sure you swipe up from the bottom edge of the screen."</string>
<string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Try holding the window for longer before releasing."</string>
<string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Make sure you swipe straight up, then pause."</string>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"You completed the switch apps gesture."</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Swipe to switch apps"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"To switch between apps, swipe up from the bottom of your screen, hold, then release."</string>
+ <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"To switch between apps, swipe up with 2 fingers from the bottom of your screen, hold, then release."</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"All set"</string>
<string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Done"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Settings"</string>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"All set!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Swipe up to go Home"</string>
<string name="allset_description" msgid="6350320429953234580">"You’re ready to start using your phone"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"You’re ready to start using your tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027">""<annotation id="link">"System navigation settings"</annotation>""</string>
<string name="action_share" msgid="2648470652637092375">"Share"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Accessibility"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Back"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME switcher"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Recents"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifications"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</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>
</resources>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index 4424735..06ee5bb 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Todo listo"</string>
<string name="allset_hint" msgid="2384632994739392447">"Desliza el dedo hacia arriba para ir a la pantalla principal"</string>
<string name="allset_description" msgid="6350320429953234580">"Ya puedes empezar a usar tu teléfono"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Ya puedes empezar a usar tu tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Configuración de navegación del sistema"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Compartir"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Captura de pantalla"</string>
@@ -97,4 +101,13 @@
<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">"Listo"</string>
+ <string name="taskbar_button_home" msgid="2151398979630664652">"Botón de inicio"</string>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Accesibilidad"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Atrás"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Botón de IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Recientes"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notificaciones"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Config. rápida"</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>
</resources>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 9f452f8..80c8b0b 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<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="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="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>
@@ -67,6 +69,7 @@
<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_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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"¡Ya está!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Desliza el dedo hacia arriba para ir a la pantalla de inicio"</string>
<string name="allset_description" msgid="6350320429953234580">"Ya puedes empezar a usar tu teléfono"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Ya puedes empezar a usar tu tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Ajustes de navegación del sistema"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Compartir"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Hacer captura"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Accesibilidad"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Atrás"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Interruptor IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Recientes"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notificaciones"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Ajustes rápidos"</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>
</resources>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 6752384..7f37a4b 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Valmis!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Avakuvale liikumiseks pühkige üles"</string>
<string name="allset_description" msgid="6350320429953234580">"Olete valmis oma telefoni kasutama."</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Olete valmis oma tahvelarvutit kasutama"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Süsteemi navigeerimisseaded"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Jaga"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Ekraanipilt"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Juurdepääsetavus"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Tagasi"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME vahetaja"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Hiljutised"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Märguanded"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Kiirseaded"</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>
</resources>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index 242ce09..4169838 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Ikasi duzu aplikazioa 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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Dena prest!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Pasatu hatza gora hasierako pantailara joateko"</string>
<string name="allset_description" msgid="6350320429953234580">"Prest zaude telefonoa erabiltzen hasteko"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Prest zaude tableta erabiltzen hasteko"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Sisteman nabigatzeko ezarpenak"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Partekatu"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Atera pantaila-argazki bat"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Erabilerraztasuna"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Atzera"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IMEaren etengailua"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Azkenak"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Jakinarazpenak"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Ezarpen bizkorrak"</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>
</resources>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index 3ba4272..de6d7e5 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"اشاره رفتن به «صفحه اصلی» را تکمیل کردید."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"اشاره جابهجا شدن بین برنامهها را تکمیل کردید."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"همه چیز آماده است!"</string>
<string name="allset_hint" msgid="2384632994739392447">"برای رفتن به «صفحه اصلی»، تند بهبالا بکشید"</string>
<string name="allset_description" msgid="6350320429953234580">"آمادهاید از تلفنتان استفاده کنید"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"آمادهاید از رایانه لوحیتان استفاده کنید"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"تنظیمات پیمایش سیستم"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"همرسانی"</string>
<string name="action_screenshot" msgid="8171125848358142917">"نماگرفت"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"انتقال به بالا/ چپ"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"انتقال به پایین/ راست"</string>
</resources>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index 52aa9b4..8c50f70 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Olet oppinut aloitusnäytölle palaamisen eleen."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Valmis"</string>
<string name="allset_hint" msgid="2384632994739392447">"Siirry aloitusnäytölle pyyhkäisemällä ylös"</string>
<string name="allset_description" msgid="6350320429953234580">"Olet valmis aloittamaan puhelimen käytön"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Olet valmis aloittamaan tabletin käytön"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Järjestelmän navigointiasetukset"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Jaa"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Kuvakaappaus"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Esteettömyys"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Takaisin"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME-vaihtopalvelu"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Viimeaikaiset"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Ilmoitukset"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Pika-asetukset"</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>
</resources>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 0ba184f..f92d55c 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -53,6 +53,7 @@
<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_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>
@@ -60,6 +61,7 @@
<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="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="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>
@@ -67,6 +69,7 @@
<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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Tout est prêt!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Balayez l\'écran vers le haut pour accéder à l\'écran d\'accueil"</string>
<string name="allset_description" msgid="6350320429953234580">"Vous êtes maintenant prêt à utiliser votre téléphone"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Vous êtes maintenant prêt à utiliser votre tablette"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Paramètres de navigation du système"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Partager"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Capture d\'écran"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Accessibilité"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Retour"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Sélecteur IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Récents"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifications"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Paramètres rapides"</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>
</resources>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index a33a751..9ffa0cc 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<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="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="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>
@@ -67,6 +69,7 @@
<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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Tout est prêt !"</string>
<string name="allset_hint" msgid="2384632994739392447">"Balayez l\'écran vers le haut pour revenir à l\'accueil"</string>
<string name="allset_description" msgid="6350320429953234580">"Vous pouvez maintenant utiliser votre téléphone"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Vous pouvez maintenant utiliser votre tablette"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Paramètres de navigation système"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Partager"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Capture d\'écran"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Accessibilité"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Retour"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Sélecteur IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Récents"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifications"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Réglages rapides"</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>
</resources>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 94a21b2..bea23b7 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Todo listo"</string>
<string name="allset_hint" msgid="2384632994739392447">"Pasa o dedo cara arriba para ir á pantalla de inicio"</string>
<string name="allset_description" msgid="6350320429953234580">"Xa podes comezar a utilizar o teléfono"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Todo está listo para comezar a utilizar a tableta"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Configuración da navegación do sistema"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Compartir"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Facer captura"</string>
@@ -97,4 +101,13 @@
<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_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>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Selector do IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Recentes"</string>
+ <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="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>
</resources>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 4b2e177..a146b24 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"તમે હોમ સ્ક્રીન પર પાછા જવાનો સંકેત પૂર્ણ કર્યો છે."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"તમે ઍપ સ્વિચ કરવાનો સંકેત પૂર્ણ કર્યો છે."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"બધું સેટ થઈ ગયું!"</string>
<string name="allset_hint" msgid="2384632994739392447">"હોમપેજ પર જવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string>
<string name="allset_description" msgid="6350320429953234580">"તમે તમારા ફોનનો ઉપયોગ કરવા માટે તૈયાર છો"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"તમે તમારા ટૅબ્લેટનો ઉપયોગ કરવા માટે તૈયાર છો"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"સિસ્ટમના નૅવિગેશન સેટિંગ"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"શેર કરો"</string>
<string name="action_screenshot" msgid="8171125848358142917">"સ્ક્રીનશૉટ"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"સૌથી ઉપર ડાબી બાજુએ ખસેડો"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"સૌથી નીચે જમણી બાજુએ ખસેડો"</string>
</resources>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index c778f83..c938e6b 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -45,28 +45,31 @@
<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_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="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"देख लें कि आप स्क्रीन पर बिलकुल नीचे तक स्वाइप न कर रहे हों."</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_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="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="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_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="overview_gesture_intro_subtitle" msgid="4968091015637850859">"एक ऐप से दूसरे पर जाने के लिए, स्क्रीन पर नीचे से ऊपर की ओर स्वाइप करें, दबाकर रखें, और फिर छोड़ दें."</string>
+ <string name="overview_gesture_spoken_intro_subtitle" msgid="3853371838260201751">"इन ऐप के बीच स्विच करने के लिए, दो उंगलियों से नीचे से ऊपर स्वाइप करें, होल्ड करें, और फिर छोड़ें."</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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"हो गया!"</string>
<string name="allset_hint" msgid="2384632994739392447">"होम स्क्रीन पर जाने के लिए, ऊपर की ओर स्वाइप करें"</string>
<string name="allset_description" msgid="6350320429953234580">"अब आपका फ़ोन, इस्तेमाल के लिए तैयार है"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"आप टैबलेट को इस्तेमाल करने के लिए तैयार हैं"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"सिस्टम नेविगेशन सेटिंग"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"शेयर करें"</string>
<string name="action_screenshot" msgid="8171125848358142917">"स्क्रीनशॉट लें"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"ऊपर/बाईं तरफ़ ले जाएं"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"नीचे/दाईं तरफ़ ले जाएं"</string>
</resources>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index 32876a0..640d7cc 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -53,6 +53,7 @@
<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_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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Sve je spremno!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Prijeđite prstom prema gore da biste otvorili početni zaslon"</string>
<string name="allset_description" msgid="6350320429953234580">"Spremni ste za početak upotrebe telefona"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Spremni ste za početak upotrebe tableta"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Postavke navigacije sustavom"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Podijeli"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Snimka zaslona"</string>
@@ -97,4 +101,13 @@
<string name="taskbar_edu_previous" msgid="459202320127201702">"Natrag"</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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Pristupačnost"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Natrag"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME prekidač"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Najnovije"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Obavijesti"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Brze postavke"</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>
</resources>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index b0e53ce..6369293 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<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="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="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>
@@ -67,6 +69,7 @@
<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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Kész is!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Felfelé csúsztatva megjelenik a Kezdőképernyő"</string>
<string name="allset_description" msgid="6350320429953234580">"Készen áll a telefon használatára"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Készen áll a táblagép használatára"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Rendszer-navigációs beállítások"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Megosztás"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Képernyőkép"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Kisegítő lehetőségek"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Vissza"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME-váltó"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Legutóbbiak"</string>
+ <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="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>
</resources>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index 8664238..9eeaa98 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Դուք սովորեցիք հիմնական էկրան անցնելու ժեստը։"</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Դուք սովորեցիք մի հավելվածից մյուսն անցնելու ժեստը։"</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Պատրաստ է"</string>
<string name="allset_hint" msgid="2384632994739392447">"Մատը սահեցրեք վերև՝ հիմնական էկրան անցնելու համար"</string>
<string name="allset_description" msgid="6350320429953234580">"Դուք արդեն կարող եք օգտագործել ձեր հեռախոսը"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Դուք արդեն կարող եք օգտագործել ձեր պլանշետը"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Նավիգացիայի համակարգային կարգավորումներ"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Կիսվել"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Սքրինշոթ անել"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"Տեղափոխել վերևի ձախ անկյուն"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Տեղափոխել ներքևի աջ անկյուն"</string>
</resources>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index 1752adc..14d8c3e 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -53,6 +53,7 @@
<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_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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Anda telah menyelesaikan gestur menuju 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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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_spoken_intro_subtitle" msgid="3853371838260201751">"Untuk beralih antar-aplikasi, geser ke atas dengan 2 jari dari bawah layar, tahan, lalu lepaskan."</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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Semua siap."</string>
<string name="allset_hint" msgid="2384632994739392447">"Geser ke atas untuk beralih ke Layar utama"</string>
<string name="allset_description" msgid="6350320429953234580">"Anda sudah siap untuk mulai menggunakan ponsel"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Anda sudah siap untuk mulai menggunakan tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Setelan navigasi sistem"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Bagikan"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
@@ -97,4 +101,13 @@
<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">"Layar utama"</string>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Aksesibilitas"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Kembali"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Pengalih IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Terbaru"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifikasi"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Setelan Cepat"</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>
</resources>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index 22099e4..1761203 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Þú 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="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>
@@ -67,6 +69,7 @@
<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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Allt tilbúið!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Strjúktu upp til að fara á heimaskjáinn"</string>
<string name="allset_description" msgid="6350320429953234580">"Þú getur byrjað að nota símann"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Þú getur byrjað að nota spjaldtölvuna"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Stillingar kerfisstjórnunar"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Deila"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Skjámynd"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Aðgengi"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Til baka"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Breyta innsláttaraðferð"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Nýlegt"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Tilkynningar"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Flýtistillingar"</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>
</resources>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index 1db4e28..874d072 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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_spoken_intro_subtitle" msgid="3853371838260201751">"Per spostarti tra le app, scorri verso l\'alto con 2 dita, tieni premuto e rilascia."</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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Finito."</string>
<string name="allset_hint" msgid="2384632994739392447">"Scorri verso l\'alto per andare alla schermata Home"</string>
<string name="allset_description" msgid="6350320429953234580">"Puoi iniziare a usare il tuo telefono"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Puoi iniziare a usare il tuo tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Impostazioni Navigazione del sistema"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Condividi"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
@@ -97,4 +101,13 @@
<string name="taskbar_edu_previous" msgid="459202320127201702">"Indietro"</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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Accessibilità"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Indietro"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Selettore IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Recenti"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notifiche"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Impostazioni rapide"</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>
</resources>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index 4feb9ee..09d76f8 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"השלמת את תנועת המעבר למסך הבית."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"השלמת את תנועת המעבר בין האפליקציות."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"הכול מוכן!"</string>
<string name="allset_hint" msgid="2384632994739392447">"כדי לעבור לדף הבית, מחליקים כלפי מעלה"</string>
<string name="allset_description" msgid="6350320429953234580">"הכול מוכן ואפשר להתחיל להשתמש בטלפון"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"הכול מוכן ואפשר להתחיל להשתמש בטאבלט"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"הגדרות הניווט של המערכת"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"שיתוף"</string>
<string name="action_screenshot" msgid="8171125848358142917">"צילום מסך"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"העברה לפינה השמאלית/העליונה"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"העברה לפינה הימנית/התחתונה"</string>
</resources>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 94e3bf5..50c031e 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"「ホームに戻る」操作を学習しました。"</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"「アプリを切り替える」操作を完了しました。"</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"設定完了"</string>
<string name="allset_hint" msgid="2384632994739392447">"ホームに移動するには上にスワイプします"</string>
<string name="allset_description" msgid="6350320429953234580">"スマートフォンを使用する準備ができました"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"これでタブレットが使えるようになりました"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"システム ナビゲーションの設定"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"共有"</string>
<string name="action_screenshot" msgid="8171125848358142917">"スクリーンショット"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"上 / 左に移動"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"下 / 右に移動"</string>
</resources>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index a5c411c..2bc0108 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"თქვენ შეასრულეთ მთავარ ეკრანზე დაბრუნების ჟესტი."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"თქვენ შეასრულეთ აპების გადართვის ჟესტი."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"მზადაა!"</string>
<string name="allset_hint" msgid="2384632994739392447">"მთავარ გვერდზე გადასასვლელად გადაფურცლეთ ზევით"</string>
<string name="allset_description" msgid="6350320429953234580">"მზად ხართ ტელეფონის გამოსაყენებლად"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"მზად ხართ ტაბლეტის გამოსაყენებლად"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"სისტემის ნავიგაციის პარამეტრები"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"გაზიარება"</string>
<string name="action_screenshot" msgid="8171125848358142917">"ეკრანის ანაბეჭდი"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"ზემოთ/მარცხნივ გადატანა"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ქვემოთ/მარჯვნივ გადატანა"</string>
</resources>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index 70a19fe..7758125 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Негізгі экранға қайту қимылын аяқтадыңыз."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Қолданбаларды ауыстыру қимылын аяқтадыңыз."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Бәрі дайын!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Негізгі экранға өту үшін жоғары қарай сырғытыңыз."</string>
<string name="allset_description" msgid="6350320429953234580">"Телефоныңыз пайдалануға дайын."</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Планшетіңіз пайдалануға дайын."</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Навигацияның жүйелік параметрлері"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Бөлісу"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"Жоғары/солға жылжыту"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Төмен/оңға жылжыту"</string>
</resources>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index ead6dc6..93b2361 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"អ្នកបានបញ្ចប់ចលនាចូលទៅកាន់ទំព័រដើមហើយ។"</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"អ្នកបានបញ្ចប់ចលនាប្ដូរកម្មវិធីហើយ។"</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"រួចហើយ!"</string>
<string name="allset_hint" msgid="2384632994739392447">"អូសឡើងលើ ដើម្បីទៅកាន់អេក្រង់ដើម"</string>
<string name="allset_description" msgid="6350320429953234580">"អ្នកអាចចាប់ផ្ដើមប្រើទូរសព្ទរបស់អ្នកបានហើយ"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"អ្នកអាចចាប់ផ្ដើមប្រើថេប្លេតរបស់អ្នកបានហើយ"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"ការកំណត់ការរុករកប្រព័ន្ធ"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"ចែករំលែក"</string>
<string name="action_screenshot" msgid="8171125848358142917">"រូបថតអេក្រង់"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"ផ្លាស់ទីទៅខាងលើ/ឆ្វេង"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ផ្លាស់ទីទៅខាងក្រោម/ស្ដាំ"</string>
</resources>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 6c6649c..2c1f699 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"ನೀವು ಗೋ ಹೋಮ್ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"ನೀವು ಆ್ಯಪ್ಗಳನ್ನು ಬದಲಾಯಿಸುವ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"ಎಲ್ಲವೂ ಸಿದ್ಧವಾಗಿದೆ!"</string>
<string name="allset_hint" msgid="2384632994739392447">"ಮುಖಪುಟಕ್ಕೆ ಹೋಗಲು ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="allset_description" msgid="6350320429953234580">"ನಿಮ್ಮ ಫೋನ್ ಬಳಸುವುದನ್ನು ಪ್ರಾರಂಭಿಸಲು ನೀವು ಸಿದ್ದರಾಗಿರುವಿರಿ"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ ಬಳಸುವುದನ್ನು ಪ್ರಾರಂಭಿಸಲು ನೀವು ಸಿದ್ದರಾಗಿರುವಿರಿ"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"ಸಿಸ್ಟಂ ನ್ಯಾವಿಗೇಶನ್ ಸೆಟ್ಟಿಂಗ್ಗಳು"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"ಹಂಚಿಕೊಳ್ಳಿ"</string>
<string name="action_screenshot" msgid="8171125848358142917">"ಸ್ಕ್ರೀನ್ಶಾಟ್"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"ಮೇಲಿನ/ಎಡಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ಕೆಳಗಿನ/ಬಲಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
</resources>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index aab3847..6626bc1 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"홈으로 이동 동작을 완료했습니다."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"앱 전환 동작을 완료했습니다."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"설정 완료"</string>
<string name="allset_hint" msgid="2384632994739392447">"위로 스와이프하여 홈으로 이동"</string>
<string name="allset_description" msgid="6350320429953234580">"휴대전화를 사용할 준비가 되었습니다."</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"태블릿을 사용할 준비가 되었습니다."</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"시스템 탐색 설정"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"공유"</string>
<string name="action_screenshot" msgid="8171125848358142917">"스크린샷"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"상단/왼쪽으로 이동"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"하단/오른쪽으로 이동"</string>
</resources>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 7d1574d..dac4d1d 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"\"Башкы бетке өтүү\" жаңсоосун үйрөндүңүз."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"\"Колдонмолорду которуштуруу\" жаңсоосун үйрөндүңүз."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Бүттү!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Башкы бетке өтүү үчүн экранды өйдө сүрүңүз"</string>
<string name="allset_description" msgid="6350320429953234580">"Телефонуңузду колдоно берсеңиз болот"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Планшетиңизди колдоно берсеңиз болот"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Өтүү аракетинин системалык параметрлери"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Бөлүшүү"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"Жогорку/сол бурчка жылдыруу"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Төмөнкү/оң бурчка жылдыруу"</string>
</resources>
diff --git a/quickstep/res/values-land/dimens.xml b/quickstep/res/values-land/dimens.xml
index 668aea2..f233bde 100644
--- a/quickstep/res/values-land/dimens.xml
+++ b/quickstep/res/values-land/dimens.xml
@@ -16,4 +16,61 @@
-->
<resources>
<dimen name="overview_task_margin">8dp</dimen>
+
+ <!-- Tips Gesture Tutorial -->
+ <dimen name="gesture_tutorial_feedback_margin_start_end">126dp</dimen>
+ <dimen name="gesture_tutorial_feedback_margin_top">24dp</dimen>
+
+ <!-- Gesture Tutorial mock conversations -->
+ <dimen name="gesture_tutorial_message_padding_start">42dp</dimen>
+ <dimen name="gesture_tutorial_message_padding_end">60dp</dimen>
+ <dimen name="gesture_tutorial_top_bar_margin_start">42dp</dimen>
+ <dimen name="gesture_tutorial_top_bar_margin_end">683dp</dimen>
+ <dimen name="gesture_tutorial_top_bar_button_margin_end">42dp</dimen>
+ <dimen name="gesture_tutorial_conversation_bottom_padding">35dp</dimen>
+ <integer name="gesture_tutorial_extra_messages_visibility">2</integer> <!-- GONE -->
+ <dimen name="gesture_tutorial_message_margin_start">505dp</dimen>
+ <dimen name="gesture_tutorial_reply_margin_end">462dp</dimen>
+ <dimen name="gesture_tutorial_input_margin_start">103dp</dimen>
+ <dimen name="gesture_tutorial_input_margin_end">103dp</dimen>
+ <dimen name="gesture_tutorial_tablet_message_1_margin">345dp</dimen>
+ <dimen name="gesture_tutorial_tablet_reply_1_margin">341dp</dimen>
+ <dimen name="gesture_tutorial_tablet_message_2_margin">501dp</dimen>
+ <dimen name="gesture_tutorial_tablet_message_3_margin">345dp</dimen>
+ <dimen name="gesture_tutorial_tablet_reply_2_margin">373dp</dimen>
+
+ <!-- Gesture Tutorial mock conversation lists -->
+ <dimen name="gesture_tutorial_conversation_line_1_margin_end">607dp</dimen>
+ <dimen name="gesture_tutorial_conversation_line_2_margin_end">460dp</dimen>
+ <dimen name="gesture_tutorial_conversation_line_3_margin_end">554dp</dimen>
+ <dimen name="gesture_tutorial_conversation_line_4_margin_end">517dp</dimen>
+ <dimen name="gesture_tutorial_conversation_line_5_margin_end">570dp</dimen>
+ <dimen name="gesture_tutorial_conversation_line_6_margin_end">336dp</dimen>
+ <dimen name="gesture_tutorial_conversation_line_7_margin_end">523dp</dimen>
+ <dimen name="gesture_tutorial_conversation_line_8_margin_end">500dp</dimen>
+ <dimen name="gesture_tutorial_tablet_conversation_line_6_margin_end">15dp</dimen>
+ <dimen name="gesture_tutorial_tablet_conversation_line_8_margin_end">72dp</dimen>
+ <dimen name="gesture_tutorial_tablet_conversation_line_10_margin_end">111dp</dimen>
+ <integer name="gesture_tutorial_extra_conversations_visibility">2</integer> <!-- GONE -->
+ <dimen name="gesture_tutorial_mock_button_margin_end">34dp</dimen>
+ <dimen name="gesture_tutorial_mock_button_margin_bottom">42dp</dimen>
+
+ <!-- Gesture Tutorial mock hotseats -->
+ <dimen name="gesture_tutorial_hotseat_width">-2px</dimen> <!-- wrap_content -->
+ <dimen name="gesture_tutorial_hotseat_height">-1px</dimen> <!-- match_parent -->
+ <dimen name="gesture_tutorial_hotseat_padding_start_end">170dp</dimen>
+
+ <!-- Gesture Tutorial mock webpages -->
+ <dimen name="gesture_tutorial_webpage_url_margin_start_end">24dp</dimen>
+ <dimen name="gesture_tutorial_webpage_top_bar_button_margin_start">48dp</dimen>
+ <dimen name="gesture_tutorial_webpage_top_bar_margin_start">121dp</dimen>
+ <dimen name="gesture_tutorial_webpage_top_bar_margin_end">355dp</dimen>
+ <dimen name="gesture_tutorial_webpage_line_1_margin_end">355dp</dimen>
+ <dimen name="gesture_tutorial_webpage_line_2_margin_end">208dp</dimen>
+ <dimen name="gesture_tutorial_webpage_line_3_margin_end">439dp</dimen>
+ <dimen name="gesture_tutorial_webpage_block_margin_end">311dp</dimen>
+ <integer name="gesture_tutorial_webpage_extra_lines_visibility">2</integer> <!-- GONE -->
+
+ <!-- Gesture Tutorial mock taskbar -->
+ <dimen name="gesture_tutorial_taskbar_padding_start_end">218dp</dimen>
</resources>
\ No newline at end of file
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index c1ca1a3..f3c3cbd 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"ທ່ານໃຊ້ທ່າທາງໄປໜ້າຫຼັກສຳເລັດແລ້ວ."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"ທ່ານໃຊ້ທ່າທາງສະຫຼັບແອັບສຳເລັດແລ້ວ."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"ຮຽບຮ້ອຍໝົດແລ້ວ!"</string>
<string name="allset_hint" msgid="2384632994739392447">"ປັດຂຶ້ນເພື່ອໄປຫາໜ້າຫຼັກ"</string>
<string name="allset_description" msgid="6350320429953234580">"ທ່ານພ້ອມເລີ່ມຕົ້ນໃຊ້ໂທລະສັບຂອງທ່ານແລ້ວ"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"ທ່ານພ້ອມເລີ່ມຕົ້ນໃຊ້ແທັບເລັດຂອງທ່ານແລ້ວ"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"ການຕັ້ງຄ່າການນຳທາງລະບົບ"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"ແບ່ງປັນ"</string>
<string name="action_screenshot" msgid="8171125848358142917">"ຮູບໜ້າຈໍ"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"ຍ້າຍໄປຊ້າຍ/ເທິງ"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ຍ້າຍໄປຂວາ/ລຸ່ມ"</string>
</resources>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index 0b1301c..25a84a7 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Paruošta!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Perbraukite aukštyn, kad grįžtumėte į pagrindinį ekraną"</string>
<string name="allset_description" msgid="6350320429953234580">"Esate pasiruošę pradėti naudoti telefoną"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Esate pasiruošę pradėti naudoti planšetinį kompiuterį"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Sistemos naršymo nustatymai"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Bendrinti"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Ekrano kopija"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Pritaikomumas"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Atgal"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IMRP perjungiklis"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Naujausi"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Pranešimai"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Spartieji nustatymai"</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>
</resources>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index c56cd5b..ee25cb5 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<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="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="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>
@@ -67,6 +69,7 @@
<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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Gatavs!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Velciet augšup, lai pārietu uz sākuma ekrānu."</string>
<string name="allset_description" msgid="6350320429953234580">"Varat sākt izmantot savu tālruni"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Varat sākt izmantot savu planšetdatoru"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Sistēmas navigācijas iestatījumi"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Kopīgot"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Veikt ekrānuzņēmumu"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Pieejamība"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Atpakaļ"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME pārslēdzējs"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Nesenie"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Paziņojumi"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Ātrie iestatīj."</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>
</resources>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index b7ecfbc..75f0933 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Го научивте движењето за отворање на почетниот екран."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Завршивте со упатството за префрлање помеѓу апликации."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Готово!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Повлечете нагоре за да појдете на почетниот екран"</string>
<string name="allset_description" msgid="6350320429953234580">"Спремни сте да почнете да го користите телефонот"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Спремни сте да почнете да го користите таблетот"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Поставки за системска навигација"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Сподели"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Слика од екранот"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"Премести горе лево"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Премести долу десно"</string>
</resources>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index d718588..9f00e91 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"ഹോമിലേക്ക് പോകുക ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"ആപ്പുകൾ തമ്മിൽ മാറുക ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"എല്ലാം സജ്ജീകരിച്ചു!"</string>
<string name="allset_hint" msgid="2384632994739392447">"ഹോമിലേക്ക് പോകാൻ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string>
<string name="allset_description" msgid="6350320429953234580">"ഫോൺ ഉപയോഗിച്ച് തുടങ്ങാൻ നിങ്ങൾ തയ്യാറാണ്"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"ടാബ്ലെറ്റ് ഉപയോഗിച്ച് തുടങ്ങാൻ നിങ്ങൾ തയ്യാറാണ്"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"സിസ്റ്റം നാവിഗേഷൻ ക്രമീകരണം"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"പങ്കിടുക"</string>
<string name="action_screenshot" msgid="8171125848358142917">"സ്ക്രീൻഷോട്ട്"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"മുകളിലേക്കോ ഇടത്തേക്കോ നീക്കുക"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"താഴേക്കോ വലത്തേക്കോ നീക്കുക"</string>
</resources>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index a588e6b..59728a6 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Та Нүүр лүү очих зангааг гүйцэтгэлээ."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Та аппуудыг сэлгэх зангааг гүйцэтгэлээ."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Тохируулж дууслаа!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Нүүр хуудас руу очихын тулд дээш шударна уу"</string>
<string name="allset_description" msgid="6350320429953234580">"Та утсаа ашиглаж эхлэхэд бэлэн боллоо"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Та таблетаа ашиглаж эхлэхэд бэлэн боллоо"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Системийн навигацын тохиргоо"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Хуваалцах"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Дэлгэцийн агшин дарах"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"Зүүн дээд хэсэг рүү зөөх"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Баруун доод хэсэг рүү зөөх"</string>
</resources>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index f19882f..5f2fb0c 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"तुम्ही गो होम जेश्चर पूर्ण केले."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"तुम्ही ॲप्स स्विच करण्याचे जेश्चर पूर्ण केले."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"सर्व तयार आहे!"</string>
<string name="allset_hint" msgid="2384632994739392447">"होम वर जाण्यासाठी वरती स्वाइप करा"</string>
<string name="allset_description" msgid="6350320429953234580">"तुम्ही तुमचा फोन वापरण्यास सुरुवात करू शकता"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"तुम्ही तुमचा टॅबलेट वापरण्यास सुरुवात करू शकता"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"सिस्टीम नेव्हिगेशन सेटिंग्ज"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"शेअर करा"</string>
<string name="action_screenshot" msgid="8171125848358142917">"स्क्रीनशॉट"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"सर्वात वरती/डावीकडे हलवा"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"तळाशी/उजवीकडे हलवा"</string>
</resources>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index 7944655..27dcc41 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Anda telah melengkapkan gerak isyarat pergi ke 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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Siap!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Leret ke atas untuk kembali ke Laman Utama"</string>
<string name="allset_description" msgid="6350320429953234580">"Anda sudah sedia untuk mula menggunakan telefon anda"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Anda bersedia untuk mula menggunakan tablet anda"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Tetapan navigasi sistem"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Kongsi"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Tangkapan skrin"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Kebolehaksesan"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Kembali"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Penukar IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Terbaharu"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Pemberitahuan"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Tetapan Pantas"</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>
</resources>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index a5f2af6..825b6f2 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"ပင်မစာမျက်နှာသို့သွားသည့် လက်ဟန် ရှင်းလင်းပို့ချချက် ပြီးပါပြီ။"</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"အက်ပ်များပြောင်းသည့် လက်ဟန် ရှင်းလင်းပို့ချချက် ပြီးပါပြီ။"</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"အားလုံး အဆင်သင့်ပါ။"</string>
<string name="allset_hint" msgid="2384632994739392447">"ပင်မစာမျက်နှာသို့သွားရန် အပေါ်သို့ ပွတ်ဆွဲပါ"</string>
<string name="allset_description" msgid="6350320429953234580">"သင့်ဖုန်း စသုံးရန် အသင့်ဖြစ်ပါပြီ"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"သင့်တက်ဘလက်ကို စသုံးရန် အသင့်ဖြစ်ပါပြီ"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"စနစ် လမ်းညွှန် ဆက်တင်များ"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"မျှဝေရန်"</string>
<string name="action_screenshot" msgid="8171125848358142917">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"အပေါ်/ဘယ်ဘက်သို့ ရွှေ့ရန်"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"အောက်ခြေ/ညာဘက်သို့ ရွှေ့ရန်"</string>
</resources>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index 118c7b1..250724e 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Alt er klart!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Sveip opp for å gå til startskjermen"</string>
<string name="allset_description" msgid="6350320429953234580">"Du er klar til å begynne å bruke telefonen"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Du er klar til å begynne å bruke nettbrettet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Innstillinger for systemnavigasjon"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Del"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Skjermdump"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Tilgjengelighet"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Tilbake"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME-veksler"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Nylige"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Varsler"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Hurtiginnst."</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>
</resources>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index a29ee60..f7214b0 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"तपाईंले \'होम स्क्रिनमा जानुहोस्\' नामक इसारा प्रयोग गर्ने तरिका सिक्नुभयो।"</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"तपाईंले \'एउटा एपबाट अर्को एपमा जानुहोस्\' नामक इसारा प्रयोग गर्ने तरिका सिक्नुभयो।"</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"सबै तयार भयो!"</string>
<string name="allset_hint" msgid="2384632994739392447">"होममा जान माथितिर स्वाइप गर्नुहोस्"</string>
<string name="allset_description" msgid="6350320429953234580">"तपाईं आफ्नो फोन चलाउन थाल्न सक्नुहुन्छ"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"तपाईं अब आफ्नो ट्याब्लेट चलाउन थाल्न सक्नुहुन्छ"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"सिस्टम नेभिगेसनसम्बन्धी सेटिङ"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"सेयर गर्नुहोस्"</string>
<string name="action_screenshot" msgid="8171125848358142917">"स्क्रिनसट"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"सिरान/बायाँतिर सार्नुहोस्"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"फेद/दायाँतिर सार्नुहोस्"</string>
</resources>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index a63b5ce..ff5e45e 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Klaar"</string>
<string name="allset_hint" msgid="2384632994739392447">"Swipe omhoog om naar het startscherm te gaan"</string>
<string name="allset_description" msgid="6350320429953234580">"Je bent klaar om je telefoon te gebruiken"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Je bent klaar om je tablet te gebruiken"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Navigatie-instellingen van systeem"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Delen"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
@@ -97,4 +101,13 @@
<string name="taskbar_edu_previous" msgid="459202320127201702">"Terug"</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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Toegankelijkheid"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Terug"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME-schakelaar"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Recent"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Meldingen"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Snelle instellingen"</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>
</resources>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index 2197695..d7246c4 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -31,11 +31,11 @@
<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="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_alt" msgid="3042360119039646356">"ଆପଣଙ୍କର ସବୁଠାରୁ ଅଧିକ-ବ୍ୟବହୃତ ଆପଗୁଡ଼ିକୁ, ସିଧା ମୂଳ ସ୍କ୍ରିନରେ ସହଜରେ ଆକ୍ସେସ୍ କରନ୍ତୁ। ଆପଣଙ୍କ ରୁଟିନଗୁଡ଼ିକ ଆଧାରରେ ପରାମର୍ଶଗୁଡ଼ିକ ପରିବର୍ତ୍ତିତ ହେବ। ତଳ ଧାଡ଼ିରେ ଥିବା ଆପଗୁଡ଼ିକ ଏକ ନୂଆ ଫୋଲ୍ଡରକୁ ମୁଭ୍ କରିଯିବ।"</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_alt" msgid="3042360119039646356">"ଆପଣଙ୍କର ସବୁଠାରୁ ଅଧିକ-ବ୍ୟବହୃତ ଆପ୍ସକୁ, ସିଧା ହୋମ ସ୍କ୍ରିନରେ ସହଜରେ ଆକ୍ସେସ କରନ୍ତୁ। ଆପଣଙ୍କ ରୁଟିନଗୁଡ଼ିକ ଆଧାରରେ ପରାମର୍ଶଗୁଡ଼ିକ ପରିବର୍ତ୍ତିତ ହେବ। ତଳ ଧାଡ଼ିରେ ଥିବା ଆପ୍ସ ଏକ ନୂଆ ଫୋଲ୍ଡରକୁ ମୁଭ ହୋଇଯିବ।"</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>
@@ -53,13 +53,15 @@
<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="home_gesture_intro_title" msgid="836590312858441830">"ମୂଳପୃଷ୍ଠାକୁ ଯିବା ପାଇଁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string>
- <string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"ଆପଣଙ୍କ ସ୍କ୍ରିନର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ। ଏହି ଜେଶ୍ଚର୍ ସର୍ବଦା ଆପଣଙ୍କୁ ମୂଳସ୍କ୍ରିନକୁ ନେଇଥାଏ।"</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="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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"ଆପଣ \'ଆପଗୁଡ଼ିକୁ ସ୍ୱିଚ୍ କରନ୍ତୁ\' ଜେଶ୍ଚର୍ ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି।"</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="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>
@@ -74,8 +77,9 @@
<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="2384632994739392447">"ମୂଳପୃଷ୍ଠାକୁ ଯିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string>
+ <string name="allset_hint" msgid="2384632994739392447">"ହୋମକୁ ଯିବା ପାଇଁ ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string>
<string name="allset_description" msgid="6350320429953234580">"ଆପଣ ଆପଣଙ୍କ ଫୋନ୍ ବ୍ୟବହାର କରିବା ପାଇଁ ପ୍ରସ୍ତୁତ ଅଛନ୍ତି"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"ଆପଣ ଆପଣଙ୍କ ଟାବଲେଟ ବ୍ୟବହାର କରିବା ଆରମ୍ଭ କରିବାକୁ ପ୍ରସ୍ତୁତ ଅଛନ୍ତି"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"ସିଷ୍ଟମ ନାଭିଗେସନ ସେଟିଂସ"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"ସେୟାର୍ କରନ୍ତୁ"</string>
<string name="action_screenshot" msgid="8171125848358142917">"ସ୍କ୍ରିନସଟ୍"</string>
@@ -85,7 +89,7 @@
<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_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_opened" msgid="3950252793551919129">"ଟାସ୍କବାର୍ ଶିକ୍ଷା ଦେଖାଯାଇଛି"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"ଶୀର୍ଷ/ବାମକୁ ମୁଭ କରନ୍ତୁ"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ନିମ୍ନ/ଡାହାଣକୁ ମୁଭ କରନ୍ତୁ"</string>
</resources>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index 341eaeb..83def85 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"ਤੁਸੀਂ \'ਹੋਮ \'ਤੇ ਜਾਓ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ।"</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"ਤੁਸੀਂ \'ਐਪਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰੋ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ।"</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"ਪੂਰੀ ਤਰ੍ਹਾਂ ਤਿਆਰ!"</string>
<string name="allset_hint" msgid="2384632994739392447">"ਹੋਮ \'ਤੇ ਜਾਣ ਲਈ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="allset_description" msgid="6350320429953234580">"ਤੁਸੀਂ ਆਪਣਾ ਫ਼ੋਨ ਵਰਤਣ ਲਈ ਤਿਆਰ ਹੋ"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"ਤੁਸੀਂ ਆਪਣਾ ਟੈਬਲੈੱਟ ਵਰਤਣ ਲਈ ਤਿਆਰ ਹੋ"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"ਸਿਸਟਮ ਨੈਵੀਗੇਸ਼ਨ ਸੈਟਿੰਗਾਂ"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"ਸਾਂਝਾ ਕਰੋ"</string>
<string name="action_screenshot" msgid="8171125848358142917">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"ਸਿਖਰਲੇ/ਖੱਬੇ ਪਾਸੇ ਲੈ ਕੇ ਜਾਓ"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ਹੇਠਾਂ/ਸੱਜੇ ਪਾਸੇ ਲੈ ਕੇ ਜਾਓ"</string>
</resources>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 66f6b75..077982a 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Wszystko gotowe"</string>
<string name="allset_hint" msgid="2384632994739392447">"Aby przejść na ekran główny, przesuń palcem w górę"</string>
<string name="allset_description" msgid="6350320429953234580">"Teraz możesz zacząć używać telefonu"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Teraz możesz zacząć używać tabletu"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Ustawienia nawigacji w systemie"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Udostępnij"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Zrzut ekranu"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Ułatwienia dostępu"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Wstecz"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Przełącznik IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Ostatnie"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Powiadomienia"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Szybkie ustawienia"</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>
</resources>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index d68ddef..124b33b 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Tudo pronto!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Deslize rapidamente para cima para aceder ao ecrã principal"</string>
<string name="allset_description" msgid="6350320429953234580">"Já pode começar a utilizar o seu telemóvel"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Já pode começar a usar o seu tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Definições de navegação do sistema"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Partilhar"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Fazer captura de ecrã"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Acessibilidade"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Voltar"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Comutador IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Recentes"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notificações"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Definiç. rápidas"</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>
</resources>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index dfe5843..199c2f4 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Você concluiu o gesto para trocar 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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Tudo pronto!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Deslize para cima para acessar a tela inicial"</string>
<string name="allset_description" msgid="6350320429953234580">"Você já pode começar a usar seu smartphone"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Você já pode começar a usar seu tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Configurações de navegação do sistema"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Compartilhar"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Capturar tela"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Acessibilidade"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Voltar"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Alternador do IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Recentes"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notificações"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Config. rápidas"</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>
</resources>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index 062827b..ba4badf 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -19,11 +19,11 @@
<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">"Fixați"</string>
+ <string name="recent_task_option_pin" msgid="7929860679018978258">"Fixează"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Formă liberă"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Niciun element recent"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Setări de utilizare a aplicației"</string>
- <string name="recents_clear_all" msgid="5328176793634888831">"Ștergeți tot"</string>
+ <string name="recents_clear_all" msgid="5328176793634888831">"Șterge tot"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplicații recente"</string>
<string name="task_view_closed" msgid="9170038230110856166">"Activitatea s-a încheiat"</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>
@@ -31,70 +31,83 @@
<string name="time_left_for_app" msgid="3111996412933644358">"Au mai rămas <xliff:g id="TIME">%1$s</xliff:g> astăzi"</string>
<string name="title_app_suggestions" msgid="4185902664111965088">"Sugestii de aplicații"</string>
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"Aplicațiile estimate"</string>
- <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Primiți sugestii de aplicații în rândul de jos al ecranului de pornire"</string>
- <string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"Primiți sugestii de aplicații în rândul de preferințe al ecranului de pornire"</string>
- <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Accesați cu ușurință cele mai folosite aplicații direct din ecranul de pornire. Sugestiile se vor modifica în funcție de rutine. Aplicațiile din rândul de jos se vor muta în sus pe ecranul de pornire."</string>
- <string name="hotseat_edu_message_migrate_landscape" msgid="4248943380443387697">"Accesați cu ușurință cele mai folosite aplicații direct din ecranul de pornire. Sugestiile se vor schimba în funcție de rutina dvs. Aplicațiile din rândul de preferințe se vor muta în ecranul de pornire."</string>
- <string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"Accesați cu ușurință cele mai folosite aplicații, direct din ecranul de pornire. Sugestiile se vor modifica în funcție de rutine. Aplicațiile din rândul de jos se vor muta într-un dosar nou."</string>
- <string name="hotseat_edu_accept" msgid="1611544083278999837">"Primiți sugestii de aplicații"</string>
+ <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Primește sugestii de aplicații în rândul de jos al ecranului de pornire"</string>
+ <string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"Primește sugestii de aplicații în rândul de preferințe al ecranului de pornire"</string>
+ <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Accesează cu ușurință cele mai folosite aplicații direct din ecranul de pornire. Sugestiile se vor modifica în funcție de rutine. Aplicațiile din rândul de jos se vor muta în sus pe ecranul de pornire."</string>
+ <string name="hotseat_edu_message_migrate_landscape" msgid="4248943380443387697">"Accesează cu ușurință cele mai folosite aplicații direct din ecranul de pornire. Sugestiile se vor schimba în funcție de rutina ta. Aplicațiile din rândul de preferințe se vor muta în ecranul de pornire."</string>
+ <string name="hotseat_edu_message_migrate_alt" msgid="3042360119039646356">"Accesează cu ușurință cele mai folosite aplicații, direct din ecranul de pornire. Sugestiile se vor modifica în funcție de rutine. Aplicațiile din rândul de jos se vor muta într-un dosar nou."</string>
+ <string name="hotseat_edu_accept" msgid="1611544083278999837">"Primește sugestii de aplicații"</string>
<string name="hotseat_edu_dismiss" msgid="2781161822780201689">"Nu, mulțumesc"</string>
<string name="hotseat_prediction_settings" msgid="6246554993566070818">"Setări"</string>
<string name="hotseat_auto_enrolled" msgid="522100018967146807">"Cele mai folosite aplicații apar aici și se modifică în funcție de rutine"</string>
- <string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"Trageți aplicații din rândul de jos pentru a primi sugestii de aplicații"</string>
+ <string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"Trage aplicații din rândul de jos pentru a primi sugestii de aplicații"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"Sugestiile de aplicații sunt adăugate în spațiile goale"</string>
<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">"Glisați dinspre marginea dreaptă îndepărtată sau dinspre marginea stângă îndepărtată."</string>
- <string name="back_gesture_feedback_cancelled" msgid="3274382913290074496">"Glisați dinspre marginea dreaptă sau stângă spre mijlocul ecranului și eliberați."</string>
- <string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Ați învățat cum să glisați dinspre dreapta pentru a reveni. În continuare, aflați cum să comutați aplicațiile."</string>
- <string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"Ați finalizat gestul „înapoi”."</string>
- <string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Nu glisați prea aproape de partea de jos a ecranului."</string>
- <string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"Schimbați sensibilitatea gestului „Înapoi” accesând Setările"</string>
- <string name="back_gesture_intro_title" msgid="19551256430224428">"Glisați pentru a reveni"</string>
- <string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Pentru a reveni la ultimul ecran, glisați de la marginea stângă sau dreaptă spre mijlocul ecranului."</string>
- <string name="home_gesture_feedback_swipe_too_far_from_edge" msgid="1446774096007065298">"Glisați în sus dinspre marginea de jos a ecranului."</string>
- <string name="home_gesture_feedback_overview_detected" msgid="1557523944897393013">"Nu întrerupeți gestul înainte de a elibera."</string>
- <string name="home_gesture_feedback_wrong_swipe_direction" msgid="6993979358080825438">"Glisați direct în sus."</string>
- <string name="home_gesture_feedback_complete_with_follow_up" msgid="1427872029729605034">"Ați finalizat gestul „accesați ecranul de pornire”. În continuare, aflați cum să reveniți."</string>
- <string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Ați finalizat gestul „accesați ecranul de pornire”."</string>
- <string name="home_gesture_intro_title" msgid="836590312858441830">"Glisați pentru a accesa ecranul de pornire"</string>
- <string name="home_gesture_intro_subtitle" msgid="2632238748497975326">"Glisați în sus din partea de jos a ecranului. Cu acest gest accesați întotdeauna ecranul de pornire."</string>
- <string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Glisați în sus dinspre marginea de jos a ecranului."</string>
- <string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Încercați să țineți fereastra mai mult înainte s-o eliberați."</string>
- <string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Glisați direct în sus, apoi întrerupeți."</string>
- <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Ați învățat cum să folosiți gesturi. Pentru a dezactiva gesturile, accesați Setările."</string>
- <string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Ați finalizat gestul „comutați între aplicații”."</string>
- <string name="overview_gesture_intro_title" msgid="2902054412868489378">"Glisați pentru a comuta între aplicații"</string>
- <string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Ca să comutați între aplicații, glisați în sus din partea de jos a ecranului, așteptați și eliberați."</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="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="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="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="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="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>
- <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Reîncercați"</string>
+ <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Reîncearcă"</string>
<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="2384632994739392447">"Glisați în sus pentru a accesa ecranul de pornire"</string>
- <string name="allset_description" msgid="6350320429953234580">"Sunteți gata să folosiți telefonul"</string>
+ <string name="allset_hint" msgid="2384632994739392447">"Glisează în sus pentru a accesa ecranul de pornire"</string>
+ <string name="allset_description" msgid="6350320429953234580">"Ești gata să folosești telefonul"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Ești gata să folosești tableta"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Setările de navigare ale sistemului"</annotation></string>
- <string name="action_share" msgid="2648470652637092375">"Distribuiți"</string>
+ <string name="action_share" msgid="2648470652637092375">"Distribuie"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Captură de ecran"</string>
<string name="action_split" msgid="2098009717623550676">"Împărțit"</string>
- <string name="toast_split_select_app" msgid="5453865907322018352">"Atingeți altă aplicație pentru a folosi ecranul împărțit"</string>
+ <string name="toast_split_select_app" msgid="5453865907322018352">"Atinge altă aplicație pentru ecranul împărțit"</string>
<string name="toast_split_app_unsupported" msgid="3271526028981899666">"Aplicația nu acceptă ecranul împărțit."</string>
- <string name="blocked_by_policy" msgid="2071401072261365546">"Această acțiune nu este permisă de aplicație sau de organizația dvs."</string>
- <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Omiteți tutorialul de navigare?"</string>
- <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Îl puteți găsi mai târziu în aplicația <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Anulați"</string>
- <string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Omiteți"</string>
- <string name="accessibility_rotate_button" msgid="4771825231336502943">"Rotiți ecranul"</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>
+ <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"Îl poți găsi mai târziu în aplicația <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"Anulează"</string>
+ <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_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_switch_apps" msgid="6942863327845784813">"Folosiți bara de activități ca să comutați între aplicații"</string>
- <string name="taskbar_edu_splitscreen" msgid="2663361731630346489">"Trageți în lateral ca să folosiți două aplicații deodată"</string>
- <string name="taskbar_edu_stashing" msgid="5212374387411764031">"Atingeți lung oricând pentru a ascunde bara de activități"</string>
+ <string name="taskbar_edu_switch_apps" msgid="6942863327845784813">"Folosește bara de activități ca să comuți între aplicații"</string>
+ <string name="taskbar_edu_splitscreen" msgid="2663361731630346489">"Trage în lateral ca să folosești două aplicații deodată"</string>
+ <string name="taskbar_edu_stashing" msgid="5212374387411764031">"Atinge lung oricând pentru a ascunde 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ți"</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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Accesibilitate"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Înapoi"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Comutator IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Recente"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Notificări"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Setări rapide"</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>
</resources>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index b1f38cd..44b72cf 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Вы выполнили жест для перехода на главный экран."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Вы выполнили жест для переключения между приложениями."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Готово!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Чтобы перейти на главный экран, проведите вверх."</string>
<string name="allset_description" msgid="6350320429953234580">"Теперь вы можете использовать телефон."</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Теперь вы можете использовать планшет."</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Системные настройки навигации"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Поделиться"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"Переместить вверх или влево"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Переместить вниз или вправо"</string>
</resources>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index 2cf7457..31749cc 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"ඔබ මුල් පිටුවට යාමේ ඉංගිතය සම්පූර්ණ කරන ලදි."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"ඔබ යෙදුම් මාරු කිරීමේ ඉංගිතය සම්පූර්ණ කර ඇත."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"සියල්ල සූදානම්!"</string>
<string name="allset_hint" msgid="2384632994739392447">"මුල් පිටුවට යාමට ඉහළට ස්වයිප් කරන්න"</string>
<string name="allset_description" msgid="6350320429953234580">"ඔබ ඔබගේ දුරකථනය භාවිත කිරීම පටන් ගැනීමට සූදානම්"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"ඔබ ඔබගේ ටැබ්ලටය භාවිත කිරීම පටන් ගැනීමට සූදානම්"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"පද්ධති සංචාලන සැකසීම්"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"බෙදා ගන්න"</string>
<string name="action_screenshot" msgid="8171125848358142917">"තිර රුව"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"ඉහළ/වම වෙත ගෙන යන්න"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"පහළ/දකුණ වෙත ගෙන යන්න"</string>
</resources>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index 82fb4fb..5d51d45 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Dokončili ste gesto na prechod 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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Hotovo"</string>
<string name="allset_hint" msgid="2384632994739392447">"Potiahnutím nahor prejdete na plochu"</string>
<string name="allset_description" msgid="6350320429953234580">"Telefón môžete začať používať"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Tablet môžete začať používať"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Nastavenia navigácie systémom"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Zdieľať"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Snímka obrazovky"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Dostupnosť"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Späť"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Prepínač IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Nedávne"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Upozornenia"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Rýchle nastavenia"</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>
</resources>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index 2385f71..e196e5d 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Končano"</string>
<string name="allset_hint" msgid="2384632994739392447">"Povlecite navzgor za začetni zaslon"</string>
<string name="allset_description" msgid="6350320429953234580">"Pripravljeni ste, da začnete uporabljati telefon"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Pripravljeni ste, da začnete uporabljati tablični računalnik."</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Nastavitve krmarjenja po sistemu"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Deli"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Posnetek zaslona"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Dostopnost"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Nazaj"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Menjava UNV"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Nedavno"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Obvestila"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Hitre nastavitve"</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>
</resources>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index 1cf7035..39771cb 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Plotësisht gati!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Rrëshqit shpejt lart për të shkuar tek \"Ekrani bazë\""</string>
<string name="allset_description" msgid="6350320429953234580">"Je gati për të filluar përdorimin e telefonit tënd"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Je gati që të fillosh të përdorësh tabletin"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Cilësimet e navigimit të sistemit"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Ndaj"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Pamja e ekranit"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Qasshmëria"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Pas"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Çelësi IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Të fundit"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Njoftimet"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Cilësimet shpejt"</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>
</resources>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index 9bbf89b..067a7fe 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Довршили сте покрет за повратак на почетну страницу."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Довршили сте покрет за промену апликација."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Готово!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Превуците нагоре да бисте отворили почетни екран"</string>
<string name="allset_description" msgid="6350320429953234580">"Спремни сте да почнете да користите телефон"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Спремни сте да почнете да користите таблет"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Подешавања кретања кроз систем"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Дели"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Снимак екрана"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"Премести горе лево"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Премести доле десно"</string>
</resources>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index 0852fb7..3bb47c3 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<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="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="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>
@@ -67,6 +69,7 @@
<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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Klart!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Svep uppåt för att öppna startskärmen"</string>
<string name="allset_description" msgid="6350320429953234580">"Nu kan du börja använda telefonen"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Nu kan du börja använda surfplattan"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Systemnavigeringsinställningar"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Dela"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Skärmbild"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Tillgänglighet"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Tillbaka"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME-väljare"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Senaste"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Aviseringar"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Snabbinställn."</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>
</resources>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index 8655576..16891a8 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Umekamilisha 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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Umekamilisha 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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Tayari!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Telezesha kidole juu ili uende kwenye skrini ya kwanza"</string>
<string name="allset_description" msgid="6350320429953234580">"Uko tayari kuanza kutumia simu yako"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Uko tayari kuanza kutumia kompyuta kibao yako"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Mipangilio ya usogezaji kwenye mfumo"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Shiriki"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Picha ya skrini"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Ufikivu"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Nyuma"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Kibadilishaji cha IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Vilivyotumika majuzi"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Arifa"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Mipangilio ya Haraka"</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>
</resources>
diff --git a/src/com/android/launcher3/allapps/DecorationInfo.java b/quickstep/res/values-sw600dp-land/dimens.xml
similarity index 64%
copy from src/com/android/launcher3/allapps/DecorationInfo.java
copy to quickstep/res/values-sw600dp-land/dimens.xml
index 50b250c..0cd9b2b 100644
--- a/src/com/android/launcher3/allapps/DecorationInfo.java
+++ b/quickstep/res/values-sw600dp-land/dimens.xml
@@ -1,19 +1,20 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
+<?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
+ * 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;
-
-public class DecorationInfo {
-}
+*/
+-->
+<resources>
+ <!-- Overview actions -->
+ <dimen name="overview_actions_top_margin">12dp</dimen>
+</resources>
diff --git a/quickstep/res/values-sw600dp/dimens.xml b/quickstep/res/values-sw600dp/dimens.xml
index 5d9e059..7494683 100644
--- a/quickstep/res/values-sw600dp/dimens.xml
+++ b/quickstep/res/values-sw600dp/dimens.xml
@@ -16,4 +16,14 @@
-->
<resources>
<dimen name="navigation_key_padding">25dp</dimen>
+
+ <!-- Task View -->
+ <dimen name="task_thumbnail_icon_size">48dp</dimen>
+ <dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
+ <dimen name="overview_task_margin">12dp</dimen>
+ <dimen name="task_thumbnail_icon_drawable_size_grid">44dp</dimen>
+ <dimen name="overview_task_margin_grid">12dp</dimen>
+ <dimen name="overview_grid_row_spacing">28dp</dimen>
+ <dimen name="overview_page_spacing">36dp</dimen>
+ <dimen name="overview_grid_side_margin">64dp</dimen>
</resources>
diff --git a/src/com/android/launcher3/allapps/DecorationInfo.java b/quickstep/res/values-sw720dp-land/dimens.xml
similarity index 64%
copy from src/com/android/launcher3/allapps/DecorationInfo.java
copy to quickstep/res/values-sw720dp-land/dimens.xml
index 50b250c..02d1189 100644
--- a/src/com/android/launcher3/allapps/DecorationInfo.java
+++ b/quickstep/res/values-sw720dp-land/dimens.xml
@@ -1,19 +1,20 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
+<?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
+ * 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;
-
-public class DecorationInfo {
-}
+*/
+-->
+<resources>
+ <!-- Overview actions -->
+ <dimen name="overview_actions_top_margin">20dp</dimen>
+</resources>
diff --git a/quickstep/res/values-sw720dp/dimens.xml b/quickstep/res/values-sw720dp/dimens.xml
index 2831a6f..ceaa8f8 100644
--- a/quickstep/res/values-sw720dp/dimens.xml
+++ b/quickstep/res/values-sw720dp/dimens.xml
@@ -15,7 +15,13 @@
*/
-->
<resources>
- <dimen name="overview_grid_row_spacing">44dp</dimen>
- <dimen name="overview_page_spacing_grid_portrait">44dp</dimen>
- <dimen name="overview_page_spacing_grid_landscape">44dp</dimen>
+ <!-- Task View -->
+ <dimen name="task_thumbnail_icon_size">48dp</dimen>
+ <dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
+ <dimen name="overview_task_margin">16dp</dimen>
+ <dimen name="task_thumbnail_icon_drawable_size_grid">44dp</dimen>
+ <dimen name="overview_task_margin_grid">16dp</dimen>
+ <dimen name="overview_grid_row_spacing">36dp</dimen>
+ <dimen name="overview_page_spacing">44dp</dimen>
+ <dimen name="overview_grid_side_margin">64dp</dimen>
</resources>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index a6f8530..5c73734 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"முகப்புக்குச் செல் சைகைப் பயிற்சியை முடித்துவிட்டீர்கள்."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"ஆப்ஸுக்கிடையே மாறும் சைகைப் பயிற்சியை முடித்துவிட்டீர்கள்."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"அனைத்தையும் அமைத்துவிட்டீர்கள்!"</string>
<string name="allset_hint" msgid="2384632994739392447">"முகப்புத் திரைக்குச் செல்ல மேல்நோக்கி ஸ்வைப் செய்யுங்கள்"</string>
<string name="allset_description" msgid="6350320429953234580">"மொபைலைப் பயன்படுத்தத் தயாராகிவிட்டீர்கள்"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"உங்கள் டேப்லெட்டைப் பயன்படுத்தத் தயாராகிவிட்டீர்கள்"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"சிஸ்டம் வழிசெலுத்தல் அமைப்புகள்"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"பகிர்"</string>
<string name="action_screenshot" msgid="8171125848358142917">"ஸ்கிரீன்ஷாட்"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"மேலே/இடதுபுறம் நகர்த்தும்"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"கீழே/வலதுபுறம் நகர்த்தும்"</string>
</resources>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index d64d8e5..332e95d 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"మీరు మొదటి ట్యాబ్కు వెళ్లే సంజ్ఞను పూర్తి చేశారు."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"మీరు \'యాప్ల మధ్య మార్పు\' సంజ్ఞను పూర్తి చేశారు."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"అంతా సెట్ అయింది!"</string>
<string name="allset_hint" msgid="2384632994739392447">"మొదటి స్క్రీన్కు వెళ్లడానికి పైకి స్వైప్ చేయండి"</string>
<string name="allset_description" msgid="6350320429953234580">"మీరు మీ ఫోన్ను ఉపయోగించడానికి సిద్ధంగా ఉన్నారు"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"మీరు మీ టాబ్లెట్ను ఉపయోగించడానికి సిద్ధంగా ఉన్నారు"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"సిస్టమ్ నావిగేషన్ సెట్టింగ్లు"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"షేర్ చేయండి"</string>
<string name="action_screenshot" msgid="8171125848358142917">"స్క్రీన్షాట్"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"ఎగువ/ఎడమ వైపునకు తరలించండి"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"దిగువ/కుడి వైపునకు తరలించండి"</string>
</resources>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 27f3af1..59a84ff 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"คุณทำท่าทางสัมผัสเพื่อไปที่หน้าแรกเสร็จแล้ว"</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"คุณทำท่าทางสัมผัสเพื่อสลับแอปเสร็จแล้ว"</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"เรียบร้อยแล้ว"</string>
<string name="allset_hint" msgid="2384632994739392447">"ปัดขึ้นเพื่อไปที่หน้าแรก"</string>
<string name="allset_description" msgid="6350320429953234580">"คุณเริ่มใช้โทรศัพท์ได้แล้ว"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"คุณเริ่มใช้แท็บเล็ตได้แล้ว"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"การตั้งค่าการนำทางของระบบ"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"แชร์"</string>
<string name="action_screenshot" msgid="8171125848358142917">"ภาพหน้าจอ"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"ย้ายไปที่ด้านบนหรือด้านซ้าย"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ย้ายไปที่ด้านล่างหรือด้านขวา"</string>
</resources>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index 1a23e6f..b22d85d 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Handa na ang lahat!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Mag-swipe pataas para pumunta sa Home"</string>
<string name="allset_description" msgid="6350320429953234580">"Handa mo nang simulan ang paggamit sa iyong telepono"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Handa mo nang simulan ang paggamit sa iyong tablet"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Mga setting ng navigation ng system"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Ibahagi"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Accessibility"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Bumalik"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME switcher"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Mga Kamakailan"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Mga Notification"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Quick Settings"</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>
</resources>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 51f60f1..b3054f7 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"İşlem tamam!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Ana ekrana gitmek için yukarı kaydırın"</string>
<string name="allset_description" msgid="6350320429953234580">"Telefonunuzu kullanmaya hazırsınız"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Tabletinizi kullanmaya hazırsınız"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Sistem gezinme ayarları"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Paylaş"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Ekran görüntüsü"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Erişilebilirlik"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Geri"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"IME değiştirici"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Son Kullanılanlar"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Bildirimler"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Hızlı Ayarlar"</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>
</resources>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 11722b3..490ac2d 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"Ви виконали жест переходу на головний екран."</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"Ви виконали жест переходу в інший додаток."</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Готово."</string>
<string name="allset_hint" msgid="2384632994739392447">"Щоб перейти на головний екран, проведіть пальцем угору"</string>
<string name="allset_description" msgid="6350320429953234580">"Тепер ви можете користуватися телефоном"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Тепер ви можете користуватися планшетом"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Системні налаштування навігації"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Поділитися"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Знімок екрана"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"Перемістити вгору або вліво"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Перемістити вниз або вправо"</string>
</resources>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index 3760caa..8f2da65 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"آپ نے ہوم پر جانے کا اشارہ مکمل کر لیا۔"</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"آپ نے ایپس کو سوئچ کرنے کا اشارہ مکمل کر لیا۔"</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"سب کچھ تیار ہے!"</string>
<string name="allset_hint" msgid="2384632994739392447">"ہوم پر جانے کے لیے اوپر سوائپ کریں"</string>
<string name="allset_description" msgid="6350320429953234580">"آپ اپنا فون استعمال شروع کرنے کے لیے تیار ہیں"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"آپ اپنے ٹیبلیٹ کا استعمال شروع کرنے کے لیے تیار ہیں"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"سسٹم نیویگیشن کی ترتیبات"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"اشتراک کریں"</string>
<string name="action_screenshot" msgid="8171125848358142917">"اسکرین شاٹ"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"اوپر/بائیں طرف منتقل کریں"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"نیچے/دائیں طرف منتقل کریں"</string>
</resources>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index 7be599d..9c47cef 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Hammasi tayyor!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Boshiga qaytish uchun tepaga suring"</string>
<string name="allset_description" msgid="6350320429953234580">"Telefoningiz xizmatga tayyor"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Planshetingiz xizmatga tayyor"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Tizim navigatsiya sozlamalari"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Ulashish"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Skrinshot"</string>
@@ -97,4 +101,13 @@
<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_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="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>
</resources>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index d212543..2e5c3e7 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<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="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="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>
@@ -67,6 +69,7 @@
<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_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_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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Đã hoàn tất!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Vuốt lên để chuyển đến Màn hình chính"</string>
<string name="allset_description" msgid="6350320429953234580">"Vậy là bạn đã sẵn sàng sử dụng điện thoại của mình"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Bạn đã sẵn sàng sử dụng máy tính bảng"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Chế độ cài đặt di chuyển trên hệ thống"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Chia sẻ"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Chụp ảnh màn hình"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Hỗ trợ tiếp cận"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Quay lại"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Trình chuyển đổi IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Gần đây"</string>
+ <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="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>
</resources>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index 1b4f7b6..0b5193f 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"您完成了“转到主屏幕”手势教程。"</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"您完成了“切换应用”手势教程。"</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"大功告成!"</string>
<string name="allset_hint" msgid="2384632994739392447">"向上滑动即可转到主屏幕"</string>
<string name="allset_description" msgid="6350320429953234580">"您可以开始使用手机了"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"您可以开始使用平板电脑了"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"系统导航设置"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"分享"</string>
<string name="action_screenshot" msgid="8171125848358142917">"屏幕截图"</string>
@@ -97,4 +101,13 @@
<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_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="move_drop_target_top_or_left" msgid="2988702185049595807">"移到顶部/左侧"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"移到底部/右侧"</string>
</resources>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index ed23e16..b700da0 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"您已完成「返回主畫面」手勢的教學課程。"</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"您已完成「切換應用程式」手勢的教學課程。"</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"設定完成!"</string>
<string name="allset_hint" msgid="2384632994739392447">"向上滑動即可前往主畫面"</string>
<string name="allset_description" msgid="6350320429953234580">"您可以開始使用手機了"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"您可以開始使用平板電腦了"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"系統導覽設定"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"分享"</string>
<string name="action_screenshot" msgid="8171125848358142917">"螢幕截圖"</string>
@@ -97,4 +101,13 @@
<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_back" msgid="8558862226461164514">"返回"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"輸入法編輯器切換工具"</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="move_drop_target_top_or_left" msgid="2988702185049595807">"移至上方/左側"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"移至底部/右側"</string>
</resources>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index 469a959..e7b74a4 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"你已完成「返回主畫面」手勢的教學課程。"</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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"你已完成「切換應用程式」手勢的教學課程。"</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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"設定完成!"</string>
<string name="allset_hint" msgid="2384632994739392447">"向上滑動即可前往主畫面"</string>
<string name="allset_description" msgid="6350320429953234580">"你可以開始使用手機了"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"你可以開始使用平板電腦了"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"系統操作機制設定"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"分享"</string>
<string name="action_screenshot" msgid="8171125848358142917">"螢幕截圖"</string>
@@ -97,4 +101,13 @@
<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_back" msgid="8558862226461164514">"返回"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"輸入法編輯器切換器"</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="move_drop_target_top_or_left" msgid="2988702185049595807">"移到上方/左側"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"移到底部/右側"</string>
</resources>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index 2a97d53..c69f63d 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -53,6 +53,7 @@
<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>
@@ -60,6 +61,7 @@
<string name="home_gesture_feedback_complete_without_follow_up" msgid="8049099486868933882">"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="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>
@@ -67,6 +69,7 @@
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"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="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>
@@ -76,6 +79,7 @@
<string name="allset_title" msgid="5021126669778966707">"Konke kusethiwe!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Swayiphela phezulu ukuze uye Ekhaya"</string>
<string name="allset_description" msgid="6350320429953234580">"Usulungele ukuqala ukusebenzisa ifoni yakho"</string>
+ <string name="allset_description_tablet" msgid="7332070270570039247">"Usulungele ukuqala ukusebenzisa ithebulethi yakho"</string>
<string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Amasethingi wokuzulazula isistimu"</annotation></string>
<string name="action_share" msgid="2648470652637092375">"Yabelana"</string>
<string name="action_screenshot" msgid="8171125848358142917">"Isithombe-skrini"</string>
@@ -97,4 +101,13 @@
<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>
+ <string name="taskbar_button_a11y" msgid="5241161324875094465">"Ukufinyeleleka"</string>
+ <string name="taskbar_button_back" msgid="8558862226461164514">"Emuva"</string>
+ <string name="taskbar_button_ime_switcher" msgid="1730244360907588541">"Isishintshi se-IME"</string>
+ <string name="taskbar_button_recents" msgid="7273376136216613134">"Okwakamuva"</string>
+ <string name="taskbar_button_notifications" msgid="7471740351507357318">"Izaziso"</string>
+ <string name="taskbar_button_quick_settings" msgid="227662894293189391">"Amasethingi Asheshayo"</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>
</resources>
diff --git a/quickstep/res/values/colors.xml b/quickstep/res/values/colors.xml
index 671a617..185c815 100644
--- a/quickstep/res/values/colors.xml
+++ b/quickstep/res/values/colors.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
<color name="chip_hint_foreground_color">#fff</color>
<color name="chip_scrim_start_color">#39000000</color>
@@ -24,7 +24,6 @@
<color name="all_apps_prediction_row_separator_dark">#3cffffff</color>
<!-- Taskbar -->
- <color name="taskbar_background">@color/overview_scrim_dark</color>
<color name="taskbar_nav_icon_selection_ripple">#E0E0E0</color>
<color name="taskbar_nav_icon_light_color">#ffffff</color>
<!-- The dark navigation button color is only used in the rare cases that taskbar isn't drawing
@@ -41,8 +40,6 @@
<color name="gesture_tutorial_fake_task_view_color">#6DA1FF</color> <!-- Light Blue -->
<!-- Must contrast gesture_tutorial_fake_wallpaper_color -->
<color name="gesture_tutorial_fake_previous_task_view_color">#3C4043</color> <!-- Gray -->
- <color name="gesture_tutorial_action_button_label_color">#FF000000</color>
- <color name="gesture_tutorial_primary_color">#B7F29F</color> <!-- Light Green -->
<color name="gesture_tutorial_taskbar_color">#202124</color>
<!-- Mock hotseat -->
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index 31c0f5f..3b4a28b 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -23,8 +23,8 @@
</string-array>
<string name="stats_log_manager_class" translatable="false">com.android.quickstep.logging.StatsLogCompatManager</string>
-
<string name="test_information_handler_class" translatable="false">com.android.quickstep.QuickstepTestInformationHandler</string>
+ <string name="window_manager_proxy_class" translatable="false">com.android.quickstep.util.SystemWindowManagerProxy</string>
<!-- The number of thumbnails and icons to keep in the cache. The thumbnail cache size also
determines how many thumbnails will be fetched in the background. -->
@@ -39,4 +39,8 @@
<string name="wellbeing_provider_pkg" translatable="false"/>
<integer name="max_depth_blur_radius">23</integer>
+
+ <!-- Accessibility actions -->
+ <item type="id" name="action_move_to_top_or_left" />
+ <item type="id" name="action_move_to_bottom_or_right" />
</resources>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 5ea94e9..3072a3e 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -15,9 +15,6 @@
-->
<resources>
- <dimen name="task_thumbnail_icon_size">48dp</dimen>
- <dimen name="task_thumbnail_icon_drawable_size">48dp</dimen>
- <dimen name="task_thumbnail_icon_drawable_size_grid">32dp</dimen>
<!-- For screens without rounded corners -->
<dimen name="task_corner_radius_small">2dp</dimen>
<!-- For Launchers that want to override the default dialog corner radius -->
@@ -27,35 +24,26 @@
<dimen name="task_menu_corner_radius">22dp</dimen>
<dimen name="task_menu_item_corner_radius">4dp</dimen>
<dimen name="task_menu_spacing">2dp</dimen>
- <dimen name="task_menu_width_grid">234dp</dimen>
+ <dimen name="task_menu_width_grid">216dp</dimen>
<dimen name="task_menu_horizontal_padding">8dp</dimen>
<dimen name="overview_proactive_row_height">48dp</dimen>
<dimen name="overview_proactive_row_bottom_margin">16dp</dimen>
<dimen name="overview_minimum_next_prev_size">50dp</dimen>
+
+ <!-- Task View -->
+ <dimen name="task_thumbnail_icon_size">48dp</dimen>
+ <dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
<dimen name="overview_task_margin">16dp</dimen>
- <dimen name="overview_task_margin_focused">12dp</dimen>
- <dimen name="overview_task_margin_grid">4dp</dimen>
+ <dimen name="overview_page_spacing">16dp</dimen>
+
<item name="overview_max_scale" format="float" type="dimen">0.7</item>
+ <item name="overview_modal_max_scale" format="float" type="dimen">1.1</item>
<!-- Overrideable in overlay that provides the Overview Actions. -->
+ <dimen name="overview_actions_top_margin">24dp</dimen>
<dimen name="overview_actions_height">48dp</dimen>
- <dimen name="overview_actions_button_spacing">32dp</dimen>
- <dimen name="overview_actions_button_spacing_grid">36dp</dimen>
- <dimen name="overview_actions_margin_gesture">28dp</dimen>
- <dimen name="overview_actions_top_margin_gesture_grid_portrait">19.37dp</dimen>
- <dimen name="overview_actions_bottom_margin_gesture_grid_portrait">22dp</dimen>
- <dimen name="overview_actions_top_margin_gesture_grid_landscape">19.1dp</dimen>
- <dimen name="overview_actions_bottom_margin_gesture_grid_landscape">10dp</dimen>
- <dimen name="overview_actions_margin_three_button">8dp</dimen>
- <dimen name="overview_actions_horizontal_margin">16dp</dimen>
-
- <dimen name="overview_grid_side_margin_portrait">60dp</dimen>
- <dimen name="overview_grid_side_margin_landscape">52dp</dimen>
- <dimen name="overview_grid_row_spacing">36dp</dimen>
- <dimen name="overview_page_spacing">16dp</dimen>
- <dimen name="overview_page_spacing_grid_portrait">36dp</dimen>
- <dimen name="overview_page_spacing_grid_landscape">38dp</dimen>
+ <dimen name="overview_actions_button_spacing">36dp</dimen>
<!-- These speeds are in dp/s -->
<dimen name="max_task_dismiss_drag_velocity">2.25dp</dimen>
@@ -121,8 +109,10 @@
<dimen name="gestures_overscroll_finish_threshold">136dp</dimen>
<!-- Tips Gesture Tutorial -->
- <dimen name="gesture_tutorial_feedback_margin_start_end">24dp</dimen>
- <dimen name="gesture_tutorial_foldable_feedback_margin_start_end">140dp</dimen>
+ <dimen name="gesture_tutorial_feedback_margin_start_end">8dp</dimen>
+ <dimen name="gesture_tutorial_tablet_feedback_margin_start_end">140dp</dimen>
+ <dimen name="gesture_tutorial_feedback_margin_top">16dp</dimen>
+ <dimen name="gesture_tutorial_tablet_feedback_margin_top">24dp</dimen>
<dimen name="gesture_tutorial_multi_row_task_view_spacing">72dp</dimen>
<dimen name="gesture_tutorial_small_task_view_corner_radius">18dp</dimen>
<dimen name="gesture_tutorial_mock_taskbar_height">80dp</dimen>
@@ -135,15 +125,46 @@
<dimen name="gesture_tutorial_message_small_margin_bottom">4dp</dimen>
<dimen name="gesture_tutorial_message_padding_start">26dp</dimen>
<dimen name="gesture_tutorial_message_padding_end">18dp</dimen>
- <dimen name="gesture_tutorial_foldable_message_padding_start_end">126dp</dimen>
+ <dimen name="gesture_tutorial_top_bar_margin_start">34dp</dimen>
+ <dimen name="gesture_tutorial_top_bar_margin_end">211dp</dimen>
+ <dimen name="gesture_tutorial_top_bar_button_margin_end">24dp</dimen>
+ <dimen name="gesture_tutorial_conversation_bottom_padding">66dp</dimen>
+ <integer name="gesture_tutorial_extra_messages_visibility">0</integer> <!-- VISIBLE -->
+ <dimen name="gesture_tutorial_message_margin_start">124dp</dimen>
+ <dimen name="gesture_tutorial_reply_margin_end">144dp</dimen>
+ <dimen name="gesture_tutorial_input_margin_start">34dp</dimen>
+ <dimen name="gesture_tutorial_input_margin_end">24dp</dimen>
+ <dimen name="gesture_tutorial_tablet_message_padding_start_end">126dp</dimen>
+ <dimen name="gesture_tutorial_tablet_message_1_margin">245dp</dimen>
+ <dimen name="gesture_tutorial_tablet_reply_1_margin">241dp</dimen>
+ <dimen name="gesture_tutorial_tablet_message_2_margin">401dp</dimen>
+ <dimen name="gesture_tutorial_tablet_message_3_margin">245dp</dimen>
+ <dimen name="gesture_tutorial_tablet_reply_2_margin">273dp</dimen>
<!-- Gesture Tutorial mock conversation lists -->
<dimen name="gesture_tutorial_conversation_icon_size">56dp</dimen>
<dimen name="gesture_tutorial_conversation_icon_corner_radius">100dp</dimen>
<dimen name="gesture_tutorial_conversation_list_padding_top">28dp</dimen>
<dimen name="gesture_tutorial_conversation_line_padding_start">20dp</dimen>
+ <dimen name="gesture_tutorial_conversation_line_1_margin_end">217dp</dimen>
+ <dimen name="gesture_tutorial_conversation_line_2_margin_end">142dp</dimen>
+ <dimen name="gesture_tutorial_conversation_line_3_margin_end">190dp</dimen>
+ <dimen name="gesture_tutorial_conversation_line_4_margin_end">171dp</dimen>
+ <dimen name="gesture_tutorial_conversation_line_5_margin_end">198dp</dimen>
+ <dimen name="gesture_tutorial_conversation_line_6_margin_end">79dp</dimen>
+ <dimen name="gesture_tutorial_conversation_line_7_margin_end">174dp</dimen>
+ <dimen name="gesture_tutorial_conversation_line_8_margin_end">117dp</dimen>
+ <dimen name="gesture_tutorial_tablet_conversation_line_6_margin_end">65dp</dimen>
+ <dimen name="gesture_tutorial_tablet_conversation_line_8_margin_end">132dp</dimen>
+ <dimen name="gesture_tutorial_tablet_conversation_line_10_margin_end">161dp</dimen>
+ <integer name="gesture_tutorial_extra_conversations_visibility">0</integer> <!-- VISIBLE -->
+ <dimen name="gesture_tutorial_mock_button_margin_end">24dp</dimen>
+ <dimen name="gesture_tutorial_mock_button_margin_bottom">66dp</dimen>
<!-- Gesture Tutorial mock hotseats -->
+ <dimen name="gesture_tutorial_hotseat_width">-1px</dimen> <!-- match_parent -->
+ <dimen name="gesture_tutorial_hotseat_height">-2px</dimen> <!-- wrap_content -->
+ <dimen name="gesture_tutorial_hotseat_padding_start_end">26dp</dimen>
<dimen name="gesture_tutorial_hotseat_icon_size">60dp</dimen>
<dimen name="gesture_tutorial_hotseat_icon_corner_radius">100dp</dimen>
<dimen name="gesture_tutorial_hotseat_search_height">50dp</dimen>
@@ -159,11 +180,20 @@
<dimen name="gesture_tutorial_webpage_small_corner_radius">4dp</dimen>
<dimen name="gesture_tutorial_webpage_large_line_height">36dp</dimen>
<dimen name="gesture_tutorial_webpage_small_line_height">22dp</dimen>
+ <dimen name="gesture_tutorial_webpage_url_margin_start_end">16dp</dimen>
+ <dimen name="gesture_tutorial_webpage_top_bar_button_margin_start">24dp</dimen>
+ <dimen name="gesture_tutorial_webpage_top_bar_margin_start">97dp</dimen>
+ <dimen name="gesture_tutorial_webpage_top_bar_margin_end">97dp</dimen>
+ <dimen name="gesture_tutorial_webpage_line_1_margin_end">126dp</dimen>
+ <dimen name="gesture_tutorial_webpage_line_2_margin_end">64dp</dimen>
+ <dimen name="gesture_tutorial_webpage_line_3_margin_end">151dp</dimen>
+ <dimen name="gesture_tutorial_webpage_block_margin_end">24dp</dimen>
+ <integer name="gesture_tutorial_webpage_extra_lines_visibility">0</integer> <!-- VISIBLE -->
<!-- Gesture Tutorial mock taskbar -->
<dimen name="gesture_tutorial_taskbar_icon_size">44dp</dimen>
<dimen name="gesture_tutorial_taskbar_icon_corner_radius">100dp</dimen>
- <dimen name="gesture_tutorial_taskbar_padding_start_end">218dp</dimen>
+ <dimen name="gesture_tutorial_taskbar_padding_start_end">52dp</dimen>
<!-- All Set page -->
<dimen name="allset_page_margin_horizontal">40dp</dimen>
@@ -228,7 +258,14 @@
<dimen name="taskbar_contextual_buttons_size">35dp</dimen>
<dimen name="taskbar_stashed_size">24dp</dimen>
<dimen name="taskbar_stashed_handle_width">220dp</dimen>
- <dimen name="taskbar_stashed_handle_height">6dp</dimen>
+ <dimen name="taskbar_unstash_input_area">316dp</dimen>
+ <dimen name="taskbar_stashed_handle_height">4dp</dimen>
<dimen name="taskbar_edu_wave_anim_trans_y">25dp</dimen>
<dimen name="taskbar_edu_wave_anim_trans_y_return_overshoot">4dp</dimen>
+ <dimen name="taskbar_nav_buttons_width_kids">88dp</dimen>
+ <dimen name="taskbar_nav_buttons_height_kids">40dp</dimen>
+ <dimen name="taskbar_nav_buttons_corner_radius_kids">40dp</dimen>
+ <dimen name="taskbar_back_button_left_margin_kids">48dp</dimen>
+ <dimen name="taskbar_home_button_left_margin_kids">48dp</dimen>
+ <dimen name="taskbar_icon_size_kids">32dp</dimen>
</resources>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 6caed1c..81b0dd2 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -109,6 +109,8 @@
<string name="back_gesture_intro_title">Swipe to go back</string>
<!-- Introduction subtitle for the Back gesture tutorial. [CHAR LIMIT=200] -->
<string name="back_gesture_intro_subtitle">To go back to the last screen, swipe from the left or right edge to the middle of the screen.</string>
+ <!-- Introduction subtitle for the Back gesture tutorial that will be spoken by screen readers. [CHAR LIMIT=200] -->
+ <string name="back_gesture_spoken_intro_subtitle">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">Make sure you swipe up from the bottom edge of the screen.</string>
<!-- Feedback shown during interactive parts of Home gesture tutorial when the Overview gesture is detected. [CHAR LIMIT=100] -->
@@ -123,6 +125,8 @@
<string name="home_gesture_intro_title">Swipe to go home</string>
<!-- Introduction subtitle for the Home gesture tutorial. [CHAR LIMIT=100] -->
<string name="home_gesture_intro_subtitle">Swipe up from the bottom of your screen. This gesture always takes you to the Home screen.</string>
+ <!-- Introduction subtitle for the Home gesture tutorial that will be spoken by screen readers. [CHAR LIMIT=100] -->
+ <string name="home_gesture_spoken_intro_subtitle">Swipe up with 2 fingers from the bottom of the screen. This gesture always takes you to the Home screen.</string>
<!-- Feedback shown during interactive parts of Overview gesture tutorial when the gesture is started too far from the edge. [CHAR LIMIT=100] -->
<string name="overview_gesture_feedback_swipe_too_far_from_edge">Make sure you swipe up from the bottom edge of the screen.</string>
@@ -138,6 +142,8 @@
<string name="overview_gesture_intro_title">Swipe to switch apps</string>
<!-- Introduction subtitle for the Overview gesture tutorial. [CHAR LIMIT=100] -->
<string name="overview_gesture_intro_subtitle">To switch between apps, swipe up from the bottom of your screen, hold, then release.</string>
+ <!-- Introduction subtitle for the Overview gesture tutorial that will be spoken by screen readers. [CHAR LIMIT=100] -->
+ <string name="overview_gesture_spoken_intro_subtitle">To switch between apps, swipe up with 2 fingers from the bottom of your screen, hold, then release.</string>
<!-- Title shown during interactive part of Assistant gesture tutorial. [CHAR LIMIT=30] -->
<string name="assistant_gesture_tutorial_playground_title" translatable="false">Tutorial: Assistant</string>
@@ -182,8 +188,10 @@
<string name="allset_title">All set!</string>
<!-- Hint string at the bottom of "All Set" page [CHAR LIMIT=NONE] -->
<string name="allset_hint">Swipe up to go Home</string>
- <!-- Description of "All Set" page [CHAR LIMIT=NONE] -->
+ <!-- Description of "All Set" page on phones [CHAR LIMIT=NONE] -->
<string name="allset_description">You\u2019re ready to start using your phone</string>
+ <!-- Description of "All Set" page on tablets [CHAR LIMIT=NONE] -->
+ <string name="allset_description_tablet">You\u2019re ready to start using your tablet</string>
<!-- String linking to navigation settings on "All Set" page [CHAR LIMIT=NONE] -->
<string name="allset_navigation_settings"><annotation id="link">System navigation settings</annotation></string>
@@ -236,4 +244,23 @@
<string name="taskbar_edu_close">Close</string>
<!-- Text on button to finish a tutorial [CHAR_LIMIT=16] -->
<string name="taskbar_edu_done">Done</string>
+ <!-- Content description for home button [CHAR_LIMIT=16] -->
+ <string name="taskbar_button_home">Home</string>
+ <!-- Content description for accessibility button [CHAR_LIMIT=16] -->
+ <string name="taskbar_button_a11y">Accessibility</string>
+ <!-- Content description for back button [CHAR_LIMIT=16] -->
+ <string name="taskbar_button_back">Back</string>
+ <!-- Content description for ime switcher button [CHAR_LIMIT=16] -->
+ <string name="taskbar_button_ime_switcher">IME switcher</string>
+ <!-- Content description for recents button [CHAR_LIMIT=16] -->
+ <string name="taskbar_button_recents">Recents</string>
+ <!-- Content description for notifications button [CHAR_LIMIT=16] -->
+ <string name="taskbar_button_notifications">Notifications</string>
+ <!-- Content description for quick settings button [CHAR_LIMIT=16] -->
+ <string name="taskbar_button_quick_settings">Quick Settings</string>
+
+ <!-- Label for moving drop target to the top or left side of the screen, depending on orientation (from the taskbar only). -->
+ <string name="move_drop_target_top_or_left">Move to top/left</string>
+ <!-- Label for moving drop target to the bottom or right side of the screen, depending on orientation (from the taskbar only). -->
+ <string name="move_drop_target_bottom_or_right">Move to bottom/right</string>
</resources>
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index 2efe72e..7225220 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -47,6 +47,12 @@
<item name="android:lineHeight">44sp</item>
</style>
+ <style name="TextAppearance.GestureTutorial.Feedback.Title.AllSet"
+ parent="TextAppearance.GestureTutorial.Feedback.Title">
+ <item name="android:letterSpacing">0.03</item>
+ <item name="android:lineHeight">44sp</item>
+ </style>
+
<style name="TextAppearance.GestureTutorial.Dialog.Title"
parent="TextAppearance.GestureTutorial.Feedback.Title">
<item name="android:gravity">center_horizontal</item>
@@ -61,6 +67,12 @@
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:fontFamily">google-sans-text</item>
<item name="android:letterSpacing">0.03</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:lineHeight">20sp</item>
+ </style>
+
+ <style name="TextAppearance.GestureTutorial.Feedback.Subtitle.AllSet"
+ parent="TextAppearance.GestureTutorial.Feedback.Subtitle">
<item name="android:textSize">18sp</item>
<item name="android:lineHeight">24sp</item>
</style>
@@ -77,8 +89,8 @@
<style name="TextAppearance.GestureTutorial.Feedback.Subtext"
parent="TextAppearance.GestureTutorial.Feedback.Subtitle">
<item name="android:textSize">16sp</item>
- <item name="android:textColor">@color/gesture_tutorial_primary_color</item>
- <item name="android:gravity">center</item>
+ <item name="android:textColor">?android:attr/colorAccent</item>
+ <item name="android:gravity">start</item>
</style>
<style name="TextAppearance.GestureTutorial.Feedback.Subtext.Dark"
@@ -89,7 +101,7 @@
<style name="TextAppearance.GestureTutorial.ButtonLabel"
parent="TextAppearance.GestureTutorial.CallToAction">
<item name="android:gravity">center</item>
- <item name="android:textColor">@color/gesture_tutorial_action_button_label_color</item>
+ <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
<item name="android:letterSpacing">0.02</item>
<item name="android:textSize">16sp</item>
<item name="android:textAllCaps">false</item>
@@ -97,12 +109,12 @@
<style name="TextAppearance.GestureTutorial.CancelButtonLabel"
parent="TextAppearance.GestureTutorial.ButtonLabel">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textColor">?android:attr/colorAccent</item>
</style>
<style name="TextAppearance.GestureTutorial.TextButtonLabel"
parent="TextAppearance.GestureTutorial.ButtonLabel">
- <item name="android:textColor">@color/gesture_tutorial_primary_color</item>
+ <item name="android:textColor">?android:attr/colorAccent</item>
</style>
<style name="TextAppearance.GestureTutorial.LinkText"
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 4ceb195..2239102 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -21,27 +21,33 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.NO_OFFSET;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE;
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
+import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition;
+import static com.android.launcher3.taskbar.LauncherTaskbarUIController.ALL_APPS_PAGE_PROGRESS_INDEX;
+import static com.android.launcher3.taskbar.LauncherTaskbarUIController.MINUS_ONE_PAGE_PROGRESS_INDEX;
+import static com.android.launcher3.taskbar.LauncherTaskbarUIController.WIDGETS_PAGE_PROGRESS_INDEX;
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.DisplayController.NavigationMode.TWO_BUTTONS;
+import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
-import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
+import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
-import android.graphics.Insets;
import android.hardware.SensorManager;
import android.hardware.devicestate.DeviceStateManager;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.IBinder;
+import android.view.Display;
import android.view.View;
-import android.view.WindowInsets;
import android.window.SplashScreen;
import androidx.annotation.Nullable;
@@ -61,14 +67,14 @@
import com.android.launcher3.uioverrides.RecentsViewStateController;
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.ObjectWrapper;
+import com.android.launcher3.util.RunnableList;
+import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.util.UiThreadHelper;
import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.RecentsModel;
-import com.android.quickstep.SysUINavigationMode;
-import com.android.quickstep.SysUINavigationMode.Mode;
-import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.TouchInteractionService.TISBinder;
@@ -89,14 +95,14 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
/**
* Extension of Launcher activity to provide quickstep specific functionality
*/
-public abstract class BaseQuickstepLauncher extends Launcher
- implements NavigationModeChangeListener {
+public abstract class BaseQuickstepLauncher extends Launcher {
private DepthController mDepthController = new DepthController(this);
private QuickstepTransitionManager mAppTransitionManager;
@@ -124,7 +130,6 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- SysUINavigationMode.INSTANCE.get(this).addModeChangeListener(this);
addMultiWindowModeChangedListener(mDepthController);
initUnfoldTransitionProgressProvider();
}
@@ -154,8 +159,6 @@
mUnfoldTransitionProgressProvider.destroy();
}
- SysUINavigationMode.INSTANCE.get(this).removeModeChangeListener(this);
-
mTISBindHelper.onDestroy();
if (mTaskbarManager != null) {
mTaskbarManager.clearActivity(this);
@@ -182,14 +185,6 @@
}
@Override
- public void onNavigationModeChanged(Mode newMode) {
- getDragLayer().recreateControllers();
- if (mActionsView != null) {
- mActionsView.updateVerticalMargin(newMode);
- }
- }
-
- @Override
public void onEnterAnimationComplete() {
super.onEnterAnimationComplete();
// After the transition to home, enable the high-res thumbnail loader if it wasn't enabled
@@ -237,6 +232,28 @@
public void onScrollChanged(float progress) {
super.onScrollChanged(progress);
mDepthController.onOverlayScrollChanged(progress);
+ onTaskbarInAppDisplayProgressUpdate(progress, MINUS_ONE_PAGE_PROGRESS_INDEX);
+ }
+
+ @Override
+ public void onAllAppsTransition(float progress) {
+ super.onAllAppsTransition(progress);
+ onTaskbarInAppDisplayProgressUpdate(progress, ALL_APPS_PAGE_PROGRESS_INDEX);
+ }
+
+ @Override
+ public void onWidgetsTransition(float progress) {
+ super.onWidgetsTransition(progress);
+ onTaskbarInAppDisplayProgressUpdate(progress, WIDGETS_PAGE_PROGRESS_INDEX);
+ }
+
+ private void onTaskbarInAppDisplayProgressUpdate(float progress, int flag) {
+ if (mTaskbarManager == null
+ || mTaskbarManager.getCurrentActivityContext() == null
+ || mTaskbarUIController == null) {
+ return;
+ }
+ mTaskbarUIController.onTaskbarInAppDisplayProgressUpdate(progress, flag);
}
@Override
@@ -298,15 +315,14 @@
protected void setupViews() {
super.setupViews();
- SysUINavigationMode.INSTANCE.get(this).updateMode();
mActionsView = findViewById(R.id.overview_actions_view);
RecentsView overviewPanel = (RecentsView) getOverviewPanel();
SplitSelectStateController controller =
- new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this),
- getStateManager(), getDepthController());
+ new SplitSelectStateController(this, mHandler, getStateManager(),
+ getDepthController());
overviewPanel.init(mActionsView, controller);
- mActionsView.setDp(getDeviceProfile());
- mActionsView.updateVerticalMargin(SysUINavigationMode.getMode(this));
+ mActionsView.updateDimension(getDeviceProfile(), overviewPanel.getLastComputedTaskSize());
+ mActionsView.updateVerticalMargin(DisplayController.getNavigationMode(this));
mAppTransitionManager = new QuickstepTransitionManager(this);
mAppTransitionManager.registerRemoteAnimations();
@@ -335,9 +351,12 @@
config,
ProxyScreenStatusProvider.INSTANCE,
getSystemService(DeviceStateManager.class),
+ getSystemService(ActivityManager.class),
getSystemService(SensorManager.class),
getMainThreadHandler(),
- getMainExecutor()
+ getMainExecutor(),
+ /* backgroundExecutor= */ THREAD_POOL_EXECUTOR,
+ /* tracingTagPrefix= */ "launcher"
);
mLauncherUnfoldAnimationController = new LauncherUnfoldAnimationController(
@@ -385,8 +404,7 @@
@Override
public boolean supportsAdaptiveIconAnimation(View clickedView) {
- return mAppTransitionManager.hasControlRemoteAppTransitionPermission()
- && FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM.get();
+ return mAppTransitionManager.hasControlRemoteAppTransitionPermission();
}
@Override
@@ -426,7 +444,7 @@
@Override
public float[] getNormalOverviewScaleAndOffset() {
- return SysUINavigationMode.getMode(this).hasGestures
+ return DisplayController.getNavigationMode(this).hasGestures
? new float[] {1, 1} : new float[] {1.1f, NO_OFFSET};
}
@@ -456,7 +474,7 @@
}
public boolean shouldBackButtonBeHidden(LauncherState toState) {
- Mode mode = SysUINavigationMode.getMode(this);
+ NavigationMode mode = DisplayController.getNavigationMode(this);
boolean shouldBackButtonBeHidden = mode.hasGestures
&& toState.hasFlag(FLAG_HIDE_BACK_BUTTON)
&& hasWindowFocus()
@@ -474,7 +492,7 @@
*/
private void onLauncherStateOrFocusChanged() {
boolean shouldBackButtonBeHidden = shouldBackButtonBeHidden(getStateManager().getState());
- if (SysUINavigationMode.getMode(this) == TWO_BUTTONS) {
+ if (DisplayController.getNavigationMode(this) == TWO_BUTTONS) {
UiThreadHelper.setBackButtonAlphaAsync(this, SET_BACK_BUTTON_ALPHA,
shouldBackButtonBeHidden ? 0f : 1f, true /* animate */);
}
@@ -493,9 +511,35 @@
}
@Override
+ public void onInitialBindComplete(IntSet boundPages, RunnableList pendingTasks) {
+ pendingTasks.add(() -> {
+ // This is added in pending task as we need to wait for views to be positioned
+ // correctly before registering them for the animation.
+ if (mLauncherUnfoldAnimationController != null) {
+ // This is needed in case items are rebound while the unfold animation is in
+ // progress.
+ mLauncherUnfoldAnimationController.updateRegisteredViewsIfNeeded();
+ }
+ });
+ super.onInitialBindComplete(boundPages, pendingTasks);
+ }
+
+ @Override
public Stream<SystemShortcut.Factory> getSupportedShortcuts() {
- return Stream.concat(Stream.of(WellbeingModel.SHORTCUT_FACTORY),
- super.getSupportedShortcuts());
+ Stream<SystemShortcut.Factory> base = Stream.of(WellbeingModel.SHORTCUT_FACTORY);
+ if (ENABLE_SPLIT_FROM_WORKSPACE.get() && mDeviceProfile.isTablet) {
+ RecentsView recentsView = getOverviewPanel();
+ // TODO: Pull it out of PagedOrentationHandler for split from workspace.
+ List<SplitPositionOption> positions =
+ recentsView.getPagedOrientationHandler().getSplitPositionOptions(
+ mDeviceProfile);
+ List<SystemShortcut.Factory<BaseQuickstepLauncher>> splitShortcuts = new ArrayList<>();
+ for (SplitPositionOption position : positions) {
+ splitShortcuts.add(getSplitSelectShortcutByPosition(position));
+ }
+ base = Stream.concat(base, splitShortcuts.stream());
+ }
+ return Stream.concat(base, super.getSupportedShortcuts());
}
@Override
@@ -508,7 +552,10 @@
ActivityOptionsCompat.setLauncherSourceInfo(
activityOptions.options, mLastTouchUpTime);
}
- activityOptions.options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+ activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+ activityOptions.options.setLaunchDisplayId(
+ (v != null && v.getDisplay() != null) ? v.getDisplay().getDisplayId()
+ : Display.DEFAULT_DISPLAY);
addLaunchCookie(item, activityOptions.options);
return activityOptions;
}
@@ -575,6 +622,13 @@
if ((flags & CHANGE_ACTIVE_SCREEN) != 0) {
getStateManager().moveToRestState();
}
+
+ if ((flags & CHANGE_NAVIGATION_MODE) != 0) {
+ getDragLayer().recreateControllers();
+ if (mActionsView != null) {
+ mActionsView.updateVerticalMargin(info.navigationMode);
+ }
+ }
}
@Override
@@ -584,17 +638,4 @@
mDepthController.dump(prefix, writer);
}
}
-
- @Override
- public void updateWindowInsets(WindowInsets.Builder updatedInsetsBuilder,
- WindowInsets oldInsets) {
- // Override the tappable insets to be 0 on the bottom for gesture nav (otherwise taskbar
- // would count towards it). This is used for the bottom protection in All Apps for example.
- if (SysUINavigationMode.getMode(this) == NO_BUTTON) {
- Insets oldTappableInsets = oldInsets.getInsets(WindowInsets.Type.tappableElement());
- Insets newTappableInsets = Insets.of(oldTappableInsets.left, oldTappableInsets.top,
- oldTappableInsets.right, 0);
- updatedInsetsBuilder.setInsets(WindowInsets.Type.tappableElement(), newTappableInsets);
- }
- }
}
diff --git a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
index 661053a..62603e9 100644
--- a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
+++ b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
@@ -16,9 +16,9 @@
package com.android.launcher3;
import static com.android.launcher3.Utilities.postAsyncCallback;
-import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
import static com.android.systemui.shared.recents.utilities.Utilities.postAtFrontOfQueueAsynchronously;
import android.animation.Animator;
diff --git a/quickstep/src/com/android/launcher3/QuickstepAccessibilityDelegate.java b/quickstep/src/com/android/launcher3/QuickstepAccessibilityDelegate.java
index 96559cb..962fd91 100644
--- a/quickstep/src/com/android/launcher3/QuickstepAccessibilityDelegate.java
+++ b/quickstep/src/com/android/launcher3/QuickstepAccessibilityDelegate.java
@@ -44,7 +44,7 @@
@Override
protected boolean performAction(View host, ItemInfo item, int action, boolean fromKeyboard) {
- QuickstepLauncher launcher = (QuickstepLauncher) mLauncher;
+ QuickstepLauncher launcher = (QuickstepLauncher) mContext;
if (action == PIN_PREDICTION) {
if (launcher.getHotseatPredictionController() == null) {
return false;
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 3b493bb..9aeb370 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -16,6 +16,7 @@
package com.android.launcher3;
+import static android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_NONE;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
@@ -27,6 +28,7 @@
import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
+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.Utilities.postAsyncCallback;
@@ -40,11 +42,10 @@
import static com.android.launcher3.config.FeatureFlags.ENABLE_SCRIM_FOR_APP_LAUNCH;
import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION;
import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY;
-import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_TRANSITIONS;
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
-import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
import static com.android.launcher3.testing.TestProtocol.BAD_STATE;
+import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import static com.android.launcher3.views.FloatingIconView.getFloatingIconView;
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
@@ -103,13 +104,13 @@
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.DynamicResource;
-import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.launcher3.util.ObjectWrapper;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.FloatingIconView;
import com.android.launcher3.views.ScrimView;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.android.quickstep.LauncherBackAnimationController;
import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskViewUtils;
@@ -192,9 +193,7 @@
private static final int WIDGET_CROSSFADE_DURATION_MILLIS = 125;
protected final BaseQuickstepLauncher mLauncher;
-
private final DragLayer mDragLayer;
- private final AlphaProperty mDragLayerAlpha;
final Handler mHandler;
@@ -215,6 +214,7 @@
private RemoteAnimationFactory mWallpaperOpenTransitionRunner;
private RemoteTransitionCompat mLauncherOpenTransition;
+ private LauncherBackAnimationController mBackAnimationController;
private final AnimatorListenerAdapter mForceInvisibleListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
@@ -237,9 +237,9 @@
public QuickstepTransitionManager(Context context) {
mLauncher = Launcher.cast(Launcher.getLauncher(context));
mDragLayer = mLauncher.getDragLayer();
- mDragLayerAlpha = mDragLayer.getAlphaProperty(ALPHA_INDEX_TRANSITIONS);
mHandler = new Handler(Looper.getMainLooper());
mDeviceProfile = mLauncher.getDeviceProfile();
+ mBackAnimationController = new LauncherBackAnimationController(mLauncher, this);
Resources res = mLauncher.getResources();
mContentScale = res.getFloat(R.dimen.content_scale);
@@ -483,6 +483,9 @@
? new float[]{1, mContentScale}
: new float[]{mContentScale, 1};
+ // Pause expensive view updates as they can lead to layer thrashing and skipped frames.
+ mLauncher.pauseExpensiveViewUpdates();
+
if (mLauncher.isInState(ALL_APPS)) {
// All Apps in portrait mode is full screen, so we only animate AllAppsContainerView.
final View appsView = mLauncher.getAppsView();
@@ -515,12 +518,13 @@
appsView.setAlpha(startAlpha);
SCALE_PROPERTY.set(appsView, startScale);
appsView.setLayerType(View.LAYER_TYPE_NONE, null);
+ mLauncher.resumeExpensiveViewUpdates();
};
} else if (mLauncher.isInState(OVERVIEW)) {
endListener = composeViewContentAnimator(launcherAnimator, alphas, scales);
} else {
List<View> viewsToAnimate = new ArrayList<>();
- Workspace workspace = mLauncher.getWorkspace();
+ Workspace<?> workspace = mLauncher.getWorkspace();
workspace.forEachVisiblePage(
view -> viewsToAnimate.add(((CellLayout) view).getShortcutsAndWidgets()));
@@ -581,9 +585,6 @@
}
}
- // Pause page indicator animations as they lead to layer trashing.
- mLauncher.getWorkspace().getPageIndicator().pauseAnimations();
-
endListener = () -> {
viewsToAnimate.forEach(view -> {
SCALE_PROPERTY.set(view, 1f);
@@ -592,7 +593,7 @@
if (scrimEnabled) {
mLauncher.getScrimView().setBackgroundColor(Color.TRANSPARENT);
}
- mLauncher.getWorkspace().getPageIndicator().skipAnimationsToEnd();
+ mLauncher.resumeExpensiveViewUpdates();
};
}
@@ -647,6 +648,7 @@
overview.setFreezeViewVisibility(false);
SCALE_PROPERTY.set(overview, 1f);
mLauncher.getStateManager().reapplyState();
+ mLauncher.resumeExpensiveViewUpdates();
};
}
@@ -707,6 +709,18 @@
appAnimator.addListener(floatingView);
appAnimator.addListener(new AnimatorListenerAdapter() {
@Override
+ public void onAnimationStart(Animator animation) {
+ LauncherTaskbarUIController taskbarController = mLauncher.getTaskbarUIController();
+ if (taskbarController != null && taskbarController.shouldShowEdu()) {
+ // LAUNCHER_TASKBAR_EDUCATION_SHOWING is set to true here, when the education
+ // flow is about to start, to avoid a race condition with other components
+ // that would show something else to the user as soon as the app is opened.
+ Settings.Secure.putInt(mLauncher.getContentResolver(),
+ LAUNCHER_TASKBAR_EDUCATION_SHOWING, 1);
+ }
+ }
+
+ @Override
public void onAnimationEnd(Animator animation) {
if (v instanceof BubbleTextView) {
((BubbleTextView) v).setStayPressed(false);
@@ -1144,7 +1158,10 @@
new LauncherAnimationRunner(mHandler, mWallpaperOpenTransitionRunner,
false /* startAtFrontOfQueue */), mLauncher.getIApplicationThread());
mLauncherOpenTransition.addHomeOpenCheck(mLauncher.getComponentName());
- SystemUiProxy.INSTANCE.getNoCreate().registerRemoteTransition(mLauncherOpenTransition);
+ SystemUiProxy.INSTANCE.get(mLauncher).registerRemoteTransition(mLauncherOpenTransition);
+ }
+ if (mBackAnimationController != null) {
+ mBackAnimationController.registerBackCallbacks(mHandler);
}
}
@@ -1152,7 +1169,7 @@
unregisterRemoteAnimations();
unregisterRemoteTransitions();
mStartingWindowListener.setTransitionManager(null);
- SystemUiProxy.INSTANCE.getNoCreate().setStartingWindowListener(null);
+ SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(null);
}
private void unregisterRemoteAnimations() {
@@ -1176,11 +1193,15 @@
}
if (hasControlRemoteAppTransitionPermission()) {
if (mLauncherOpenTransition == null) return;
- SystemUiProxy.INSTANCE.getNoCreate().unregisterRemoteTransition(
+ SystemUiProxy.INSTANCE.get(mLauncher).unregisterRemoteTransition(
mLauncherOpenTransition);
mLauncherOpenTransition = null;
mWallpaperOpenTransitionRunner = null;
}
+ if (mBackAnimationController != null) {
+ mBackAnimationController.unregisterBackCallbacks();
+ mBackAnimationController = null;
+ }
}
private boolean launcherIsATargetWithMode(RemoteAnimationTargetCompat[] targets, int mode) {
@@ -1196,6 +1217,19 @@
return false;
}
+ private boolean hasMultipleTargetsWithMode(RemoteAnimationTargetCompat[] targets, int mode) {
+ int numTargets = 0;
+ for (RemoteAnimationTargetCompat target : targets) {
+ if (target.mode == mode) {
+ numTargets++;
+ }
+ if (numTargets > 1) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* @return Runner that plays when user goes to Launcher
* ie. pressing home, swiping up from nav bar.
@@ -1320,8 +1354,9 @@
/**
* Closing animator that animates the window into its final location on the workspace.
*/
- private void getClosingWindowAnimators(AnimatorSet animation,
- RemoteAnimationTargetCompat[] targets, View launcherView, PointF velocityPxPerS) {
+ private RectFSpringAnim getClosingWindowAnimators(AnimatorSet animation,
+ RemoteAnimationTargetCompat[] targets, View launcherView, PointF velocityPxPerS,
+ RectF closingWindowStartRect, float startWindowCornerRadius) {
FloatingIconView floatingIconView = null;
FloatingWidgetView floatingWidget = null;
RectF targetRect = new RectF();
@@ -1353,8 +1388,7 @@
targetRect.set(getDefaultWindowTargetRect());
}
- final RectF startRect = new RectF(0, 0, mDeviceProfile.widthPx, mDeviceProfile.heightPx);
- RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mLauncher,
+ RectFSpringAnim anim = new RectFSpringAnim(closingWindowStartRect, targetRect, mLauncher,
mDeviceProfile);
// Hook up floating views to the closing window animators.
@@ -1371,7 +1405,7 @@
final float windowAlphaThreshold = 1f - SHAPE_PROGRESS_DURATION;
RectFSpringAnim.OnUpdateListener runner = new SpringAnimRunner(targets, targetRect,
- windowTargetBounds) {
+ windowTargetBounds, startWindowCornerRadius) {
@Override
public void onUpdate(RectF currentRectF, float progress) {
finalFloatingIconView.update(1f, 255 /* fgAlpha */, currentRectF, progress,
@@ -1388,8 +1422,8 @@
final float floatingWidgetAlpha = isTransluscent ? 0 : 1;
FloatingWidgetView finalFloatingWidget = floatingWidget;
- RectFSpringAnim.OnUpdateListener runner = new SpringAnimRunner(targets, targetRect,
- windowTargetBounds) {
+ RectFSpringAnim.OnUpdateListener runner = new SpringAnimRunner(targets, targetRect,
+ windowTargetBounds, startWindowCornerRadius) {
@Override
public void onUpdate(RectF currentRectF, float progress) {
final float fallbackBackgroundAlpha =
@@ -1403,6 +1437,11 @@
}
};
anim.addOnUpdateListener(runner);
+ } else {
+ // If no floating icon or widget is present, animate the to the default window
+ // target rect.
+ anim.addOnUpdateListener(new SpringAnimRunner(
+ targets, targetRect, windowTargetBounds, startWindowCornerRadius));
}
// Use a fixed velocity to start the animation.
@@ -1412,6 +1451,7 @@
anim.start(mLauncher, velocityPxPerS);
}
});
+ return anim;
}
/**
@@ -1536,6 +1576,105 @@
}
/**
+ * Creates the {@link RectFSpringAnim} and {@link AnimatorSet} required to animate
+ * the transition.
+ */
+ public Pair<RectFSpringAnim, AnimatorSet> createWallpaperOpenAnimations(
+ RemoteAnimationTargetCompat[] appTargets,
+ RemoteAnimationTargetCompat[] wallpaperTargets,
+ boolean fromUnlock,
+ RectF startRect,
+ float startWindowCornerRadius) {
+ AnimatorSet anim = null;
+ RectFSpringAnim rectFSpringAnim = null;
+
+ RemoteAnimationProvider provider = mRemoteAnimationProvider;
+ if (provider != null) {
+ anim = provider.createWindowAnimation(appTargets, wallpaperTargets);
+ }
+
+ if (anim == null) {
+ anim = new AnimatorSet();
+
+ final boolean launcherIsForceInvisibleOrOpening = mLauncher.isForceInvisible()
+ || launcherIsATargetWithMode(appTargets, MODE_OPENING);
+
+ View launcherView = findLauncherView(appTargets);
+ boolean playFallBackAnimation = (launcherView == null
+ && launcherIsForceInvisibleOrOpening)
+ || mLauncher.getWorkspace().isOverlayShown()
+ || hasMultipleTargetsWithMode(appTargets, MODE_CLOSING);
+
+ 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)) {
+ anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y,
+ true /* animateOverviewScrim */, launcherView).getAnimators());
+
+ if (!areAllTargetsTranslucent(appTargets)) {
+ anim.play(ObjectAnimator.ofFloat(mLauncher.getDepthController(), DEPTH,
+ BACKGROUND_APP.getDepth(mLauncher), NORMAL.getDepth(mLauncher)));
+ }
+
+ // We play StaggeredWorkspaceAnim as a part of the closing window animation.
+ playWorkspaceReveal = false;
+ } else {
+ // Skip scaling all apps, otherwise FloatingIconView will get wrong
+ // layout bounds.
+ skipAllAppsScale = true;
+ }
+ } 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());
+ }
+ }
+ }
+ }
+
+ return new Pair(rectFSpringAnim, anim);
+ }
+
+ /**
* Remote animation runner for animation from the app to Launcher, including recents.
*/
protected class WallpaperOpenLauncherAnimationRunner implements RemoteAnimationFactory {
@@ -1561,97 +1700,18 @@
return;
}
- if (!mLauncher.hasBeenResumed()) {
- // If launcher is not resumed, wait until new async-frame after resume
- mLauncher.addOnResumeCallback(() ->
- postAsyncCallback(mHandler, () ->
- onCreateAnimation(transit, appTargets, wallpaperTargets,
- nonAppTargets, result)));
- return;
- }
-
if (mLauncher.hasSomeInvisibleFlag(PENDING_INVISIBLE_BY_WALLPAPER_ANIMATION)) {
mLauncher.addForceInvisibleFlag(INVISIBLE_BY_PENDING_FLAGS);
mLauncher.getStateManager().moveToRestState();
}
- AnimatorSet anim = null;
- RemoteAnimationProvider provider = mRemoteAnimationProvider;
- if (provider != null) {
- anim = provider.createWindowAnimation(appTargets, wallpaperTargets);
- }
-
- if (anim == null) {
- anim = new AnimatorSet();
-
- final boolean launcherIsForceInvisibleOrOpening = mLauncher.isForceInvisible()
- || launcherIsATargetWithMode(appTargets, MODE_OPENING);
-
- View launcherView = findLauncherView(appTargets);
- boolean playFallBackAnimation = (launcherView == null
- && launcherIsForceInvisibleOrOpening)
- || mLauncher.getWorkspace().isOverlayShown();
-
- boolean playWorkspaceReveal = true;
- boolean skipAllAppsScale = false;
- if (mFromUnlock) {
- 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);
- getClosingWindowAnimators(anim, appTargets, launcherView, velocity);
- if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
- anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y,
- true /* animateOverviewScrim */, launcherView).getAnimators());
- // We play StaggeredWorkspaceAnim as a part of the closing window animation.
- playWorkspaceReveal = false;
- } else {
- // Skip scaling all apps, otherwise FloatingIconView will get wrong
- // layout bounds.
- skipAllAppsScale = true;
- }
- } 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());
- }
- }
- }
- }
+ Pair<RectFSpringAnim, AnimatorSet> pair = createWallpaperOpenAnimations(
+ appTargets, wallpaperTargets, mFromUnlock,
+ new RectF(0, 0, mDeviceProfile.widthPx, mDeviceProfile.heightPx),
+ QuickStepContract.getWindowCornerRadius(mLauncher));
mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL);
- result.setAnimation(anim, mLauncher);
+ result.setAnimation(pair.second, mLauncher);
}
}
@@ -1811,9 +1871,9 @@
private final Rect mTmpRect = new Rect();
SpringAnimRunner(RemoteAnimationTargetCompat[] appTargets, RectF targetRect,
- Rect windowTargetBounds) {
+ Rect windowTargetBounds, float startWindowCornerRadius) {
mAppTargets = appTargets;
- mStartRadius = QuickStepContract.getWindowCornerRadius(mLauncher);
+ mStartRadius = startWindowCornerRadius;
mEndRadius = Math.max(1, targetRect.width()) / 2f;
mSurfaceApplier = new SurfaceTransactionApplier(mDragLayer);
mWindowTargetBounds.set(windowTargetBounds);
diff --git a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
index 1b0f967..f42b39f 100644
--- a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
@@ -16,12 +16,11 @@
package com.android.launcher3.appprediction;
-import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
-import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.Build;
import android.text.Layout;
@@ -33,24 +32,17 @@
import androidx.annotation.ColorInt;
import androidx.core.content.ContextCompat;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.allapps.FloatingHeaderRow;
import com.android.launcher3.allapps.FloatingHeaderView;
-import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.util.Themes;
+import com.android.launcher3.views.ActivityContext;
/**
* A view which shows a horizontal divider
*/
@TargetApi(Build.VERSION_CODES.O)
-public class AppsDividerView extends View implements StateListener<LauncherState>,
- FloatingHeaderRow {
-
- private static final String ALL_APPS_VISITED_COUNT = "launcher.all_apps_visited_count";
- private static final int SHOW_ALL_APPS_LABEL_ON_ALL_APPS_VISITED_COUNT = 20;
+public class AppsDividerView extends View implements FloatingHeaderRow {
public enum DividerType {
NONE,
@@ -58,7 +50,6 @@
ALL_APPS_LABEL
}
- private final Launcher mLauncher;
private final TextPaint mPaint = new TextPaint();
private DividerType mDividerType = DividerType.NONE;
@@ -86,7 +77,6 @@
public AppsDividerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mLauncher = Launcher.getLauncher(context);
boolean isMainColorDark = Themes.getAttrBoolean(context, R.attr.isMainColorDark);
mDividerSize = new int[]{
@@ -101,6 +91,9 @@
mAllAppsLabelTextColor = ContextCompat.getColor(context, isMainColorDark
? R.color.all_apps_label_text_dark
: R.color.all_apps_label_text);
+
+ mShowAllAppsLabel = !ActivityContext.lookupContext(
+ getContext()).getOnboardingPrefs().hasReachedMaxCount(ALL_APPS_VISITED_COUNT);
}
public void setup(FloatingHeaderView parent, FloatingHeaderRow[] rows, boolean tabsHidden) {
@@ -110,6 +103,14 @@
updateDividerType();
}
+ /** {@code true} if all apps label should be shown in place of divider. */
+ public void setShowAllAppsLabel(boolean showAllAppsLabel) {
+ if (showAllAppsLabel != mShowAllAppsLabel) {
+ mShowAllAppsLabel = showAllAppsLabel;
+ updateDividerType();
+ }
+ }
+
@Override
public int getExpectedHeight() {
return getPaddingTop() + getPaddingBottom();
@@ -191,7 +192,7 @@
@Override
protected void onDraw(Canvas canvas) {
if (mDividerType == DividerType.LINE) {
- int l = (getWidth() - getPaddingLeft() - mDividerSize[0]) / 2;
+ int l = (getWidth() - mDividerSize[0]) / 2;
int t = getHeight() - (getPaddingBottom() / 2);
int radius = mDividerSize[1];
canvas.drawRoundRect(l, t, l + mDividerSize[0], t + mDividerSize[1], radius, radius,
@@ -209,7 +210,7 @@
private Layout getAllAppsLabelLayout() {
if (mAllAppsLabelLayout == null) {
mPaint.setAntiAlias(true);
- mPaint.setTypeface(Typeface.create("sans-serif-medium", Typeface.NORMAL));
+ mPaint.setTypeface(Typeface.create("google-sans", Typeface.NORMAL));
mPaint.setTextSize(
getResources().getDimensionPixelSize(R.dimen.all_apps_label_text_size));
@@ -236,57 +237,6 @@
}
@Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- if (shouldShowAllAppsLabel()) {
- mShowAllAppsLabel = true;
- mLauncher.getStateManager().addStateListener(this);
- updateDividerType();
- }
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- mLauncher.getStateManager().removeStateListener(this);
- }
-
- @Override
- public void onStateTransitionComplete(LauncherState finalState) {
- if (finalState == ALL_APPS) {
- setAllAppsVisitedCount(getAllAppsVisitedCount() + 1);
- } else {
- if (mShowAllAppsLabel != shouldShowAllAppsLabel()) {
- mShowAllAppsLabel = !mShowAllAppsLabel;
- updateDividerType();
- }
-
- if (!mShowAllAppsLabel) {
- mLauncher.getStateManager().removeStateListener(this);
- }
- }
- }
-
- private void setAllAppsVisitedCount(int count) {
- mLauncher.getSharedPrefs().edit().putInt(ALL_APPS_VISITED_COUNT, count).apply();
- }
-
- private int getAllAppsVisitedCount() {
- return mLauncher.getSharedPrefs().getInt(ALL_APPS_VISITED_COUNT, 0);
- }
-
- private boolean shouldShowAllAppsLabel() {
- return getAllAppsVisitedCount() < SHOW_ALL_APPS_LABEL_ON_ALL_APPS_VISITED_COUNT;
- }
-
- @Override
- public void setInsets(Rect insets, DeviceProfile grid) {
- int leftRightPadding = grid.allAppsLeftRightPadding;
- setPadding(leftRightPadding, getPaddingTop(), leftRightPadding, getPaddingBottom());
- }
-
- @Override
public void setVerticalScroll(int scroll, boolean isScrolledOut) {
setTranslationY(scroll);
mIsScrolledOut = isScrolledOut;
diff --git a/quickstep/src/com/android/launcher3/appprediction/InstantAppItemInfo.java b/quickstep/src/com/android/launcher3/appprediction/InstantAppItemInfo.java
index 6c4c601..9c3b881 100644
--- a/quickstep/src/com/android/launcher3/appprediction/InstantAppItemInfo.java
+++ b/quickstep/src/com/android/launcher3/appprediction/InstantAppItemInfo.java
@@ -19,6 +19,7 @@
import static com.android.quickstep.InstantAppResolverImpl.COMPONENT_CLASS_MARKER;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import com.android.launcher3.LauncherSettings;
@@ -38,8 +39,8 @@
}
@Override
- public WorkspaceItemInfo makeWorkspaceItem() {
- WorkspaceItemInfo workspaceItemInfo = super.makeWorkspaceItem();
+ public WorkspaceItemInfo makeWorkspaceItem(Context context) {
+ WorkspaceItemInfo workspaceItemInfo = super.makeWorkspaceItem(context);
workspaceItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
workspaceItemInfo.status = WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON
| WorkspaceItemInfo.FLAG_RESTORE_STARTED
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index 9ad8bb2..351a3bc 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -19,7 +19,6 @@
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
-import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -31,8 +30,8 @@
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
-import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.allapps.FloatingHeaderRow;
import com.android.launcher3.allapps.FloatingHeaderView;
@@ -43,18 +42,18 @@
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.ItemClickHandler;
import com.android.launcher3.touch.ItemLongClickListener;
+import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@TargetApi(Build.VERSION_CODES.P)
-public class PredictionRowView extends LinearLayout implements
- OnDeviceProfileChangeListener, FloatingHeaderRow {
+public class PredictionRowView<T extends Context & ActivityContext & DeviceProfileListenable>
+ extends LinearLayout implements OnDeviceProfileChangeListener, FloatingHeaderRow {
- private final Launcher mLauncher;
+ private final T mActivityContext;
private int mNumPredictedAppsPerRow;
// Helper to drawing the focus indicator.
@@ -64,12 +63,10 @@
private final List<WorkspaceItemInfo> mPredictedApps = new ArrayList<>();
private FloatingHeaderView mParent;
- private boolean mScrolledOut;
private boolean mPredictionsEnabled = false;
-
- @Nullable
- private List<ItemInfo> mPendingPredictedItems;
+ private @Nullable List<ItemInfo> mPendingPredictedItems;
+ private OnLongClickListener mOnIconLongClickListener = ItemLongClickListener.INSTANCE_ALL_APPS;
public PredictionRowView(@NonNull Context context) {
this(context, null);
@@ -80,9 +77,9 @@
setOrientation(LinearLayout.HORIZONTAL);
mFocusHelper = new SimpleFocusIndicatorHelper(this);
- mLauncher = Launcher.getLauncher(context);
- mLauncher.addOnDeviceProfileChangeListener(this);
- mNumPredictedAppsPerRow = mLauncher.getDeviceProfile().numShownAllAppsColumns;
+ mActivityContext = ActivityContext.lookupContext(context);
+ mActivityContext.addOnDeviceProfileChangeListener(this);
+ mNumPredictedAppsPerRow = mActivityContext.getDeviceProfile().numShownAllAppsColumns;
updateVisibility();
}
@@ -97,11 +94,11 @@
private void updateVisibility() {
setVisibility(mPredictionsEnabled ? VISIBLE : GONE);
- if (mLauncher.getAppsView() != null) {
+ if (mActivityContext.getAppsView() != null) {
if (mPredictionsEnabled) {
- mLauncher.getAppsView().getAppsStore().registerIconContainer(this);
+ mActivityContext.getAppsView().getAppsStore().registerIconContainer(this);
} else {
- mLauncher.getAppsView().getAppsStore().unregisterIconContainer(this);
+ mActivityContext.getAppsView().getAppsStore().unregisterIconContainer(this);
}
}
}
@@ -120,9 +117,9 @@
@Override
public int getExpectedHeight() {
- return getVisibility() == GONE ? 0 :
- Launcher.getLauncher(getContext()).getDeviceProfile().allAppsCellHeightPx
- + getPaddingTop() + getPaddingBottom();
+ return getVisibility() == GONE ? 0
+ : mActivityContext.getDeviceProfile().allAppsCellHeightPx + getPaddingTop()
+ + getPaddingBottom();
}
@Override
@@ -158,13 +155,12 @@
*/
public void setPredictedApps(List<ItemInfo> items) {
if (!FeatureFlags.ENABLE_APP_PREDICTIONS_WHILE_VISIBLE.get()
- && !mLauncher.isWorkspaceLoading()
+ && !mActivityContext.isBindingItems()
&& isShown()
&& getWindowVisibility() == View.VISIBLE) {
mPendingPredictedItems = items;
return;
}
-
applyPredictedApps(items);
}
@@ -177,6 +173,15 @@
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;
@@ -189,18 +194,18 @@
while (getChildCount() > mNumPredictedAppsPerRow) {
removeViewAt(0);
}
- LayoutInflater inflater = mLauncher.getAppsView().getLayoutInflater();
+ LayoutInflater inflater = mActivityContext.getAppsView().getLayoutInflater();
while (getChildCount() < mNumPredictedAppsPerRow) {
BubbleTextView icon = (BubbleTextView) inflater.inflate(
R.layout.all_apps_icon, this, false);
- icon.setOnClickListener(ItemClickHandler.INSTANCE);
- icon.setOnLongClickListener(ItemLongClickListener.INSTANCE_ALL_APPS);
+ icon.setOnClickListener(mActivityContext.getItemOnClickListener());
+ icon.setOnLongClickListener(mOnIconLongClickListener);
icon.setLongPressTimeoutFactor(1f);
icon.setOnFocusChangeListener(mFocusHelper);
LayoutParams lp = (LayoutParams) icon.getLayoutParams();
// Ensure the all apps icon height matches the workspace icons in portrait mode.
- lp.height = mLauncher.getDeviceProfile().allAppsCellHeightPx;
+ lp.height = mActivityContext.getDeviceProfile().allAppsCellHeightPx;
lp.width = 0;
lp.weight = 1;
addView(icon);
@@ -223,7 +228,6 @@
boolean predictionsEnabled = predictionCount > 0;
if (predictionsEnabled != mPredictionsEnabled) {
mPredictionsEnabled = predictionsEnabled;
- mLauncher.reapplyUi(false /* cancelCurrentAnimation */);
updateVisibility();
}
mParent.onHeightUpdated();
@@ -237,23 +241,16 @@
@Override
public void setVerticalScroll(int scroll, boolean isScrolledOut) {
- mScrolledOut = isScrolledOut;
if (!isScrolledOut) {
setTranslationY(scroll);
}
- setAlpha(mScrolledOut ? 0 : 1);
+ setAlpha(isScrolledOut ? 0 : 1);
if (getVisibility() != GONE) {
AlphaUpdateListener.updateVisibility(this);
}
}
@Override
- public void setInsets(Rect insets, DeviceProfile grid) {
- int leftRightPadding = grid.allAppsLeftRightPadding;
- setPadding(leftRightPadding, getPaddingTop(), leftRightPadding, getPaddingBottom());
- }
-
- @Override
public Class<PredictionRowView> getTypeClass() {
return PredictionRowView.class;
}
@@ -263,6 +260,7 @@
return getChildAt(0);
}
+
@Override
public void onVisibilityAggregated(boolean isVisible) {
super.onVisibilityAggregated(isVisible);
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
index 680012c..d63bc18 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
@@ -131,7 +131,7 @@
private int placeFoldersInWorkspace(ArrayDeque<FolderInfo> folders) {
if (folders.isEmpty()) return 0;
- Workspace workspace = mLauncher.getWorkspace();
+ Workspace<?> workspace = mLauncher.getWorkspace();
InvariantDeviceProfile idp = mLauncher.getDeviceProfile().inv;
GridOccupancy[] occupancyList = new GridOccupancy[workspace.getChildCount()];
@@ -176,7 +176,7 @@
* @return pageId where items are migrated
*/
private int migrateHotseatWhole() {
- Workspace workspace = mLauncher.getWorkspace();
+ Workspace<?> workspace = mLauncher.getWorkspace();
int pageId = -1;
int toRow = 0;
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
index 85d9f01..05b8167 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -55,13 +55,13 @@
import com.android.launcher3.touch.ItemLongClickListener;
import com.android.launcher3.uioverrides.PredictedAppIcon;
import com.android.launcher3.uioverrides.QuickstepLauncher;
-import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.views.Snackbar;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
@@ -409,11 +409,11 @@
@Nullable
@Override
public SystemShortcut<QuickstepLauncher> getShortcut(QuickstepLauncher activity,
- ItemInfo itemInfo) {
+ ItemInfo itemInfo, View originalView) {
if (itemInfo.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION) {
return null;
}
- return new PinPrediction(activity, itemInfo);
+ return new PinPrediction(activity, itemInfo, originalView);
}
private void preparePredictionInfo(WorkspaceItemInfo itemInfo, int rank) {
@@ -480,8 +480,8 @@
*
* @param matcher filter matching items that have been removed
*/
- public void onModelItemsRemoved(ItemInfoMatcher matcher) {
- if (mPredictedItems.removeIf(matcher::matchesInfo)) {
+ public void onModelItemsRemoved(Predicate<ItemInfo> matcher) {
+ if (mPredictedItems.removeIf(matcher)) {
fillGapsWithPrediction(true);
}
}
@@ -498,9 +498,9 @@
private class PinPrediction extends SystemShortcut<QuickstepLauncher> {
- private PinPrediction(QuickstepLauncher target, ItemInfo itemInfo) {
+ private PinPrediction(QuickstepLauncher target, ItemInfo itemInfo, View originalView) {
super(R.drawable.ic_pin, R.string.pin_prediction, target,
- itemInfo);
+ itemInfo, originalView);
}
@Override
diff --git a/quickstep/src/com/android/launcher3/model/AppEventProducer.java b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
index 7c29c5b..9f3be69 100644
--- a/quickstep/src/com/android/launcher3/model/AppEventProducer.java
+++ b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
@@ -18,12 +18,15 @@
import static android.app.prediction.AppTargetEvent.ACTION_DISMISS;
import static android.app.prediction.AppTargetEvent.ACTION_LAUNCH;
import static android.app.prediction.AppTargetEvent.ACTION_PIN;
+import static android.app.prediction.AppTargetEvent.ACTION_UNDISMISS;
import static android.app.prediction.AppTargetEvent.ACTION_UNPIN;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
+import static com.android.launcher3.logger.LauncherAtomExtensions.ExtendedContainers.ContainerCase.DEVICE_SEARCH_RESULT_CONTAINER;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DISMISS_PREDICTION_UNDO;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_CONVERTED_TO_ICON;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_PREDICTION_PINNED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DRAG_STARTED;
@@ -59,6 +62,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
+import com.android.launcher3.Utilities;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
import com.android.launcher3.logger.LauncherAtom.FolderContainer;
@@ -113,7 +117,8 @@
@AnyThread
private void sendEvent(AppTarget target, LauncherAtom.ItemInfo locationInfo, int eventId,
int targetPredictor) {
- if (target != null) {
+ // TODO: remove the running test check when b/231648228 is fixed.
+ if (target != null && !Utilities.IS_RUNNING_IN_TEST_HARNESS) {
AppTargetEvent event = new AppTargetEvent.Builder(target, eventId)
.setLaunchLocation(getContainer(locationInfo))
.build();
@@ -137,12 +142,12 @@
if (mLastDragItem == null) {
return;
}
- if (isTrackedForHotseatPrediction(atomInfo)) {
- sendEvent(atomInfo, ACTION_PIN, CONTAINER_HOTSEAT_PREDICTION);
- }
if (isTrackedForHotseatPrediction(mLastDragItem)) {
sendEvent(mLastDragItem, ACTION_UNPIN, CONTAINER_HOTSEAT_PREDICTION);
}
+ if (isTrackedForHotseatPrediction(atomInfo)) {
+ sendEvent(atomInfo, ACTION_PIN, CONTAINER_HOTSEAT_PREDICTION);
+ }
if (isTrackedForWidgetPrediction(atomInfo)) {
sendEvent(atomInfo, ACTION_PIN, CONTAINER_WIDGETS_PREDICTION);
}
@@ -175,6 +180,8 @@
mContext.getPackageName(), Process.myUserHandle())
.build();
sendEvent(target, atomInfo, ACTION_LAUNCH, CONTAINER_PREDICTION);
+ } else if (event == LAUNCHER_DISMISS_PREDICTION_UNDO) {
+ sendEvent(atomInfo, ACTION_UNDISMISS, CONTAINER_HOTSEAT_PREDICTION);
}
}
@@ -293,10 +300,9 @@
case SEARCH_RESULT_CONTAINER:
return "search-results";
case EXTENDED_CONTAINERS: {
- switch(ci.getExtendedContainers().getContainerCase()) {
- case DEVICE_SEARCH_RESULT_CONTAINER:
- case CORRECTED_DEVICE_SEARCH_RESULT_CONTAINER:
- return "search-results";
+ if (ci.getExtendedContainers().getContainerCase()
+ == DEVICE_SEARCH_RESULT_CONTAINER) {
+ return "search-results";
}
}
default: // fall out
diff --git a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
index b0fba3d..7e3ee7d 100644
--- a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
@@ -34,7 +34,6 @@
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
-import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -60,13 +59,13 @@
Utilities.getDevicePrefs(context).edit()
.putBoolean(LAST_PREDICTION_ENABLED_STATE, !mTargets.isEmpty()).apply();
- FixedContainerItems fci = mPredictorState.items;
- Set<UserHandle> usersForChangedShortcuts = new HashSet<>(fci.items.stream()
- .filter(info -> info.itemType == ITEM_TYPE_DEEP_SHORTCUT)
- .map(info -> info.user)
- .collect(Collectors.toSet()));
- fci.items.clear();
+ Set<UserHandle> usersForChangedShortcuts =
+ dataModel.extraItems.get(mPredictorState.containerId).items.stream()
+ .filter(info -> info.itemType == ITEM_TYPE_DEEP_SHORTCUT)
+ .map(info -> info.user)
+ .collect(Collectors.toSet());
+ FixedContainerItems fci = new FixedContainerItems(mPredictorState.containerId);
for (AppTarget target : mTargets) {
WorkspaceItemInfo itemInfo;
ShortcutInfo si = target.getShortcutInfo();
@@ -86,7 +85,7 @@
.filter(info -> user.equals(info.user) && cn.equals(info.componentName))
.map(ai -> {
app.getIconCache().getTitleAndIcon(ai, false);
- return ai.makeWorkspaceItem();
+ return ai.makeWorkspaceItem(context);
})
.findAny()
.orElseGet(() -> {
@@ -97,7 +96,7 @@
}
AppInfo ai = new AppInfo(context, lai, user);
app.getIconCache().getTitleAndIcon(ai, lai, false);
- return ai.makeWorkspaceItem();
+ return ai.makeWorkspaceItem(context);
});
if (itemInfo == null) {
@@ -109,6 +108,7 @@
fci.items.add(itemInfo);
}
+ dataModel.extraItems.put(fci.containerId, fci);
bindExtraContainerItems(fci);
usersForChangedShortcuts.forEach(
u -> dataModel.updateShortcutPinnedState(app.getContext(), u));
diff --git a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
index 4d06956..770dfb2 100644
--- a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
+++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
@@ -119,18 +119,19 @@
WorkspaceItemFactory allAppsFactory = new WorkspaceItemFactory(
mApp, ums, pinnedShortcuts, mIDP.numDatabaseAllAppsColumns);
- mAllAppsState.items.setItems(
+ FixedContainerItems allAppsItems = new FixedContainerItems(mAllAppsState.containerId,
mAllAppsState.storage.read(mApp.getContext(), allAppsFactory, ums.allUsers::get));
- mDataModel.extraItems.put(CONTAINER_PREDICTION, mAllAppsState.items);
+ mDataModel.extraItems.put(mAllAppsState.containerId, allAppsItems);
WorkspaceItemFactory hotseatFactory =
new WorkspaceItemFactory(mApp, ums, pinnedShortcuts, mIDP.numDatabaseHotseatIcons);
- mHotseatState.items.setItems(
+ FixedContainerItems hotseatItems = new FixedContainerItems(mHotseatState.containerId,
mHotseatState.storage.read(mApp.getContext(), hotseatFactory, ums.allUsers::get));
- mDataModel.extraItems.put(CONTAINER_HOTSEAT_PREDICTION, mHotseatState.items);
+ mDataModel.extraItems.put(mHotseatState.containerId, hotseatItems);
// Widgets prediction isn't used frequently. And thus, it is not persisted on disk.
- mDataModel.extraItems.put(CONTAINER_WIDGETS_PREDICTION, mWidgetsRecommendationState.items);
+ mDataModel.extraItems.put(mWidgetsRecommendationState.containerId,
+ new FixedContainerItems(mWidgetsRecommendationState.containerId));
mActive = true;
}
@@ -233,9 +234,9 @@
"Item info: %s found with invalid container: %s",
info,
containerInfo));
- } else {
- return (FolderInfo) containerInfo;
}
+ // Allow crash to help debug b/173838775
+ return (FolderInfo) containerInfo;
}
return null;
}
@@ -371,14 +372,14 @@
static class PredictorState {
- public final FixedContainerItems items;
+ public final int containerId;
public final PersistedItemArray<ItemInfo> storage;
public AppPredictor predictor;
private List<AppTarget> mLastTargets;
- PredictorState(int container, String storageName) {
- items = new FixedContainerItems(container);
+ PredictorState(int containerId, String storageName) {
+ this.containerId = containerId;
storage = new PersistedItemArray<>(storageName);
mLastTargets = Collections.emptyList();
}
@@ -459,7 +460,7 @@
AppInfo info = new AppInfo(lai, user, mUMS.isUserQuiet(user));
mAppState.getIconCache().getTitleAndIcon(info, lai, false);
mReadCount++;
- return info.makeWorkspaceItem();
+ return info.makeWorkspaceItem(mAppState.getContext());
}
case ITEM_TYPE_DEEP_SHORTCUT: {
ShortcutKey key = ShortcutKey.fromIntent(intent, user);
diff --git a/quickstep/src/com/android/launcher3/model/WellbeingModel.java b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
index e489cb3..68ed682 100644
--- a/quickstep/src/com/android/launcher3/model/WellbeingModel.java
+++ b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
@@ -40,6 +40,7 @@
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
+import android.view.View;
import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
@@ -193,7 +194,7 @@
@MainThread
private SystemShortcut getShortcutForApp(String packageName, int userId,
- BaseDraggingActivity activity, ItemInfo info) {
+ BaseDraggingActivity activity, ItemInfo info, View originalView) {
Preconditions.assertUIThread();
// Work profile apps are not recognized by digital wellbeing.
if (userId != UserHandle.myUserId()) {
@@ -217,7 +218,7 @@
"getShortcutForApp [" + packageName + "]: action: '" + action.getTitle()
+ "'");
}
- return new RemoteActionShortcut(action, activity, info);
+ return new RemoteActionShortcut(action, activity, info, originalView);
}
}
@@ -378,8 +379,8 @@
* Shortcut factory for generating wellbeing action
*/
public static final SystemShortcut.Factory<BaseDraggingActivity> SHORTCUT_FACTORY =
- (activity, info) -> (info.getTargetComponent() == null) ? null : INSTANCE.get(activity)
- .getShortcutForApp(
+ (activity, info, originalView) -> (info.getTargetComponent() == null) ? null
+ : INSTANCE.get(activity).getShortcutForApp(
info.getTargetComponent().getPackageName(), info.user.getIdentifier(),
- activity, info);
+ activity, info, originalView);
}
diff --git a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
index 4be83dc..9cd9d85 100644
--- a/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/WidgetsPredictionUpdateTask.java
@@ -59,8 +59,8 @@
Map<PackageUserKey, List<WidgetItem>> allWidgets =
dataModel.widgetsModel.getAllWidgetsWithoutShortcuts();
- FixedContainerItems fixedContainerItems = mPredictorState.items;
- fixedContainerItems.items.clear();
+ FixedContainerItems fixedContainerItems =
+ new FixedContainerItems(mPredictorState.containerId);
if (FeatureFlags.ENABLE_LOCAL_RECOMMENDED_WIDGETS_FILTER.get()) {
for (AppTarget app : mTargets) {
@@ -100,6 +100,7 @@
}
}
}
+ dataModel.extraItems.put(mPredictorState.containerId, fixedContainerItems);
bindExtraContainerItems(fixedContainerItems);
// Don't store widgets prediction to disk because it is not used frequently.
diff --git a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
new file mode 100644
index 0000000..4e59790
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
@@ -0,0 +1,93 @@
+/*
+ * 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.popup;
+
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+import android.view.View;
+
+import com.android.launcher3.BaseQuickstepLauncher;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
+import com.android.quickstep.views.RecentsView;
+
+public interface QuickstepSystemShortcut {
+
+ String TAG = QuickstepSystemShortcut.class.getSimpleName();
+
+ static SystemShortcut.Factory<BaseQuickstepLauncher> getSplitSelectShortcutByPosition(
+ SplitPositionOption position) {
+ return (activity, itemInfo, originalView) ->
+ new QuickstepSystemShortcut.SplitSelectSystemShortcut(activity, itemInfo,
+ originalView, position);
+ }
+
+ class SplitSelectSystemShortcut extends SystemShortcut<BaseQuickstepLauncher> {
+
+ private final SplitPositionOption mPosition;
+
+ public SplitSelectSystemShortcut(BaseQuickstepLauncher launcher, ItemInfo itemInfo,
+ View originalView, SplitPositionOption position) {
+ super(position.iconResId, position.textResId, launcher, itemInfo, originalView);
+
+ mPosition = position;
+ }
+
+ @Override
+ public void onClick(View view) {
+ Bitmap bitmap;
+ Intent intent;
+ if (mItemInfo instanceof WorkspaceItemInfo) {
+ final WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) mItemInfo;
+ bitmap = workspaceItemInfo.bitmap.icon;
+ intent = workspaceItemInfo.intent;
+ } else if (mItemInfo instanceof com.android.launcher3.model.data.AppInfo) {
+ final com.android.launcher3.model.data.AppInfo appInfo =
+ (com.android.launcher3.model.data.AppInfo) mItemInfo;
+ bitmap = appInfo.bitmap.icon;
+ intent = appInfo.intent;
+ } else {
+ Log.e(TAG, "unknown item type");
+ return;
+ }
+
+ RecentsView recentsView = mTarget.getOverviewPanel();
+ recentsView.initiateSplitSelect(
+ new SplitSelectSource(mOriginalView, new BitmapDrawable(bitmap), intent,
+ mPosition));
+ }
+ }
+
+ class SplitSelectSource {
+
+ public final View view;
+ public final Drawable drawable;
+ public final Intent intent;
+ public final SplitPositionOption position;
+
+ public SplitSelectSource(View view, Drawable drawable, Intent intent,
+ SplitPositionOption position) {
+ this.view = view;
+ this.drawable = drawable;
+ this.intent = intent;
+ this.position = position;
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/proxy/StartActivityParams.java b/quickstep/src/com/android/launcher3/proxy/StartActivityParams.java
index bee8bb8..b47ef47 100644
--- a/quickstep/src/com/android/launcher3/proxy/StartActivityParams.java
+++ b/quickstep/src/com/android/launcher3/proxy/StartActivityParams.java
@@ -16,6 +16,10 @@
package com.android.launcher3.proxy;
+import static android.app.PendingIntent.FLAG_MUTABLE;
+import static android.app.PendingIntent.FLAG_ONE_SHOT;
+import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
+
import android.app.Activity;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
@@ -45,7 +49,7 @@
public StartActivityParams(Activity activity, int requestCode) {
this(activity.createPendingResult(requestCode, new Intent(),
- PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT), requestCode);
+ FLAG_ONE_SHOT | FLAG_UPDATE_CURRENT | FLAG_MUTABLE), requestCode);
}
public StartActivityParams(PendingIntent pendingIntent, int requestCode) {
diff --git a/quickstep/src/com/android/launcher3/statehandlers/BackButtonAlphaHandler.java b/quickstep/src/com/android/launcher3/statehandlers/BackButtonAlphaHandler.java
index 1f268cc..07d3a51 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/BackButtonAlphaHandler.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/BackButtonAlphaHandler.java
@@ -17,17 +17,17 @@
package com.android.launcher3.statehandlers;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.util.DisplayController.NavigationMode.TWO_BUTTONS;
import static com.android.quickstep.AnimatedFloat.VALUE;
-import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.UiThreadHelper;
import com.android.quickstep.AnimatedFloat;
-import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SystemUiProxy;
/**
@@ -48,7 +48,7 @@
@Override
public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config,
PendingAnimation animation) {
- if (SysUINavigationMode.getMode(mLauncher) != TWO_BUTTONS) {
+ if (DisplayController.getNavigationMode(mLauncher) != TWO_BUTTONS) {
return;
}
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index 3242d42..eda0823 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -23,6 +23,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
+import android.app.WallpaperManager;
import android.os.IBinder;
import android.os.SystemProperties;
import android.util.FloatProperty;
@@ -42,7 +43,6 @@
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.systemui.shared.system.BlurUtils;
-import com.android.systemui.shared.system.WallpaperManagerCompat;
import java.io.PrintWriter;
import java.util.function.Consumer;
@@ -53,6 +53,7 @@
public class DepthController implements StateHandler<LauncherState>,
BaseActivity.MultiWindowModeChangedListener {
+ private static final boolean OVERLAY_SCROLL_ENABLED = false;
public static final FloatProperty<DepthController> DEPTH =
new FloatProperty<DepthController>("depth") {
@Override
@@ -127,7 +128,7 @@
*/
private int mMaxBlurRadius;
private boolean mCrossWindowBlursEnabled;
- private WallpaperManagerCompat mWallpaperManager;
+ private WallpaperManager mWallpaperManager;
private SurfaceControl mSurface;
/**
* How visible the -1 overlay is, from 0 to 1.
@@ -168,7 +169,7 @@
private void ensureDependencies() {
if (mWallpaperManager == null) {
mMaxBlurRadius = mLauncher.getResources().getInteger(R.integer.max_depth_blur_radius);
- mWallpaperManager = new WallpaperManagerCompat(mLauncher);
+ mWallpaperManager = mLauncher.getSystemService(WallpaperManager.class);
}
if (mLauncher.getRootView() != null && mOnAttachListener == null) {
@@ -294,6 +295,14 @@
}
public void onOverlayScrollChanged(float progress) {
+ if (!OVERLAY_SCROLL_ENABLED) {
+ return;
+ }
+ // Add some padding to the progress, such we don't change the depth on the last frames of
+ // the animation. It's possible that a user flinging the feed quickly would scroll
+ // horizontally by accident, causing the device to enter client composition unnecessarily.
+ progress = Math.min(progress * 1.1f, 1f);
+
// Round out the progress to dedupe frequent, non-perceptable updates
int progressI = (int) (progress * 256);
float progressF = Utilities.boundToRange(progressI / 256f, 0f, 1f);
diff --git a/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java b/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java
new file mode 100644
index 0000000..b4052e3
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar;
+
+import android.content.Context;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
+
+import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
+import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
+import com.android.launcher3.util.Themes;
+import com.android.launcher3.views.AppLauncher;
+
+import java.util.ArrayList;
+import java.util.List;
+
+// TODO(b/218912746): Share more behavior to avoid all apps context depending directly on taskbar.
+/** Base for common behavior between taskbar window contexts. */
+public abstract class BaseTaskbarContext extends ContextThemeWrapper implements AppLauncher,
+ DeviceProfileListenable {
+
+ protected final LayoutInflater mLayoutInflater;
+ private final List<OnDeviceProfileChangeListener> mDPChangeListeners = new ArrayList<>();
+
+ public BaseTaskbarContext(Context windowContext) {
+ super(windowContext, Themes.getActivityThemeRes(windowContext));
+ mLayoutInflater = LayoutInflater.from(this).cloneInContext(this);
+ }
+
+ @Override
+ public final LayoutInflater getLayoutInflater() {
+ return mLayoutInflater;
+ }
+
+ @Override
+ public final List<OnDeviceProfileChangeListener> getOnDeviceProfileChangeListeners() {
+ return mDPChangeListeners;
+ }
+
+ /** Callback invoked when a drag is initiated within this context. */
+ public abstract void onDragStart();
+
+ /** Callback invoked when a drag is finished within this context. */
+ public abstract void onDragEnd();
+
+ /** Callback invoked when a popup is shown or closed within this context. */
+ public abstract void onPopupVisibilityChanged(boolean isVisible);
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
new file mode 100644
index 0000000..0ab3cfd5
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar;
+
+import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_NOTIFICATIONS;
+import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_QUICK_SETTINGS;
+
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.launcher3.R;
+
+/**
+ * Controller for managing buttons and status icons in taskbar in a desktop environment.
+ */
+public class DesktopNavbarButtonsViewController extends NavbarButtonsViewController {
+
+ private final TaskbarActivityContext mContext;
+ private final FrameLayout mNavButtonsView;
+ private final ViewGroup mNavButtonContainer;
+
+ private TaskbarControllers mControllers;
+
+ public DesktopNavbarButtonsViewController(TaskbarActivityContext context,
+ FrameLayout navButtonsView) {
+ super(context, navButtonsView);
+ mContext = context;
+ mNavButtonsView = navButtonsView;
+ mNavButtonContainer = mNavButtonsView.findViewById(R.id.end_nav_buttons);
+ }
+
+ /**
+ * Initializes the controller
+ */
+ @Override
+ public void init(TaskbarControllers controllers) {
+ mControllers = controllers;
+ mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarSize;
+
+ // Quick settings and notifications buttons
+ addButton(R.drawable.ic_sysbar_quick_settings, BUTTON_QUICK_SETTINGS,
+ mNavButtonContainer, mControllers.navButtonController,
+ R.id.quick_settings_button);
+ addButton(R.drawable.ic_sysbar_notifications, BUTTON_NOTIFICATIONS,
+ mNavButtonContainer, mControllers.navButtonController,
+ R.id.notifications_button);
+ }
+
+ /** Cleans up on destroy */
+ @Override
+ public void onDestroy() { }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java
new file mode 100644
index 0000000..e2359c0
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar;
+
+import com.android.launcher3.BaseQuickstepLauncher;
+
+/**
+ * A data source which integrates with a Launcher instance, used specifically for a
+ * desktop environment.
+ */
+public class DesktopTaskbarUIController extends TaskbarUIController {
+
+ private final BaseQuickstepLauncher mLauncher;
+
+ public DesktopTaskbarUIController(BaseQuickstepLauncher launcher) {
+ mLauncher = launcher;
+ }
+
+ @Override
+ protected void init(TaskbarControllers taskbarControllers) {
+ mLauncher.getHotseat().setIconsAlpha(0f);
+ }
+
+ @Override
+ protected void onDestroy() {
+ mLauncher.getHotseat().setIconsAlpha(1f);
+ }
+
+ @Override
+ /** Disable taskbar stashing in desktop environment. */
+ public boolean supportsVisualStashing() {
+ return false;
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 5e8db69..ca30e72 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -19,14 +19,18 @@
import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTRA_NAVIGATION_BAR;
import android.animation.Animator;
+import android.animation.AnimatorSet;
import android.annotation.ColorInt;
import android.os.RemoteException;
import android.util.Log;
+import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.TaskTransitionSpec;
import android.view.WindowManagerGlobal;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.DeviceProfile;
@@ -34,15 +38,15 @@
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
+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.util.OnboardingPrefs;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.RecentsAnimationCallbacks;
+import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Stream;
@@ -54,10 +58,22 @@
private static final String TAG = "TaskbarUIController";
+ public static final int MINUS_ONE_PAGE_PROGRESS_INDEX = 0;
+ public static final int ALL_APPS_PAGE_PROGRESS_INDEX = 1;
+ public static final int WIDGETS_PAGE_PROGRESS_INDEX = 2;
+ public static final int SYSUI_SURFACE_PROGRESS_INDEX = 3;
+
+ private final SparseArray<Float> mTaskbarInAppDisplayProgress = new SparseArray<>(4);
+
private final BaseQuickstepLauncher mLauncher;
private final DeviceProfile.OnDeviceProfileChangeListener mOnDeviceProfileChangeListener =
- this::onStashedInAppChanged;
+ dp -> {
+ onStashedInAppChanged(dp);
+ if (mControllers != null && mControllers.taskbarViewController != null) {
+ mControllers.taskbarViewController.onRotationChanged(dp);
+ }
+ };
// Initialized in init.
private AnimatedFloat mTaskbarOverrideBackgroundAlpha;
@@ -65,15 +81,6 @@
private final TaskbarLauncherStateController
mTaskbarLauncherStateController = new TaskbarLauncherStateController();
- private final DeviceProfile.OnDeviceProfileChangeListener mProfileChangeListener =
- new DeviceProfile.OnDeviceProfileChangeListener() {
- @Override
- public void onDeviceProfileChanged(DeviceProfile dp) {
- mControllers.taskbarViewController.onRotationChanged(
- mLauncher.getDeviceProfile());
- }
- };
-
public LauncherTaskbarUIController(BaseQuickstepLauncher launcher) {
mLauncher = launcher;
}
@@ -93,7 +100,6 @@
onStashedInAppChanged(mLauncher.getDeviceProfile());
mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
- mLauncher.addOnDeviceProfileChangeListener(mProfileChangeListener);
}
@Override
@@ -102,9 +108,8 @@
onLauncherResumedOrPaused(false);
mTaskbarLauncherStateController.onDestroy();
- mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
mLauncher.setTaskbarUIController(null);
- mLauncher.removeOnDeviceProfileChangeListener(mProfileChangeListener);
+ mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
updateTaskTransitionSpec(true);
}
@@ -113,6 +118,47 @@
return !mTaskbarLauncherStateController.isAnimatingToLauncher();
}
+ public void setShouldDelayLauncherStateAnim(boolean shouldDelayLauncherStateAnim) {
+ mTaskbarLauncherStateController.setShouldDelayLauncherStateAnim(
+ shouldDelayLauncherStateAnim);
+ }
+
+ /**
+ * Enables manual taskbar stashing. This method should only be used for tests that need to
+ * stash/unstash the taskbar.
+ */
+ @VisibleForTesting
+ public void enableManualStashingForTests(boolean enableManualStashing) {
+ mControllers.taskbarStashController.enableManualStashingForTests(enableManualStashing);
+ }
+
+ /**
+ * Unstashes the Taskbar if it is stashed. This method should only be used to unstash the
+ * taskbar at the end of a test.
+ */
+ @VisibleForTesting
+ public void unstashTaskbarIfStashed() {
+ mControllers.taskbarStashController.onLongPressToUnstashTaskbar();
+ }
+
+ /**
+ * Adds the Launcher resume animator to the given animator set.
+ *
+ * This should be used to run a Launcher resume animation whose progress matches a
+ * swipe progress.
+ *
+ * @param placeholderDuration a placeholder duration to be used to ensure all full-length
+ * sub-animations are properly coordinated. This duration should not
+ * actually be used since this animation tracks a swipe progress.
+ */
+ protected void addLauncherResumeAnimation(AnimatorSet animation, int placeholderDuration) {
+ animation.play(onLauncherResumedOrPaused(
+ /* isResumed= */ true,
+ /* fromInit= */ false,
+ /* startAnimation= */ false,
+ placeholderDuration));
+ }
+
/**
* Should be called from onResume() and onPause(), and animates the Taskbar accordingly.
*/
@@ -121,9 +167,19 @@
}
private void onLauncherResumedOrPaused(boolean isResumed, boolean fromInit) {
+ onLauncherResumedOrPaused(
+ isResumed,
+ fromInit,
+ /* startAnimation= */ true,
+ QuickstepTransitionManager.CONTENT_ALPHA_DURATION);
+ }
+
+ @Nullable
+ private Animator onLauncherResumedOrPaused(
+ boolean isResumed, boolean fromInit, boolean startAnimation, int duration) {
if (mKeyguardController.isScreenOff()) {
if (!isResumed) {
- return;
+ return null;
} else {
// Resuming implicitly means device unlocked
mKeyguardController.setScreenOn();
@@ -131,8 +187,7 @@
}
mTaskbarLauncherStateController.updateStateForFlag(FLAG_RESUMED, isResumed);
- mTaskbarLauncherStateController.applyState(
- fromInit ? 0 : QuickstepTransitionManager.CONTENT_ALPHA_DURATION);
+ return mTaskbarLauncherStateController.applyState(fromInit ? 0 : duration, startAnimation);
}
/**
@@ -211,9 +266,7 @@
* Starts the taskbar education flow, if the user hasn't seen it yet.
*/
public void showEdu() {
- if (!FeatureFlags.ENABLE_TASKBAR_EDU.get()
- || Utilities.IS_RUNNING_IN_TEST_HARNESS
- || mLauncher.getOnboardingPrefs().getBoolean(OnboardingPrefs.TASKBAR_EDU_SEEN)) {
+ if (!shouldShowEdu()) {
return;
}
mLauncher.getOnboardingPrefs().markChecked(OnboardingPrefs.TASKBAR_EDU_SEEN);
@@ -222,18 +275,22 @@
}
/**
+ * Whether the taskbar education should be shown.
+ */
+ public boolean shouldShowEdu() {
+ return !Utilities.IS_RUNNING_IN_TEST_HARNESS
+ && !mLauncher.getOnboardingPrefs().getBoolean(OnboardingPrefs.TASKBAR_EDU_SEEN);
+ }
+
+ /**
* Manually ends the taskbar education flow.
*/
public void hideEdu() {
- if (!FeatureFlags.ENABLE_TASKBAR_EDU.get()) {
- return;
- }
-
mControllers.taskbarEduController.hideEdu();
}
@Override
- public void onTaskbarIconLaunched(WorkspaceItemInfo item) {
+ public void onTaskbarIconLaunched(ItemInfo item) {
InstanceId instanceId = new InstanceIdSequence().newInstanceId();
mLauncher.logAppLaunch(mControllers.taskbarActivityContext.getStatsLogManager(), item,
instanceId);
@@ -246,4 +303,85 @@
// gesture ends, start drawing taskbar's background again since launcher might stop drawing.
forceHideBackground(inProgress);
}
+
+ /**
+ * Animates Taskbar elements during a transition to a Launcher state that should use in-app
+ * layouts.
+ *
+ * @param progress [0, 1]
+ * 0 => use home layout
+ * 1 => use in-app layout
+ */
+ public void onTaskbarInAppDisplayProgressUpdate(float progress, int progressIndex) {
+ if (mControllers == null) {
+ // This method can be called before init() is called.
+ return;
+ }
+ mTaskbarInAppDisplayProgress.put(progressIndex, progress);
+ if (!mControllers.taskbarStashController.isInApp()
+ && !mTaskbarLauncherStateController.isAnimatingToLauncher()) {
+ // Only animate the nav buttons while home and not animating home, otherwise let
+ // the TaskbarViewController handle it.
+ mControllers.navbarButtonsViewController
+ .getTaskbarNavButtonTranslationYForInAppDisplay()
+ .updateValue(mLauncher.getDeviceProfile().getTaskbarOffsetY()
+ * getInAppDisplayProgress());
+ }
+ }
+
+ /** Returns true iff any in-app display progress > 0. */
+ public boolean shouldUseInAppLayout() {
+ return getInAppDisplayProgress() > 0;
+ }
+
+ private float getInAppDisplayProgress(int index) {
+ if (!mTaskbarInAppDisplayProgress.contains(index)) {
+ mTaskbarInAppDisplayProgress.put(index, 0f);
+ }
+ return mTaskbarInAppDisplayProgress.get(index);
+ }
+
+ private float getInAppDisplayProgress() {
+ return Stream.of(
+ getInAppDisplayProgress(MINUS_ONE_PAGE_PROGRESS_INDEX),
+ getInAppDisplayProgress(ALL_APPS_PAGE_PROGRESS_INDEX),
+ getInAppDisplayProgress(WIDGETS_PAGE_PROGRESS_INDEX),
+ getInAppDisplayProgress(SYSUI_SURFACE_PROGRESS_INDEX))
+ .max(Float::compareTo)
+ .get();
+ }
+
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ super.dumpLogs(prefix, pw);
+
+ pw.println(String.format(
+ "%s\tmTaskbarOverrideBackgroundAlpha=%.2f",
+ prefix,
+ mTaskbarOverrideBackgroundAlpha.value));
+
+ pw.println(String.format("%s\tTaskbar in-app display progress:", prefix));
+ if (mControllers == null) {
+ pw.println(String.format("%s\t\tMissing mControllers", prefix));
+ } else {
+ pw.println(String.format(
+ "%s\t\tprogress at MINUS_ONE_PAGE_PROGRESS_INDEX=%.2f",
+ prefix,
+ getInAppDisplayProgress(MINUS_ONE_PAGE_PROGRESS_INDEX)));
+ pw.println(String.format(
+ "%s\t\tprogress at ALL_APPS_PAGE_PROGRESS_INDEX=%.2f",
+ prefix,
+ getInAppDisplayProgress(ALL_APPS_PAGE_PROGRESS_INDEX)));
+ pw.println(String.format(
+ "%s\t\tprogress at WIDGETS_PAGE_PROGRESS_INDEX=%.2f",
+ prefix,
+ getInAppDisplayProgress(WIDGETS_PAGE_PROGRESS_INDEX)));
+ pw.println(String.format(
+ "%s\t\tprogress at SYSUI_SURFACE_PROGRESS_INDEX=%.2f",
+ prefix,
+ getInAppDisplayProgress(SYSUI_SURFACE_PROGRESS_INDEX)));
+ }
+
+ mTaskbarLauncherStateController.dumpLogs(prefix + "\t", pw);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 50637a1..5d576f7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -16,12 +16,15 @@
package com.android.launcher3.taskbar;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
+import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
+import static com.android.launcher3.taskbar.LauncherTaskbarUIController.SYSUI_SURFACE_PROGRESS_INDEX;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_HOME;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_IME_SWITCH;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_RECENTS;
import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_KEYGUARD;
+import static com.android.launcher3.taskbar.Utilities.appendFlag;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISABLED;
@@ -32,6 +35,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
+import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
@@ -41,19 +45,26 @@
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
+import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Region.Op;
import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.PaintDrawable;
+import android.inputmethodservice.InputMethodService;
+import android.os.Handler;
import android.util.Property;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnClickListener;
import android.view.View.OnHoverListener;
import android.view.ViewGroup;
+import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.R;
@@ -61,18 +72,24 @@
import com.android.launcher3.anim.AlphaUpdateListener;
import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton;
import com.android.launcher3.util.MultiValueAlpha;
+import com.android.launcher3.util.TouchController;
+import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.AnimatedFloat;
import com.android.systemui.shared.rotation.FloatingRotationButton;
import com.android.systemui.shared.rotation.RotationButton;
import com.android.systemui.shared.rotation.RotationButtonController;
+import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.ViewTreeObserverWrapper;
+import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.StringJoiner;
import java.util.function.IntPredicate;
/**
* Controller for managing nav bar buttons in taskbar
*/
-public class NavbarButtonsViewController {
+public class NavbarButtonsViewController implements TaskbarControllers.LoggableTaskbarController {
private final Rect mTempRect = new Rect();
@@ -91,6 +108,12 @@
private static final int MASK_IME_SWITCHER_VISIBLE = FLAG_SWITCHER_SUPPORTED | FLAG_IME_VISIBLE;
+ private static final String NAV_BUTTONS_SEPARATE_WINDOW_TITLE = "Taskbar Nav Buttons";
+
+ public static final int ALPHA_INDEX_IMMERSIVE_MODE = 0;
+ public static final int ALPHA_INDEX_KEYGUARD_OR_DISABLE = 1;
+ private static final int NUM_ALPHA_CHANNELS = 2;
+
private final ArrayList<StatePropertyHolder> mPropertyHolders = new ArrayList<>();
private final ArrayList<ImageView> mAllButtons = new ArrayList<>();
private int mState;
@@ -106,11 +129,13 @@
private final AnimatedFloat mTaskbarNavButtonTranslationY = new AnimatedFloat(
this::updateNavButtonTranslationY);
+ private final AnimatedFloat mTaskbarNavButtonTranslationYForInAppDisplay = new AnimatedFloat(
+ this::updateNavButtonTranslationY);
private final AnimatedFloat mTaskbarNavButtonTranslationYForIme = new AnimatedFloat(
this::updateNavButtonTranslationY);
- // Only applies to mTaskbarNavButtonTranslationY
- private final AnimatedFloat mNavButtonTranslationYMultiplier = new AnimatedFloat(
- this::updateNavButtonTranslationY);
+ // Used for System UI state updates that should translate the nav button for in-app display.
+ private final AnimatedFloat mNavButtonInAppDisplayProgressForSysui = new AnimatedFloat(
+ this::updateNavButtonInAppDisplayProgressForSysui);
private final AnimatedFloat mTaskbarNavButtonDarkIntensity = new AnimatedFloat(
this::updateNavButtonDarkIntensity);
private final AnimatedFloat mNavButtonDarkIntensityMultiplier = new AnimatedFloat(
@@ -121,11 +146,22 @@
// Initialized in init.
private TaskbarControllers mControllers;
+ private boolean mIsImeRenderingNavButtons;
private View mA11yButton;
private int mSysuiStateFlags;
private View mBackButton;
+ private View mHomeButton;
+ private MultiValueAlpha mBackButtonAlpha;
+ private MultiValueAlpha mHomeButtonAlpha;
private FloatingRotationButton mFloatingRotationButton;
+ // Variables for moving nav buttons to a separate window above IME
+ private boolean mAreNavButtonsInSeparateWindow = false;
+ private BaseDragLayer<TaskbarActivityContext> mSeparateWindowParent; // Initialized in init.
+ private final ViewTreeObserverWrapper.OnComputeInsetsListener mSeparateWindowInsetsComputer =
+ this::onComputeInsetsForSeparateWindow;
+ private final RecentsHitboxExtender mHitboxExtender = new RecentsHitboxExtender();
+
public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) {
mContext = context;
mNavButtonsView = navButtonsView;
@@ -143,46 +179,48 @@
public void init(TaskbarControllers controllers) {
mControllers = controllers;
mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarSize;
- mNavButtonTranslationYMultiplier.value = 1;
boolean isThreeButtonNav = mContext.isThreeButtonNav();
- // IME switcher
- View imeSwitcherButton = addButton(R.drawable.ic_ime_switcher, BUTTON_IME_SWITCH,
- isThreeButtonNav ? mStartContextualContainer : mEndContextualContainer,
- mControllers.navButtonController, R.id.ime_switcher);
- mPropertyHolders.add(new StatePropertyHolder(imeSwitcherButton,
- flags -> ((flags & MASK_IME_SWITCHER_VISIBLE) == MASK_IME_SWITCHER_VISIBLE)
- && ((flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0)));
+ mIsImeRenderingNavButtons =
+ InputMethodService.canImeRenderGesturalNavButtons() && mContext.imeDrawsImeNavBar();
+ if (!mIsImeRenderingNavButtons) {
+ // IME switcher
+ View imeSwitcherButton = addButton(R.drawable.ic_ime_switcher, BUTTON_IME_SWITCH,
+ isThreeButtonNav ? mStartContextualContainer : mEndContextualContainer,
+ mControllers.navButtonController, R.id.ime_switcher);
+ mPropertyHolders.add(new StatePropertyHolder(imeSwitcherButton,
+ flags -> ((flags & MASK_IME_SWITCHER_VISIBLE) == MASK_IME_SWITCHER_VISIBLE)
+ && ((flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0)));
+ }
mPropertyHolders.add(new StatePropertyHolder(
mControllers.taskbarViewController.getTaskbarIconAlpha()
.getProperty(ALPHA_INDEX_KEYGUARD),
flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0
- && (flags & FLAG_SCREEN_PINNING_ACTIVE) == 0,
- MultiValueAlpha.VALUE, 1, 0));
+ && (flags & FLAG_SCREEN_PINNING_ACTIVE) == 0));
mPropertyHolders.add(new StatePropertyHolder(mControllers.taskbarDragLayerController
- .getKeyguardBgTaskbar(),
- flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0, AnimatedFloat.VALUE, 1, 0));
+ .getKeyguardBgTaskbar(), flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0));
// Force nav buttons (specifically back button) to be visible during setup wizard.
boolean isInSetup = !mContext.isUserSetupComplete();
+ boolean isInKidsMode = mContext.isNavBarKidsModeActive();
boolean alwaysShowButtons = isThreeButtonNav || isInSetup;
// Make sure to remove nav bar buttons translation when notification shade is expanded or
// IME is showing (add separate translation for IME).
int flagsToRemoveTranslation = FLAG_NOTIFICATION_SHADE_EXPANDED | FLAG_IME_VISIBLE;
- mPropertyHolders.add(new StatePropertyHolder(mNavButtonTranslationYMultiplier,
+ mPropertyHolders.add(new StatePropertyHolder(mNavButtonInAppDisplayProgressForSysui,
flags -> (flags & flagsToRemoveTranslation) != 0, AnimatedFloat.VALUE,
- 0, 1));
+ 1, 0));
// Center nav buttons in new height for IME.
float transForIme = (mContext.getDeviceProfile().taskbarSize
- - mContext.getTaskbarHeightForIme()) / 2f;
+ - mControllers.taskbarInsetsController.getTaskbarHeightForIme()) / 2f;
// For gesture nav, nav buttons only show for IME anyway so keep them translated down.
float defaultButtonTransY = alwaysShowButtons ? 0 : transForIme;
mPropertyHolders.add(new StatePropertyHolder(mTaskbarNavButtonTranslationYForIme,
- flags -> (flags & FLAG_IME_VISIBLE) != 0, AnimatedFloat.VALUE, transForIme,
- defaultButtonTransY));
+ flags -> (flags & FLAG_IME_VISIBLE) != 0 && !isInKidsMode, AnimatedFloat.VALUE,
+ transForIme, defaultButtonTransY));
if (alwaysShowButtons) {
initButtons(mNavButtonContainer, mEndContextualContainer,
@@ -204,14 +242,76 @@
& Configuration.UI_MODE_NIGHT_MASK;
boolean isDarkTheme = mode == Configuration.UI_MODE_NIGHT_YES;
mTaskbarNavButtonDarkIntensity.updateValue(isDarkTheme ? 0 : 1);
+ } else if (isInKidsMode) {
+ int iconSize = mContext.getResources().getDimensionPixelSize(
+ R.dimen.taskbar_icon_size_kids);
+ int buttonWidth = mContext.getResources().getDimensionPixelSize(
+ R.dimen.taskbar_nav_buttons_width_kids);
+ int buttonHeight = mContext.getResources().getDimensionPixelSize(
+ R.dimen.taskbar_nav_buttons_height_kids);
+ int buttonRadius = mContext.getResources().getDimensionPixelSize(
+ R.dimen.taskbar_nav_buttons_corner_radius_kids);
+ int paddingleft = (buttonWidth - iconSize) / 2;
+ int paddingRight = paddingleft;
+ int paddingTop = (buttonHeight - iconSize) / 2;
+ int paddingBottom = paddingTop;
+
+ // Update icons
+ ((ImageView) mBackButton).setImageDrawable(
+ mBackButton.getContext().getDrawable(R.drawable.ic_sysbar_back_kids));
+ ((ImageView) mBackButton).setScaleType(ImageView.ScaleType.FIT_CENTER);
+ mBackButton.setPadding(paddingleft, paddingTop, paddingRight, paddingBottom);
+ ((ImageView) mHomeButton).setImageDrawable(
+ mHomeButton.getContext().getDrawable(R.drawable.ic_sysbar_home_kids));
+ ((ImageView) mHomeButton).setScaleType(ImageView.ScaleType.FIT_CENTER);
+ mHomeButton.setPadding(paddingleft, paddingTop, paddingRight, paddingBottom);
+
+ // Home button layout
+ LinearLayout.LayoutParams homeLayoutparams = new LinearLayout.LayoutParams(
+ buttonWidth,
+ buttonHeight
+ );
+ int homeButtonLeftMargin = mContext.getResources().getDimensionPixelSize(
+ R.dimen.taskbar_home_button_left_margin_kids);
+ homeLayoutparams.setMargins(homeButtonLeftMargin, 0, 0, 0);
+ mHomeButton.setLayoutParams(homeLayoutparams);
+
+ // Back button layout
+ LinearLayout.LayoutParams backLayoutParams = new LinearLayout.LayoutParams(
+ buttonWidth,
+ buttonHeight
+ );
+ int backButtonLeftMargin = mContext.getResources().getDimensionPixelSize(
+ R.dimen.taskbar_back_button_left_margin_kids);
+ backLayoutParams.setMargins(backButtonLeftMargin, 0, 0, 0);
+ mBackButton.setLayoutParams(backLayoutParams);
+
+ // Button backgrounds
+ int whiteWith10PctAlpha = Color.argb(0.1f, 1, 1, 1);
+ PaintDrawable buttonBackground = new PaintDrawable(whiteWith10PctAlpha);
+ buttonBackground.setCornerRadius(buttonRadius);
+ mHomeButton.setBackground(buttonBackground);
+ mBackButton.setBackground(buttonBackground);
+
+ // Update alignment within taskbar
+ FrameLayout.LayoutParams navButtonsLayoutParams = (FrameLayout.LayoutParams)
+ mNavButtonContainer.getLayoutParams();
+ navButtonsLayoutParams.setMarginStart(navButtonsLayoutParams.getMarginEnd() / 2);
+ navButtonsLayoutParams.setMarginEnd(navButtonsLayoutParams.getMarginStart());
+ navButtonsLayoutParams.gravity = Gravity.CENTER;
+ mNavButtonContainer.requestLayout();
+
+ mHomeButton.setOnLongClickListener(null);
}
- // Animate taskbar background when any of these flags are enabled
- int flagsToShowBg = FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE
- | FLAG_NOTIFICATION_SHADE_EXPANDED;
+ // Animate taskbar background when either..
+ // notification shade expanded AND not on keyguard
+ // back is visible for bouncer
mPropertyHolders.add(new StatePropertyHolder(
mControllers.taskbarDragLayerController.getNavbarBackgroundAlpha(),
- flags -> (flags & flagsToShowBg) != 0, AnimatedFloat.VALUE, 1, 0));
+ flags -> ((flags & FLAG_NOTIFICATION_SHADE_EXPANDED) != 0
+ && (flags & FLAG_KEYGUARD_VISIBLE) == 0)
+ || (flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0));
// Rotation button
RotationButton rotationButton = new RotationButtonImpl(
@@ -233,16 +333,34 @@
mControllers.rotationButtonController.setRotationButton(mFloatingRotationButton,
mRotationButtonListener);
- View imeDownButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
- mStartContextualContainer, mControllers.navButtonController, R.id.back);
- imeDownButton.setRotation(Utilities.isRtl(mContext.getResources()) ? 90 : -90);
- // Rotate when Ime visible
- mPropertyHolders.add(new StatePropertyHolder(imeDownButton,
- flags -> (flags & FLAG_IME_VISIBLE) != 0));
+ if (!mIsImeRenderingNavButtons) {
+ View imeDownButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
+ mStartContextualContainer, mControllers.navButtonController, R.id.back);
+ imeDownButton.setRotation(Utilities.isRtl(mContext.getResources()) ? 90 : -90);
+ // Only show when IME is visible.
+ mPropertyHolders.add(new StatePropertyHolder(imeDownButton,
+ flags -> (flags & FLAG_IME_VISIBLE) != 0));
+ }
}
applyState();
mPropertyHolders.forEach(StatePropertyHolder::endAnimation);
+
+ // Initialize things needed to move nav buttons to separate window.
+ mSeparateWindowParent = new BaseDragLayer<TaskbarActivityContext>(mContext, null, 0) {
+ @Override
+ public void recreateControllers() {
+ mControllers = new TouchController[0];
+ }
+
+ @Override
+ protected boolean canFindActiveController() {
+ // We don't have any controllers, but we don't want any floating views such as
+ // folder to intercept, either. This ensures nav buttons can always be pressed.
+ return false;
+ }
+ };
+ mSeparateWindowParent.recreateControllers();
}
private void initButtons(ViewGroup navContainer, ViewGroup endContainer,
@@ -250,7 +368,10 @@
mBackButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
mNavButtonContainer, mControllers.navButtonController, R.id.back);
- mPropertyHolders.add(new StatePropertyHolder(mBackButton,
+ mBackButtonAlpha = new MultiValueAlpha(mBackButton, NUM_ALPHA_CHANNELS);
+ mBackButtonAlpha.setUpdateVisibility(true);
+ mPropertyHolders.add(new StatePropertyHolder(
+ mBackButtonAlpha.getProperty(ALPHA_INDEX_KEYGUARD_OR_DISABLE),
flags -> {
// Show only if not disabled, and if not on the keyguard or otherwise only when
// the bouncer or a lockscreen app is showing above the keyguard
@@ -261,9 +382,9 @@
&& ((flags & FLAG_KEYGUARD_VISIBLE) == 0 || showingOnKeyguard);
}));
boolean isRtl = Utilities.isRtl(mContext.getResources());
- mPropertyHolders.add(new StatePropertyHolder(
- mBackButton, flags -> (flags & FLAG_IME_VISIBLE) != 0, View.ROTATION,
- isRtl ? 90 : -90, 0));
+ mPropertyHolders.add(new StatePropertyHolder(mBackButton,
+ flags -> (flags & FLAG_IME_VISIBLE) != 0 && !mContext.isNavBarKidsModeActive(),
+ View.ROTATION, isRtl ? 90 : -90, 0));
// Translate back button to be at end/start of other buttons for keyguard
int navButtonSize = mContext.getResources().getDimensionPixelSize(
R.dimen.taskbar_nav_buttons_size);
@@ -272,18 +393,34 @@
|| (flags & FLAG_KEYGUARD_VISIBLE) != 0,
VIEW_TRANSLATE_X, navButtonSize * (isRtl ? -2 : 2), 0));
-
- // home and recents buttons
- View homeButton = addButton(R.drawable.ic_sysbar_home, BUTTON_HOME, navContainer,
+ // home button
+ mHomeButton = addButton(R.drawable.ic_sysbar_home, BUTTON_HOME, navContainer,
navButtonController, R.id.home);
- mPropertyHolders.add(new StatePropertyHolder(homeButton,
+ mHomeButtonAlpha = new MultiValueAlpha(mHomeButton, NUM_ALPHA_CHANNELS);
+ mHomeButtonAlpha.setUpdateVisibility(true);
+ mPropertyHolders.add(
+ new StatePropertyHolder(mHomeButtonAlpha.getProperty(
+ ALPHA_INDEX_KEYGUARD_OR_DISABLE),
flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 &&
(flags & FLAG_DISABLE_HOME) == 0));
+
+ // Recents button
View recentsButton = addButton(R.drawable.ic_sysbar_recent, BUTTON_RECENTS,
navContainer, navButtonController, R.id.recent_apps);
+ mHitboxExtender.init(recentsButton, mNavButtonsView, mContext.getDeviceProfile(),
+ () -> {
+ float[] recentsCoords = new float[2];
+ getDescendantCoordRelativeToAncestor(recentsButton, mNavButtonsView,
+ recentsCoords, false);
+ return recentsCoords;
+ }, new Handler());
+ recentsButton.setOnClickListener(v -> {
+ navButtonController.onButtonClick(BUTTON_RECENTS);
+ mHitboxExtender.onRecentsButtonClicked();
+ });
mPropertyHolders.add(new StatePropertyHolder(recentsButton,
- flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 &&
- (flags & FLAG_DISABLE_RECENTS) == 0));
+ flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 && (flags & FLAG_DISABLE_RECENTS) == 0
+ && !mContext.isNavBarKidsModeActive()));
// A11y button
mA11yButton = addButton(R.drawable.ic_sysbar_accessibility_button, BUTTON_A11Y,
@@ -378,22 +515,44 @@
/**
* Adds the bounds corresponding to all visible buttons to provided region
*/
- public void addVisibleButtonsRegion(TaskbarDragLayer parent, Region outRegion) {
+ public void addVisibleButtonsRegion(BaseDragLayer<?> parent, Region outRegion) {
int count = mAllButtons.size();
for (int i = 0; i < count; i++) {
View button = mAllButtons.get(i);
if (button.getVisibility() == View.VISIBLE) {
parent.getDescendantRectRelativeToSelf(button, mTempRect);
+ if (mHitboxExtender.extendedHitboxEnabled()) {
+ mTempRect.bottom += mContext.getDeviceProfile().getTaskbarOffsetY();
+ }
outRegion.op(mTempRect, Op.UNION);
}
}
}
+ /**
+ * Returns multi-value alpha controller for back button.
+ */
+ public MultiValueAlpha getBackButtonAlpha() {
+ return mBackButtonAlpha;
+ }
+
+ /**
+ * Returns multi-value alpha controller for home button.
+ */
+ public MultiValueAlpha getHomeButtonAlpha() {
+ return mHomeButtonAlpha;
+ }
+
/** Use to set the translationY for the all nav+contextual buttons */
public AnimatedFloat getTaskbarNavButtonTranslationY() {
return mTaskbarNavButtonTranslationY;
}
+ /** Use to set the translationY for the all nav+contextual buttons when in Launcher */
+ public AnimatedFloat getTaskbarNavButtonTranslationYForInAppDisplay() {
+ return mTaskbarNavButtonTranslationYForInAppDisplay;
+ }
+
/** Use to set the dark intensity for the all nav+contextual buttons */
public AnimatedFloat getTaskbarNavButtonDarkIntensity() {
return mTaskbarNavButtonDarkIntensity;
@@ -422,11 +581,26 @@
}
}
+ private void updateNavButtonInAppDisplayProgressForSysui() {
+ TaskbarUIController uiController = mControllers.uiController;
+ if (uiController instanceof LauncherTaskbarUIController) {
+ ((LauncherTaskbarUIController) uiController).onTaskbarInAppDisplayProgressUpdate(
+ mNavButtonInAppDisplayProgressForSysui.value, SYSUI_SURFACE_PROGRESS_INDEX);
+ }
+ }
+
private void updateNavButtonTranslationY() {
- float normalTranslationY = mTaskbarNavButtonTranslationY.value
- * mNavButtonTranslationYMultiplier.value;
- float otherTranslationY = mTaskbarNavButtonTranslationYForIme.value;
- mNavButtonsView.setTranslationY(normalTranslationY + otherTranslationY);
+ final float normalTranslationY = mTaskbarNavButtonTranslationY.value;
+ final float imeAdjustmentTranslationY = mTaskbarNavButtonTranslationYForIme.value;
+ TaskbarUIController uiController = mControllers.uiController;
+ final float inAppDisplayAdjustmentTranslationY =
+ (uiController instanceof LauncherTaskbarUIController
+ && ((LauncherTaskbarUIController) uiController).shouldUseInAppLayout())
+ ? mTaskbarNavButtonTranslationYForInAppDisplay.value : 0;
+
+ mNavButtonsView.setTranslationY(normalTranslationY
+ + imeAdjustmentTranslationY
+ + inAppDisplayAdjustmentTranslationY);
}
private void updateNavButtonDarkIntensity() {
@@ -439,7 +613,7 @@
}
}
- private ImageView addButton(@DrawableRes int drawableId, @TaskbarButton int buttonType,
+ protected ImageView addButton(@DrawableRes int drawableId, @TaskbarButton int buttonType,
ViewGroup parent, TaskbarNavButtonController navButtonController, @IdRes int id) {
return addButton(drawableId, buttonType, parent, navButtonController, id,
R.layout.taskbar_nav_button);
@@ -450,6 +624,8 @@
@LayoutRes int layoutId) {
ImageView buttonView = addButton(parent, id, layoutId);
buttonView.setImageResource(drawableId);
+ buttonView.setContentDescription(parent.getContext().getString(
+ navButtonController.getButtonContentDescription(buttonType)));
buttonView.setOnClickListener(view -> navButtonController.onButtonClick(buttonType));
buttonView.setOnLongClickListener(view ->
navButtonController.onButtonLongClick(buttonType));
@@ -481,6 +657,111 @@
if (mFloatingRotationButton != null) {
mFloatingRotationButton.hide();
}
+
+ moveNavButtonsBackToTaskbarWindow();
+ }
+
+ /**
+ * Moves mNavButtonsView from TaskbarDragLayer to a placeholder BaseDragLayer on a new window.
+ */
+ public void moveNavButtonsToNewWindow() {
+ if (mAreNavButtonsInSeparateWindow) {
+ return;
+ }
+
+ if (mIsImeRenderingNavButtons) {
+ // IME is rendering the nav buttons, so we don't need to create a new layer for them.
+ return;
+ }
+
+ mSeparateWindowParent.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View view) {
+ ViewTreeObserverWrapper.addOnComputeInsetsListener(
+ mSeparateWindowParent.getViewTreeObserver(), mSeparateWindowInsetsComputer);
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View view) {
+ mSeparateWindowParent.removeOnAttachStateChangeListener(this);
+ ViewTreeObserverWrapper.removeOnComputeInsetsListener(
+ mSeparateWindowInsetsComputer);
+ }
+ });
+
+ mAreNavButtonsInSeparateWindow = true;
+ mContext.getDragLayer().removeView(mNavButtonsView);
+ mSeparateWindowParent.addView(mNavButtonsView);
+ WindowManager.LayoutParams windowLayoutParams = mContext.createDefaultWindowLayoutParams();
+ windowLayoutParams.setTitle(NAV_BUTTONS_SEPARATE_WINDOW_TITLE);
+ mContext.addWindowView(mSeparateWindowParent, windowLayoutParams);
+
+ }
+
+ /**
+ * Moves mNavButtonsView from its temporary window and reattaches it to TaskbarDragLayer.
+ */
+ public void moveNavButtonsBackToTaskbarWindow() {
+ if (!mAreNavButtonsInSeparateWindow) {
+ return;
+ }
+
+ mAreNavButtonsInSeparateWindow = false;
+ mContext.removeWindowView(mSeparateWindowParent);
+ mSeparateWindowParent.removeView(mNavButtonsView);
+ mContext.getDragLayer().addView(mNavButtonsView);
+ }
+
+ private void onComputeInsetsForSeparateWindow(ViewTreeObserverWrapper.InsetsInfo insetsInfo) {
+ addVisibleButtonsRegion(mSeparateWindowParent, insetsInfo.touchableRegion);
+ insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
+ }
+
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "NavbarButtonsViewController:");
+
+ pw.println(String.format("%s\tmState=%s", prefix, getStateString(mState)));
+ pw.println(String.format(
+ "%s\tmLightIconColor=0x%s", prefix, Integer.toHexString(mLightIconColor)));
+ pw.println(String.format(
+ "%s\tmDarkIconColor=0x%s", prefix, Integer.toHexString(mDarkIconColor)));
+ pw.println(String.format(
+ "%s\tmFloatingRotationButtonBounds=%s", prefix, mFloatingRotationButtonBounds));
+ pw.println(String.format(
+ "%s\tmSysuiStateFlags=%s",
+ prefix,
+ QuickStepContract.getSystemUiStateString(mSysuiStateFlags)));
+ }
+
+ private static String getStateString(int flags) {
+ StringJoiner str = new StringJoiner("|");
+ appendFlag(str, flags, FLAG_SWITCHER_SUPPORTED, "FLAG_SWITCHER_SUPPORTED");
+ appendFlag(str, flags, FLAG_IME_VISIBLE, "FLAG_IME_VISIBLE");
+ appendFlag(str, flags, FLAG_ROTATION_BUTTON_VISIBLE, "FLAG_ROTATION_BUTTON_VISIBLE");
+ appendFlag(str, flags, FLAG_A11Y_VISIBLE, "FLAG_A11Y_VISIBLE");
+ appendFlag(str, flags, FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE,
+ "FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE");
+ appendFlag(str, flags, FLAG_KEYGUARD_VISIBLE, "FLAG_KEYGUARD_VISIBLE");
+ appendFlag(str, flags, FLAG_KEYGUARD_OCCLUDED, "FLAG_KEYGUARD_OCCLUDED");
+ appendFlag(str, flags, FLAG_DISABLE_HOME, "FLAG_DISABLE_HOME");
+ appendFlag(str, flags, FLAG_DISABLE_RECENTS, "FLAG_DISABLE_RECENTS");
+ appendFlag(str, flags, FLAG_DISABLE_BACK, "FLAG_DISABLE_BACK");
+ appendFlag(str, flags, FLAG_NOTIFICATION_SHADE_EXPANDED,
+ "FLAG_NOTIFICATION_SHADE_EXPANDED");
+ appendFlag(str, flags, FLAG_SCREEN_PINNING_ACTIVE, "FLAG_SCREEN_PINNING_ACTIVE");
+ return str.toString();
+ }
+
+ public TouchController getTouchController() {
+ return mHitboxExtender;
+ }
+
+ /**
+ * @param alignment 0 -> Taskbar, 1 -> Workspace
+ */
+ public void updateTaskbarAlignment(float alignment) {
+ mHitboxExtender.onAnimationProgressToOverview(alignment);
}
private class RotationButtonListener implements RotationButton.RotationButtonUpdatesCallback {
@@ -585,6 +866,15 @@
mAnimator.addListener(new AlphaUpdateListener(view));
}
+ StatePropertyHolder(MultiValueAlpha.AlphaProperty alphaProperty,
+ IntPredicate enableCondition) {
+ this(alphaProperty, enableCondition, MultiValueAlpha.VALUE, 1, 0);
+ }
+
+ StatePropertyHolder(AnimatedFloat animatedFloat, IntPredicate enableCondition) {
+ this(animatedFloat, enableCondition, AnimatedFloat.VALUE, 1, 0);
+ }
+
<T> StatePropertyHolder(T target, IntPredicate enabledCondition,
Property<T, Float> property, float enabledValue, float disabledValue) {
mEnableCondition = enabledCondition;
diff --git a/quickstep/src/com/android/launcher3/taskbar/RecentsHitboxExtender.java b/quickstep/src/com/android/launcher3/taskbar/RecentsHitboxExtender.java
new file mode 100644
index 0000000..4651570
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/RecentsHitboxExtender.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar;
+
+import android.graphics.Rect;
+import android.os.Handler;
+import android.view.MotionEvent;
+import android.view.TouchDelegate;
+import android.view.View;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.util.TouchController;
+
+import java.util.function.Supplier;
+
+/**
+ * Extends the Recents touch area during the taskbar to overview animation
+ * to give user some error room when trying to quickly double tap recents button since it moves.
+ *
+ * Listens for icon alignment as our indication for the animation.
+ */
+public class RecentsHitboxExtender implements TouchController {
+
+ private static final int RECENTS_HITBOX_TIMEOUT_MS = 500;
+
+ private View mRecentsButton;
+ private View mRecentsParent;
+ private DeviceProfile mDeviceProfile;
+ private Supplier<float[]> mParentCoordSupplier;
+ private TouchDelegate mRecentsTouchDelegate;
+ /**
+ * Will be true while the animation from taskbar to overview is occurring.
+ * Lifecycle of this variable slightly extends past the animation by
+ * {@link #RECENTS_HITBOX_TIMEOUT_MS}, so can use this variable as a proxy for if
+ * the current hitbox is extended or not.
+ */
+ private boolean mAnimatingFromTaskbarToOverview;
+ private float mLastIconAlignment;
+ private final Rect mRecentsHitBox = new Rect();
+ private boolean mRecentsButtonClicked;
+ private Handler mHandler;
+ private final Runnable mRecentsHitboxResetRunnable = this::reset;
+
+ public void init(View recentsButton, View recentsParent, DeviceProfile deviceProfile,
+ Supplier<float[]> parentCoordSupplier, Handler handler) {
+ mRecentsButton = recentsButton;
+ mRecentsParent = recentsParent;
+ mDeviceProfile = deviceProfile;
+ mParentCoordSupplier = parentCoordSupplier;
+ mHandler = handler;
+ }
+
+ public void onRecentsButtonClicked() {
+ mRecentsButtonClicked = true;
+ }
+
+ /**
+ * @param progress 0 -> Taskbar, 1 -> Overview
+ */
+ public void onAnimationProgressToOverview(float progress) {
+ if (progress == 1 || progress == 0) {
+ // Done w/ animation
+ mLastIconAlignment = progress;
+ if (mAnimatingFromTaskbarToOverview) {
+ if (progress == 1) {
+ // Finished animation to workspace, remove the touch delegate shortly
+ mHandler.postDelayed(mRecentsHitboxResetRunnable, RECENTS_HITBOX_TIMEOUT_MS);
+ return;
+ } else {
+ // Went back to taskbar, reset immediately
+ mHandler.removeCallbacks(mRecentsHitboxResetRunnable);
+ reset();
+ }
+ }
+ }
+
+ if (mAnimatingFromTaskbarToOverview) {
+ return;
+ }
+
+ if (progress > 0 && mLastIconAlignment == 0 && mRecentsButtonClicked) {
+ // Starting animation, previously we were showing taskbar
+ mAnimatingFromTaskbarToOverview = true;
+ float[] recentsCoords = mParentCoordSupplier.get();
+ int x = (int) recentsCoords[0];
+ int y = (int) (recentsCoords[1]);
+ // Extend hitbox vertically by the offset amount from mDeviceProfile.getTaskbarOffsetY()
+ mRecentsHitBox.set(x, y,
+ x + mRecentsButton.getWidth(),
+ y + mRecentsButton.getHeight() + mDeviceProfile.getTaskbarOffsetY()
+ );
+ mRecentsTouchDelegate = new TouchDelegate(mRecentsHitBox, mRecentsButton);
+ mRecentsParent.setTouchDelegate(mRecentsTouchDelegate);
+ }
+ }
+
+ private void reset() {
+ mAnimatingFromTaskbarToOverview = false;
+ mRecentsButton.setTouchDelegate(null);
+ mRecentsHitBox.setEmpty();
+ mRecentsButtonClicked = false;
+ }
+
+ /**
+ * @return {@code true} if the bounds for recents touches are currently extended
+ */
+ public boolean extendedHitboxEnabled() {
+ return mAnimatingFromTaskbarToOverview;
+ }
+
+ @Override
+ public boolean onControllerTouchEvent(MotionEvent ev) {
+ return mRecentsTouchDelegate.onTouchEvent(ev);
+ }
+
+ @Override
+ public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ return mRecentsHitBox.contains((int)ev.getX(), (int)ev.getY());
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index 22ca63f..b797807 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -34,10 +34,12 @@
import com.android.quickstep.AnimatedFloat;
import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
+import java.io.PrintWriter;
+
/**
* Handles properties/data collection, then passes the results to our stashed handle View to render.
*/
-public class StashedHandleViewController {
+public class StashedHandleViewController implements TaskbarControllers.LoggableTaskbarController {
public static final int ALPHA_INDEX_STASHED = 0;
public static final int ALPHA_INDEX_HOME_DISABLED = 1;
@@ -174,7 +176,8 @@
return revealAnim;
}
- public void onIsStashed(boolean isStashed) {
+ /** Called when taskbar is stashed or unstashed. */
+ public void onIsStashedChanged(boolean isStashed) {
mRegionSamplingHelper.setWindowVisible(isStashed);
if (isStashed) {
mStashedHandleView.updateSampledRegion(mStashedHandleBounds);
@@ -200,4 +203,15 @@
public boolean isStashedHandleVisible() {
return mStashedHandleView.getVisibility() == View.VISIBLE;
}
+
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "StashedHandleViewController:");
+
+ pw.println(String.format(
+ "%s\tisStashedHandleVisible=%b", prefix, isStashedHandleVisible()));
+ pw.println(String.format("%s\tmStashedHandleWidth=%dpx", prefix, mStashedHandleWidth));
+ pw.println(String.format("%s\tmStashedHandleHeight=%dpx", prefix, mStashedHandleHeight));
+ mRegionSamplingHelper.dump(prefix, pw);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index c612a84..dc2e3b6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -15,18 +15,21 @@
*/
package com.android.launcher3.taskbar;
-import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES;
+import static android.content.pm.PackageManager.FEATURE_PC;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
+import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
+import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
+import static com.android.launcher3.ResourceUtils.getBoolByName;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
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.WindowManagerWrapper.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
-import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTRA_NAVIGATION_BAR;
import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
import android.app.ActivityOptions;
import android.content.ActivityNotFoundException;
import android.content.Context;
@@ -34,56 +37,68 @@
import android.content.pm.ActivityInfo.Config;
import android.content.pm.LauncherApps;
import android.content.res.Resources;
-import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Process;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Log;
-import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.RoundedCorner;
import android.view.View;
import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
import android.widget.FrameLayout;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.R;
+import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.logger.LauncherAtom;
+import com.android.launcher3.logging.StatsLogManager;
+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.WorkspaceItemInfo;
+import com.android.launcher3.popup.PopupDataProvider;
+import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
+import com.android.launcher3.testing.TestLogging;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.ItemClickHandler;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.SettingsCache;
-import com.android.launcher3.util.Themes;
import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.ViewCache;
import com.android.launcher3.views.ActivityContext;
-import com.android.quickstep.SysUINavigationMode;
-import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.rotation.RotationButtonController;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
+import java.io.PrintWriter;
+
/**
* The {@link ActivityContext} with which we inflate Taskbar-related Views. This allows UI elements
* that are used by both Launcher and Taskbar (such as Folder) to reference a generic
* ActivityContext and BaseDragLayer instead of the Launcher activity and its DragLayer.
*/
-public class TaskbarActivityContext extends ContextThemeWrapper implements ActivityContext {
+public class TaskbarActivityContext extends BaseTaskbarContext {
+
+ 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);
@@ -91,47 +106,61 @@
private static final String WINDOW_TITLE = "Taskbar";
- private final LayoutInflater mLayoutInflater;
private final TaskbarDragLayer mDragLayer;
private final TaskbarControllers mControllers;
- private DeviceProfile mDeviceProfile;
-
private final WindowManager mWindowManager;
private final @Nullable RoundedCorner mLeftCorner, mRightCorner;
- private final int mTaskbarHeightForIme;
+ private DeviceProfile mDeviceProfile;
private WindowManager.LayoutParams mWindowLayoutParams;
private boolean mIsFullscreen;
// The size we should return to when we call setTaskbarWindowFullscreen(false)
private int mLastRequestedNonFullscreenHeight;
- private final SysUINavigationMode.Mode mNavMode;
+ private final NavigationMode mNavMode;
+ private final boolean mImeDrawsImeNavBar;
private final ViewCache mViewCache = new ViewCache();
private final boolean mIsSafeModeEnabled;
private final boolean mIsUserSetupComplete;
+ private final boolean mIsNavBarForceVisible;
+ private final boolean mIsNavBarKidsMode;
private boolean mIsDestroyed = false;
// The flag to know if the window is excluded from magnification region computation.
private boolean mIsExcludeFromMagnificationRegion = false;
+ private boolean mBindingItems = false;
+
+ private final TaskbarShortcutMenuAccessibilityDelegate mAccessibilityDelegate;
public TaskbarActivityContext(Context windowContext, DeviceProfile dp,
TaskbarNavButtonController buttonController, ScopedUnfoldTransitionProgressProvider
unfoldTransitionProgressProvider) {
- super(windowContext, Themes.getActivityThemeRes(windowContext));
- mDeviceProfile = dp;
+ super(windowContext);
+ mDeviceProfile = dp.copy(this);
- mNavMode = SysUINavigationMode.getMode(windowContext);
+ final Resources resources = getResources();
+
+ mNavMode = DisplayController.getNavigationMode(windowContext);
+ mImeDrawsImeNavBar = getBoolByName(IME_DRAWS_IME_NAV_BAR_RES_NAME, resources, false);
mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode",
() -> getPackageManager().isSafeMode());
mIsUserSetupComplete = SettingsCache.INSTANCE.get(this).getValue(
Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 0);
+ mIsNavBarForceVisible = SettingsCache.INSTANCE.get(this).getValue(
+ Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_KIDS_MODE), 0);
+ mIsNavBarKidsMode = SettingsCache.INSTANCE.get(this).getValue(
+ Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_KIDS_MODE), 0);
- final Resources resources = getResources();
updateIconSize(resources);
- mTaskbarHeightForIme = resources.getDimensionPixelSize(R.dimen.taskbar_ime_size);
-
- mLayoutInflater = LayoutInflater.from(this).cloneInContext(this);
+ // 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);
+ mWindowManager = c.getSystemService(WindowManager.class);
+ mLeftCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
+ mRightCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
// Inflate views.
mDragLayer = (TaskbarDragLayer) mLayoutInflater.inflate(
@@ -141,19 +170,15 @@
FrameLayout navButtonsView = mDragLayer.findViewById(R.id.navbuttons_view);
StashedHandleView stashedHandleView = mDragLayer.findViewById(R.id.stashed_handle);
- Display display = windowContext.getDisplay();
- Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY
- ? windowContext.getApplicationContext()
- : windowContext.getApplicationContext().createDisplayContext(display);
- mWindowManager = c.getSystemService(WindowManager.class);
- mLeftCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
- mRightCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
+ mAccessibilityDelegate = new TaskbarShortcutMenuAccessibilityDelegate(this);
// Construct controllers.
mControllers = new TaskbarControllers(this,
new TaskbarDragController(this),
buttonController,
- new NavbarButtonsViewController(this, navButtonsView),
+ getPackageManager().hasSystemFeature(FEATURE_PC)
+ ? new DesktopNavbarButtonsViewController(this, navButtonsView) :
+ new NavbarButtonsViewController(this, navButtonsView),
new RotationButtonController(this,
c.getColor(R.color.taskbar_nav_icon_light_color),
c.getColor(R.color.taskbar_nav_icon_dark_color),
@@ -165,44 +190,22 @@
new TaskbarDragLayerController(this, mDragLayer),
new TaskbarViewController(this, taskbarView),
new TaskbarScrimViewController(this, taskbarScrimView),
- new TaskbarUnfoldAnimationController(unfoldTransitionProgressProvider,
- mWindowManager),
+ new TaskbarUnfoldAnimationController(this, unfoldTransitionProgressProvider,
+ mWindowManager, WindowManagerGlobal.getWindowManagerService()),
new TaskbarKeyguardController(this),
new StashedHandleViewController(this, stashedHandleView),
new TaskbarStashController(this),
new TaskbarEduController(this),
new TaskbarAutohideSuspendController(this),
- new TaskbarPopupController());
+ new TaskbarPopupController(this),
+ new TaskbarForceVisibleImmersiveController(this),
+ new TaskbarAllAppsController(this, dp),
+ new TaskbarInsetsController(this));
}
- public void init(TaskbarSharedState sharedState) {
+ public void init(@NonNull TaskbarSharedState sharedState) {
mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight();
- mWindowLayoutParams = new WindowManager.LayoutParams(
- MATCH_PARENT,
- mLastRequestedNonFullscreenHeight,
- TYPE_NAVIGATION_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_SLIPPERY,
- PixelFormat.TRANSLUCENT);
- mWindowLayoutParams.setTitle(WINDOW_TITLE);
- mWindowLayoutParams.packageName = getPackageName();
- mWindowLayoutParams.gravity = Gravity.BOTTOM;
- mWindowLayoutParams.setFitInsetsTypes(0);
- mWindowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
- mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
- mWindowLayoutParams.privateFlags =
- WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
-
- WindowManagerWrapper wmWrapper = WindowManagerWrapper.getInstance();
- wmWrapper.setProvidesInsetsTypes(
- mWindowLayoutParams,
- new int[] { ITYPE_EXTRA_NAVIGATION_BAR, ITYPE_BOTTOM_TAPPABLE_ELEMENT,
- ITYPE_BOTTOM_MANDATORY_GESTURES }
- );
- // Adjust the frame by the rounded corners (ie. leaving just the bar as the inset) when
- // the IME is showing
- mWindowLayoutParams.providedInternalImeInsets = Insets.of(0,
- getDefaultTaskbarWindowHeight() - mTaskbarHeightForIme, 0, 0);
+ mWindowLayoutParams = createDefaultWindowLayoutParams();
// Initialize controllers after all are constructed.
mControllers.init(sharedState);
@@ -211,10 +214,22 @@
mWindowManager.addView(mDragLayer, mWindowLayoutParams);
}
- /** Updates the Device profile instance to the latest representation of the screen. */
+ @Override
+ public DeviceProfile getDeviceProfile() {
+ return mDeviceProfile;
+ }
+
+ /** Updates {@link DeviceProfile} instances for any Taskbar windows. */
public void updateDeviceProfile(DeviceProfile dp) {
- mDeviceProfile = dp;
+ mControllers.taskbarAllAppsController.updateDeviceProfile(dp);
+ mDeviceProfile = dp.copy(this);
updateIconSize(getResources());
+
+ AbstractFloatingView.closeAllOpenViewsExcept(this, false, TYPE_REBIND_SAFE);
+ // Reapply fullscreen to take potential new screen size into account.
+ setTaskbarWindowFullscreen(mIsFullscreen);
+
+ dispatchDeviceProfileChanged();
}
private void updateIconSize(Resources resources) {
@@ -224,12 +239,48 @@
mDeviceProfile.updateIconSize(iconScale, resources);
}
+ @VisibleForTesting
+ @Override
+ public StatsLogManager getStatsLogManager() {
+ // Used to mock, can't mock a default interface method directly
+ return super.getStatsLogManager();
+ }
+
+ /** Creates LayoutParams for adding a view directly to WindowManager as a new window */
+ public WindowManager.LayoutParams createDefaultWindowLayoutParams() {
+ WindowManager.LayoutParams windowLayoutParams = new WindowManager.LayoutParams(
+ MATCH_PARENT,
+ mLastRequestedNonFullscreenHeight,
+ TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_SLIPPERY,
+ PixelFormat.TRANSLUCENT);
+ windowLayoutParams.setTitle(WINDOW_TITLE);
+ windowLayoutParams.packageName = getPackageName();
+ windowLayoutParams.gravity = Gravity.BOTTOM;
+ windowLayoutParams.setFitInsetsTypes(0);
+ windowLayoutParams.receiveInsetsIgnoringZOrder = true;
+ windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
+ windowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ windowLayoutParams.privateFlags =
+ WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+ return windowLayoutParams;
+ }
+
public void onConfigurationChanged(@Config int configChanges) {
mControllers.onConfigurationChanged(configChanges);
}
public boolean isThreeButtonNav() {
- return mNavMode == Mode.THREE_BUTTONS;
+ return mNavMode == NavigationMode.THREE_BUTTONS;
+ }
+
+ public boolean isGestureNav() {
+ return mNavMode == NavigationMode.NO_BUTTON;
+ }
+
+ public boolean imeDrawsImeNavBar() {
+ return mImeDrawsImeNavBar;
}
public int getLeftCornerRadius() {
@@ -240,9 +291,8 @@
return mRightCorner == null ? 0 : mRightCorner.getRadius();
}
- @Override
- public LayoutInflater getLayoutInflater() {
- return mLayoutInflater;
+ public WindowManager.LayoutParams getWindowLayoutParams() {
+ return mWindowLayoutParams;
}
@Override
@@ -251,11 +301,6 @@
}
@Override
- public DeviceProfile getDeviceProfile() {
- return mDeviceProfile;
- }
-
- @Override
public Rect getFolderBoundingBox() {
return mControllers.taskbarDragLayerController.getFolderBoundingBox();
}
@@ -271,14 +316,6 @@
}
@Override
- public boolean supportsIme() {
- // Currently we don't support IME because we have FLAG_NOT_FOCUSABLE. We can remove that
- // flag when opening a floating view that needs IME (such as Folder), but then that means
- // Taskbar will be below IME and thus users can't click the back button.
- return false;
- }
-
- @Override
public View.OnClickListener getItemOnClickListener() {
return this::onTaskbarIconClicked;
}
@@ -334,9 +371,57 @@
folderBuilder.clearHotseat();
itemInfoBuilder.setContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
.setFolder(folderBuilder));
+ } else if (oldContainer.hasAllAppsContainer()) {
+ itemInfoBuilder.setContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
+ .setAllAppsContainer(oldContainer.getAllAppsContainer().toBuilder()
+ .setTaskbarContainer(LauncherAtom.TaskBarContainer.newBuilder())));
+ } else if (oldContainer.hasPredictionContainer()) {
+ itemInfoBuilder.setContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
+ .setPredictionContainer(oldContainer.getPredictionContainer().toBuilder()
+ .setTaskbarContainer(LauncherAtom.TaskBarContainer.newBuilder())));
}
}
+ @Override
+ public DotInfo getDotInfoForItem(ItemInfo info) {
+ return getPopupDataProvider().getDotInfoForItem(info);
+ }
+
+ @NonNull
+ @Override
+ public PopupDataProvider getPopupDataProvider() {
+ return mControllers.taskbarPopupController.getPopupDataProvider();
+ }
+
+ @Override
+ public View.AccessibilityDelegate getAccessibilityDelegate() {
+ return mAccessibilityDelegate;
+ }
+
+ @Override
+ public boolean isBindingItems() {
+ return mBindingItems;
+ }
+
+ public void setBindingItems(boolean bindingItems) {
+ mBindingItems = bindingItems;
+ }
+
+ @Override
+ public void onDragStart() {
+ setTaskbarWindowFullscreen(true);
+ }
+
+ @Override
+ public void onDragEnd() {
+ maybeSetTaskbarWindowNotFullscreen();
+ }
+
+ @Override
+ public void onPopupVisibilityChanged(boolean isVisible) {
+ setTaskbarWindowFocusable(isVisible);
+ }
+
/**
* Sets a new data-source for this taskbar instance
*/
@@ -372,14 +457,17 @@
| SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
onNotificationShadeExpandChanged((systemUiStateFlags & shadeExpandedFlags) != 0, fromInit);
mControllers.taskbarViewController.setRecentsButtonDisabled(
- mControllers.navbarButtonsViewController.isRecentsDisabled());
+ mControllers.navbarButtonsViewController.isRecentsDisabled()
+ || isNavBarKidsModeActive());
mControllers.stashedHandleViewController.setIsHomeButtonDisabled(
mControllers.navbarButtonsViewController.isHomeDisabled());
mControllers.taskbarKeyguardController.updateStateForSysuiFlags(systemUiStateFlags);
- mControllers.taskbarStashController.updateStateForSysuiFlags(systemUiStateFlags, fromInit);
+ mControllers.taskbarStashController.updateStateForSysuiFlags(
+ systemUiStateFlags, fromInit || !isUserSetupComplete());
mControllers.taskbarScrimViewController.updateStateForSysuiFlags(systemUiStateFlags,
fromInit);
mControllers.navButtonController.updateSysuiFlags(systemUiStateFlags);
+ mControllers.taskbarForceVisibleImmersiveController.updateSysuiFlags(systemUiStateFlags);
}
/**
@@ -433,11 +521,34 @@
setTaskbarWindowHeight(fullscreen ? MATCH_PARENT : mLastRequestedNonFullscreenHeight);
}
+ /**
+ * Reverts Taskbar window to its original size, if all floating views are closed and there is
+ * no system drag operation in progress.
+ */
+ void maybeSetTaskbarWindowNotFullscreen() {
+ if (AbstractFloatingView.getAnyView(this, TYPE_ALL) == null
+ && !mControllers.taskbarDragController.isSystemDragInProgress()) {
+ setTaskbarWindowFullscreen(false);
+ }
+ }
+
public boolean isTaskbarWindowFullscreen() {
return mIsFullscreen;
}
/**
+ * Notify system to inset the rounded corner frame based on the task bar insets.
+ */
+ public void updateInsetRoundedCornerFrame(boolean shouldInsetsRoundedCorner) {
+ if (!mDragLayer.isAttachedToWindow()
+ || mWindowLayoutParams.insetsRoundedCornerFrame == shouldInsetsRoundedCorner) {
+ return;
+ }
+ mWindowLayoutParams.insetsRoundedCornerFrame = shouldInsetsRoundedCorner;
+ mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
+ }
+
+ /**
* Updates the TaskbarContainer height (pass {@link #getDefaultTaskbarWindowHeight()} to reset).
*/
public void setTaskbarWindowHeight(int height) {
@@ -457,8 +568,7 @@
}
}
mWindowLayoutParams.height = height;
- mWindowLayoutParams.providedInternalImeInsets =
- Insets.of(0, height - mTaskbarHeightForIme, 0, 0);
+ mControllers.taskbarInsetsController.onTaskbarWindowHeightOrInsetsChanged();
mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
}
@@ -470,10 +580,39 @@
}
/**
- * Returns the bottom insets taskbar provides to the IME when IME is visible.
+ * Either adds or removes {@link WindowManager.LayoutParams#FLAG_NOT_FOCUSABLE} on the taskbar
+ * window.
*/
- public int getTaskbarHeightForIme() {
- return mTaskbarHeightForIme;
+ public void setTaskbarWindowFocusable(boolean focusable) {
+ if (focusable) {
+ mWindowLayoutParams.flags &= ~FLAG_NOT_FOCUSABLE;
+ } else {
+ mWindowLayoutParams.flags |= FLAG_NOT_FOCUSABLE;
+ }
+ mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
+ }
+
+ /**
+ * Either adds or removes {@link WindowManager.LayoutParams#FLAG_NOT_FOCUSABLE} on the taskbar
+ * window. If we're now focusable, also move nav buttons to a separate window above IME.
+ */
+ public void setTaskbarWindowFocusableForIme(boolean focusable) {
+ if (focusable) {
+ mControllers.navbarButtonsViewController.moveNavButtonsToNewWindow();
+ } else {
+ mControllers.navbarButtonsViewController.moveNavButtonsBackToTaskbarWindow();
+ }
+ setTaskbarWindowFocusable(focusable);
+ }
+
+ /** Adds the given view to WindowManager with the provided LayoutParams (creates new window). */
+ public void addWindowView(View view, WindowManager.LayoutParams windowLayoutParams) {
+ mWindowManager.addView(view, windowLayoutParams);
+ }
+
+ /** Removes the given view from WindowManager. See {@link #addWindowView}. */
+ public void removeWindowView(View view) {
+ mWindowManager.removeViewImmediate(view);
}
protected void onTaskbarIconClicked(View view) {
@@ -485,6 +624,17 @@
} else if (tag instanceof FolderInfo) {
FolderIcon folderIcon = (FolderIcon) view;
Folder folder = folderIcon.getFolder();
+
+ folder.setOnFolderStateChangedListener(newState -> {
+ if (newState == Folder.STATE_OPEN) {
+ setTaskbarWindowFocusableForIme(true);
+ } else if (newState == Folder.STATE_CLOSED) {
+ // Defer by a frame to ensure we're no longer fullscreen and thus won't jump.
+ getDragLayer().post(() -> setTaskbarWindowFocusableForIme(false));
+ folder.setOnFolderStateChangedListener(null);
+ }
+ });
+
setTaskbarWindowFullscreen(true);
getDragLayer().post(() -> {
@@ -511,21 +661,22 @@
Toast.makeText(this, R.string.safemode_shortcut_error,
Toast.LENGTH_SHORT).show();
} else if (info.isPromise()) {
+ TestLogging.recordEvent(
+ TestProtocol.SEQUENCE_MAIN, "start: taskbarPromiseIcon");
intent = new PackageManagerHelper(this)
.getMarketIntent(info.getTargetPackage())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else if (info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+ TestLogging.recordEvent(
+ TestProtocol.SEQUENCE_MAIN, "start: taskbarDeepShortcut");
String id = info.getDeepShortcutId();
String packageName = intent.getPackage();
getSystemService(LauncherApps.class)
.startShortcut(packageName, id, null, null, info.user);
- } else if (info.user.equals(Process.myUserHandle())) {
- startActivity(intent);
} else {
- getSystemService(LauncherApps.class).startMainActivity(
- intent.getComponent(), info.user, intent.getSourceBounds(), null);
+ startItemInfoActivity(info);
}
mControllers.uiController.onTaskbarIconLaunched(info);
@@ -535,6 +686,9 @@
Log.e(TAG, "Unable to launch. tag=" + info + " intent=" + intent, e);
}
}
+ } else if (tag instanceof AppInfo) {
+ startItemInfoActivity((AppInfo) tag);
+ mControllers.uiController.onTaskbarIconLaunched((AppInfo) tag);
} else {
Log.e(TAG, "Unknown type clicked: " + tag);
}
@@ -542,6 +696,25 @@
AbstractFloatingView.closeAllOpenViews(this);
}
+ private void startItemInfoActivity(ItemInfo info) {
+ Intent intent = new Intent(info.getIntent())
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "start: taskbarAppIcon");
+ if (info.user.equals(Process.myUserHandle())) {
+ // TODO(b/216683257): Use startActivityForResult for search results that require it.
+ startActivity(intent);
+ } else {
+ getSystemService(LauncherApps.class).startMainActivity(
+ intent.getComponent(), info.user, intent.getSourceBounds(), null);
+ }
+ } catch (NullPointerException | ActivityNotFoundException | SecurityException e) {
+ Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT)
+ .show();
+ Log.e(TAG, "Unable to launch. tag=" + info + " intent=" + intent, e);
+ }
+ }
+
/**
* 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.
@@ -562,6 +735,53 @@
return mIsUserSetupComplete;
}
+ protected boolean isNavBarKidsModeActive() {
+ return mIsNavBarKidsMode && isThreeButtonNav();
+ }
+
+ protected boolean isNavBarForceVisible() {
+ return mIsNavBarForceVisible;
+ }
+
+ /**
+ * Displays a single frame of the Launcher start from SUW animation.
+ *
+ * This animation is a combination of the Launcher resume animation, which animates the hotseat
+ * icons into position, the Taskbar unstash to hotseat animation, which animates the Taskbar
+ * stash bar into the hotseat icons, and an override to prevent showing the Taskbar all apps
+ * button.
+ *
+ * This should be used to run a Taskbar unstash to hotseat animation whose progress matches a
+ * swipe progress.
+ *
+ * @param duration a placeholder duration to be used to ensure all full-length
+ * sub-animations are properly coordinated. This duration should not actually
+ * be used since this animation tracks a swipe progress.
+ */
+ protected AnimatorPlaybackController createLauncherStartFromSuwAnim(int duration) {
+ AnimatorSet fullAnimation = new AnimatorSet();
+ fullAnimation.setDuration(duration);
+
+ TaskbarUIController uiController = mControllers.uiController;
+ if (uiController instanceof LauncherTaskbarUIController) {
+ ((LauncherTaskbarUIController) uiController).addLauncherResumeAnimation(
+ fullAnimation, duration);
+ }
+ mControllers.taskbarStashController.addUnstashToHotseatAnimation(fullAnimation, duration);
+
+ if (!FeatureFlags.ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT.get()) {
+ ValueAnimator alphaOverride = ValueAnimator.ofFloat(0, 1);
+ alphaOverride.setDuration(duration);
+ alphaOverride.addUpdateListener(a -> {
+ // Override the alpha updates in the icon alignment animation.
+ mControllers.taskbarViewController.getAllAppsButtonView().setAlpha(0);
+ });
+ fullAnimation.play(alphaOverride);
+ }
+
+ return AnimatorPlaybackController.wrap(fullAnimation, duration);
+ }
+
/**
* Called when we determine the touchable region.
*
@@ -582,4 +802,26 @@
}
mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
}
+
+ public void showPopupMenuForIcon(BubbleTextView btv) {
+ setTaskbarWindowFullscreen(true);
+ btv.post(() -> mControllers.taskbarPopupController.showForIcon(btv));
+ }
+
+ protected void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarActivityContext:");
+
+ pw.println(String.format(
+ "%s\tmNavMode=%s", prefix, mNavMode));
+ pw.println(String.format(
+ "%s\tmImeDrawsImeNavBar=%b", prefix, mImeDrawsImeNavBar));
+ pw.println(String.format(
+ "%s\tmIsUserSetupComplete=%b", prefix, mIsUserSetupComplete));
+ pw.println(String.format(
+ "%s\tmWindowLayoutParams.height=%dpx", prefix, mWindowLayoutParams.height));
+ pw.println(String.format(
+ "%s\tmBindInProgress=%b", prefix, mBindingItems));
+ mControllers.dumpLogs(prefix + "\t", pw);
+ mDeviceProfile.dump(prefix, pw);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
index e42f83d..c5615c7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
@@ -15,21 +15,27 @@
*/
package com.android.launcher3.taskbar;
+import static com.android.launcher3.taskbar.Utilities.appendFlag;
+
import androidx.annotation.IntDef;
import com.android.quickstep.SystemUiProxy;
+import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.StringJoiner;
/**
* Normally Taskbar will auto-hide when entering immersive (fullscreen) apps. This controller allows
* us to suspend that behavior in certain cases (e.g. opening a Folder or dragging an icon).
*/
-public class TaskbarAutohideSuspendController {
+public class TaskbarAutohideSuspendController implements
+ TaskbarControllers.LoggableTaskbarController {
public static final int FLAG_AUTOHIDE_SUSPEND_FULLSCREEN = 1 << 0;
public static final int FLAG_AUTOHIDE_SUSPEND_DRAGGING = 1 << 1;
+
@IntDef(flag = true, value = {
FLAG_AUTOHIDE_SUSPEND_FULLSCREEN,
FLAG_AUTOHIDE_SUSPEND_DRAGGING,
@@ -60,4 +66,20 @@
}
mSystemUiProxy.notifyTaskbarAutohideSuspend(mAutohideSuspendFlags != 0);
}
+
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarAutohideSuspendController:");
+
+ pw.println(String.format(
+ "%s\tmAutohideSuspendFlags=%s", prefix, getStateString(mAutohideSuspendFlags)));
+ }
+
+ private static String getStateString(int flags) {
+ StringJoiner str = new StringJoiner("|");
+ appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_FULLSCREEN,
+ "FLAG_AUTOHIDE_SUSPEND_FULLSCREEN");
+ appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_DRAGGING, "FLAG_AUTOHIDE_SUSPEND_DRAGGING");
+ return str.toString();
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
new file mode 100644
index 0000000..1177bdb
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar
+
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.graphics.Path
+import com.android.launcher3.R
+
+/**
+ * Helps draw the taskbar background, made up of a rectangle plus two inverted rounded corners.
+ */
+class TaskbarBackgroundRenderer(context: TaskbarActivityContext) {
+
+ val paint: Paint = Paint()
+ var backgroundHeight = context.deviceProfile.taskbarSize.toFloat()
+
+ private val leftCornerRadius = context.leftCornerRadius.toFloat()
+ private val rightCornerRadius = context.rightCornerRadius.toFloat()
+ private val invertedLeftCornerPath: Path = Path()
+ private val invertedRightCornerPath: Path = Path()
+
+ init {
+ paint.color = context.getColor(R.color.taskbar_background)
+ paint.flags = Paint.ANTI_ALIAS_FLAG
+ paint.style = Paint.Style.FILL
+
+ // Create the paths for the inverted rounded corners above the taskbar. Start with a filled
+ // square, and then subtract out a circle from the appropriate corner.
+ val square = Path()
+ square.addRect(0f, 0f, leftCornerRadius, leftCornerRadius, Path.Direction.CW)
+ val circle = Path()
+ circle.addCircle(leftCornerRadius, 0f, leftCornerRadius, Path.Direction.CW)
+ invertedLeftCornerPath.op(square, circle, Path.Op.DIFFERENCE)
+ square.reset()
+ square.addRect(0f, 0f, rightCornerRadius, rightCornerRadius, Path.Direction.CW)
+ circle.reset()
+ circle.addCircle(0f, 0f, rightCornerRadius, Path.Direction.CW)
+ invertedRightCornerPath.op(square, circle, Path.Op.DIFFERENCE)
+ }
+
+ /**
+ * Draws the background with the given paint and height, on the provided canvas.
+ */
+ fun draw(canvas: Canvas) {
+ canvas.save()
+ canvas.translate(0f, canvas.height - backgroundHeight)
+
+ // Draw the background behind taskbar content.
+ canvas.drawRect(0f, 0f, canvas.width.toFloat(), backgroundHeight, paint)
+
+ // Draw the inverted rounded corners above the taskbar.
+ canvas.translate(0f, -leftCornerRadius)
+ canvas.drawPath(invertedLeftCornerPath, paint)
+ canvas.translate(0f, leftCornerRadius)
+ canvas.translate(canvas.width - rightCornerRadius, -rightCornerRadius)
+ canvas.drawPath(invertedRightCornerPath, paint)
+
+ canvas.restore()
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index c43fbf9..449e0a7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -18,9 +18,13 @@
import android.content.pm.ActivityInfo.Config;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
import com.android.systemui.shared.rotation.RotationButtonController;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -30,6 +34,7 @@
public class TaskbarControllers {
public final TaskbarActivityContext taskbarActivityContext;
+
public final TaskbarDragController taskbarDragController;
public final TaskbarNavButtonController navButtonController;
public final NavbarButtonsViewController navbarButtonsViewController;
@@ -44,6 +49,11 @@
public final TaskbarEduController taskbarEduController;
public final TaskbarAutohideSuspendController taskbarAutohideSuspendController;
public final TaskbarPopupController taskbarPopupController;
+ public final TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController;
+ public final TaskbarAllAppsController taskbarAllAppsController;
+ public final TaskbarInsetsController taskbarInsetsController;
+
+ @Nullable private LoggableTaskbarController[] mControllersToLog = null;
/** Do not store this controller, as it may change at runtime. */
@NonNull public TaskbarUIController uiController = TaskbarUIController.DEFAULT;
@@ -51,6 +61,8 @@
private boolean mAreAllControllersInitialized;
private final List<Runnable> mPostInitCallbacks = new ArrayList<>();
+ @Nullable private TaskbarSharedState mSharedState = null;
+
public TaskbarControllers(TaskbarActivityContext taskbarActivityContext,
TaskbarDragController taskbarDragController,
TaskbarNavButtonController navButtonController,
@@ -65,7 +77,10 @@
TaskbarStashController taskbarStashController,
TaskbarEduController taskbarEduController,
TaskbarAutohideSuspendController taskbarAutoHideSuspendController,
- TaskbarPopupController taskbarPopupController) {
+ TaskbarPopupController taskbarPopupController,
+ TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController,
+ TaskbarAllAppsController taskbarAllAppsController,
+ TaskbarInsetsController taskbarInsetsController) {
this.taskbarActivityContext = taskbarActivityContext;
this.taskbarDragController = taskbarDragController;
this.navButtonController = navButtonController;
@@ -81,6 +96,9 @@
this.taskbarEduController = taskbarEduController;
this.taskbarAutohideSuspendController = taskbarAutoHideSuspendController;
this.taskbarPopupController = taskbarPopupController;
+ this.taskbarForceVisibleImmersiveController = taskbarForceVisibleImmersiveController;
+ this.taskbarAllAppsController = taskbarAllAppsController;
+ this.taskbarInsetsController = taskbarInsetsController;
}
/**
@@ -88,8 +106,9 @@
* TaskbarControllers instance, but should be careful to only access things that were created
* in constructors for now, as some controllers may still be waiting for init().
*/
- public void init(TaskbarSharedState sharedState) {
+ public void init(@NonNull TaskbarSharedState sharedState) {
mAreAllControllersInitialized = false;
+ mSharedState = sharedState;
taskbarDragController.init(this);
navbarButtonsViewController.init(this);
@@ -100,8 +119,21 @@
taskbarUnfoldAnimationController.init(this);
taskbarKeyguardController.init(navbarButtonsViewController);
stashedHandleViewController.init(this);
- taskbarStashController.init(this, sharedState);
+ taskbarStashController.init(this, sharedState.setupUIVisible);
taskbarEduController.init(this);
+ taskbarPopupController.init(this);
+ taskbarForceVisibleImmersiveController.init(this);
+ taskbarAllAppsController.init(this, sharedState.allAppsVisible);
+ navButtonController.init(this);
+ taskbarInsetsController.init(this);
+
+ mControllersToLog = new LoggableTaskbarController[] {
+ taskbarDragController, navButtonController, navbarButtonsViewController,
+ taskbarDragLayerController, taskbarScrimViewController, taskbarViewController,
+ taskbarUnfoldAnimationController, taskbarKeyguardController,
+ stashedHandleViewController, taskbarStashController, taskbarEduController,
+ taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController
+ };
mAreAllControllersInitialized = true;
for (Runnable postInitCallback : mPostInitCallbacks) {
@@ -110,6 +142,12 @@
mPostInitCallbacks.clear();
}
+ @Nullable
+ public TaskbarSharedState getSharedState() {
+ // This should only be null if called before init() and after destroy().
+ return mSharedState;
+ }
+
public void onConfigurationChanged(@Config int configChanges) {
navbarButtonsViewController.onConfigurationChanged(configChanges);
}
@@ -118,6 +156,8 @@
* Cleans up all controllers.
*/
public void onDestroy() {
+ mSharedState = null;
+
navbarButtonsViewController.onDestroy();
uiController.onDestroy();
rotationButtonController.onDestroy();
@@ -127,6 +167,13 @@
taskbarViewController.onDestroy();
stashedHandleViewController.onDestroy();
taskbarAutohideSuspendController.onDestroy();
+ taskbarPopupController.onDestroy();
+ taskbarForceVisibleImmersiveController.onDestroy();
+ taskbarAllAppsController.onDestroy();
+ navButtonController.onDestroy();
+ taskbarInsetsController.onDestroy();
+
+ mControllersToLog = null;
}
/**
@@ -141,4 +188,32 @@
mPostInitCallbacks.add(callback);
}
}
+
+ protected void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarControllers:");
+
+ if (mControllersToLog == null) {
+ pw.println(String.format(
+ "%s\t%s", prefix, "All taskbar controllers have already been destroyed."));
+ return;
+ }
+
+ pw.println(String.format(
+ "%s\tmAreAllControllersInitialized=%b", prefix, mAreAllControllersInitialized));
+ for (LoggableTaskbarController controller : mControllersToLog) {
+ controller.dumpLogs(prefix + "\t", pw);
+ }
+ uiController.dumpLogs(prefix + "\t", pw);
+ rotationButtonController.dumpLogs(prefix + "\t", pw);
+ }
+
+ @VisibleForTesting
+ TaskbarActivityContext getTaskbarActivityContext() {
+ // Used to mock
+ return taskbarActivityContext;
+ }
+
+ protected interface LoggableTaskbarController {
+ void dumpLogs(String prefix, PrintWriter pw);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 21d7411..c522888 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -15,6 +15,12 @@
*/
package com.android.launcher3.taskbar;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.Intent;
@@ -27,7 +33,10 @@
import android.os.UserHandle;
import android.view.DragEvent;
import android.view.MotionEvent;
+import android.view.SurfaceControl;
import android.view.View;
+import android.view.ViewRootImpl;
+import android.window.SurfaceSyncer;
import androidx.annotation.Nullable;
@@ -39,7 +48,9 @@
import com.android.launcher3.DropTarget;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
+import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragDriver;
@@ -51,14 +62,26 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.PopupContainerWithArrow;
+import com.android.launcher3.shortcuts.DeepShortcutView;
+import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
+import com.android.launcher3.testing.TestLogging;
+import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.util.IntSet;
+import com.android.launcher3.util.ItemInfoMatcher;
import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.system.ClipDescriptionCompat;
-import com.android.systemui.shared.system.LauncherAppsCompat;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.function.Predicate;
/**
* Handles long click on Taskbar items to start a system drag and drop operation.
*/
-public class TaskbarDragController extends DragController<TaskbarActivityContext> {
+public class TaskbarDragController extends DragController<BaseTaskbarContext> implements
+ TaskbarControllers.LoggableTaskbarController {
+
+ private static boolean DEBUG_DRAG_SHADOW_SURFACE = false;
private final int mDragIconSize;
private final int[] mTempXY = new int[2];
@@ -72,7 +95,10 @@
private boolean mIsSystemDragInProgress;
- public TaskbarDragController(TaskbarActivityContext activity) {
+ // Animation for the drag shadow back into position after an unsuccessful drag
+ private ValueAnimator mReturnAnimator;
+
+ public TaskbarDragController(BaseTaskbarContext activity) {
super(activity);
Resources resources = mActivity.getResources();
mDragIconSize = resources.getDimensionPixelSize(R.dimen.taskbar_icon_drag_icon_size);
@@ -87,16 +113,33 @@
* generate the ClipDescription and Intent.
* @return Whether {@link View#startDragAndDrop} started successfully.
*/
- protected boolean startDragOnLongClick(View view) {
+ public boolean startDragOnLongClick(View view) {
+ return startDragOnLongClick(view, null, null);
+ }
+
+ protected boolean startDragOnLongClick(
+ DeepShortcutView shortcutView, Point iconShift) {
+ return startDragOnLongClick(
+ shortcutView.getBubbleText(),
+ new ShortcutDragPreviewProvider(shortcutView.getIconView(), iconShift),
+ iconShift);
+ }
+
+ private boolean startDragOnLongClick(
+ View view,
+ @Nullable DragPreviewProvider dragPreviewProvider,
+ @Nullable Point iconShift) {
if (!(view instanceof BubbleTextView)) {
return false;
}
-
+ TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onTaskbarItemLongClick");
BubbleTextView btv = (BubbleTextView) view;
-
- mActivity.setTaskbarWindowFullscreen(true);
+ mActivity.onDragStart();
btv.post(() -> {
- startInternalDrag(btv);
+ DragView dragView = startInternalDrag(btv, dragPreviewProvider);
+ if (iconShift != null) {
+ dragView.animateShift(-iconShift.x, -iconShift.y);
+ }
btv.getIcon().setIsDisabled(true);
mControllers.taskbarAutohideSuspendController.updateFlag(
TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING, true);
@@ -104,7 +147,8 @@
return true;
}
- private void startInternalDrag(BubbleTextView btv) {
+ private DragView startInternalDrag(
+ BubbleTextView btv, @Nullable DragPreviewProvider dragPreviewProvider) {
float iconScale = btv.getIcon().getAnimatedScale();
// Clear the pressed state if necessary
@@ -112,7 +156,8 @@
btv.setPressed(false);
btv.clearPressedBackground();
- final DragPreviewProvider previewProvider = new DragPreviewProvider(btv);
+ final DragPreviewProvider previewProvider = dragPreviewProvider == null
+ ? new DragPreviewProvider(btv) : dragPreviewProvider;
final Drawable drawable = previewProvider.createDrawable();
final float scale = previewProvider.getScaleAndPosition(drawable, mTempXY);
int dragLayerX = mTempXY[0];
@@ -123,40 +168,49 @@
dragLayerY += dragRect.top;
DragOptions dragOptions = new DragOptions();
- dragOptions.preDragCondition = new DragOptions.PreDragCondition() {
- private DragView mDragView;
-
- @Override
- public boolean shouldStartDrag(double distanceDragged) {
- return mDragView != null && mDragView.isAnimationFinished();
- }
-
- @Override
- public void onPreDragStart(DropTarget.DragObject dragObject) {
- mDragView = dragObject.dragView;
- }
-
- @Override
- public void onPreDragEnd(DropTarget.DragObject dragObject, boolean dragStarted) {
- mDragView = null;
- }
- };
+ dragOptions.preDragCondition = null;
if (FeatureFlags.ENABLE_TASKBAR_POPUP_MENU.get()) {
- PopupContainerWithArrow<TaskbarActivityContext> popupContainer =
+ PopupContainerWithArrow<BaseTaskbarContext> popupContainer =
mControllers.taskbarPopupController.showForIcon(btv);
if (popupContainer != null) {
dragOptions.preDragCondition = popupContainer.createPreDragCondition(false);
}
}
+ if (dragOptions.preDragCondition == null) {
+ dragOptions.preDragCondition = new DragOptions.PreDragCondition() {
+ private DragView mDragView;
- startDrag(
+ @Override
+ public boolean shouldStartDrag(double distanceDragged) {
+ return mDragView != null && mDragView.isAnimationFinished();
+ }
+
+ @Override
+ public void onPreDragStart(DropTarget.DragObject dragObject) {
+ mDragView = dragObject.dragView;
+
+ if (FeatureFlags.ENABLE_TASKBAR_POPUP_MENU.get()
+ && !shouldStartDrag(0)) {
+ // Immediately close the popup menu.
+ mDragView.setOnAnimationEndCallback(() -> callOnDragStart());
+ }
+ }
+
+ @Override
+ public void onPreDragEnd(DropTarget.DragObject dragObject, boolean dragStarted) {
+ mDragView = null;
+ }
+ };
+ }
+
+ return startDrag(
drawable,
/* view = */ null,
/* originalView = */ btv,
dragLayerX,
dragLayerY,
(View target, DropTarget.DragObject d, boolean success) -> {} /* DragSource */,
- (WorkspaceItemInfo) btv.getTag(),
+ (ItemInfo) btv.getTag(),
/* dragVisualizeOffset = */ null,
dragRect,
scale * iconScale,
@@ -241,7 +295,8 @@
@Override
public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
- shadowSize.set(mDragIconSize, mDragIconSize);
+ int iconSize = Math.max(mDragIconSize, btv.getWidth());
+ shadowSize.set(iconSize, iconSize);
// The registration point was taken before the icon scaled to mDragIconSize, so
// offset the registration to where the touch is on the new size.
int offsetX = (mDragIconSize - mDragObject.dragView.getDragRegionWidth()) / 2;
@@ -252,6 +307,9 @@
@Override
public void onDrawShadow(Canvas canvas) {
canvas.save();
+ if (DEBUG_DRAG_SHADOW_SURFACE) {
+ canvas.drawColor(0xffff0000);
+ }
float scale = mDragObject.dragView.getScaleX();
canvas.scale(scale, scale);
mDragObject.dragView.draw(canvas);
@@ -262,33 +320,40 @@
Object tag = btv.getTag();
ClipDescription clipDescription = null;
Intent intent = null;
- if (tag instanceof WorkspaceItemInfo) {
- WorkspaceItemInfo item = (WorkspaceItemInfo) tag;
+ if (tag instanceof ItemInfo) {
+ ItemInfo item = (ItemInfo) tag;
LauncherApps launcherApps = mActivity.getSystemService(LauncherApps.class);
clipDescription = new ClipDescription(item.title,
new String[] {
item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
- ? ClipDescriptionCompat.MIMETYPE_APPLICATION_SHORTCUT
- : ClipDescriptionCompat.MIMETYPE_APPLICATION_ACTIVITY
+ ? ClipDescription.MIMETYPE_APPLICATION_SHORTCUT
+ : ClipDescription.MIMETYPE_APPLICATION_ACTIVITY
});
intent = new Intent();
if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+ String deepShortcutId = ((WorkspaceItemInfo) item).getDeepShortcutId();
+ intent.putExtra(ClipDescription.EXTRA_PENDING_INTENT,
+ launcherApps.getShortcutIntent(
+ item.getIntent().getPackage(),
+ deepShortcutId,
+ null,
+ item.user));
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, item.getIntent().getPackage());
- intent.putExtra(Intent.EXTRA_SHORTCUT_ID, item.getDeepShortcutId());
+ intent.putExtra(Intent.EXTRA_SHORTCUT_ID, deepShortcutId);
} else {
- intent.putExtra(ClipDescriptionCompat.EXTRA_PENDING_INTENT,
- LauncherAppsCompat.getMainActivityLaunchIntent(launcherApps,
- item.getIntent().getComponent(), null, item.user));
+ intent.putExtra(ClipDescription.EXTRA_PENDING_INTENT,
+ launcherApps.getMainActivityLaunchIntent(item.getIntent().getComponent(),
+ null, item.user));
}
intent.putExtra(Intent.EXTRA_USER, item.user);
} else if (tag instanceof Task) {
Task task = (Task) tag;
clipDescription = new ClipDescription(task.titleDescription,
new String[] {
- ClipDescriptionCompat.MIMETYPE_APPLICATION_TASK
+ ClipDescription.MIMETYPE_APPLICATION_TASK
});
intent = new Intent();
- intent.putExtra(ClipDescriptionCompat.EXTRA_TASK_ID, task.key.id);
+ intent.putExtra(Intent.EXTRA_TASK_ID, task.key.id);
intent.putExtra(Intent.EXTRA_USER, UserHandle.of(task.key.userId));
}
@@ -303,8 +368,9 @@
ClipData clipData = new ClipData(clipDescription, new ClipData.Item(intent));
if (btv.startDragAndDrop(clipData, shadowBuilder, null /* localState */,
- View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_OPAQUE)) {
- onSystemDragStarted();
+ View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_OPAQUE
+ | View.DRAG_FLAG_REQUEST_SURFACE_FOR_RETURN_ANIMATION)) {
+ onSystemDragStarted(btv);
mActivity.getStatsLogManager().logger().withItemInfo(mDragObject.dragInfo)
.withInstanceId(launcherInstanceId)
@@ -313,7 +379,7 @@
}
}
- private void onSystemDragStarted() {
+ private void onSystemDragStarted(BubbleTextView btv) {
mIsSystemDragInProgress = true;
mActivity.getDragLayer().setOnDragListener((view, dragEvent) -> {
switch (dragEvent.getAction()) {
@@ -322,7 +388,12 @@
return true;
case DragEvent.ACTION_DRAG_ENDED:
mIsSystemDragInProgress = false;
- maybeOnDragEnd();
+ if (dragEvent.getResult()) {
+ maybeOnDragEnd();
+ } else {
+ // This will take care of calling maybeOnDragEnd() after the animation
+ animateGlobalDragViewToOriginalPosition(btv, dragEvent);
+ }
return true;
}
return false;
@@ -334,11 +405,17 @@
return super.isDragging() || mIsSystemDragInProgress;
}
+ /** {@code true} if the system is currently handling the drag. */
+ public boolean isSystemDragInProgress() {
+ return mIsSystemDragInProgress;
+ }
+
private void maybeOnDragEnd() {
if (!isDragging()) {
((BubbleTextView) mDragObject.originalView).getIcon().setIsDisabled(false);
mControllers.taskbarAutohideSuspendController.updateFlag(
TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING, false);
+ mActivity.onDragEnd();
}
}
@@ -348,6 +425,96 @@
maybeOnDragEnd();
}
+ private void animateGlobalDragViewToOriginalPosition(BubbleTextView btv,
+ DragEvent dragEvent) {
+ SurfaceControl dragSurface = dragEvent.getDragSurface();
+
+ // For top level icons, the target is the icon itself
+ View target = btv;
+ Object tag = btv.getTag();
+ if (tag instanceof ItemInfo) {
+ ItemInfo item = (ItemInfo) tag;
+ TaskbarViewController taskbarViewController = mControllers.taskbarViewController;
+ if (item.container == CONTAINER_ALL_APPS) {
+ // Since all apps closes when the drag starts, target the all apps button instead.
+ target = taskbarViewController.getAllAppsButtonView();
+ } else if (item.container >= 0) {
+ // Since folders close when the drag starts, target the folder icon instead.
+ Predicate<ItemInfo> matcher = ItemInfoMatcher.forFolderMatch(
+ ItemInfoMatcher.ofItemIds(IntSet.wrap(item.id)));
+ target = taskbarViewController.getFirstIconMatch(matcher);
+ } else if (item.itemType == ITEM_TYPE_DEEP_SHORTCUT) {
+ // Find first icon with same package/user as the deep shortcut.
+ Predicate<ItemInfo> packageUserMatcher = ItemInfoMatcher.ofPackages(
+ Collections.singleton(item.getTargetPackage()), item.user);
+ target = taskbarViewController.getFirstIconMatch(packageUserMatcher);
+ }
+ }
+
+ // Finish any pending return animation before starting a new drag
+ if (mReturnAnimator != null) {
+ mReturnAnimator.end();
+ }
+
+ float fromX = dragEvent.getX() - dragEvent.getOffsetX();
+ float fromY = dragEvent.getY() - dragEvent.getOffsetY();
+ int[] toPosition = target.getLocationOnScreen();
+ float toScale = (float) target.getWidth() / mDragIconSize;
+ float toAlpha = (target == btv) ? 1f : 0f;
+ final ViewRootImpl viewRoot = target.getViewRootImpl();
+ SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
+ mReturnAnimator = ValueAnimator.ofFloat(0f, 1f);
+ mReturnAnimator.setDuration(300);
+ mReturnAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ mReturnAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float t = animation.getAnimatedFraction();
+ float accelT = Interpolators.ACCEL_2.getInterpolation(t);
+ float scale = 1f - t * (1f - toScale);
+ float alpha = 1f - accelT * (1f - toAlpha);
+ tx.setPosition(dragSurface, Utilities.mapRange(t, fromX, toPosition[0]),
+ Utilities.mapRange(t, fromY, toPosition[1]));
+ tx.setScale(dragSurface, scale, scale);
+ tx.setAlpha(dragSurface, alpha);
+ tx.apply();
+ }
+ });
+ mReturnAnimator.addListener(new AnimatorListenerAdapter() {
+ private boolean mCanceled = false;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ cleanUpSurface();
+ mCanceled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mCanceled) {
+ return;
+ }
+ cleanUpSurface();
+ }
+
+ private void cleanUpSurface() {
+ tx.close();
+ maybeOnDragEnd();
+ // Synchronize removing the drag surface with the next draw after calling
+ // maybeOnDragEnd()
+ SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
+ transaction.remove(dragSurface);
+ SurfaceSyncer syncer = new SurfaceSyncer();
+ int syncId = syncer.setupSync(transaction::close);
+ syncer.addToSync(syncId, viewRoot.getView());
+ syncer.addTransactionToSync(syncId, transaction);
+ syncer.markSyncReady(syncId);
+ mReturnAnimator = null;
+ }
+ });
+ mReturnAnimator.start();
+ }
+
@Override
protected float getX(MotionEvent ev) {
// We will resize to fill the screen while dragging, so use screen coordinates. This ensures
@@ -386,4 +553,18 @@
protected DropTarget getDefaultDropTarget(int[] dropCoordinates) {
return null;
}
+
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarDragController:");
+
+ pw.println(String.format("%s\tmDragIconSize=%dpx", prefix, mDragIconSize));
+ pw.println(String.format("%s\tmTempXY=%s", prefix, Arrays.toString(mTempXY)));
+ pw.println(String.format("%s\tmRegistrationX=%d", prefix, mRegistrationX));
+ pw.println(String.format("%s\tmRegistrationY=%d", prefix, mRegistrationY));
+ pw.println(String.format(
+ "%s\tmIsSystemDragInProgress=%b", prefix, mIsSystemDragInProgress));
+ pw.println(String.format(
+ "%s\tisInternalDragInProgess=%b", prefix, super.isDragging()));
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index b42a60c..c1a6185 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -15,21 +15,22 @@
*/
package com.android.launcher3.taskbar;
+import static android.view.KeyEvent.ACTION_UP;
+import static android.view.KeyEvent.KEYCODE_BACK;
+
import android.content.Context;
import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
import android.util.AttributeSet;
+import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.R;
+import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
-import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
import com.android.systemui.shared.system.ViewTreeObserverWrapper;
import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo;
@@ -40,13 +41,11 @@
*/
public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
- private final Paint mTaskbarBackgroundPaint;
- private final Path mInvertedLeftCornerPath, mInvertedRightCornerPath;
+ private final TaskbarBackgroundRenderer mBackgroundRenderer;
private final OnComputeInsetsListener mTaskbarInsetsComputer = this::onComputeTaskbarInsets;
// Initialized in init.
private TaskbarDragLayerController.TaskbarDragLayerCallbacks mControllerCallbacks;
- private float mLeftCornerRadius, mRightCornerRadius;
private float mTaskbarBackgroundOffset;
@@ -66,47 +65,24 @@
public TaskbarDragLayer(@NonNull Context context, @Nullable AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, 1 /* alphaChannelCount */);
- mTaskbarBackgroundPaint = new Paint();
- mTaskbarBackgroundPaint.setColor(getResources().getColor(R.color.taskbar_background));
- mTaskbarBackgroundPaint.setAlpha(0);
- mTaskbarBackgroundPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
- mTaskbarBackgroundPaint.setStyle(Paint.Style.FILL);
-
- // Will be set in init(), but this ensures they are always non-null.
- mInvertedLeftCornerPath = new Path();
- mInvertedRightCornerPath = new Path();
+ mBackgroundRenderer = new TaskbarBackgroundRenderer(mActivity);
+ mBackgroundRenderer.getPaint().setAlpha(0);
}
public void init(TaskbarDragLayerController.TaskbarDragLayerCallbacks callbacks) {
mControllerCallbacks = callbacks;
- // Create the paths for the inverted rounded corners above the taskbar. Start with a filled
- // square, and then subtracting out a circle from the appropriate corner.
- mLeftCornerRadius = mActivity.getLeftCornerRadius();
- mRightCornerRadius = mActivity.getRightCornerRadius();
- Path square = new Path();
- square.addRect(0, 0, mLeftCornerRadius, mLeftCornerRadius, Path.Direction.CW);
- Path circle = new Path();
- circle.addCircle(mLeftCornerRadius, 0, mLeftCornerRadius, Path.Direction.CW);
- mInvertedLeftCornerPath.op(square, circle, Path.Op.DIFFERENCE);
- square.reset();
- square.addRect(0, 0, mRightCornerRadius, mRightCornerRadius, Path.Direction.CW);
- circle.reset();
- circle.addCircle(0, 0, mRightCornerRadius, Path.Direction.CW);
- mInvertedRightCornerPath.op(square, circle, Path.Op.DIFFERENCE);
-
recreateControllers();
}
@Override
public void recreateControllers() {
- mControllers = new TouchController[] {mActivity.getDragController()};
+ mControllers = mControllerCallbacks.getTouchControllers();
}
private void onComputeTaskbarInsets(InsetsInfo insetsInfo) {
if (mControllerCallbacks != null) {
mControllerCallbacks.updateInsetsTouchability(insetsInfo);
- mControllerCallbacks.updateContentInsets(insetsInfo.contentInsets);
}
}
@@ -147,20 +123,8 @@
protected void dispatchDraw(Canvas canvas) {
float backgroundHeight = mControllerCallbacks.getTaskbarBackgroundHeight()
* (1f - mTaskbarBackgroundOffset);
- canvas.save();
- canvas.translate(0, canvas.getHeight() - backgroundHeight);
-
- // Draw the background behind taskbar content.
- canvas.drawRect(0, 0, canvas.getWidth(), backgroundHeight, mTaskbarBackgroundPaint);
-
- // Draw the inverted rounded corners above the taskbar.
- canvas.translate(0, -mLeftCornerRadius);
- canvas.drawPath(mInvertedLeftCornerPath, mTaskbarBackgroundPaint);
- canvas.translate(0, mLeftCornerRadius);
- canvas.translate(canvas.getWidth() - mRightCornerRadius, -mRightCornerRadius);
- canvas.drawPath(mInvertedRightCornerPath, mTaskbarBackgroundPaint);
-
- canvas.restore();
+ mBackgroundRenderer.setBackgroundHeight(backgroundHeight);
+ mBackgroundRenderer.draw(canvas);
super.dispatchDraw(canvas);
}
@@ -169,7 +133,7 @@
* @param alpha 0 is fully transparent, 1 is fully opaque.
*/
protected void setTaskbarBackgroundAlpha(float alpha) {
- mTaskbarBackgroundPaint.setAlpha((int) (alpha * 255));
+ mBackgroundRenderer.getPaint().setAlpha((int) (alpha * 255));
invalidate();
}
@@ -187,4 +151,17 @@
TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev);
return super.dispatchTouchEvent(ev);
}
+
+ /** Called while Taskbar window is focusable, e.g. when pressing back while a folder is open */
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) {
+ AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
+ if (topView != null && topView.onBackPressed()) {
+ // Handled by the floating view.
+ return true;
+ }
+ }
+ return super.dispatchKeyEvent(event);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index a918016..99c59a8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -15,24 +15,20 @@
*/
package com.android.launcher3.taskbar;
-import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
-import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_CONTENT;
-import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_FRAME;
-import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION;
-
import android.content.res.Resources;
import android.graphics.Rect;
-import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.R;
-import com.android.launcher3.anim.AlphaUpdateListener;
+import com.android.launcher3.util.TouchController;
import com.android.quickstep.AnimatedFloat;
import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo;
+import java.io.PrintWriter;
+
/**
* Handles properties/data collection, then passes the results to TaskbarDragLayer to render.
*/
-public class TaskbarDragLayerController {
+public class TaskbarDragLayerController implements TaskbarControllers.LoggableTaskbarController {
private final TaskbarActivityContext mActivity;
private final TaskbarDragLayer mTaskbarDragLayer;
@@ -144,6 +140,16 @@
mNavButtonDarkIntensityMultiplier.updateValue(1 - effectiveBgAlpha);
}
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarDragLayerController:");
+
+ pw.println(String.format("%s\tmBgOffset=%.2f", prefix, mBgOffset.value));
+ pw.println(String.format("%s\tmFolderMargin=%dpx", prefix, mFolderMargin));
+ pw.println(String.format(
+ "%s\tmLastSetBackgroundAlpha=%.2f", prefix, mLastSetBackgroundAlpha));
+ }
+
/**
* Callbacks for {@link TaskbarDragLayer} to interact with its controller.
*/
@@ -154,49 +160,14 @@
* @see InsetsInfo#setTouchableInsets(int)
*/
public void updateInsetsTouchability(InsetsInfo insetsInfo) {
- insetsInfo.touchableRegion.setEmpty();
- // Always have nav buttons be touchable
- mControllers.navbarButtonsViewController.addVisibleButtonsRegion(
- mTaskbarDragLayer, insetsInfo.touchableRegion);
- boolean insetsIsTouchableRegion = true;
-
- if (mTaskbarDragLayer.getAlpha() < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) {
- // Let touches pass through us.
- insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
- } else if (mControllers.navbarButtonsViewController.isImeVisible()) {
- insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
- } else if (!mControllers.uiController.isTaskbarTouchable()) {
- // Let touches pass through us.
- insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
- } else if (mControllers.taskbarViewController.areIconsVisible()
- || AbstractFloatingView.getOpenView(mActivity, TYPE_ALL) != null) {
- // Taskbar has some touchable elements, take over the full taskbar area
- insetsInfo.setTouchableInsets(mActivity.isTaskbarWindowFullscreen()
- ? TOUCHABLE_INSETS_FRAME : TOUCHABLE_INSETS_CONTENT);
- insetsIsTouchableRegion = false;
- } else {
- insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
- }
- mActivity.excludeFromMagnificationRegion(insetsIsTouchableRegion);
- }
-
- /**
- * Called to update the {@link InsetsInfo#contentInsets}. This is reported to apps but our
- * internal launcher will ignore these insets.
- */
- public void updateContentInsets(Rect outContentInsets) {
- int contentHeight = mControllers.taskbarStashController
- .getContentHeightToReportToApps();
- outContentInsets.top = mTaskbarDragLayer.getHeight() - contentHeight;
+ mControllers.taskbarInsetsController.updateInsetsTouchability(insetsInfo);
}
/**
* Called when a child is removed from TaskbarDragLayer.
*/
public void onDragLayerViewRemoved() {
- if (AbstractFloatingView.getAnyView(mActivity, TYPE_ALL) == null) {
- mActivity.setTaskbarWindowFullscreen(false);
- }
+ mActivity.maybeSetTaskbarWindowNotFullscreen();
}
/**
@@ -205,5 +176,14 @@
public int getTaskbarBackgroundHeight() {
return mActivity.getDeviceProfile().taskbarSize;
}
+
+ /**
+ * Returns touch controllers.
+ */
+ public TouchController[] getTouchControllers() {
+ return new TouchController[]{mActivity.getDragController(),
+ mControllers.taskbarForceVisibleImmersiveController,
+ mControllers.navbarButtonsViewController.getTouchController()};
+ }
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragView.java
index cf28eff..7a42432 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragView.java
@@ -25,8 +25,8 @@
* while the pre-drag is still in progress (i.e. when the long press popup is still open). After
* that ends, we switch to a system drag and drop view instead.
*/
-public class TaskbarDragView extends DragView<TaskbarActivityContext> {
- public TaskbarDragView(TaskbarActivityContext launcher, Drawable drawable, int registrationX,
+public class TaskbarDragView extends DragView<BaseTaskbarContext> {
+ public TaskbarDragView(BaseTaskbarContext launcher, Drawable drawable, int registrationX,
int registrationY, float initialScale, float scaleOnDrop, float finalScaleDps) {
super(launcher, drawable, registrationX, registrationY, initialScale, scaleOnDrop,
finalScaleDps);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
index fd5c2ea..e29b14b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
@@ -37,12 +37,13 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.uioverrides.PredictedAppIcon;
+import java.io.PrintWriter;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/** Handles the Taskbar Education flow. */
-public class TaskbarEduController {
+public class TaskbarEduController implements TaskbarControllers.LoggableTaskbarController {
private static final long WAVE_ANIM_DELAY = 250;
private static final long WAVE_ANIM_STAGGER = 50;
@@ -186,6 +187,18 @@
return waveAnim;
}
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarEduController:");
+
+ pw.println(String.format("%s\tisShowingEdu=%b", prefix, mTaskbarEduView != null));
+ pw.println(String.format("%s\tmWaveAnimTranslationY=%.2f", prefix, mWaveAnimTranslationY));
+ pw.println(String.format(
+ "%s\tmWaveAnimTranslationYReturnOvershoot=%.2f",
+ prefix,
+ mWaveAnimTranslationYReturnOvershoot));
+ }
+
/**
* Callbacks for {@link TaskbarEduView} to interact with its controller.
*/
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java
index 5efcc4d..8e57ea6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java
@@ -52,7 +52,7 @@
}
@Override
- protected int getChildGap() {
+ protected int getChildGap(int fromIndex, int toIndex) {
return mTaskbarEduView.getPaddingLeft() + mTaskbarEduView.getPaddingRight();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java
index 8525427..89d67be 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java
@@ -20,6 +20,7 @@
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.graphics.Rect;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Pair;
import android.view.View;
@@ -92,6 +93,14 @@
getPopupContainer().addView(this, 1);
}
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING, 0);
+ }
+
/** Show the Education flow. */
public void show() {
attachToContainer();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarForceVisibleImmersiveController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarForceVisibleImmersiveController.java
new file mode 100644
index 0000000..c99cebb
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarForceVisibleImmersiveController.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar;
+
+import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS;
+import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_ICONS;
+
+import static com.android.launcher3.taskbar.NavbarButtonsViewController.ALPHA_INDEX_IMMERSIVE_MODE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IMMERSIVE_MODE;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.view.MotionEvent;
+
+import com.android.launcher3.compat.AccessibilityManagerCompat;
+import com.android.launcher3.util.MultiValueAlpha;
+import com.android.launcher3.util.TouchController;
+import com.android.quickstep.AnimatedFloat;
+
+import java.util.Optional;
+import java.util.function.Consumer;
+
+/**
+ * Controller for taskbar when force visible in immersive mode is set.
+ */
+public class TaskbarForceVisibleImmersiveController implements TouchController {
+ private static final int NAV_BAR_ICONS_DIM_ANIMATION_START_DELAY_MS = 4500;
+ private static final int NAV_BAR_ICONS_DIM_ANIMATION_DURATION_MS = 500;
+ private static final int NAV_BAR_ICONS_UNDIM_ANIMATION_DURATION_MS = 250;
+ private static final float NAV_BAR_ICONS_DIM_PCT = 0.15f;
+ private static final float NAV_BAR_ICONS_UNDIM_PCT = 1f;
+
+ private final TaskbarActivityContext mContext;
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
+ private final Runnable mDimmingRunnable = this::dimIcons;
+ private final Runnable mUndimmingRunnable = this::undimIcons;
+ private final AnimatedFloat mIconAlphaForDimming = new AnimatedFloat(
+ this::updateIconDimmingAlpha);
+ private final Consumer<MultiValueAlpha> mImmersiveModeAlphaUpdater = alpha -> alpha.getProperty(
+ ALPHA_INDEX_IMMERSIVE_MODE).setValue(mIconAlphaForDimming.value);
+
+ // Initialized in init.
+ private TaskbarControllers mControllers;
+ private boolean mIsImmersiveMode;
+
+ public TaskbarForceVisibleImmersiveController(TaskbarActivityContext context) {
+ mContext = context;
+ }
+
+ /**
+ * Initialize controllers.
+ */
+ public void init(TaskbarControllers controllers) {
+ mControllers = controllers;
+ }
+
+ /** Update values tracked via sysui flags. */
+ public void updateSysuiFlags(int sysuiFlags) {
+ mIsImmersiveMode = (sysuiFlags & SYSUI_STATE_IMMERSIVE_MODE) != 0;
+ if (mContext.isNavBarForceVisible()) {
+ if (mIsImmersiveMode) {
+ startIconDimming();
+ } else {
+ startIconUndimming();
+ }
+ }
+ }
+
+ /** Clean up animations. */
+ public void onDestroy() {
+ startIconUndimming();
+ }
+
+ private void startIconUndimming() {
+ mHandler.removeCallbacks(mDimmingRunnable);
+ mHandler.removeCallbacks(mUndimmingRunnable);
+ mHandler.post(mUndimmingRunnable);
+ }
+
+ private void undimIcons() {
+ mIconAlphaForDimming.animateToValue(NAV_BAR_ICONS_UNDIM_PCT).setDuration(
+ NAV_BAR_ICONS_UNDIM_ANIMATION_DURATION_MS).start();
+ }
+
+ private void startIconDimming() {
+ mHandler.removeCallbacks(mDimmingRunnable);
+ int accessibilityDimmingTimeout = AccessibilityManagerCompat.getRecommendedTimeoutMillis(
+ mContext, NAV_BAR_ICONS_DIM_ANIMATION_START_DELAY_MS,
+ (FLAG_CONTENT_ICONS | FLAG_CONTENT_CONTROLS));
+ mHandler.postDelayed(mDimmingRunnable, accessibilityDimmingTimeout);
+ }
+
+ private void dimIcons() {
+ mIconAlphaForDimming.animateToValue(NAV_BAR_ICONS_DIM_PCT).setDuration(
+ NAV_BAR_ICONS_DIM_ANIMATION_DURATION_MS).start();
+ }
+
+ /**
+ * Returns whether the taskbar is always visible in immersive mode.
+ */
+ private boolean isNavbarShownInImmersiveMode() {
+ return mIsImmersiveMode && mContext.isNavBarForceVisible();
+ }
+
+ private void updateIconDimmingAlpha() {
+ getBackButtonAlphaOptional().ifPresent(mImmersiveModeAlphaUpdater);
+ getHomeButtonAlphaOptional().ifPresent(mImmersiveModeAlphaUpdater);
+ }
+
+ private Optional<MultiValueAlpha> getBackButtonAlphaOptional() {
+ if (mControllers == null || mControllers.navbarButtonsViewController == null) {
+ return Optional.empty();
+ }
+ return Optional.ofNullable(mControllers.navbarButtonsViewController.getBackButtonAlpha());
+ }
+
+ private Optional<MultiValueAlpha> getHomeButtonAlphaOptional() {
+ if (mControllers == null || mControllers.navbarButtonsViewController == null) {
+ return Optional.empty();
+ }
+ return Optional.ofNullable(mControllers.navbarButtonsViewController.getHomeButtonAlpha());
+ }
+
+ @Override
+ public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ if (!isNavbarShownInImmersiveMode()
+ || mControllers.taskbarStashController.supportsManualStashing()) {
+ return false;
+ }
+ return onControllerTouchEvent(ev);
+ }
+
+ @Override
+ public boolean onControllerTouchEvent(MotionEvent ev) {
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ startIconUndimming();
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ startIconDimming();
+ break;
+ }
+ return false;
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
new file mode 100644
index 0000000..6a6a693
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar
+
+import android.graphics.Insets
+import android.graphics.Region
+import android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES
+import android.view.WindowManager
+import com.android.launcher3.AbstractFloatingView
+import com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_ALL_APPS
+import com.android.launcher3.DeviceProfile
+import com.android.launcher3.anim.AlphaUpdateListener
+import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
+import com.android.quickstep.KtR
+import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo
+import com.android.systemui.shared.system.WindowManagerWrapper
+import com.android.systemui.shared.system.WindowManagerWrapper.*
+import java.io.PrintWriter
+
+/**
+ * Handles the insets that Taskbar provides to underlying apps and the IME.
+ */
+class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTaskbarController {
+
+ /** The bottom insets taskbar provides to the IME when IME is visible. */
+ val taskbarHeightForIme: Int = context.resources.getDimensionPixelSize(
+ KtR.dimen.taskbar_ime_size)
+ private val contentRegion: Region = Region()
+ private val deviceProfileChangeListener = { _: DeviceProfile ->
+ onTaskbarWindowHeightOrInsetsChanged()
+ }
+
+ // Initialized in init.
+ private lateinit var controllers: TaskbarControllers
+ private lateinit var windowLayoutParams: WindowManager.LayoutParams
+
+ fun init(controllers: TaskbarControllers) {
+ this.controllers = controllers
+ windowLayoutParams = context.windowLayoutParams
+
+ val wmWrapper: WindowManagerWrapper = getInstance()
+ wmWrapper.setProvidesInsetsTypes(
+ windowLayoutParams,
+ intArrayOf(
+ ITYPE_EXTRA_NAVIGATION_BAR,
+ ITYPE_BOTTOM_TAPPABLE_ELEMENT,
+ ITYPE_BOTTOM_MANDATORY_GESTURES
+ )
+ )
+
+ windowLayoutParams.providedInternalInsets = arrayOfNulls<Insets>(ITYPE_SIZE)
+ windowLayoutParams.providedInternalImeInsets = arrayOfNulls<Insets>(ITYPE_SIZE)
+
+ onTaskbarWindowHeightOrInsetsChanged()
+
+ windowLayoutParams.insetsRoundedCornerFrame = true
+ context.addOnDeviceProfileChangeListener(deviceProfileChangeListener)
+ }
+
+ fun onDestroy() {
+ context.removeOnDeviceProfileChangeListener(deviceProfileChangeListener)
+ }
+
+ fun onTaskbarWindowHeightOrInsetsChanged() {
+ var reducingSize = getReducingInsetsForTaskbarInsetsHeight(
+ controllers.taskbarStashController.contentHeightToReportToApps)
+
+ contentRegion.set(0, reducingSize.top,
+ context.deviceProfile.widthPx, windowLayoutParams.height)
+ windowLayoutParams.providedInternalInsets[ITYPE_EXTRA_NAVIGATION_BAR] = reducingSize
+ windowLayoutParams.providedInternalInsets[ITYPE_BOTTOM_MANDATORY_GESTURES] = reducingSize
+ reducingSize = getReducingInsetsForTaskbarInsetsHeight(
+ controllers.taskbarStashController.tappableHeightToReportToApps)
+ windowLayoutParams.providedInternalInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT] = reducingSize
+ windowLayoutParams.providedInternalInsets[ITYPE_BOTTOM_MANDATORY_GESTURES] = reducingSize
+
+ reducingSize = getReducingInsetsForTaskbarInsetsHeight(taskbarHeightForIme)
+ windowLayoutParams.providedInternalImeInsets[ITYPE_EXTRA_NAVIGATION_BAR] = reducingSize
+ windowLayoutParams.providedInternalImeInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT] = reducingSize
+ windowLayoutParams.providedInternalImeInsets[ITYPE_BOTTOM_MANDATORY_GESTURES] = reducingSize
+ }
+
+ /**
+ * WindowLayoutParams.providedInternal*Insets expects Insets that subtract from the window frame
+ * height (i.e. WindowLayoutParams#height). So for Taskbar to report bottom insets to apps, it
+ * actually provides insets from the top of its window frame.
+ * @param height The number of pixels from the bottom of the screen that Taskbar insets.
+ */
+ private fun getReducingInsetsForTaskbarInsetsHeight(height: Int): Insets {
+ return Insets.of(0, windowLayoutParams.height - height, 0, 0)
+ }
+
+ /**
+ * Called to update the touchable insets.
+ * @see InsetsInfo.setTouchableInsets
+ */
+ fun updateInsetsTouchability(insetsInfo: InsetsInfo) {
+ insetsInfo.touchableRegion.setEmpty()
+ // Always have nav buttons be touchable
+ controllers.navbarButtonsViewController.addVisibleButtonsRegion(
+ context.dragLayer, insetsInfo.touchableRegion
+ )
+ var insetsIsTouchableRegion = true
+ if (context.dragLayer.alpha < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) {
+ // Let touches pass through us.
+ insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION)
+ } else if (controllers.navbarButtonsViewController.isImeVisible) {
+ insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION)
+ } else if (!controllers.uiController.isTaskbarTouchable) {
+ // Let touches pass through us.
+ insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION)
+ } else if (controllers.taskbarDragController.isSystemDragInProgress) {
+ // Let touches pass through us.
+ insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION)
+ } else if (AbstractFloatingView.hasOpenView(context, TYPE_TASKBAR_ALL_APPS)) {
+ // Let touches pass through us.
+ insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION)
+ } else if (controllers.taskbarViewController.areIconsVisible()
+ || AbstractFloatingView.hasOpenView(context, AbstractFloatingView.TYPE_ALL)
+ || context.isNavBarKidsModeActive
+ ) {
+ // Taskbar has some touchable elements, take over the full taskbar area
+ insetsInfo.setTouchableInsets(
+ if (context.isTaskbarWindowFullscreen) {
+ InsetsInfo.TOUCHABLE_INSETS_FRAME
+ } else {
+ insetsInfo.touchableRegion.set(contentRegion)
+ InsetsInfo.TOUCHABLE_INSETS_REGION
+ }
+ )
+ insetsIsTouchableRegion = false
+ } else {
+ insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION)
+ }
+ context.excludeFromMagnificationRegion(insetsIsTouchableRegion)
+ }
+
+ override fun dumpLogs(prefix: String, pw: PrintWriter) {
+ pw.println(prefix + "TaskbarInsetsController:")
+ pw.println("$prefix\twindowHeight=${windowLayoutParams.height}")
+ pw.println("$prefix\tprovidedInternalInsets[ITYPE_EXTRA_NAVIGATION_BAR]=" +
+ "${windowLayoutParams.providedInternalInsets[ITYPE_EXTRA_NAVIGATION_BAR]}")
+ pw.println("$prefix\tprovidedInternalInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT]=" +
+ "${windowLayoutParams.providedInternalInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT]}")
+ pw.println("$prefix\tprovidedInternalImeInsets[ITYPE_EXTRA_NAVIGATION_BAR]=" +
+ "${windowLayoutParams.providedInternalImeInsets[ITYPE_EXTRA_NAVIGATION_BAR]}")
+ pw.println("$prefix\tprovidedInternalImeInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT]=" +
+ "${windowLayoutParams.providedInternalImeInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT]}")
+ }
+}
\ No newline at end of file
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
index 5fc0695..56648ea 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
@@ -1,5 +1,6 @@
package com.android.launcher3.taskbar;
+import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DOZING;
@@ -14,10 +15,15 @@
import android.content.Intent;
import android.content.IntentFilter;
+import com.android.launcher3.AbstractFloatingView;
+import com.android.systemui.shared.system.QuickStepContract;
+
+import java.io.PrintWriter;
+
/**
* Controller for managing keyguard state for taskbar
*/
-public class TaskbarKeyguardController {
+public class TaskbarKeyguardController implements TaskbarControllers.LoggableTaskbarController {
private static final int KEYGUARD_SYSUI_FLAGS = SYSUI_STATE_BOUNCER_SHOWING |
SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING | SYSUI_STATE_DEVICE_DOZING |
@@ -35,6 +41,7 @@
@Override
public void onReceive(Context context, Intent intent) {
mIsScreenOff = true;
+ AbstractFloatingView.closeOpenViews(mContext, false, TYPE_ALL);
}
};
@@ -67,6 +74,10 @@
mNavbarButtonsViewController.setKeyguardVisible(keyguardShowing || dozing,
keyguardOccluded);
updateIconsForBouncer();
+
+ if (keyguardShowing) {
+ AbstractFloatingView.closeOpenViews(mContext, true, TYPE_ALL);
+ }
}
public boolean isScreenOff() {
@@ -95,4 +106,16 @@
public void onDestroy() {
mContext.unregisterReceiver(mScreenOffReceiver);
}
+
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarKeyguardController:");
+
+ pw.println(String.format(
+ "%s\tmKeyguardSysuiFlags=%s",
+ prefix,
+ QuickStepContract.getSystemUiStateString(mKeyguardSysuiFlags)));
+ pw.println(String.format("%s\tmBouncerShowing=%b", prefix, mBouncerShowing));
+ pw.println(String.format("%s\tmIsScreenOff=%b", prefix, mIsScreenOff));
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index be5ab55..dc0ef27 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -26,18 +26,24 @@
import android.animation.ObjectAnimator;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.Utilities;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.RecentsAnimationCallbacks;
import com.android.quickstep.RecentsAnimationController;
import com.android.quickstep.views.RecentsView;
+import com.android.systemui.animation.ViewRootSync;
import com.android.systemui.shared.recents.model.ThumbnailData;
+import java.io.PrintWriter;
import java.util.HashMap;
+import java.util.StringJoiner;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -70,9 +76,16 @@
private int mState;
private LauncherState mLauncherState = LauncherState.NORMAL;
+ private @Nullable TaskBarRecentsAnimationListener mTaskBarRecentsAnimationListener;
+
private boolean mIsAnimatingToLauncherViaGesture;
private boolean mIsAnimatingToLauncherViaResume;
+ private boolean mShouldDelayLauncherStateAnim;
+
+ // We skip any view synchronizations during init/destroy.
+ private boolean mCanSyncViews;
+
private final StateManager.StateListener<LauncherState> mStateListener =
new StateManager.StateListener<LauncherState>() {
@@ -85,7 +98,9 @@
mLauncherState = toState;
}
updateStateForFlag(FLAG_TRANSITION_STATE_RUNNING, true);
- applyState();
+ if (!mShouldDelayLauncherStateAnim) {
+ applyState();
+ }
}
@Override
@@ -97,6 +112,8 @@
};
public void init(TaskbarControllers controllers, BaseQuickstepLauncher launcher) {
+ mCanSyncViews = false;
+
mControllers = controllers;
mLauncher = launcher;
@@ -116,9 +133,13 @@
updateStateForFlag(FLAG_RESUMED, launcher.hasBeenResumed());
mLauncherState = launcher.getStateManager().getState();
applyState(0);
+
+ mCanSyncViews = true;
}
public void onDestroy() {
+ mCanSyncViews = false;
+
mIconAlignmentForResumedState.finishAnimation();
mIconAlignmentForGestureState.finishAnimation();
mIconAlignmentForLauncherState.finishAnimation();
@@ -126,6 +147,8 @@
mIconAlphaForHome.setConsumer(null);
mLauncher.getHotseat().setIconsAlpha(1f);
mLauncher.getStateManager().removeStateListener(mStateListener);
+
+ mCanSyncViews = true;
}
public Animator createAnimToLauncher(@NonNull LauncherState toState,
@@ -144,12 +167,11 @@
animatorSet.play(stashController.applyStateWithoutStart(duration));
animatorSet.play(applyState(duration, false));
- TaskBarRecentsAnimationListener listener = new TaskBarRecentsAnimationListener(callbacks);
- callbacks.addListener(listener);
+ mTaskBarRecentsAnimationListener = new TaskBarRecentsAnimationListener(callbacks);
+ callbacks.addListener(mTaskBarRecentsAnimationListener);
RecentsView recentsView = mLauncher.getOverviewPanel();
recentsView.setTaskLaunchListener(() -> {
- listener.endGestureStateOverride(true);
- callbacks.removeListener(listener);
+ mTaskBarRecentsAnimationListener.endGestureStateOverride(true);
});
return animatorSet;
}
@@ -158,6 +180,15 @@
return mIsAnimatingToLauncherViaResume || mIsAnimatingToLauncherViaGesture;
}
+ public void setShouldDelayLauncherStateAnim(boolean shouldDelayLauncherStateAnim) {
+ if (!shouldDelayLauncherStateAnim && mShouldDelayLauncherStateAnim) {
+ // Animate the animation we have delayed immediately. This is usually triggered when
+ // the user has released their finger.
+ applyState();
+ }
+ mShouldDelayLauncherStateAnim = shouldDelayLauncherStateAnim;
+ }
+
/**
* Updates the proper flag to change the state of the task bar.
*
@@ -229,7 +260,10 @@
if (hasAnyFlag(changedFlags, FLAG_RESUMED)
|| launcherStateChangedDuringAnimToResumeAlignment) {
boolean isResumed = isResumed();
- float toAlignmentForResumedState = isResumed && goingToUnstashedLauncherState() ? 1 : 0;
+ // If launcher is resumed, we show the icons when going to an unstashed launcher state
+ // or launcher state is not changed (e.g. in overview, launcher is paused and resumed).
+ float toAlignmentForResumedState = isResumed && (goingToUnstashedLauncherState()
+ || !goingToUnstashedLauncherStateChanged) ? 1 : 0;
// If we're already animating to the value, just leave it be instead of restarting it.
if (!mIconAlignmentForResumedState.isAnimatingToValue(toAlignmentForResumedState)) {
ObjectAnimator resumeAlignAnim = mIconAlignmentForResumedState
@@ -288,6 +322,10 @@
if (hasAnyFlag(changedFlags, FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING)) {
boolean goingToLauncher = hasAnyFlag(FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING);
+ if (goingToLauncher) {
+ // Handle closing open popups when going home/overview
+ AbstractFloatingView.closeAllOpenViews(mControllers.taskbarActivityContext);
+ }
animatorSet.play(mTaskbarBackgroundAlpha.animateToValue(goingToLauncher ? 0 : 1)
.setDuration(duration));
}
@@ -333,6 +371,7 @@
// If we're already animating to the value, just leave it be instead of restarting it.
if (!mIconAlignmentForLauncherState.isAnimatingToValue(toAlignment)) {
+ mIconAlignmentForLauncherState.finishAnimation();
animatorSet.play(mIconAlignmentForLauncherState.animateToValue(toAlignment)
.setDuration(duration));
}
@@ -347,7 +386,7 @@
}
private void onIconAlignmentRatioChangedForStateTransition() {
- if (!isResumed()) {
+ if (!isResumed() && mTaskBarRecentsAnimationListener == null) {
return;
}
onIconAlignmentRatioChanged(this::getCurrentIconAlignmentRatioForLauncherState);
@@ -362,11 +401,28 @@
return;
}
float alignment = alignmentSupplier.get();
+ float currentValue = mIconAlphaForHome.getValue();
+ boolean taskbarWillBeVisible = alignment < 1;
+ boolean firstFrameVisChanged = (taskbarWillBeVisible && Float.compare(currentValue, 1) != 0)
+ || (!taskbarWillBeVisible && Float.compare(currentValue, 0) != 0);
+
+ updateIconAlignment(alignment);
+
+ // Sync the first frame where we swap taskbar and hotseat.
+ if (firstFrameVisChanged && mCanSyncViews && !Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ ViewRootSync.synchronizeNextDraw(mLauncher.getHotseat(),
+ mControllers.taskbarActivityContext.getDragLayer(),
+ () -> {});
+ }
+ }
+
+ private void updateIconAlignment(float alignment) {
mControllers.taskbarViewController.setLauncherIconAlignment(
alignment, mLauncher.getDeviceProfile());
// Switch taskbar and hotseat in last frame
setTaskbarViewVisible(alignment < 1);
+ mControllers.navbarButtonsViewController.updateTaskbarAlignment(alignment);
}
private float getCurrentIconAlignmentRatioBetweenAppAndHome() {
@@ -391,7 +447,8 @@
@Override
public void onRecentsAnimationCanceled(HashMap<Integer, ThumbnailData> thumbnailDatas) {
- endGestureStateOverride(true);
+ boolean isInOverview = mLauncher.isInState(LauncherState.OVERVIEW);
+ endGestureStateOverride(!isInOverview);
}
@Override
@@ -401,6 +458,7 @@
private void endGestureStateOverride(boolean finishedToApp) {
mCallbacks.removeListener(this);
+ mTaskBarRecentsAnimationListener = null;
// Update the resumed state immediately to ensure a seamless handoff
boolean launcherResumed = !finishedToApp;
@@ -416,4 +474,48 @@
controller.applyState();
}
}
+
+ private static String getStateString(int flags) {
+ StringJoiner str = new StringJoiner("|");
+ str.add((flags & FLAG_RESUMED) != 0 ? "FLAG_RESUMED" : "");
+ str.add((flags & FLAG_RECENTS_ANIMATION_RUNNING) != 0
+ ? "FLAG_RECENTS_ANIMATION_RUNNING" : "");
+ str.add((flags & FLAG_TRANSITION_STATE_RUNNING) != 0
+ ? "FLAG_TRANSITION_STATE_RUNNING" : "");
+ return str.toString();
+ }
+
+ protected void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarLauncherStateController:");
+
+ pw.println(String.format(
+ "%s\tmIconAlignmentForResumedState=%.2f",
+ prefix,
+ mIconAlignmentForResumedState.value));
+ pw.println(String.format(
+ "%s\tmIconAlignmentForGestureState=%.2f",
+ prefix,
+ mIconAlignmentForGestureState.value));
+ pw.println(String.format(
+ "%s\tmIconAlignmentForLauncherState=%.2f",
+ prefix,
+ mIconAlignmentForLauncherState.value));
+ pw.println(String.format(
+ "%s\tmTaskbarBackgroundAlpha=%.2f", prefix, mTaskbarBackgroundAlpha.value));
+ pw.println(String.format(
+ "%s\tmIconAlphaForHome=%.2f", prefix, mIconAlphaForHome.getValue()));
+ pw.println(String.format("%s\tmPrevState=%s", prefix, getStateString(mPrevState)));
+ pw.println(String.format("%s\tmState=%s", prefix, getStateString(mState)));
+ pw.println(String.format("%s\tmLauncherState=%s", prefix, mLauncherState));
+ pw.println(String.format(
+ "%s\tmIsAnimatingToLauncherViaGesture=%b",
+ prefix,
+ mIsAnimatingToLauncherViaGesture));
+ pw.println(String.format(
+ "%s\tmIsAnimatingToLauncherViaResume=%b",
+ prefix,
+ mIsAnimatingToLauncherViaResume));
+ pw.println(String.format(
+ "%s\tmShouldDelayLauncherStateAnim=%b", prefix, mShouldDelayLauncherStateAnim));
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index bec717d..06262c0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -15,12 +15,12 @@
*/
package com.android.launcher3.taskbar;
+import static android.content.pm.PackageManager.FEATURE_PC;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
-import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
-import static com.android.launcher3.util.DisplayController.CHANGE_SUPPORTED_BOUNDS;
+import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
import android.content.ComponentCallbacks;
import android.content.Context;
@@ -39,40 +39,45 @@
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.taskbar.unfold.NonDestroyableScopedUnfoldTransitionProgressProvider;
import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.SettingsCache;
import com.android.launcher3.util.SimpleBroadcastReceiver;
import com.android.quickstep.RecentsActivity;
-import com.android.quickstep.SysUINavigationMode;
-import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TouchInteractionService;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
+import java.io.PrintWriter;
+
/**
* Class to manage taskbar lifecycle
*/
-public class TaskbarManager implements DisplayController.DisplayInfoChangeListener,
- SysUINavigationMode.NavigationModeChangeListener {
+public class TaskbarManager {
private static final Uri USER_SETUP_COMPLETE_URI = Settings.Secure.getUriFor(
Settings.Secure.USER_SETUP_COMPLETE);
+ private static final Uri NAV_BAR_KIDS_MODE = Settings.Secure.getUriFor(
+ Settings.Secure.NAV_BAR_KIDS_MODE);
+
private final Context mContext;
private final DisplayController mDisplayController;
- private final SysUINavigationMode mSysUINavigationMode;
private final TaskbarNavButtonController mNavButtonController;
private final SettingsCache.OnChangeListener mUserSetupCompleteListener;
+ private final SettingsCache.OnChangeListener mNavBarKidsModeListener;
private final ComponentCallbacks mComponentCallbacks;
private final SimpleBroadcastReceiver mShutdownReceiver;
// 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
+ // as it is tied to the activity lifecycle, not the taskbar lifecycle.
+ // It's destruction/creation will be managed by the activity.
private final ScopedUnfoldTransitionProgressProvider mUnfoldProgressProvider =
- new ScopedUnfoldTransitionProgressProvider();
+ new NonDestroyableScopedUnfoldTransitionProgressProvider();
private TaskbarActivityContext mTaskbarActivityContext;
private StatefulActivity mActivity;
@@ -82,40 +87,68 @@
*/
private final TaskbarSharedState mSharedState = new TaskbarSharedState();
- private static final int CHANGE_FLAGS =
- CHANGE_ACTIVE_SCREEN | CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS;
+ /**
+ * 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}
+ */
+ private static final int CHANGE_FLAGS = CHANGE_NAVIGATION_MODE | CHANGE_DENSITY;
+ private final DisplayController.DisplayInfoChangeListener mDispInfoChangeListener;
private boolean mUserUnlocked = false;
public TaskbarManager(TouchInteractionService service) {
mDisplayController = DisplayController.INSTANCE.get(service);
- mSysUINavigationMode = SysUINavigationMode.INSTANCE.get(service);
Display display =
service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
mContext = service.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null);
mNavButtonController = new TaskbarNavButtonController(service,
SystemUiProxy.INSTANCE.get(mContext), new Handler());
mUserSetupCompleteListener = isUserSetupComplete -> recreateTaskbar();
+ mNavBarKidsModeListener = isNavBarKidsMode -> recreateTaskbar();
+ // TODO(b/227669780): Consolidate this w/ DisplayController callbacks
mComponentCallbacks = new ComponentCallbacks() {
private Configuration mOldConfig = mContext.getResources().getConfiguration();
@Override
public void onConfigurationChanged(Configuration newConfig) {
+ DeviceProfile dp = mUserUnlocked
+ ? LauncherAppState.getIDP(mContext).getDeviceProfile(mContext)
+ : null;
int configDiff = mOldConfig.diff(newConfig);
int configsRequiringRecreate = ActivityInfo.CONFIG_ASSETS_PATHS
- | ActivityInfo.CONFIG_LAYOUT_DIRECTION | ActivityInfo.CONFIG_UI_MODE;
- if ((configDiff & configsRequiringRecreate) != 0) {
- // Color has changed, recreate taskbar to reload background color & icons.
+ | ActivityInfo.CONFIG_LAYOUT_DIRECTION | ActivityInfo.CONFIG_UI_MODE
+ | ActivityInfo.CONFIG_SCREEN_SIZE;
+ boolean requiresRecreate = (configDiff & configsRequiringRecreate) != 0;
+ if ((configDiff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0
+ && mTaskbarActivityContext != null && dp != null) {
+ // Additional check since this callback gets fired multiple times w/o
+ // screen size changing, or when simply rotating the device.
+ DeviceProfile oldDp = mTaskbarActivityContext.getDeviceProfile();
+ boolean isOrientationChange =
+ (configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0;
+ int oldWidth = isOrientationChange ? oldDp.heightPx : oldDp.widthPx;
+ int oldHeight = isOrientationChange ? oldDp.widthPx : oldDp.heightPx;
+ if (dp.widthPx == oldWidth && dp.heightPx == oldHeight) {
+ configDiff &= ~ActivityInfo.CONFIG_SCREEN_SIZE;
+ requiresRecreate = (configDiff & configsRequiringRecreate) != 0;
+ }
+ }
+
+ if (requiresRecreate) {
recreateTaskbar();
} else {
// Config change might be handled without re-creating the taskbar
if (mTaskbarActivityContext != null) {
- DeviceProfile dp = mUserUnlocked
- ? LauncherAppState.getIDP(mContext).getDeviceProfile(mContext)
- : null;
-
if (dp != null && dp.isTaskbarPresent) {
- mTaskbarActivityContext.updateDeviceProfile(dp.copy(mContext));
+ mTaskbarActivityContext.updateDeviceProfile(dp);
}
mTaskbarActivityContext.onConfigurationChanged(configDiff);
}
@@ -127,29 +160,22 @@
public void onLowMemory() { }
};
mShutdownReceiver = new SimpleBroadcastReceiver(i -> destroyExistingTaskbar());
-
- mDisplayController.addChangeListener(this);
- mSysUINavigationMode.addModeChangeListener(this);
+ mDispInfoChangeListener = (context, info, flags) -> {
+ if ((flags & CHANGE_FLAGS) != 0) {
+ recreateTaskbar();
+ }
+ };
+ mDisplayController.addChangeListener(mDispInfoChangeListener);
SettingsCache.INSTANCE.get(mContext).register(USER_SETUP_COMPLETE_URI,
mUserSetupCompleteListener);
+ SettingsCache.INSTANCE.get(mContext).register(NAV_BAR_KIDS_MODE,
+ mNavBarKidsModeListener);
mContext.registerComponentCallbacks(mComponentCallbacks);
mShutdownReceiver.register(mContext, Intent.ACTION_SHUTDOWN);
recreateTaskbar();
}
- @Override
- public void onNavigationModeChanged(Mode newMode) {
- recreateTaskbar();
- }
-
- @Override
- public void onDisplayInfoChanged(Context context, Info info, int flags) {
- if ((flags & CHANGE_FLAGS) != 0) {
- recreateTaskbar();
- }
- }
-
private void destroyExistingTaskbar() {
if (mTaskbarActivityContext != null) {
mTaskbarActivityContext.onDestroy();
@@ -158,6 +184,17 @@
}
/**
+ * 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
+ * progress.
+ */
+ public AnimatorPlaybackController createLauncherStartFromSuwAnim(int duration) {
+ return mTaskbarActivityContext == null
+ ? null : mTaskbarActivityContext.createLauncherStartFromSuwAnim(duration);
+ }
+
+ /**
* Called when the user is unlocked
*/
public void onUserUnlocked() {
@@ -169,6 +206,9 @@
* Sets a {@link StatefulActivity} to act as taskbar callback
*/
public void setActivity(@NonNull StatefulActivity activity) {
+ if (mActivity == activity) {
+ return;
+ }
mActivity = activity;
mUnfoldProgressProvider.setSourceProvider(getUnfoldTransitionProgressProviderForActivity(
activity));
@@ -196,6 +236,9 @@
*/
private TaskbarUIController createTaskbarUIControllerForActivity(StatefulActivity activity) {
if (activity instanceof BaseQuickstepLauncher) {
+ if (mTaskbarActivityContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
+ return new DesktopTaskbarUIController((BaseQuickstepLauncher) activity);
+ }
return new LauncherTaskbarUIController((BaseQuickstepLauncher) activity);
}
if (activity instanceof RecentsActivity) {
@@ -223,8 +266,7 @@
DeviceProfile dp =
mUserUnlocked ? LauncherAppState.getIDP(mContext).getDeviceProfile(mContext) : null;
- boolean isTaskBarEnabled =
- FeatureFlags.ENABLE_TASKBAR.get() && dp != null && dp.isTaskbarPresent;
+ boolean isTaskBarEnabled = dp != null && dp.isTaskbarPresent;
if (!isTaskBarEnabled) {
SystemUiProxy.INSTANCE.get(mContext)
@@ -232,8 +274,8 @@
return;
}
- mTaskbarActivityContext = new TaskbarActivityContext(mContext, dp.copy(mContext),
- mNavButtonController, mUnfoldProgressProvider);
+ mTaskbarActivityContext = new TaskbarActivityContext(mContext, dp, mNavButtonController,
+ mUnfoldProgressProvider);
mTaskbarActivityContext.init(mSharedState);
if (mActivity != null) {
@@ -288,10 +330,11 @@
*/
public void destroy() {
destroyExistingTaskbar();
- mDisplayController.removeChangeListener(this);
- mSysUINavigationMode.removeModeChangeListener(this);
+ mDisplayController.removeChangeListener(mDispInfoChangeListener);
SettingsCache.INSTANCE.get(mContext).unregister(USER_SETUP_COMPLETE_URI,
mUserSetupCompleteListener);
+ SettingsCache.INSTANCE.get(mContext).unregister(NAV_BAR_KIDS_MODE,
+ mNavBarKidsModeListener);
mContext.unregisterComponentCallbacks(mComponentCallbacks);
mContext.unregisterReceiver(mShutdownReceiver);
}
@@ -299,4 +342,13 @@
public @Nullable TaskbarActivityContext getCurrentActivityContext() {
return mTaskbarActivityContext;
}
+
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarManager:");
+ if (mTaskbarActivityContext == null) {
+ pw.println(prefix + "\tTaskbarActivityContext: null");
+ } else {
+ mTaskbarActivityContext.dumpLogs(prefix + "\t", pw);
+ }
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
index 37a9b5e..75881a3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
@@ -21,6 +21,7 @@
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
+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.util.ComponentKey;
@@ -29,11 +30,13 @@
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LauncherBindableItemsContainer;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.function.Predicate;
/**
* Launcher model Callbacks for rendering taskbar.
@@ -50,8 +53,6 @@
// Initialized in init.
private TaskbarControllers mControllers;
- private boolean mBindInProgress = false;
-
public TaskbarModelCallbacks(
TaskbarActivityContext context, TaskbarView container) {
mContext = context;
@@ -64,14 +65,14 @@
@Override
public void startBinding() {
- mBindInProgress = true;
+ mContext.setBindingItems(true);
mHotseatItems.clear();
mPredictedItems = Collections.emptyList();
}
@Override
public void finishBindingItems(IntSet pagesBoundFirst) {
- mBindInProgress = false;
+ mContext.setBindingItems(false);
commitItemsToUI();
}
@@ -126,16 +127,16 @@
}
@Override
- public void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher) {
+ public void bindWorkspaceComponentsRemoved(Predicate<ItemInfo> matcher) {
if (handleItemsRemoved(matcher)) {
commitItemsToUI();
}
}
- private boolean handleItemsRemoved(ItemInfoMatcher matcher) {
+ private boolean handleItemsRemoved(Predicate<ItemInfo> matcher) {
boolean modified = false;
for (int i = mHotseatItems.size() - 1; i >= 0; i--) {
- if (matcher.matchesInfo(mHotseatItems.valueAt(i))) {
+ if (matcher.test(mHotseatItems.valueAt(i))) {
modified = true;
mHotseatItems.removeAt(i);
}
@@ -157,11 +158,13 @@
if (item.containerId == Favorites.CONTAINER_HOTSEAT_PREDICTION) {
mPredictedItems = item.items;
commitItemsToUI();
+ } else if (item.containerId == Favorites.CONTAINER_PREDICTION) {
+ mControllers.taskbarAllAppsController.setPredictedApps(item.items);
}
}
private void commitItemsToUI() {
- if (mBindInProgress) {
+ if (mContext.isBindingItems()) {
return;
}
@@ -196,4 +199,19 @@
public void bindDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMapCopy) {
mControllers.taskbarPopupController.setDeepShortcutMap(deepShortcutMapCopy);
}
+
+ @Override
+ public void bindAllApplications(AppInfo[] apps, int flags) {
+ mControllers.taskbarAllAppsController.setApps(apps, flags);
+ }
+
+ protected void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarModelCallbacks:");
+
+ pw.println(String.format("%s\thotseat items count=%s", prefix, mHotseatItems.size()));
+ if (mPredictedItems != null) {
+ pw.println(
+ String.format("%s\tpredicted items count=%s", prefix, mPredictedItems.size()));
+ }
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index d233365..4ff0649 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -16,22 +16,38 @@
package com.android.launcher3.taskbar;
-
import static com.android.internal.app.AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS;
import static com.android.internal.app.AssistUtils.INVOCATION_TYPE_KEY;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_A11Y_BUTTON_LONGPRESS;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_A11Y_BUTTON_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_BACK_BUTTON_LONGPRESS;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_BACK_BUTTON_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_HOME_BUTTON_LONGPRESS;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_HOME_BUTTON_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_IME_SWITCHER_BUTTON_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_OVERVIEW_BUTTON_LONGPRESS;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_OVERVIEW_BUTTON_TAP;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import android.os.Bundle;
import android.os.Handler;
+import android.util.Log;
import androidx.annotation.IntDef;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import com.android.launcher3.R;
+import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.TaskUtils;
import com.android.quickstep.TouchInteractionService;
+import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -40,15 +56,25 @@
* Handles all the functionality of the various buttons, making/routing the right calls into
* launcher or sysui/system.
*/
-public class TaskbarNavButtonController {
+public class TaskbarNavButtonController implements TaskbarControllers.LoggableTaskbarController {
/** Allow some time in between the long press for back and recents. */
static final int SCREEN_PIN_LONG_PRESS_THRESHOLD = 200;
static final int SCREEN_PIN_LONG_PRESS_RESET = SCREEN_PIN_LONG_PRESS_THRESHOLD + 100;
+ private static final String TAG = TaskbarNavButtonController.class.getSimpleName();
private long mLastScreenPinLongPress;
private boolean mScreenPinned;
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarNavButtonController:");
+
+ pw.println(String.format(
+ "%s\tmLastScreenPinLongPress=%dms", prefix, mLastScreenPinLongPress));
+ pw.println(String.format("%s\tmScreenPinned=%b", prefix, mScreenPinned));
+ }
+
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {
BUTTON_BACK,
@@ -56,6 +82,8 @@
BUTTON_RECENTS,
BUTTON_IME_SWITCH,
BUTTON_A11Y,
+ BUTTON_QUICK_SETTINGS,
+ BUTTON_NOTIFICATIONS,
})
public @interface TaskbarButton {}
@@ -65,6 +93,8 @@
static final int BUTTON_RECENTS = BUTTON_HOME << 1;
static final int BUTTON_IME_SWITCH = BUTTON_RECENTS << 1;
static final int BUTTON_A11Y = BUTTON_IME_SWITCH << 1;
+ static final int BUTTON_QUICK_SETTINGS = BUTTON_A11Y << 1;
+ static final int BUTTON_NOTIFICATIONS = BUTTON_QUICK_SETTINGS << 1;
private static final int SCREEN_UNPIN_COMBO = BUTTON_BACK | BUTTON_RECENTS;
private int mLongPressedButtons = 0;
@@ -72,6 +102,7 @@
private final TouchInteractionService mService;
private final SystemUiProxy mSystemUiProxy;
private final Handler mHandler;
+ @Nullable private StatsLogManager mStatsLogManager;
private final Runnable mResetLongPress = this::resetScreenUnpin;
@@ -85,41 +116,82 @@
public void onButtonClick(@TaskbarButton int buttonType) {
switch (buttonType) {
case BUTTON_BACK:
+ logEvent(LAUNCHER_TASKBAR_BACK_BUTTON_TAP);
executeBack();
break;
case BUTTON_HOME:
+ logEvent(LAUNCHER_TASKBAR_HOME_BUTTON_TAP);
navigateHome();
break;
case BUTTON_RECENTS:
+ logEvent(LAUNCHER_TASKBAR_OVERVIEW_BUTTON_TAP);
navigateToOverview();
break;
case BUTTON_IME_SWITCH:
+ logEvent(LAUNCHER_TASKBAR_IME_SWITCHER_BUTTON_TAP);
showIMESwitcher();
break;
case BUTTON_A11Y:
+ logEvent(LAUNCHER_TASKBAR_A11Y_BUTTON_TAP);
notifyA11yClick(false /* longClick */);
break;
+ case BUTTON_QUICK_SETTINGS:
+ showQuickSettings();
+ break;
+ case BUTTON_NOTIFICATIONS:
+ showNotifications();
+ break;
}
}
public boolean onButtonLongClick(@TaskbarButton int buttonType) {
switch (buttonType) {
case BUTTON_HOME:
+ logEvent(LAUNCHER_TASKBAR_HOME_BUTTON_LONGPRESS);
startAssistant();
return true;
case BUTTON_A11Y:
+ logEvent(LAUNCHER_TASKBAR_A11Y_BUTTON_LONGPRESS);
notifyA11yClick(true /* longClick */);
return true;
case BUTTON_BACK:
+ logEvent(LAUNCHER_TASKBAR_BACK_BUTTON_LONGPRESS);
+ return backRecentsLongpress(buttonType);
case BUTTON_RECENTS:
- mLongPressedButtons |= buttonType;
- return determineScreenUnpin();
+ logEvent(LAUNCHER_TASKBAR_OVERVIEW_BUTTON_LONGPRESS);
+ return backRecentsLongpress(buttonType);
case BUTTON_IME_SWITCH:
default:
return false;
}
}
+ public @StringRes int getButtonContentDescription(@TaskbarButton int buttonType) {
+ switch (buttonType) {
+ case BUTTON_HOME:
+ return R.string.taskbar_button_home;
+ case BUTTON_A11Y:
+ return R.string.taskbar_button_a11y;
+ case BUTTON_BACK:
+ return R.string.taskbar_button_back;
+ case BUTTON_IME_SWITCH:
+ return R.string.taskbar_button_ime_switcher;
+ case BUTTON_RECENTS:
+ return R.string.taskbar_button_recents;
+ case BUTTON_NOTIFICATIONS:
+ return R.string.taskbar_button_notifications;
+ case BUTTON_QUICK_SETTINGS:
+ return R.string.taskbar_button_quick_settings;
+ default:
+ return 0;
+ }
+ }
+
+ private boolean backRecentsLongpress(@TaskbarButton int buttonType) {
+ mLongPressedButtons |= buttonType;
+ return determineScreenUnpin();
+ }
+
/**
* Checks if the user has long pressed back and recents buttons
* "together" (within {@link #SCREEN_PIN_LONG_PRESS_THRESHOLD})ms
@@ -166,6 +238,22 @@
mScreenPinned = (sysuiFlags & SYSUI_STATE_SCREEN_PINNING) != 0;
}
+ public void init(TaskbarControllers taskbarControllers) {
+ mStatsLogManager = taskbarControllers.getTaskbarActivityContext().getStatsLogManager();
+ }
+
+ public void onDestroy() {
+ mStatsLogManager = null;
+ }
+
+ private void logEvent(StatsLogManager.LauncherEvent event) {
+ if (mStatsLogManager == null) {
+ Log.w(TAG, "No stats log manager to log taskbar button event");
+ return;
+ }
+ mStatsLogManager.logger().log(event);
+ }
+
private void navigateHome() {
mService.getOverviewCommandHelper().addCommand(OverviewCommandHelper.TYPE_HOME);
}
@@ -175,6 +263,7 @@
return;
}
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onOverviewToggle");
+ TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
mService.getOverviewCommandHelper().addCommand(OverviewCommandHelper.TYPE_TOGGLE);
}
@@ -202,4 +291,12 @@
args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS);
mSystemUiProxy.startAssistant(args);
}
+
+ private void showQuickSettings() {
+ mSystemUiProxy.toggleNotificationPanel();
+ }
+
+ private void showNotifications() {
+ mSystemUiProxy.toggleNotificationPanel();
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index 952f597..7b4501a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -15,35 +15,73 @@
*/
package com.android.launcher3.taskbar;
+import android.content.Intent;
+import android.content.pm.LauncherApps;
+import android.graphics.Point;
+import android.view.MotionEvent;
+import android.view.View;
+
import androidx.annotation.NonNull;
+import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.dot.FolderDotInfo;
+import com.android.launcher3.folder.Folder;
+import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.popup.PopupDataProvider;
+import com.android.launcher3.popup.PopupLiveUpdateHandler;
import com.android.launcher3.popup.SystemShortcut;
+import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.LauncherBindableItemsContainer;
+import com.android.launcher3.util.PackageUserKey;
+import com.android.launcher3.util.ShortcutUtil;
+import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.views.ActivityContext;
+import com.android.quickstep.SystemUiProxy;
+import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Objects;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Implements interfaces required to show and allow interacting with a PopupContainerWithArrow.
*/
-public class TaskbarPopupController {
+public class TaskbarPopupController implements TaskbarControllers.LoggableTaskbarController {
- private static final SystemShortcut.Factory<TaskbarActivityContext>
+ private static final SystemShortcut.Factory<BaseTaskbarContext>
APP_INFO = SystemShortcut.AppInfo::new;
+ private final TaskbarActivityContext mContext;
private final PopupDataProvider mPopupDataProvider;
- public TaskbarPopupController() {
- // TODO (b/198438631): add notifications dots change listener
- mPopupDataProvider = new PopupDataProvider(packageUserKey -> {});
+ // Initialized in init.
+ private TaskbarControllers mControllers;
+
+ public TaskbarPopupController(TaskbarActivityContext context) {
+ mContext = context;
+ mPopupDataProvider = new PopupDataProvider(this::updateNotificationDots);
+ }
+
+ public void init(TaskbarControllers controllers) {
+ mControllers = controllers;
+
+ NotificationListener.addNotificationsChangedListener(mPopupDataProvider);
+ }
+
+ public void onDestroy() {
+ NotificationListener.removeNotificationsChangedListener(mPopupDataProvider);
}
@NonNull
@@ -55,36 +93,197 @@
mPopupDataProvider.setDeepShortcutMap(deepShortcutMapCopy);
}
+ private void updateNotificationDots(Predicate<PackageUserKey> updatedDots) {
+ final PackageUserKey packageUserKey = new PackageUserKey(null, null);
+ Predicate<ItemInfo> matcher = info -> !packageUserKey.updateFromItemInfo(info)
+ || updatedDots.test(packageUserKey);
+
+ LauncherBindableItemsContainer.ItemOperator op = (info, v) -> {
+ if (info instanceof WorkspaceItemInfo && v instanceof BubbleTextView) {
+ if (matcher.test(info)) {
+ ((BubbleTextView) v).applyDotState(info, true /* animate */);
+ }
+ } else if (info instanceof FolderInfo && v instanceof FolderIcon) {
+ FolderInfo fi = (FolderInfo) info;
+ if (fi.contents.stream().anyMatch(matcher)) {
+ FolderDotInfo folderDotInfo = new FolderDotInfo();
+ for (WorkspaceItemInfo si : fi.contents) {
+ folderDotInfo.addDotInfo(mPopupDataProvider.getDotInfoForItem(si));
+ }
+ ((FolderIcon) v).setDotInfo(folderDotInfo);
+ }
+ }
+
+ // process all the shortcuts
+ return false;
+ };
+
+ mControllers.taskbarViewController.mapOverItems(op);
+ Folder folder = Folder.getOpen(mContext);
+ if (folder != null) {
+ folder.iterateOverItems(op);
+ }
+ }
+
/**
* Shows the notifications and deep shortcuts associated with a Taskbar {@param icon}.
* @return the container if shown or null.
*/
- public PopupContainerWithArrow<TaskbarActivityContext> showForIcon(BubbleTextView icon) {
- TaskbarActivityContext context = ActivityContext.lookupContext(icon.getContext());
+ public PopupContainerWithArrow<BaseTaskbarContext> showForIcon(BubbleTextView icon) {
+ BaseTaskbarContext context = ActivityContext.lookupContext(icon.getContext());
if (PopupContainerWithArrow.getOpen(context) != null) {
// There is already an items container open, so don't open this one.
icon.clearFocus();
return null;
}
ItemInfo item = (ItemInfo) icon.getTag();
- if (!PopupContainerWithArrow.canShow(icon, item)) {
+ if (!ShortcutUtil.supportsShortcuts(item)) {
return null;
}
- final PopupContainerWithArrow<TaskbarActivityContext> container =
- (PopupContainerWithArrow) context.getLayoutInflater().inflate(
+ final PopupContainerWithArrow<BaseTaskbarContext> container =
+ (PopupContainerWithArrow<BaseTaskbarContext>) context.getLayoutInflater().inflate(
R.layout.popup_container, context.getDragLayer(), false);
+ container.addOnAttachStateChangeListener(
+ new PopupLiveUpdateHandler<BaseTaskbarContext>(context, container) {
+ @Override
+ protected void showPopupContainerForIcon(BubbleTextView originalIcon) {
+ showForIcon(originalIcon);
+ }
+ });
// TODO (b/198438631): configure for taskbar/context
+ container.setPopupItemDragHandler(new TaskbarPopupItemDragHandler());
+ mControllers.taskbarDragController.addDragListener(container);
container.populateAndShow(icon,
mPopupDataProvider.getShortcutCountForItem(item),
mPopupDataProvider.getNotificationKeysForItem(item),
// TODO (b/198438631): add support for INSTALL shortcut factory
- Stream.of(APP_INFO)
- .map(s -> s.getShortcut(context, item))
+ getSystemShortcuts()
+ .map(s -> s.getShortcut(context, item, icon))
.filter(Objects::nonNull)
.collect(Collectors.toList()));
container.requestFocus();
+
+ // Make focusable to receive back events
+ context.onPopupVisibilityChanged(true);
+ container.setOnCloseCallback(() -> {
+ context.getDragLayer().post(() -> context.onPopupVisibilityChanged(false));
+ container.setOnCloseCallback(null);
+ });
+
return container;
}
+
+ // Create a Stream of all applicable system shortcuts
+ // TODO(b/227800345): Add "Split bottom" option when tablet is in portrait mode.
+ private Stream<SystemShortcut.Factory> getSystemShortcuts() {
+ // concat a Stream of split options with a Stream of APP_INFO
+ return Stream.concat(
+ Utilities.getSplitPositionOptions(mContext.getDeviceProfile())
+ .stream()
+ .map(this::createSplitShortcutFactory),
+ Stream.of(APP_INFO)
+ );
+ }
+
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarPopupController:");
+
+ mPopupDataProvider.dump(prefix + "\t", pw);
+ }
+
+ private class TaskbarPopupItemDragHandler implements
+ PopupContainerWithArrow.PopupItemDragHandler {
+
+ protected final Point mIconLastTouchPos = new Point();
+
+ TaskbarPopupItemDragHandler() {}
+
+ @Override
+ public boolean onTouch(View view, MotionEvent ev) {
+ // Touched a shortcut, update where it was touched so we can drag from there on
+ // long click.
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_MOVE:
+ mIconLastTouchPos.set((int) ev.getX(), (int) ev.getY());
+ break;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onLongClick(View v) {
+ // Return early if not the correct view
+ if (!(v.getParent() instanceof DeepShortcutView)) return false;
+
+ DeepShortcutView sv = (DeepShortcutView) v.getParent();
+ sv.setWillDrawIcon(false);
+
+ // Move the icon to align with the center-top of the touch point
+ Point iconShift = new Point();
+ iconShift.x = mIconLastTouchPos.x - sv.getIconCenter().x;
+ iconShift.y = mIconLastTouchPos.y - mContext.getDeviceProfile().iconSizePx;
+
+ ((TaskbarDragController) ActivityContext.lookupContext(
+ v.getContext()).getDragController()).startDragOnLongClick(sv, iconShift);
+
+ return false;
+ }
+ }
+
+ /**
+ * Creates a factory function representing a single "split position" menu item ("Split left,"
+ * "Split right," or "Split top").
+ * @param position A SplitPositionOption representing whether we are splitting top, left, or
+ * right.
+ * @return A factory function to be used in populating the long-press menu.
+ */
+ private SystemShortcut.Factory<BaseTaskbarContext> createSplitShortcutFactory(
+ SplitPositionOption position) {
+ return (context, itemInfo, originalView) -> new TaskbarSplitShortcut(context, itemInfo,
+ originalView, position);
+ }
+
+ /**
+ * A single menu item ("Split left," "Split right," or "Split top") that executes a split
+ * from the taskbar, as if the user performed a drag and drop split.
+ * Includes an onClick method that initiates the actual split.
+ */
+ private static class TaskbarSplitShortcut extends SystemShortcut<BaseTaskbarContext> {
+ private final SplitPositionOption mPosition;
+
+ TaskbarSplitShortcut(BaseTaskbarContext context, ItemInfo itemInfo, View originalView,
+ SplitPositionOption position) {
+ super(position.iconResId, position.textResId, context, itemInfo, originalView);
+ mPosition = position;
+ }
+
+ @Override
+ public void onClick(View view) {
+ AbstractFloatingView.closeAllOpenViews(mTarget);
+
+ if (mItemInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+ WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) mItemInfo;
+ SystemUiProxy.INSTANCE.get(mTarget).startShortcut(
+ workspaceItemInfo.getIntent().getPackage(),
+ workspaceItemInfo.getDeepShortcutId(),
+ mPosition.stagePosition,
+ null,
+ workspaceItemInfo.user);
+ } else {
+ SystemUiProxy.INSTANCE.get(mTarget).startIntent(
+ mTarget.getSystemService(LauncherApps.class).getMainActivityLaunchIntent(
+ mItemInfo.getIntent().getComponent(),
+ null,
+ mItemInfo.user),
+ new Intent(),
+ mPosition.stagePosition,
+ null);
+ }
+ }
+ }
}
+
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
index 94a3307..1d3757f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
@@ -17,22 +17,19 @@
import android.content.Context;
import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
+import com.android.launcher3.views.ActivityContext;
+
/**
* View that handles scrimming the taskbar and the inverted corners it draws. The scrim is used
* when bubbles is expanded.
*/
public class TaskbarScrimView extends View {
- private final Paint mTaskbarScrimPaint;
- private final Path mInvertedLeftCornerPath, mInvertedRightCornerPath;
+ private final TaskbarBackgroundRenderer mRenderer;
private boolean mShowScrim;
- private float mLeftCornerRadius, mRightCornerRadius;
- private float mBackgroundHeight;
public TaskbarScrimView(Context context) {
this(context, null);
@@ -49,14 +46,9 @@
public TaskbarScrimView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
-
- mTaskbarScrimPaint = new Paint();
- mTaskbarScrimPaint.setColor(getResources().getColor(android.R.color.system_neutral1_1000));
- mTaskbarScrimPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
- mTaskbarScrimPaint.setStyle(Paint.Style.FILL);
-
- mInvertedLeftCornerPath = new Path();
- mInvertedRightCornerPath = new Path();
+ mRenderer = new TaskbarBackgroundRenderer(ActivityContext.lookupContext(context));
+ mRenderer.getPaint().setColor(getResources().getColor(
+ android.R.color.system_neutral1_1000));
}
@Override
@@ -64,31 +56,7 @@
super.onDraw(canvas);
if (mShowScrim) {
- canvas.save();
- canvas.translate(0, canvas.getHeight() - mBackgroundHeight);
-
- // Scrim the taskbar itself.
- canvas.drawRect(0, 0, canvas.getWidth(), mBackgroundHeight, mTaskbarScrimPaint);
-
- // Scrim the inverted rounded corners above the taskbar.
- canvas.translate(0, -mLeftCornerRadius);
- canvas.drawPath(mInvertedLeftCornerPath, mTaskbarScrimPaint);
- canvas.translate(0, mLeftCornerRadius);
- canvas.translate(canvas.getWidth() - mRightCornerRadius, -mRightCornerRadius);
- canvas.drawPath(mInvertedRightCornerPath, mTaskbarScrimPaint);
-
- canvas.restore();
- }
- }
-
- /**
- * Sets the height of the taskbar background.
- * @param height the height of the background.
- */
- protected void setBackgroundHeight(float height) {
- mBackgroundHeight = height;
- if (mShowScrim) {
- invalidate();
+ mRenderer.draw(canvas);
}
}
@@ -98,32 +66,7 @@
*/
protected void setScrimAlpha(float alpha) {
mShowScrim = alpha > 0f;
- mTaskbarScrimPaint.setAlpha((int) (alpha * 255));
+ mRenderer.getPaint().setAlpha((int) (alpha * 255));
invalidate();
}
-
- /**
- * Sets the radius of the left and right corners above the taskbar.
- * @param leftCornerRadius the radius of the left corner.
- * @param rightCornerRadius the radius of the right corner.
- */
- protected void setCornerSizes(float leftCornerRadius, float rightCornerRadius) {
- mLeftCornerRadius = leftCornerRadius;
- mRightCornerRadius = rightCornerRadius;
-
- Path square = new Path();
- square.addRect(0, 0, mLeftCornerRadius, mLeftCornerRadius, Path.Direction.CW);
- Path circle = new Path();
- circle.addCircle(mLeftCornerRadius, 0, mLeftCornerRadius, Path.Direction.CW);
- mInvertedLeftCornerPath.op(square, circle, Path.Op.DIFFERENCE);
- square.reset();
- square.addRect(0, 0, mRightCornerRadius, mRightCornerRadius, Path.Direction.CW);
- circle.reset();
- circle.addCircle(0, 0, mRightCornerRadius, Path.Direction.CW);
- mInvertedRightCornerPath.op(square, circle, Path.Op.DIFFERENCE);
-
- if (mShowScrim) {
- invalidate();
- }
- }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
index 4b4ee44..58ace17 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
@@ -25,10 +25,12 @@
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.SystemUiProxy;
+import java.io.PrintWriter;
+
/**
* Handles properties/data collection, and passes the results to {@link TaskbarScrimView} to render.
*/
-public class TaskbarScrimViewController {
+public class TaskbarScrimViewController implements TaskbarControllers.LoggableTaskbarController {
private static final float SCRIM_ALPHA = 0.6f;
@@ -47,9 +49,6 @@
public TaskbarScrimViewController(TaskbarActivityContext activity, TaskbarScrimView scrimView) {
mActivity = activity;
mScrimView = scrimView;
- mScrimView.setCornerSizes(mActivity.getLeftCornerRadius(),
- mActivity.getRightCornerRadius());
- mScrimView.setBackgroundHeight(mActivity.getDeviceProfile().taskbarSize);
}
/**
@@ -94,4 +93,11 @@
private void onClick() {
SystemUiProxy.INSTANCE.get(mActivity).onBackPressed();
}
+
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarScrimViewController:");
+
+ pw.println(String.format("%s\tmScrimAlpha.value=%.2f", prefix, mScrimAlpha.value));
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
index 23beef0..87b3789 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
@@ -24,4 +24,5 @@
public boolean setupUIVisible = false;
+ public boolean allAppsVisible = false;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java
new file mode 100644
index 0000000..f131595
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar;
+
+import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.DEEP_SHORTCUTS;
+import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.SHORTCUTS_AND_NOTIFICATIONS;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
+
+import android.content.Intent;
+import android.content.pm.LauncherApps;
+import android.view.KeyEvent;
+import android.view.View;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.R;
+import com.android.launcher3.accessibility.BaseAccessibilityDelegate;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.notification.NotificationListener;
+import com.android.launcher3.util.ShortcutUtil;
+import com.android.quickstep.SystemUiProxy;
+
+import java.util.List;
+
+/**
+ * Accessibility delegate for the Taskbar. This provides an accessible interface for taskbar
+ * features.
+ */
+public class TaskbarShortcutMenuAccessibilityDelegate
+ extends BaseAccessibilityDelegate<TaskbarActivityContext> {
+
+ public static final int MOVE_TO_TOP_OR_LEFT = R.id.action_move_to_top_or_left;
+ public static final int MOVE_TO_BOTTOM_OR_RIGHT = R.id.action_move_to_bottom_or_right;
+
+ private final LauncherApps mLauncherApps;
+
+ public TaskbarShortcutMenuAccessibilityDelegate(TaskbarActivityContext context) {
+ super(context);
+ mLauncherApps = context.getSystemService(LauncherApps.class);
+
+ mActions.put(DEEP_SHORTCUTS, new LauncherAction(DEEP_SHORTCUTS,
+ R.string.action_deep_shortcut, KeyEvent.KEYCODE_S));
+ mActions.put(SHORTCUTS_AND_NOTIFICATIONS, new LauncherAction(DEEP_SHORTCUTS,
+ R.string.shortcuts_menu_with_notifications_description, KeyEvent.KEYCODE_S));
+ mActions.put(MOVE_TO_TOP_OR_LEFT, new LauncherAction(
+ MOVE_TO_TOP_OR_LEFT, R.string.move_drop_target_top_or_left, KeyEvent.KEYCODE_L));
+ mActions.put(MOVE_TO_BOTTOM_OR_RIGHT, new LauncherAction(
+ MOVE_TO_BOTTOM_OR_RIGHT,
+ R.string.move_drop_target_bottom_or_right,
+ KeyEvent.KEYCODE_R));
+ }
+
+ @Override
+ protected void getSupportedActions(View host, ItemInfo item, List<LauncherAction> out) {
+ if (ShortcutUtil.supportsShortcuts(item) && FeatureFlags.ENABLE_TASKBAR_POPUP_MENU.get()) {
+ out.add(mActions.get(NotificationListener.getInstanceIfConnected() != null
+ ? SHORTCUTS_AND_NOTIFICATIONS : DEEP_SHORTCUTS));
+ }
+ out.add(mActions.get(MOVE_TO_TOP_OR_LEFT));
+ out.add(mActions.get(MOVE_TO_BOTTOM_OR_RIGHT));
+ }
+
+ @Override
+ protected boolean performAction(View host, ItemInfo item, int action, boolean fromKeyboard) {
+ if (item instanceof WorkspaceItemInfo
+ && (action == MOVE_TO_TOP_OR_LEFT || action == MOVE_TO_BOTTOM_OR_RIGHT)) {
+ WorkspaceItemInfo info = (WorkspaceItemInfo) item;
+ int side = action == MOVE_TO_TOP_OR_LEFT
+ ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT;
+
+ if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+ SystemUiProxy.INSTANCE.get(mContext).startShortcut(
+ info.getIntent().getPackage(),
+ info.getDeepShortcutId(),
+ side,
+ /* bundleOpts= */ null,
+ info.user);
+ } else {
+ SystemUiProxy.INSTANCE.get(mContext).startIntent(
+ mLauncherApps.getMainActivityLaunchIntent(
+ item.getIntent().getComponent(),
+ /* startActivityOptions= */null,
+ item.user),
+ new Intent(), side, null);
+ }
+ return true;
+ } else if (action == DEEP_SHORTCUTS || action == SHORTCUTS_AND_NOTIFICATIONS) {
+ mContext.showPopupMenuForIcon((BubbleTextView) host);
+
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected boolean beginAccessibleDrag(View item, ItemInfo info, boolean fromKeyboard) {
+ return false;
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 7f75850..fc9f9d0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -17,8 +17,10 @@
import static android.view.HapticFeedbackConstants.LONG_PRESS;
+import static com.android.launcher3.LauncherState.ALL_APPS;
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.taskbar.Utilities.appendFlag;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
@@ -27,22 +29,29 @@
import android.animation.AnimatorSet;
import android.annotation.Nullable;
import android.content.SharedPreferences;
-import android.content.res.Resources;
+import android.util.Log;
import android.view.ViewConfiguration;
+import android.view.WindowInsets;
-import com.android.launcher3.R;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.AnimatorListeners;
+import com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.SystemUiProxy;
+import com.android.systemui.shared.system.WindowManagerWrapper;
+import java.io.PrintWriter;
+import java.util.StringJoiner;
import java.util.function.IntPredicate;
/**
* Coordinates between controllers such as TaskbarViewController and StashedHandleViewController to
* create a cohesive animation between stashed/unstashed states.
*/
-public class TaskbarStashController {
+public class TaskbarStashController implements TaskbarControllers.LoggableTaskbarController {
public static final int FLAG_IN_APP = 1 << 0;
public static final int FLAG_STASHED_IN_APP_MANUAL = 1 << 1; // long press, persisted
@@ -51,23 +60,32 @@
public static final int FLAG_STASHED_IN_APP_SETUP = 1 << 4; // setup wizard and AllSetActivity
public static final int FLAG_STASHED_IN_APP_IME = 1 << 5; // IME is visible
public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 6;
+ public static final int FLAG_STASHED_IN_APP_ALL_APPS = 1 << 7; // All apps is visible.
+ public static final int FLAG_IN_SETUP = 1 << 8; // In the Setup Wizard
+
+ // If any of these flags are enabled, isInApp should return true.
+ private static final int FLAGS_IN_APP = FLAG_IN_APP | FLAG_IN_SETUP;
// If we're in an app and any of these flags are enabled, taskbar should be stashed.
private static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL
| FLAG_STASHED_IN_APP_PINNED | FLAG_STASHED_IN_APP_EMPTY | FLAG_STASHED_IN_APP_SETUP
- | FLAG_STASHED_IN_APP_IME;
+ | FLAG_STASHED_IN_APP_IME | FLAG_STASHED_IN_APP_ALL_APPS;
+
+ private static final int FLAGS_STASHED_IN_APP_IGNORING_IME =
+ FLAGS_STASHED_IN_APP & ~FLAG_STASHED_IN_APP_IME;
// If any of these flags are enabled, inset apps by our stashed height instead of our unstashed
// height. This way the reported insets are consistent even during transitions out of the app.
- // Currently any flag that causes us to stash in an app is included, except for IME since that
- // covers the underlying app anyway and thus the app shouldn't change insets.
+ // Currently any flag that causes us to stash in an app is included, except for IME or All Apps
+ // since those cover the underlying app anyway and thus the app shouldn't change insets.
private static final int FLAGS_REPORT_STASHED_INSETS_TO_APP = FLAGS_STASHED_IN_APP
- & ~FLAG_STASHED_IN_APP_IME;
+ & ~FLAG_STASHED_IN_APP_IME & ~FLAG_STASHED_IN_APP_ALL_APPS;
/**
* How long to stash/unstash when manually invoked via long press.
*/
- public static final long TASKBAR_STASH_DURATION = 300;
+ public static final long TASKBAR_STASH_DURATION =
+ WindowManagerWrapper.ANIMATION_DURATION_RESIZE;
/**
* How long to stash/unstash when keyboard is appearing/disappearing.
@@ -132,10 +150,12 @@
private boolean mIsSystemGestureInProgress;
private boolean mIsImeShowing;
+ private boolean mEnableManualStashingForTests = false;
+
// Evaluate whether the handle should be stashed
private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder(
flags -> {
- boolean inApp = hasAnyFlag(flags, FLAG_IN_APP);
+ boolean inApp = hasAnyFlag(flags, FLAGS_IN_APP);
boolean stashedInApp = hasAnyFlag(flags, FLAGS_STASHED_IN_APP);
boolean stashedLauncherState = hasAnyFlag(flags, FLAG_IN_STASHED_LAUNCHER_STATE);
return (inApp && stashedInApp) || (!inApp && stashedLauncherState);
@@ -144,13 +164,12 @@
public TaskbarStashController(TaskbarActivityContext activity) {
mActivity = activity;
mPrefs = Utilities.getPrefs(mActivity);
- final Resources resources = mActivity.getResources();
- mStashedHeight = resources.getDimensionPixelSize(R.dimen.taskbar_stashed_size);
mSystemUiProxy = SystemUiProxy.INSTANCE.get(activity);
mUnstashedHeight = mActivity.getDeviceProfile().taskbarSize;
+ mStashedHeight = mActivity.getDeviceProfile().stashedTaskbarSize;
}
- public void init(TaskbarControllers controllers, TaskbarSharedState sharedState) {
+ public void init(TaskbarControllers controllers, boolean setupUIVisible) {
mControllers = controllers;
TaskbarDragLayerController dragLayerController = controllers.taskbarDragLayerController;
@@ -171,14 +190,10 @@
boolean isManuallyStashedInApp = supportsManualStashing()
&& mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF);
- boolean isInSetup = !mActivity.isUserSetupComplete() || sharedState.setupUIVisible;
+ boolean isInSetup = !mActivity.isUserSetupComplete() || setupUIVisible;
updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp);
- // TODO(b/204384193): Temporarily disable SUW specific logic
- // updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup);
- if (isInSetup) {
- // Update the in-app state to ensure isStashed() reflects right state during SUW
- updateStateForFlag(FLAG_IN_APP, true);
- }
+ updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup);
+ updateStateForFlag(FLAG_IN_SETUP, isInSetup);
applyState();
notifyStashChange(/* visible */ false, /* stashed */ isStashedInApp());
@@ -188,30 +203,34 @@
* Returns whether the taskbar can visually stash into a handle based on the current device
* state.
*/
- private boolean supportsVisualStashing() {
- return !mActivity.isThreeButtonNav();
+ public boolean supportsVisualStashing() {
+ return mControllers.uiController.supportsVisualStashing();
}
/**
* Returns whether the user can manually stash the taskbar based on the current device state.
*/
- private boolean supportsManualStashing() {
+ protected boolean supportsManualStashing() {
return supportsVisualStashing()
- && (!Utilities.IS_RUNNING_IN_TEST_HARNESS || supportsStashingForTests());
+ && (!Utilities.IS_RUNNING_IN_TEST_HARNESS || mEnableManualStashingForTests);
}
- private boolean supportsStashingForTests() {
- // TODO: enable this for tests that specifically check stash/unstash behavior.
- return false;
+ /**
+ * Enables support for manual stashing. This should only be used to add this functionality
+ * to Launcher specific tests.
+ */
+ public void enableManualStashingForTests(boolean enableManualStashing) {
+ mEnableManualStashingForTests = enableManualStashing;
}
/**
* Sets the flag indicating setup UI is visible
*/
protected void setSetupUIVisible(boolean isVisible) {
- updateStateForFlag(FLAG_STASHED_IN_APP_SETUP,
- isVisible || !mActivity.isUserSetupComplete());
- applyState();
+ boolean hideTaskbar = isVisible || !mActivity.isUserSetupComplete();
+ updateStateForFlag(FLAG_IN_SETUP, hideTaskbar);
+ updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, hideTaskbar);
+ applyState(hideTaskbar ? 0 : TASKBAR_STASH_DURATION);
}
/**
@@ -229,6 +248,13 @@
}
/**
+ * Returns whether the taskbar should be stashed in apps regardless of the IME visibility.
+ */
+ public boolean isStashedInAppIgnoringIme() {
+ return hasAnyFlag(FLAGS_STASHED_IN_APP_IGNORING_IME);
+ }
+
+ /**
* Returns whether the taskbar should be stashed in the current LauncherState.
*/
public boolean isInStashedLauncherState() {
@@ -248,21 +274,50 @@
* Returns whether the taskbar is currently visible and in an app.
*/
public boolean isInAppAndNotStashed() {
- return !mIsStashed && (mState & FLAG_IN_APP) != 0;
+ return !mIsStashed && isInApp();
+ }
+
+ public boolean isInApp() {
+ return hasAnyFlag(FLAGS_IN_APP);
}
/**
* Returns the height that taskbar will inset when inside apps.
+ * @see WindowInsets.Type#navigationBars()
+ * @see WindowInsets.Type#systemBars()
*/
public int getContentHeightToReportToApps() {
- if (hasAnyFlag(FLAGS_REPORT_STASHED_INSETS_TO_APP)) {
+ if (supportsVisualStashing() && hasAnyFlag(FLAGS_REPORT_STASHED_INSETS_TO_APP)) {
+ DeviceProfile dp = mActivity.getDeviceProfile();
+ if (hasAnyFlag(FLAG_STASHED_IN_APP_SETUP) && dp.isTaskbarPresent && !dp.isLandscape) {
+ // We always show the back button in SUW but in portrait the SUW layout may not
+ // be wide enough to support overlapping the nav bar with its content. For now,
+ // just inset by the bar height.
+ return mUnstashedHeight;
+ }
boolean isAnimating = mAnimator != null && mAnimator.isStarted();
- return mControllers.stashedHandleViewController.isStashedHandleVisible() || isAnimating
- ? mStashedHeight : 0;
+ if (!mControllers.stashedHandleViewController.isStashedHandleVisible()
+ && isInApp()
+ && !isAnimating) {
+ // We are in a settled state where we're not showing the handle even though taskbar
+ // is stashed. This can happen for example when home button is disabled (see
+ // StashedHandleViewController#setIsHomeButtonDisabled()).
+ return 0;
+ }
+ return mStashedHeight;
}
return mUnstashedHeight;
}
+ /**
+ * Returns the height that taskbar will inset when inside apps.
+ * @see WindowInsets.Type#tappableElement()
+ */
+ public int getTappableHeightToReportToApps() {
+ int contentHeight = getContentHeightToReportToApps();
+ return contentHeight <= mStashedHeight ? 0 : contentHeight;
+ }
+
public int getStashedHeight() {
return mStashedHeight;
}
@@ -277,6 +332,9 @@
// taskbar, we use an OnLongClickListener on TaskbarView instead.
return false;
}
+ if (!canCurrentlyManuallyUnstash()) {
+ return false;
+ }
if (updateAndAnimateIsManuallyStashedInApp(false)) {
mControllers.taskbarActivityContext.getDragLayer().performHapticFeedback(LONG_PRESS);
return true;
@@ -285,6 +343,16 @@
}
/**
+ * Returns whether taskbar will unstash when long pressing it based on the current state. The
+ * only time this is true is if the user is in an app and the taskbar is only stashed because
+ * the user previously long pressed to manually stash (not due to other reasons like IME).
+ */
+ private boolean canCurrentlyManuallyUnstash() {
+ return (mState & (FLAG_IN_APP | FLAGS_STASHED_IN_APP))
+ == (FLAG_IN_APP | FLAG_STASHED_IN_APP_MANUAL);
+ }
+
+ /**
* Updates whether we should stash the taskbar when in apps, and animates to the changed state.
* @return Whether we started an animation to either be newly stashed or unstashed.
*/
@@ -302,12 +370,33 @@
}
/**
+ * Adds the Taskbar unstash to Hotseat animator to the animator set.
+ *
+ * This should be used to run a Taskbar unstash to Hotseat animation whose progress matches a
+ * swipe progress.
+ *
+ * @param placeholderDuration a placeholder duration to be used to ensure all full-length
+ * sub-animations are properly coordinated. This duration should not
+ * actually be used since this animation tracks a swipe progress.
+ */
+ protected void addUnstashToHotseatAnimation(AnimatorSet animation, int placeholderDuration) {
+ createAnimToIsStashed(
+ /* isStashed= */ false,
+ placeholderDuration,
+ /* startDelay= */ 0,
+ /* animateBg= */ false);
+ animation.play(mAnimator);
+ }
+
+ /**
* Create a stash animation and save to {@link #mAnimator}.
* @param isStashed whether it's a stash animation or an unstash animation
* @param duration duration of the animation
* @param startDelay how many milliseconds to delay the animation after starting it.
+ * @param animateBg whether the taskbar's background should be animated
*/
- private void createAnimToIsStashed(boolean isStashed, long duration, long startDelay) {
+ private void createAnimToIsStashed(
+ boolean isStashed, long duration, long startDelay, boolean animateBg) {
if (mAnimator != null) {
mAnimator.cancel();
}
@@ -342,10 +431,14 @@
secondHalfDurationScale = 0.5f;
final float stashTranslation = (mUnstashedHeight - mStashedHeight) / 2f;
- fullLengthAnimatorSet.playTogether(
- mTaskbarBackgroundOffset.animateToValue(1),
- mIconTranslationYForStash.animateToValue(stashTranslation)
- );
+ fullLengthAnimatorSet.play(mIconTranslationYForStash.animateToValue(stashTranslation));
+ if (animateBg) {
+ fullLengthAnimatorSet.play(mTaskbarBackgroundOffset.animateToValue(1));
+ } else {
+ fullLengthAnimatorSet.addListener(AnimatorListeners.forEndCallback(
+ () -> mTaskbarBackgroundOffset.updateValue(1)));
+ }
+
firstHalfAnimatorSet.playTogether(
mIconAlphaForStash.animateToValue(0),
mIconScaleForStash.animateToValue(STASHED_TASKBAR_SCALE)
@@ -358,10 +451,15 @@
secondHalfDurationScale = 0.75f;
fullLengthAnimatorSet.playTogether(
- mTaskbarBackgroundOffset.animateToValue(0),
mIconScaleForStash.animateToValue(1),
- mIconTranslationYForStash.animateToValue(0)
- );
+ mIconTranslationYForStash.animateToValue(0));
+ if (animateBg) {
+ fullLengthAnimatorSet.play(mTaskbarBackgroundOffset.animateToValue(0));
+ } else {
+ fullLengthAnimatorSet.addListener(AnimatorListeners.forEndCallback(
+ () -> mTaskbarBackgroundOffset.updateValue(0)));
+ }
+
firstHalfAnimatorSet.playTogether(
mTaskbarStashedHandleAlpha.animateToValue(0)
);
@@ -388,7 +486,7 @@
@Override
public void onAnimationStart(Animator animation) {
mIsStashed = isStashed;
- onIsStashed(mIsStashed);
+ onIsStashedChanged(mIsStashed);
}
@Override
@@ -425,17 +523,25 @@
// Already unstashed, no need to hint in that direction.
return;
}
+ if (!canCurrentlyManuallyUnstash()) {
+ // If any other flags are causing us to be stashed, long press won't cause us to
+ // unstash, so don't hint that it will.
+ return;
+ }
mTaskbarStashedHandleHintScale.animateToValue(
animateForward ? UNSTASHED_TASKBAR_HANDLE_HINT_SCALE : 1)
.setDuration(TASKBAR_HINT_STASH_DURATION).start();
}
- private void onIsStashed(boolean isStashed) {
- mControllers.stashedHandleViewController.onIsStashed(isStashed);
+ private void onIsStashedChanged(boolean isStashed) {
+ mControllers.runAfterInit(() -> {
+ mControllers.stashedHandleViewController.onIsStashedChanged(isStashed);
+ mControllers.taskbarInsetsController.onTaskbarWindowHeightOrInsetsChanged();
+ });
}
public void applyState() {
- applyState(TASKBAR_STASH_DURATION);
+ applyState(hasAnyFlag(FLAG_IN_SETUP) ? 0 : TASKBAR_STASH_DURATION);
}
public void applyState(long duration) {
@@ -460,14 +566,42 @@
*/
public void setSystemGestureInProgress(boolean inProgress) {
mIsSystemGestureInProgress = inProgress;
- // Only update FLAG_STASHED_IN_APP_IME when system gesture is not in progress.
- if (!mIsSystemGestureInProgress) {
+ if (mIsSystemGestureInProgress) {
+ return;
+ }
+
+ // Only update the following flags when system gesture is not in progress.
+ maybeResetStashedInAppAllApps(hasAnyFlag(FLAG_STASHED_IN_APP_IME) == mIsImeShowing);
+ if (hasAnyFlag(FLAG_STASHED_IN_APP_IME) != mIsImeShowing) {
updateStateForFlag(FLAG_STASHED_IN_APP_IME, mIsImeShowing);
applyState(TASKBAR_STASH_DURATION_FOR_IME, getTaskbarStashStartDelayForIme());
}
}
/**
+ * Reset stashed in all apps only if no system gesture is in progress.
+ * <p>
+ * Otherwise, the reset should be deferred until after the gesture is finished.
+ *
+ * @see #setSystemGestureInProgress
+ */
+ public void maybeResetStashedInAppAllApps() {
+ maybeResetStashedInAppAllApps(true);
+ }
+
+ private void maybeResetStashedInAppAllApps(boolean applyState) {
+ if (mIsSystemGestureInProgress) {
+ return;
+ }
+
+ updateStateForFlag(FLAG_STASHED_IN_APP_ALL_APPS, false);
+ if (applyState) {
+ applyState(ALL_APPS.getTransitionDuration(
+ mControllers.taskbarActivityContext, false /* isToState */));
+ }
+ }
+
+ /**
* When hiding the IME, delay the unstash animation to align with the end of the transition.
*/
private long getTaskbarStashStartDelayForIme() {
@@ -510,6 +644,10 @@
* unstashed.
*/
public void updateStateForFlag(int flag, boolean enabled) {
+ if (flag == FLAG_IN_APP && TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.TASKBAR_IN_APP_STATE, String.format(
+ "setting flag FLAG_IN_APP to: %b", enabled), new Exception());
+ }
if (enabled) {
mState |= flag;
} else {
@@ -525,8 +663,8 @@
if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP)) {
mControllers.uiController.onStashedInAppChanged();
}
- if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP | FLAG_IN_APP)) {
- notifyStashChange(/* visible */ hasAnyFlag(FLAG_IN_APP),
+ if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP | FLAGS_IN_APP)) {
+ notifyStashChange(/* visible */ hasAnyFlag(FLAGS_IN_APP),
/* stashed */ isStashedInApp());
}
if (hasAnyFlag(changedFlags, FLAG_STASHED_IN_APP_MANUAL)) {
@@ -540,9 +678,43 @@
private void notifyStashChange(boolean visible, boolean stashed) {
mSystemUiProxy.notifyTaskbarStatus(visible, stashed);
+ // If stashing taskbar is caused by IME visibility, we could just skip updating rounded
+ // corner insets since the rounded corners will be covered by IME during IME is showing and
+ // taskbar will be restored back to unstashed when IME is hidden.
+ mControllers.taskbarActivityContext.updateInsetRoundedCornerFrame(
+ visible && !isStashedInAppIgnoringIme());
mControllers.rotationButtonController.onTaskbarStateChange(visible, stashed);
}
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarStashController:");
+
+ pw.println(String.format("%s\tmStashedHeight=%dpx", prefix, mStashedHeight));
+ pw.println(String.format("%s\tmUnstashedHeight=%dpx", prefix, mUnstashedHeight));
+ pw.println(String.format("%s\tmIsStashed=%b", prefix, mIsStashed));
+ pw.println(String.format(
+ "%s\tappliedState=%s", prefix, getStateString(mStatePropertyHolder.mPrevFlags)));
+ pw.println(String.format("%s\tmState=%s", prefix, getStateString(mState)));
+ pw.println(String.format(
+ "%s\tmIsSystemGestureInProgress=%b", prefix, mIsSystemGestureInProgress));
+ pw.println(String.format("%s\tmIsImeShowing=%b", prefix, mIsImeShowing));
+ }
+
+ private static String getStateString(int flags) {
+ StringJoiner str = new StringJoiner("|");
+ appendFlag(str, flags, FLAGS_IN_APP, "FLAG_IN_APP");
+ appendFlag(str, flags, FLAG_STASHED_IN_APP_MANUAL, "FLAG_STASHED_IN_APP_MANUAL");
+ appendFlag(str, flags, FLAG_STASHED_IN_APP_PINNED, "FLAG_STASHED_IN_APP_PINNED");
+ appendFlag(str, flags, FLAG_STASHED_IN_APP_EMPTY, "FLAG_STASHED_IN_APP_EMPTY");
+ appendFlag(str, flags, FLAG_STASHED_IN_APP_SETUP, "FLAG_STASHED_IN_APP_SETUP");
+ appendFlag(str, flags, FLAG_STASHED_IN_APP_IME, "FLAG_STASHED_IN_APP_IME");
+ appendFlag(str, flags, FLAG_IN_STASHED_LAUNCHER_STATE, "FLAG_IN_STASHED_LAUNCHER_STATE");
+ appendFlag(str, flags, FLAG_STASHED_IN_APP_ALL_APPS, "FLAG_STASHED_IN_APP_ALL_APPS");
+ appendFlag(str, flags, FLAG_IN_SETUP, "FLAG_IN_SETUP");
+ return str.toString();
+ }
+
private class StatePropertyHolder {
private final IntPredicate mStashCondition;
@@ -577,10 +749,18 @@
}
boolean isStashed = mStashCondition.test(flags);
if (mIsStashed != isStashed) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.TASKBAR_IN_APP_STATE, String.format(
+ "setState: mIsStashed=%b, isStashed=%b, duration=%d, start=:%b",
+ mIsStashed,
+ isStashed,
+ duration,
+ start));
+ }
mIsStashed = isStashed;
// This sets mAnimator.
- createAnimToIsStashed(mIsStashed, duration, startDelay);
+ createAnimToIsStashed(mIsStashed, duration, startDelay, /* animateBg= */ true);
if (start) {
mAnimator.start();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index abad906..fcc34c6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -19,9 +19,10 @@
import androidx.annotation.CallSuper;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
+import java.io.PrintWriter;
import java.util.stream.Stream;
/**
@@ -48,13 +49,19 @@
return true;
}
+ public boolean supportsVisualStashing() {
+ if (mControllers == null) return false;
+ return !mControllers.taskbarActivityContext.isThreeButtonNav();
+ }
+
protected void onStashedInAppChanged() { }
public Stream<ItemInfoWithIcon> getAppIconsForEdu() {
return Stream.empty();
}
- public void onTaskbarIconLaunched(WorkspaceItemInfo item) { }
+ /** Called when an icon is launched. */
+ public void onTaskbarIconLaunched(ItemInfo item) { }
public View getRootView() {
return mControllers.taskbarActivityContext.getDragLayer();
@@ -67,4 +74,30 @@
public void setSystemGestureInProgress(boolean inProgress) {
mControllers.taskbarStashController.setSystemGestureInProgress(inProgress);
}
+
+ /**
+ * Manually closes the all apps window.
+ */
+ public void hideAllApps() {
+ mControllers.taskbarAllAppsController.hide();
+ }
+
+ /**
+ * User expands PiP to full-screen (or split-screen) mode, try to hide the Taskbar.
+ */
+ public void onExpandPip() {
+ if (mControllers != null) {
+ final TaskbarStashController stashController = mControllers.taskbarStashController;
+ stashController.updateStateForFlag(TaskbarStashController.FLAG_IN_APP, true);
+ stashController.applyState();
+ }
+ }
+
+ @CallSuper
+ protected void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(String.format(
+ "%sTaskbarUIController: using an instance of %s",
+ prefix,
+ getClass().getSimpleName()));
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java
index c785186..64a4fa7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java
@@ -15,27 +15,36 @@
*/
package com.android.launcher3.taskbar;
+import android.view.IWindowManager;
import android.view.View;
import android.view.WindowManager;
import com.android.quickstep.util.LauncherViewsMoveFromCenterTranslationApplier;
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
+import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
+import java.io.PrintWriter;
+
/**
* Controls animation of taskbar icons when unfolding foldable devices
*/
-public class TaskbarUnfoldAnimationController {
+public class TaskbarUnfoldAnimationController implements
+ TaskbarControllers.LoggableTaskbarController {
- private final ScopedUnfoldTransitionProgressProvider mUnfoldTransitionProgressProvider;
+ private final ScopedUnfoldTransitionProgressProvider mScopedUnfoldTransitionProgressProvider;
+ private final NaturalRotationUnfoldProgressProvider mNaturalUnfoldTransitionProgressProvider;
private final UnfoldMoveFromCenterAnimator mMoveFromCenterAnimator;
private final TransitionListener mTransitionListener = new TransitionListener();
private TaskbarViewController mTaskbarViewController;
- public TaskbarUnfoldAnimationController(ScopedUnfoldTransitionProgressProvider
- unfoldTransitionProgressProvider, WindowManager windowManager) {
- mUnfoldTransitionProgressProvider = unfoldTransitionProgressProvider;
+ public TaskbarUnfoldAnimationController(BaseTaskbarContext context,
+ ScopedUnfoldTransitionProgressProvider source,
+ WindowManager windowManager, IWindowManager iWindowManager) {
+ mScopedUnfoldTransitionProgressProvider = source;
+ mNaturalUnfoldTransitionProgressProvider =
+ new NaturalRotationUnfoldProgressProvider(context, iWindowManager, source);
mMoveFromCenterAnimator = new UnfoldMoveFromCenterAnimator(windowManager,
new LauncherViewsMoveFromCenterTranslationApplier());
}
@@ -45,18 +54,26 @@
* @param taskbarControllers references to all other taskbar controllers
*/
public void init(TaskbarControllers taskbarControllers) {
+ mNaturalUnfoldTransitionProgressProvider.init();
mTaskbarViewController = taskbarControllers.taskbarViewController;
mTaskbarViewController.addOneTimePreDrawListener(() ->
- mUnfoldTransitionProgressProvider.setReadyToHandleTransition(true));
- mUnfoldTransitionProgressProvider.addCallback(mTransitionListener);
+ mScopedUnfoldTransitionProgressProvider.setReadyToHandleTransition(true));
+ mNaturalUnfoldTransitionProgressProvider.addCallback(mTransitionListener);
}
/**
* Destroys the controller
*/
public void onDestroy() {
- mUnfoldTransitionProgressProvider.setReadyToHandleTransition(false);
- mUnfoldTransitionProgressProvider.removeCallback(mTransitionListener);
+ mScopedUnfoldTransitionProgressProvider.setReadyToHandleTransition(false);
+ mNaturalUnfoldTransitionProgressProvider.removeCallback(mTransitionListener);
+ mNaturalUnfoldTransitionProgressProvider.destroy();
+ mTaskbarViewController = null;
+ }
+
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarUnfoldAnimationController:");
}
private class TransitionListener implements TransitionProgressListener {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 59393d7..6f88d64 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -22,29 +22,41 @@
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.core.graphics.ColorUtils;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.icons.ThemedIconDrawable;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.util.LauncherBindableItemsContainer;
import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.AllAppsButton;
+import com.android.launcher3.views.DoubleShadowBubbleTextView;
+
+import java.util.function.Predicate;
/**
* Hosts the Taskbar content such as Hotseat and Recent Apps. Drawn on top of other apps.
*/
public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconParent, Insettable {
- private final int[] mTempOutLocation = new int[2];
+ private static final float TASKBAR_BACKGROUND_LUMINANCE = 0.30f;
+ public int mThemeIconsBackground;
+ private final int[] mTempOutLocation = new int[2];
private final Rect mIconLayoutBounds = new Rect();
private final int mIconTouchSize;
private final int mItemMarginLeftRight;
@@ -63,6 +75,9 @@
// Only non-null when the corresponding Folder is open.
private @Nullable FolderIcon mLeaveBehindFolderIcon;
+ // Only non-null when device supports having an All Apps button.
+ private @Nullable AllAppsButton mAllAppsButton;
+
public TaskbarView(@NonNull Context context) {
this(context, null);
}
@@ -93,6 +108,30 @@
// Needed to draw folder leave-behind when opening one.
setWillNotDraw(false);
+
+ mThemeIconsBackground = calculateThemeIconsBackground();
+
+ if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
+ mAllAppsButton = new AllAppsButton(context);
+ mAllAppsButton.setLayoutParams(
+ new ViewGroup.LayoutParams(mIconTouchSize, mIconTouchSize));
+ mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
+ }
+ }
+
+ private int getColorWithGivenLuminance(int color, float luminance) {
+ float[] colorHSL = new float[3];
+ ColorUtils.colorToHSL(color, colorHSL);
+ colorHSL[2] = luminance;
+ return ColorUtils.HSLToColor(colorHSL);
+ }
+
+ private int calculateThemeIconsBackground() {
+ int color = ThemedIconDrawable.getColors(mContext)[0];
+ if (Utilities.isDarkTheme(mContext)) {
+ return getColorWithGivenLuminance(color, TASKBAR_BACKGROUND_LUMINANCE);
+ }
+ return color;
}
protected void init(TaskbarViewController.TaskbarViewCallbacks callbacks) {
@@ -101,6 +140,10 @@
mIconLongClickListener = mControllerCallbacks.getIconOnLongClickListener();
setOnLongClickListener(mControllerCallbacks.getBackgroundOnLongClickListener());
+
+ if (mAllAppsButton != null) {
+ mAllAppsButton.setOnClickListener(mControllerCallbacks.getAllAppsButtonClickListener());
+ }
}
private void removeAndRecycle(View view) {
@@ -120,6 +163,10 @@
int nextViewIndex = 0;
int numViewsAnimated = 0;
+ if (mAllAppsButton != null) {
+ removeView(mAllAppsButton);
+ }
+
for (int i = 0; i < hotseatItemInfos.length; i++) {
ItemInfo hotseatItemInfo = hotseatItemInfos[i];
if (hotseatItemInfo == null) {
@@ -190,6 +237,29 @@
while (nextViewIndex < getChildCount()) {
removeAndRecycle(getChildAt(nextViewIndex));
}
+
+ if (mAllAppsButton != null) {
+ int index = Utilities.isRtl(getResources()) ? 0 : getChildCount();
+ addView(mAllAppsButton, index);
+ }
+
+ mThemeIconsBackground = calculateThemeIconsBackground();
+ setThemedIconsBackgroundColor(mThemeIconsBackground);
+ }
+
+ /**
+ * Traverse all the child views and change the background of themeIcons
+ **/
+ public void setThemedIconsBackgroundColor(int color) {
+ for (View icon : getIconViews()) {
+ if (icon instanceof DoubleShadowBubbleTextView) {
+ DoubleShadowBubbleTextView textView = ((DoubleShadowBubbleTextView) icon);
+ if (textView.getIcon() != null
+ && textView.getIcon() instanceof ThemedIconDrawable) {
+ ((ThemedIconDrawable) textView.getIcon()).changeBackgroundColor(color);
+ }
+ }
+ }
}
/**
@@ -243,8 +313,8 @@
if (!mTouchEnabled) {
return true;
}
- if (mIconLayoutBounds.contains((int) event.getX(), (int) event.getY())) {
- // Don't allow long pressing between icons.
+ if (mIconLayoutBounds.left <= event.getX() && event.getX() <= mIconLayoutBounds.right) {
+ // Don't allow long pressing between icons, or above/below them.
return true;
}
if (mControllerCallbacks.onTouchEvent(event)) {
@@ -290,6 +360,13 @@
return icons;
}
+ /**
+ * Returns the all apps button in the taskbar.
+ */
+ public View getAllAppsButtonView() {
+ return mAllAppsButton;
+ }
+
// FolderIconParent implemented methods.
@Override
@@ -330,4 +407,38 @@
// Consider the overall visibility
return getVisibility() == VISIBLE;
}
+
+ /**
+ * Maps {@code op} over all the child views.
+ */
+ public void mapOverItems(LauncherBindableItemsContainer.ItemOperator op) {
+ // map over all the shortcuts on the taskbar
+ for (int i = 0; i < getChildCount(); i++) {
+ View item = getChildAt(i);
+ if (op.evaluate((ItemInfo) item.getTag(), item)) {
+ return;
+ }
+ }
+ }
+
+ /**
+ * Finds the first icon to match one of the given matchers, from highest to lowest priority.
+ * @return The first match, or All Apps button if no match was found.
+ */
+ public View getFirstMatch(Predicate<ItemInfo>... matchers) {
+ for (Predicate<ItemInfo> matcher : matchers) {
+ for (int i = 0; i < getChildCount(); i++) {
+ View item = getChildAt(i);
+ if (!(item.getTag() instanceof ItemInfo)) {
+ // Should only happen for All Apps button.
+ continue;
+ }
+ ItemInfo info = (ItemInfo) item.getTag();
+ if (matcher.test(info)) {
+ return item;
+ }
+ }
+ }
+ return mAllAppsButton;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 445a23b..3562f5b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -18,14 +18,18 @@
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.Utilities.squaredHypot;
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.quickstep.AnimatedFloat.VALUE;
+import android.annotation.NonNull;
import android.graphics.Rect;
import android.util.FloatProperty;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewTreeObserver;
-import android.view.ViewTreeObserver.OnPreDrawListener;
+
+import androidx.core.graphics.ColorUtils;
+import androidx.core.view.OneShotPreDrawListener;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
@@ -33,15 +37,25 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.icons.ThemedIconDrawable;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.util.ItemInfoMatcher;
+import com.android.launcher3.util.LauncherBindableItemsContainer;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.quickstep.AnimatedFloat;
+import java.io.PrintWriter;
+import java.util.function.Predicate;
+
/**
* Handles properties/data collection, then passes the results to TaskbarView to render.
*/
-public class TaskbarViewController {
+public class TaskbarViewController implements TaskbarControllers.LoggableTaskbarController {
+
+ private static final String TAG = TaskbarViewController.class.getSimpleName();
+
private static final Runnable NO_OP = () -> { };
public static final int ALPHA_INDEX_HOME = 0;
@@ -60,6 +74,10 @@
private final AnimatedFloat mTaskbarIconTranslationYForStash = new AnimatedFloat(
this::updateTranslationY);
private AnimatedFloat mTaskbarNavButtonTranslationY;
+ private AnimatedFloat mTaskbarNavButtonTranslationYForInAppDisplay;
+
+ private final AnimatedFloat mThemeIconsBackground = new AnimatedFloat(
+ this::updateIconsBackground);
private final TaskbarModelCallbacks mModelCallbacks;
@@ -71,6 +89,8 @@
private AnimatorPlaybackController mIconAlignControllerLazy = null;
private Runnable mOnControllerPreCreateCallback = NO_OP;
+ private int mThemeIconsColor;
+
public TaskbarViewController(TaskbarActivityContext activity, TaskbarView taskbarView) {
mActivity = activity;
mTaskbarView = taskbarView;
@@ -83,6 +103,7 @@
mControllers = controllers;
mTaskbarView.init(new TaskbarViewCallbacks());
mTaskbarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;
+ mThemeIconsColor = ThemedIconDrawable.getColors(mTaskbarView.getContext())[0];
mTaskbarIconScaleForStash.updateValue(1f);
@@ -93,6 +114,8 @@
}
mTaskbarNavButtonTranslationY =
controllers.navbarButtonsViewController.getTaskbarNavButtonTranslationY();
+ mTaskbarNavButtonTranslationYForInAppDisplay = controllers.navbarButtonsViewController
+ .getTaskbarNavButtonTranslationYForInAppDisplay();
}
public void onDestroy() {
@@ -134,18 +157,8 @@
* drawing a frame and invoked only once
* @param listener callback that will be invoked before drawing the next frame
*/
- public void addOneTimePreDrawListener(Runnable listener) {
- mTaskbarView.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- final ViewTreeObserver viewTreeObserver = mTaskbarView.getViewTreeObserver();
- if (viewTreeObserver.isAlive()) {
- listener.run();
- viewTreeObserver.removeOnPreDrawListener(this);
- }
- return true;
- }
- });
+ public void addOneTimePreDrawListener(@NonNull Runnable listener) {
+ OneShotPreDrawListener.add(mTaskbarView, listener);
}
public Rect getIconLayoutBounds() {
@@ -156,6 +169,10 @@
return mTaskbarView.getIconViews();
}
+ public View getAllAppsButtonView() {
+ return mTaskbarView.getAllAppsButtonView();
+ }
+
public AnimatedFloat getTaskbarIconScaleForStash() {
return mTaskbarIconScaleForStash;
}
@@ -178,6 +195,15 @@
+ mTaskbarIconTranslationYForStash.value);
}
+ private void updateIconsBackground() {
+ mTaskbarView.setThemedIconsBackgroundColor(
+ ColorUtils.blendARGB(
+ mThemeIconsColor,
+ mTaskbarView.mThemeIconsBackground,
+ mThemeIconsBackground.value
+ ));
+ }
+
/**
* Sets the taskbar icon alignment relative to Launcher hotseat icons
* @param alignmentRatio [0, 1]
@@ -203,13 +229,20 @@
PendingAnimation setter = new PendingAnimation(100);
Rect hotseatPadding = launcherDp.getHotseatLayoutPadding(mActivity);
float scaleUp = ((float) launcherDp.iconSizePx) / mActivity.getDeviceProfile().iconSizePx;
- int hotseatCellSize =
- (launcherDp.availableWidthPx - hotseatPadding.left - hotseatPadding.right)
- / launcherDp.numShownHotseatIcons;
+ int borderSpacing = launcherDp.hotseatBorderSpace;
+ int hotseatCellSize = DeviceProfile.calculateCellWidth(
+ launcherDp.availableWidthPx - hotseatPadding.left - hotseatPadding.right,
+ borderSpacing,
+ launcherDp.numShownHotseatIcons);
int offsetY = launcherDp.getTaskbarOffsetY();
setter.setFloat(mTaskbarIconTranslationYForHome, VALUE, -offsetY, LINEAR);
setter.setFloat(mTaskbarNavButtonTranslationY, VALUE, -offsetY, LINEAR);
+ setter.setFloat(mTaskbarNavButtonTranslationYForInAppDisplay, VALUE, offsetY, LINEAR);
+
+ if (Utilities.isDarkTheme(mTaskbarView.getContext())) {
+ setter.addFloat(mThemeIconsBackground, VALUE, 0f, 1f, LINEAR);
+ }
int collapsedHeight = mActivity.getDefaultTaskbarWindowHeight();
int expandedHeight = Math.max(collapsedHeight,
@@ -217,16 +250,36 @@
setter.addOnFrameListener(anim -> mActivity.setTaskbarWindowHeight(
anim.getAnimatedFraction() > 0 ? expandedHeight : collapsedHeight));
- int count = mTaskbarView.getChildCount();
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < mTaskbarView.getChildCount(); i++) {
View child = mTaskbarView.getChildAt(i);
- ItemInfo info = (ItemInfo) child.getTag();
- setter.setFloat(child, SCALE_PROPERTY, scaleUp, LINEAR);
- float childCenter = (child.getLeft() + child.getRight()) / 2;
- float hotseatIconCenter = hotseatPadding.left + hotseatCellSize * info.screenId
- + hotseatCellSize / 2;
+ int positionInHotseat;
+ if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()
+ && child == mTaskbarView.getAllAppsButtonView()) {
+ // Note that there is no All Apps button in the hotseat, this position is only used
+ // as its convenient for animation purposes.
+ positionInHotseat = Utilities.isRtl(child.getResources())
+ ? -1
+ : mActivity.getDeviceProfile().numShownHotseatIcons;
+
+ if (!FeatureFlags.ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT.get()) {
+ setter.setViewAlpha(child, 0, LINEAR);
+ }
+ } else if (child.getTag() instanceof ItemInfo) {
+ positionInHotseat = ((ItemInfo) child.getTag()).screenId;
+ } else {
+ Log.w(TAG, "Unsupported view found in createIconAlignmentController, v=" + child);
+ continue;
+ }
+
+ float hotseatIconCenter = hotseatPadding.left
+ + (hotseatCellSize + borderSpacing) * positionInHotseat
+ + hotseatCellSize / 2f;
+
+ float childCenter = (child.getLeft() + child.getRight()) / 2f;
setter.setFloat(child, ICON_TRANSLATE_X, hotseatIconCenter - childCenter, LINEAR);
+
+ setter.setFloat(child, SCALE_PROPERTY, scaleUp, LINEAR);
}
AnimatorPlaybackController controller = setter.createPlaybackController();
@@ -235,14 +288,34 @@
}
public void onRotationChanged(DeviceProfile deviceProfile) {
- if (areIconsVisible()) {
+ if (mControllers.taskbarStashController.isInApp()) {
// We only translate on rotation when on home
return;
}
+ mActivity.setTaskbarWindowHeight(
+ deviceProfile.taskbarSize + deviceProfile.getTaskbarOffsetY());
mTaskbarNavButtonTranslationY.updateValue(-deviceProfile.getTaskbarOffsetY());
}
/**
+ * Maps the given operator to all the top-level children of TaskbarView.
+ */
+ public void mapOverItems(LauncherBindableItemsContainer.ItemOperator op) {
+ mTaskbarView.mapOverItems(op);
+ }
+
+ /**
+ * Returns the first icon to match the given parameter, in priority from:
+ * 1) Icons directly on Taskbar
+ * 2) FolderIcon of the Folder containing the given icon
+ * 3) All Apps button
+ */
+ public View getFirstIconMatch(Predicate<ItemInfo> matcher) {
+ Predicate<ItemInfo> folderMatcher = ItemInfoMatcher.forFolderMatch(matcher);
+ return mTaskbarView.getFirstMatch(matcher, folderMatcher);
+ }
+
+ /**
* Returns whether the given MotionEvent, *in screen coorindates*, is within any Taskbar item's
* touch bounds.
*/
@@ -250,6 +323,12 @@
return mTaskbarView.isEventOverAnyItem(ev);
}
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "TaskbarViewController:");
+ mModelCallbacks.dumpLogs(prefix + "\t", pw);
+ }
+
/**
* Callbacks for {@link TaskbarView} to interact with its controller.
*/
@@ -263,6 +342,13 @@
return mActivity.getItemOnClickListener();
}
+ public View.OnClickListener getAllAppsButtonClickListener() {
+ return v -> {
+ mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP);
+ mControllers.taskbarAllAppsController.show();
+ };
+ }
+
public View.OnLongClickListener getIconOnLongClickListener() {
return mControllers.taskbarDragController::startDragOnLongClick;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/Utilities.java b/quickstep/src/com/android/launcher3/taskbar/Utilities.java
new file mode 100644
index 0000000..fda6453
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/Utilities.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar;
+
+import java.util.StringJoiner;
+
+/**
+ * Various utilities shared amongst the Taskbar's classes.
+ */
+public final class Utilities {
+
+ private Utilities() {}
+
+ static void appendFlag(StringJoiner str, int flags, int flag, String flagName) {
+ if ((flags & flag) != 0) {
+ str.add(flagName);
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
new file mode 100644
index 0000000..51fa4d9
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar.allapps;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.WindowInsets;
+
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
+import com.android.launcher3.allapps.AllAppsGridAdapter;
+import com.android.launcher3.allapps.AlphabeticalAppsList;
+import com.android.launcher3.allapps.BaseAdapterProvider;
+import com.android.launcher3.allapps.BaseAllAppsAdapter;
+
+/** All apps container accessible from taskbar. */
+public class TaskbarAllAppsContainerView extends
+ ActivityAllAppsContainerView<TaskbarAllAppsContext> {
+
+ public TaskbarAllAppsContainerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public TaskbarAllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ setInsets(insets.getInsets(WindowInsets.Type.systemBars()).toRect());
+ return super.onApplyWindowInsets(insets);
+ }
+
+ @Override
+ protected BaseAllAppsAdapter<TaskbarAllAppsContext> createAdapter(
+ AlphabeticalAppsList<TaskbarAllAppsContext> appsList,
+ BaseAdapterProvider[] adapterProviders) {
+ return new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), appsList,
+ adapterProviders);
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java
new file mode 100644
index 0000000..e2f7522
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar.allapps;
+
+import static android.view.KeyEvent.ACTION_UP;
+import static android.view.KeyEvent.KEYCODE_BACK;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
+import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION;
+
+import android.content.Context;
+import android.graphics.Insets;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowInsets;
+
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
+import com.android.launcher3.allapps.search.DefaultSearchAdapterProvider;
+import com.android.launcher3.allapps.search.SearchAdapterProvider;
+import com.android.launcher3.dot.DotInfo;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.popup.PopupDataProvider;
+import com.android.launcher3.taskbar.BaseTaskbarContext;
+import com.android.launcher3.taskbar.TaskbarActivityContext;
+import com.android.launcher3.taskbar.TaskbarDragController;
+import com.android.launcher3.taskbar.TaskbarStashController;
+import com.android.launcher3.testing.TestLogging;
+import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.util.OnboardingPrefs;
+import com.android.launcher3.util.TouchController;
+import com.android.launcher3.views.BaseDragLayer;
+import com.android.systemui.shared.system.ViewTreeObserverWrapper;
+import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo;
+import com.android.systemui.shared.system.ViewTreeObserverWrapper.OnComputeInsetsListener;
+
+/**
+ * Window context for the taskbar all apps overlay.
+ * <p>
+ * All apps has its own window and needs a window context. Some properties are delegated to the
+ * {@link TaskbarActivityContext} such as {@link DeviceProfile} and {@link PopupDataProvider}.
+ */
+class TaskbarAllAppsContext extends BaseTaskbarContext {
+ private final TaskbarActivityContext mTaskbarContext;
+ private final OnboardingPrefs<TaskbarAllAppsContext> mOnboardingPrefs;
+
+ private final TaskbarAllAppsController mWindowController;
+ private final TaskbarAllAppsViewController mAllAppsViewController;
+ private final TaskbarDragController mDragController;
+ private final TaskbarAllAppsDragLayer mDragLayer;
+ private final TaskbarAllAppsContainerView mAppsView;
+
+ // We automatically stash taskbar when all apps is opened in gesture navigation mode.
+ private final boolean mWillTaskbarBeVisuallyStashed;
+ private final int mStashedTaskbarHeight;
+
+ TaskbarAllAppsContext(
+ TaskbarActivityContext taskbarContext,
+ TaskbarAllAppsController windowController,
+ TaskbarStashController taskbarStashController) {
+ super(taskbarContext.createWindowContext(TYPE_APPLICATION_OVERLAY, null));
+ mTaskbarContext = taskbarContext;
+ mWindowController = windowController;
+ mDragController = new TaskbarDragController(this);
+ mOnboardingPrefs = new OnboardingPrefs<>(this, Utilities.getPrefs(this));
+
+ mDragLayer = new TaskbarAllAppsDragLayer(this);
+ TaskbarAllAppsSlideInView slideInView = (TaskbarAllAppsSlideInView) mLayoutInflater.inflate(
+ R.layout.taskbar_all_apps, mDragLayer, false);
+ mAllAppsViewController = new TaskbarAllAppsViewController(
+ this,
+ slideInView,
+ windowController,
+ taskbarStashController);
+ mAppsView = slideInView.getAppsView();
+
+ mWillTaskbarBeVisuallyStashed = taskbarStashController.supportsVisualStashing();
+ mStashedTaskbarHeight = taskbarStashController.getStashedHeight();
+ }
+
+ TaskbarAllAppsViewController getAllAppsViewController() {
+ return mAllAppsViewController;
+ }
+
+ @Override
+ public DeviceProfile getDeviceProfile() {
+ return mWindowController.getDeviceProfile();
+ }
+
+ @Override
+ public TaskbarDragController getDragController() {
+ return mDragController;
+ }
+
+ @Override
+ public TaskbarAllAppsDragLayer getDragLayer() {
+ return mDragLayer;
+ }
+
+ @Override
+ public TaskbarAllAppsContainerView getAppsView() {
+ return mAppsView;
+ }
+
+ @Override
+ public OnboardingPrefs<TaskbarAllAppsContext> getOnboardingPrefs() {
+ return mOnboardingPrefs;
+ }
+
+ @Override
+ public boolean isBindingItems() {
+ return mTaskbarContext.isBindingItems();
+ }
+
+ @Override
+ public View.OnClickListener getItemOnClickListener() {
+ return mTaskbarContext.getItemOnClickListener();
+ }
+
+ @Override
+ public PopupDataProvider getPopupDataProvider() {
+ return mTaskbarContext.getPopupDataProvider();
+ }
+
+ @Override
+ public DotInfo getDotInfoForItem(ItemInfo info) {
+ return mTaskbarContext.getDotInfoForItem(info);
+ }
+
+ @Override
+ public void onDragStart() {}
+
+ @Override
+ public void onDragEnd() {
+ mWindowController.maybeCloseWindow();
+ }
+
+ @Override
+ public void onPopupVisibilityChanged(boolean isVisible) {}
+
+ @Override
+ public SearchAdapterProvider<?> createSearchAdapterProvider(
+ ActivityAllAppsContainerView<?> appsView) {
+ return new DefaultSearchAdapterProvider(this);
+ }
+
+ /** Root drag layer for this context. */
+ private static class TaskbarAllAppsDragLayer extends
+ BaseDragLayer<TaskbarAllAppsContext> implements OnComputeInsetsListener {
+
+ private TaskbarAllAppsDragLayer(Context context) {
+ super(context, null, 1);
+ setClipChildren(false);
+ recreateControllers();
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ ViewTreeObserverWrapper.addOnComputeInsetsListener(
+ getViewTreeObserver(), this);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ ViewTreeObserverWrapper.removeOnComputeInsetsListener(this);
+ }
+
+ @Override
+ public void recreateControllers() {
+ mControllers = new TouchController[]{mActivity.mDragController};
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev);
+ return super.dispatchTouchEvent(ev);
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) {
+ AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
+ if (topView != null && topView.onBackPressed()) {
+ return true;
+ }
+ }
+ return super.dispatchKeyEvent(event);
+ }
+
+ @Override
+ public void onComputeInsets(InsetsInfo inoutInfo) {
+ if (mActivity.mDragController.isSystemDragInProgress()) {
+ inoutInfo.touchableRegion.setEmpty();
+ inoutInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
+ }
+ }
+
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ return updateInsetsDueToStashing(insets);
+ }
+
+ /**
+ * 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
+ * layout according to the stashed insets rather than the unstashed insets. So this method
+ * does two things:
+ * 1) Sets navigationBars bottom inset to stashedHeight.
+ * 2) Sets tappableInsets bottom inset to 0.
+ */
+ private WindowInsets updateInsetsDueToStashing(WindowInsets oldInsets) {
+ if (!mActivity.mWillTaskbarBeVisuallyStashed) {
+ return oldInsets;
+ }
+ WindowInsets.Builder updatedInsetsBuilder = new WindowInsets.Builder(oldInsets);
+
+ Insets oldNavInsets = oldInsets.getInsets(WindowInsets.Type.navigationBars());
+ Insets newNavInsets = Insets.of(oldNavInsets.left, oldNavInsets.top, oldNavInsets.right,
+ mActivity.mStashedTaskbarHeight);
+ updatedInsetsBuilder.setInsets(WindowInsets.Type.navigationBars(), newNavInsets);
+
+ Insets oldTappableInsets = oldInsets.getInsets(WindowInsets.Type.tappableElement());
+ Insets newTappableInsets = Insets.of(oldTappableInsets.left, oldTappableInsets.top,
+ oldTappableInsets.right, 0);
+ updatedInsetsBuilder.setInsets(WindowInsets.Type.tappableElement(), newTappableInsets);
+
+ return updatedInsetsBuilder.build();
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
new file mode 100644
index 0000000..6fd98db
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar.allapps;
+
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
+import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
+import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.appprediction.PredictionRowView;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.taskbar.TaskbarActivityContext;
+import com.android.launcher3.taskbar.TaskbarControllers;
+import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.shared.system.TaskStackChangeListeners;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Handles the all apps overlay window initialization, updates, and its data.
+ * <p>
+ * All apps is in an application overlay window instead of taskbar's navigation bar panel window,
+ * because a navigation bar panel is higher than UI components that all apps should be below such as
+ * the notification tray.
+ * <p>
+ * The all apps window is created and destroyed upon opening and closing all apps, respectively.
+ * Application data may be bound while the window does not exist, so this controller will store
+ * the models for the next all apps session.
+ */
+public final class TaskbarAllAppsController {
+
+ private static final String WINDOW_TITLE = "Taskbar All Apps";
+
+ private final TaskbarActivityContext mTaskbarContext;
+ private final TaskbarAllAppsProxyView mProxyView;
+ private final LayoutParams mLayoutParams;
+
+ private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
+ @Override
+ public void onTaskStackChanged() {
+ mProxyView.close(false);
+ }
+ };
+
+ private DeviceProfile mDeviceProfile;
+ private TaskbarControllers mControllers;
+ /** Window context for all apps if it is open. */
+ private @Nullable TaskbarAllAppsContext mAllAppsContext;
+
+ // Application data models.
+ private AppInfo[] mApps;
+ private int mAppsModelFlags;
+ private List<ItemInfo> mPredictedApps;
+
+ public TaskbarAllAppsController(TaskbarActivityContext context, DeviceProfile dp) {
+ mDeviceProfile = dp;
+ mTaskbarContext = context;
+ mProxyView = new TaskbarAllAppsProxyView(mTaskbarContext);
+ mLayoutParams = createLayoutParams();
+ }
+
+ /** Initialize the controller. */
+ public void init(TaskbarControllers controllers, boolean allAppsVisible) {
+ if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
+ return;
+ }
+ mControllers = controllers;
+
+ /*
+ * Recreate All Apps if it was open in the previous Taskbar instance (e.g. the configuration
+ * changed).
+ */
+ if (allAppsVisible) {
+ show(false);
+ }
+ }
+
+ /** Updates the current {@link AppInfo} instances. */
+ public void setApps(AppInfo[] apps, int flags) {
+ if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
+ return;
+ }
+
+ mApps = apps;
+ mAppsModelFlags = flags;
+ if (mAllAppsContext != null) {
+ mAllAppsContext.getAppsView().getAppsStore().setApps(mApps, mAppsModelFlags);
+ }
+ }
+
+ /** Updates the current predictions. */
+ public void setPredictedApps(List<ItemInfo> predictedApps) {
+ if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
+ return;
+ }
+
+ mPredictedApps = predictedApps;
+ if (mAllAppsContext != null) {
+ mAllAppsContext.getAppsView().getFloatingHeaderView()
+ .findFixedRowByType(PredictionRowView.class)
+ .setPredictedApps(mPredictedApps);
+ }
+ }
+
+ /** Opens the {@link TaskbarAllAppsContainerView} in a new window. */
+ public void show() {
+ show(true);
+ }
+
+ private void show(boolean animate) {
+ if (mProxyView.isOpen()) {
+ return;
+ }
+ mProxyView.show();
+ // mControllers and getSharedState should never be null here. Do not handle null-pointer
+ // to catch invalid states.
+ mControllers.getSharedState().allAppsVisible = true;
+
+ mAllAppsContext = new TaskbarAllAppsContext(mTaskbarContext,
+ this,
+ mControllers.taskbarStashController);
+ mAllAppsContext.getDragController().init(mControllers);
+ TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
+ Optional.ofNullable(mAllAppsContext.getSystemService(WindowManager.class))
+ .ifPresent(m -> m.addView(mAllAppsContext.getDragLayer(), mLayoutParams));
+
+ mAllAppsContext.getAppsView().getAppsStore().setApps(mApps, mAppsModelFlags);
+ mAllAppsContext.getAppsView().getFloatingHeaderView()
+ .findFixedRowByType(PredictionRowView.class)
+ .setPredictedApps(mPredictedApps);
+ mAllAppsContext.getAllAppsViewController().show(animate);
+ }
+
+ /** Closes the {@link TaskbarAllAppsContainerView}. */
+ public void hide() {
+ mProxyView.close(true);
+ }
+
+ /**
+ * Removes the all apps window from the hierarchy, if all floating views are closed and there is
+ * no system drag operation in progress.
+ * <p>
+ * This method should be called after an exit animation finishes, if applicable.
+ */
+ void maybeCloseWindow() {
+ if (AbstractFloatingView.getOpenView(mAllAppsContext, TYPE_ALL) != null
+ || mAllAppsContext.getDragController().isSystemDragInProgress()) {
+ return;
+ }
+ mProxyView.close(false);
+ // mControllers and getSharedState should never be null here. Do not handle null-pointer
+ // to catch invalid states.
+ mControllers.getSharedState().allAppsVisible = false;
+ onDestroy();
+ }
+
+ /** Destroys the controller and any All Apps window if present. */
+ public void onDestroy() {
+ TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
+ Optional.ofNullable(mAllAppsContext)
+ .map(c -> c.getSystemService(WindowManager.class))
+ .ifPresent(m -> m.removeView(mAllAppsContext.getDragLayer()));
+ mAllAppsContext = null;
+ }
+
+ /** Updates {@link DeviceProfile} instance for Taskbar's All Apps window. */
+ public void updateDeviceProfile(DeviceProfile dp) {
+ mDeviceProfile = dp;
+ Optional.ofNullable(mAllAppsContext).ifPresent(c -> {
+ AbstractFloatingView.closeAllOpenViewsExcept(c, false, TYPE_REBIND_SAFE);
+ c.dispatchDeviceProfileChanged();
+ });
+ }
+
+ DeviceProfile getDeviceProfile() {
+ return mDeviceProfile;
+ }
+
+ private LayoutParams createLayoutParams() {
+ LayoutParams layoutParams = new LayoutParams(
+ TYPE_APPLICATION_OVERLAY,
+ 0,
+ PixelFormat.TRANSLUCENT);
+ layoutParams.setTitle(WINDOW_TITLE);
+ layoutParams.gravity = Gravity.BOTTOM;
+ layoutParams.packageName = mTaskbarContext.getPackageName();
+ layoutParams.setFitInsetsTypes(0); // Handled by container view.
+ layoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ layoutParams.setSystemApplicationOverlay(true);
+ return layoutParams;
+ }
+
+ /**
+ * Proxy view connecting taskbar drag layer to the all apps window.
+ * <p>
+ * The all apps view is in a separate window and has its own drag layer, but this proxy lets it
+ * behave as though its in the taskbar drag layer. For instance, when the taskbar closes all
+ * {@link AbstractFloatingView} instances, the all apps window will also close.
+ */
+ private class TaskbarAllAppsProxyView extends AbstractFloatingView {
+
+ private TaskbarAllAppsProxyView(Context context) {
+ super(context, null);
+ }
+
+ private void show() {
+ mIsOpen = true;
+ mTaskbarContext.getDragLayer().addView(this);
+ }
+
+ @Override
+ protected void handleClose(boolean animate) {
+ mTaskbarContext.getDragLayer().removeView(this);
+ Optional.ofNullable(mAllAppsContext)
+ .map(TaskbarAllAppsContext::getAllAppsViewController)
+ .ifPresent(v -> v.close(animate));
+ }
+
+ @Override
+ protected boolean isOfType(int type) {
+ return (type & TYPE_TASKBAR_ALL_APPS) != 0;
+ }
+
+ @Override
+ public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ return false;
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsFallbackSearchContainer.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsFallbackSearchContainer.java
new file mode 100644
index 0000000..53fe06d
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsFallbackSearchContainer.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar.allapps;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.ExtendedEditText;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
+import com.android.launcher3.allapps.SearchUiManager;
+
+/** Empty search container for Taskbar All Apps used as a fallback if search is not supported. */
+public class TaskbarAllAppsFallbackSearchContainer extends View implements SearchUiManager {
+ public TaskbarAllAppsFallbackSearchContainer(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public TaskbarAllAppsFallbackSearchContainer(
+ Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ public void initializeSearch(ActivityAllAppsContainerView<?> containerView) {
+ // Do nothing.
+ }
+
+ @Override
+ public void resetSearch() {
+ // Do nothing.
+ }
+
+ @Nullable
+ @Override
+ public ExtendedEditText getEditText() {
+ return null;
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
new file mode 100644
index 0000000..c4837a0
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar.allapps;
+
+import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
+import static com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE;
+
+import android.animation.PropertyValuesHolder;
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.animation.Interpolator;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Insettable;
+import com.android.launcher3.R;
+import com.android.launcher3.views.AbstractSlideInView;
+
+import java.util.Optional;
+
+/** Wrapper for taskbar all apps with slide-in behavior. */
+public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarAllAppsContext>
+ implements Insettable, DeviceProfile.OnDeviceProfileChangeListener {
+ private TaskbarAllAppsContainerView mAppsView;
+ private OnCloseListener mOnCloseBeginListener;
+ private float mShiftRange;
+
+ public TaskbarAllAppsSlideInView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public TaskbarAllAppsSlideInView(Context context, AttributeSet attrs,
+ int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ /** Opens the all apps view. */
+ void show(boolean animate) {
+ if (mIsOpen || mOpenCloseAnimator.isRunning()) {
+ return;
+ }
+ mIsOpen = true;
+ attachToContainer();
+
+ if (animate) {
+ mOpenCloseAnimator.setValues(
+ PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
+ mOpenCloseAnimator.setInterpolator(AGGRESSIVE_EASE);
+ mOpenCloseAnimator.setDuration(
+ ALL_APPS.getTransitionDuration(mActivityContext, true /* isToState */)).start();
+ } else {
+ mTranslationShift = TRANSLATION_SHIFT_OPENED;
+ }
+ }
+
+ /** The apps container inside this view. */
+ TaskbarAllAppsContainerView getAppsView() {
+ return mAppsView;
+ }
+
+ /** Callback invoked when the view is beginning to close (e.g. close animation is started). */
+ void setOnCloseBeginListener(OnCloseListener onCloseBeginListener) {
+ mOnCloseBeginListener = onCloseBeginListener;
+ }
+
+ @Override
+ protected void handleClose(boolean animate) {
+ Optional.ofNullable(mOnCloseBeginListener).ifPresent(OnCloseListener::onSlideInViewClosed);
+ handleClose(animate,
+ ALL_APPS.getTransitionDuration(mActivityContext, false /* isToState */));
+ }
+
+ @Override
+ protected Interpolator getIdleInterpolator() {
+ return EMPHASIZED_ACCELERATE;
+ }
+
+ @Override
+ protected boolean isOfType(int type) {
+ return (type & TYPE_TASKBAR_ALL_APPS) != 0;
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mAppsView = findViewById(R.id.apps_view);
+ mContent = mAppsView;
+
+ DeviceProfile dp = mActivityContext.getDeviceProfile();
+ setShiftRange(dp.allAppsShiftRange);
+
+ mActivityContext.addOnDeviceProfileChangeListener(this);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ setTranslationShift(mTranslationShift);
+ }
+
+ @Override
+ protected int getScrimColor(Context context) {
+ return context.getColor(R.color.widgets_picker_scrim);
+ }
+
+ @Override
+ public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ mNoIntercept = !mAppsView.shouldContainerScroll(ev);
+ }
+ return super.onControllerInterceptTouchEvent(ev);
+ }
+
+ @Override
+ public void setInsets(Rect insets) {
+ mAppsView.setInsets(insets);
+ }
+
+ @Override
+ public void onDeviceProfileChanged(DeviceProfile dp) {
+ setShiftRange(dp.allAppsShiftRange);
+ setTranslationShift(TRANSLATION_SHIFT_OPENED);
+ }
+
+ private void setShiftRange(float shiftRange) {
+ mShiftRange = shiftRange;
+ }
+
+ @Override
+ protected float getShiftRange() {
+ return mShiftRange;
+ }
+
+ @Override
+ protected boolean isEventOverContent(MotionEvent ev) {
+ return getPopupContainer().isEventOverView(mAppsView.getVisibleContainerView(), ev);
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
new file mode 100644
index 0000000..a39e872
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar.allapps;
+
+import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_IN_APP_ALL_APPS;
+import static com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT;
+
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.appprediction.AppsDividerView;
+import com.android.launcher3.appprediction.PredictionRowView;
+import com.android.launcher3.taskbar.TaskbarStashController;
+
+/**
+ * Handles the {@link TaskbarAllAppsContainerView} behavior and synchronizes its transitions with
+ * taskbar stashing.
+ */
+final class TaskbarAllAppsViewController {
+
+ private final TaskbarAllAppsContext mContext;
+ private final TaskbarAllAppsSlideInView mSlideInView;
+ private final TaskbarAllAppsContainerView mAppsView;
+ private final TaskbarStashController mTaskbarStashController;
+
+ TaskbarAllAppsViewController(
+ TaskbarAllAppsContext context,
+ TaskbarAllAppsSlideInView slideInView,
+ TaskbarAllAppsController windowController,
+ TaskbarStashController taskbarStashController) {
+
+ mContext = context;
+ mSlideInView = slideInView;
+ mAppsView = mSlideInView.getAppsView();
+ mTaskbarStashController = taskbarStashController;
+
+ setUpIconLongClick();
+ setUpAppDivider();
+ setUpTaskbarStashing();
+ mSlideInView.addOnCloseListener(windowController::maybeCloseWindow);
+ }
+
+ /** Starts the {@link TaskbarAllAppsSlideInView} enter transition. */
+ void show(boolean animate) {
+ mSlideInView.show(animate);
+ }
+
+ /** Closes the {@link TaskbarAllAppsSlideInView}. */
+ void close(boolean animate) {
+ 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)
+ .setShowAllAppsLabel(!mContext.getOnboardingPrefs().hasReachedMaxCount(
+ ALL_APPS_VISITED_COUNT));
+ mContext.getOnboardingPrefs().incrementEventCount(ALL_APPS_VISITED_COUNT);
+ }
+
+ private void setUpTaskbarStashing() {
+ mTaskbarStashController.updateStateForFlag(FLAG_STASHED_IN_APP_ALL_APPS, true);
+ mTaskbarStashController.applyState(
+ ALL_APPS.getTransitionDuration(mContext, true /* isToState */));
+ mSlideInView.setOnCloseBeginListener(() -> {
+ AbstractFloatingView.closeOpenContainer(
+ mContext, AbstractFloatingView.TYPE_ACTION_POPUP);
+ // Post in case view is closing due to gesture navigation. If a gesture is in progress,
+ // wait to unstash until after the gesture is finished.
+ mSlideInView.post(mTaskbarStashController::maybeResetStashedInAppAllApps);
+ });
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/unfold/NonDestroyableScopedUnfoldTransitionProgressProvider.java b/quickstep/src/com/android/launcher3/taskbar/unfold/NonDestroyableScopedUnfoldTransitionProgressProvider.java
new file mode 100644
index 0000000..f9da4e4
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/unfold/NonDestroyableScopedUnfoldTransitionProgressProvider.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar.unfold;
+
+import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
+
+/**
+ * ScopedUnfoldTransitionProgressProvider that doesn't propagate destroy method
+ */
+public class NonDestroyableScopedUnfoldTransitionProgressProvider extends
+ ScopedUnfoldTransitionProgressProvider {
+
+ @Override
+ public void destroy() {
+ // no-op
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
index aa26645..2f8e4d9 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
@@ -20,12 +20,11 @@
import android.content.Context;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
-import android.view.Display;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.quickstep.SysUINavigationMode;
-import com.android.quickstep.SysUINavigationMode.Mode;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.DisplayController.NavigationMode;
public class ApiWrapper {
@@ -37,24 +36,10 @@
}
/**
- * Returns true if the display is an internal displays
- */
- public static boolean isInternalDisplay(Display display) {
- return display.getType() == Display.TYPE_INTERNAL;
- }
-
- /**
- * Returns a unique ID representing the display
- */
- public static String getUniqueId(Display display) {
- return display.getUniqueId();
- }
-
- /**
* Returns the minimum space that should be left empty at the end of hotseat
*/
public static int getHotseatEndOffset(Context context) {
- if (SysUINavigationMode.INSTANCE.get(context).getMode() == Mode.THREE_BUTTONS) {
+ if (DisplayController.getNavigationMode(context) == NavigationMode.THREE_BUTTONS) {
Resources res = context.getResources();
/*
* 3 nav buttons +
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
index ee6e8ce..5f3a990 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
@@ -16,6 +16,7 @@
package com.android.launcher3.uioverrides;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
+import static com.android.launcher3.icons.BitmapInfo.FLAG_THEMED;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -179,7 +180,7 @@
: null;
super.applyFromWorkspaceItem(info, animate, staggerIndex);
int oldPlateColor = mPlateColor;
- int newPlateColor = ColorUtils.setAlphaComponent(mDotParams.color, 200);
+ int newPlateColor = ColorUtils.setAlphaComponent(mDotParams.appColor, 200);
if (!animate) {
mPlateColor = newPlateColor;
}
@@ -236,7 +237,7 @@
mSlotMachineIcons = new ArrayList<>(iconsToAnimate.size() + 2);
mSlotMachineIcons.add(getIcon());
iconsToAnimate.stream()
- .map(iconInfo -> iconInfo.newThemedIcon(mContext))
+ .map(iconInfo -> iconInfo.newIcon(mContext, FLAG_THEMED))
.forEach(mSlotMachineIcons::add);
if (endWithOriginalIcon) {
mSlotMachineIcons.add(getIcon());
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
index ed71562..08d147f 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
@@ -79,7 +79,7 @@
}
}
activityOptions.options.setPendingIntentLaunchFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- activityOptions.options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_EMPTY);
+ activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
options = Pair.create(options.first, activityOptions.options);
if (pendingIntent.isActivity()) {
logAppLaunch(itemInfo);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 9050ddc..4bb4343 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -68,15 +68,13 @@
import com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.TransposedQuickSwitchTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.TwoButtonNavbarTouchController;
-import com.android.launcher3.util.ItemInfoMatcher;
-import com.android.launcher3.util.OnboardingPrefs;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.launcher3.util.PendingRequestArgs;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.util.UiThreadHelper;
import com.android.launcher3.util.UiThreadHelper.AsyncCommand;
import com.android.launcher3.widget.LauncherAppWidgetHost;
-import com.android.quickstep.SysUINavigationMode;
-import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.QuickstepOnboardingPrefs;
@@ -87,6 +85,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Objects;
+import java.util.function.Predicate;
import java.util.stream.Stream;
public class QuickstepLauncher extends BaseQuickstepLauncher {
@@ -162,7 +161,7 @@
}
@Override
- protected OnboardingPrefs createOnboardingPrefs(SharedPreferences sharedPrefs) {
+ protected QuickstepOnboardingPrefs createOnboardingPrefs(SharedPreferences sharedPrefs) {
return new QuickstepOnboardingPrefs(this, sharedPrefs);
}
@@ -221,8 +220,7 @@
(getActivityFlags() & ACTIVITY_STATE_USER_WILL_BE_ACTIVE) != 0;
boolean visible = (state == NORMAL || state == OVERVIEW)
&& (willUserBeActive || isUserActive())
- && !profile.isVerticalBarLayout()
- && profile.isPhone && !profile.isLandscape;
+ && !profile.isVerticalBarLayout();
UiThreadHelper.runAsyncCommand(this, SET_SHELF_HEIGHT, visible ? 1 : 0,
profile.hotseatBarSizePx);
}
@@ -235,8 +233,10 @@
public void bindExtraContainerItems(FixedContainerItems item) {
if (item.containerId == Favorites.CONTAINER_PREDICTION) {
mAllAppsPredictions = item;
- getAppsView().getFloatingHeaderView().findFixedRowByType(PredictionRowView.class)
- .setPredictedApps(item.items);
+ PredictionRowView<?> predictionRowView =
+ getAppsView().getFloatingHeaderView().findFixedRowByType(
+ PredictionRowView.class);
+ predictionRowView.setPredictedApps(item.items);
} else if (item.containerId == Favorites.CONTAINER_HOTSEAT_PREDICTION) {
mHotseatPredictionController.setPredictedItems(item);
} else if (item.containerId == Favorites.CONTAINER_WIDGETS_PREDICTION) {
@@ -245,7 +245,7 @@
}
@Override
- public void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher) {
+ public void bindWorkspaceComponentsRemoved(Predicate<ItemInfo> matcher) {
super.bindWorkspaceComponentsRemoved(matcher);
mHotseatPredictionController.onModelItemsRemoved(matcher);
}
@@ -262,7 +262,7 @@
switch (state.ordinal) {
case HINT_STATE_ORDINAL: {
- Workspace workspace = getWorkspace();
+ Workspace<?> workspace = getWorkspace();
getStateManager().goToState(NORMAL);
if (workspace.getNextPage() != Workspace.DEFAULT_PAGE) {
workspace.post(workspace::moveToDefaultScreen);
@@ -302,7 +302,7 @@
@Override
public TouchController[] createTouchControllers() {
- Mode mode = SysUINavigationMode.getMode(this);
+ NavigationMode mode = DisplayController.getNavigationMode(this);
ArrayList<TouchController> list = new ArrayList<>();
list.add(getDragController());
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 32ce1c4..00a98c0 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -107,7 +107,6 @@
*/
private void handleSplitSelectionState(@NonNull LauncherState toState,
@Nullable PendingAnimation builder) {
- LauncherState currentState = mLauncher.getStateManager().getState();
boolean animate = builder != null;
PagedOrientationHandler orientationHandler =
((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler();
@@ -116,39 +115,27 @@
TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
mLauncher.getDeviceProfile());
- if (isSplitSelectionState(currentState, toState)) {
+ if (toState == OVERVIEW_SPLIT_SELECT) {
// Animation to "dismiss" selected taskView
- PendingAnimation splitSelectInitAnimation =
- mRecentsView.createSplitSelectInitAnimation();
+ PendingAnimation splitSelectInitAnimation = mRecentsView.createSplitSelectInitAnimation(
+ toState.getTransitionDuration(mLauncher, true /* isToState */));
// Add properties to shift remaining taskViews to get out of placeholder view
splitSelectInitAnimation.setFloat(mRecentsView, taskViewsFloat.first,
toState.getSplitSelectTranslation(mLauncher), LINEAR);
splitSelectInitAnimation.setFloat(mRecentsView, taskViewsFloat.second, 0, LINEAR);
- if (!animate && isSplitSelectionState(currentState, toState)) {
+ if (!animate) {
splitSelectInitAnimation.buildAnim().start();
- } else if (animate &&
- isSplitSelectionState(currentState, toState)) {
+ } else {
builder.add(splitSelectInitAnimation.buildAnim());
}
- }
- if (isSplitSelectionState(currentState, toState)) {
mRecentsView.applySplitPrimaryScrollOffset();
} else {
mRecentsView.resetSplitPrimaryScrollOffset();
}
}
- /**
- * @return true if {@param toState} is {@link LauncherState#OVERVIEW_SPLIT_SELECT}
- * and {@param fromState} is not {@link LauncherState#OVERVIEW_SPLIT_SELECT}
- */
- private boolean isSplitSelectionState(@NonNull LauncherState fromState,
- @NonNull LauncherState toState) {
- return fromState != OVERVIEW_SPLIT_SELECT && toState == OVERVIEW_SPLIT_SELECT;
- }
-
private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config,
LauncherState state) {
float clearAllButtonAlpha = state.areElementsVisible(mLauncher, CLEAR_ALL_BUTTON) ? 1 : 0;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
index df0ac7c..fe0bca6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
@@ -33,12 +33,12 @@
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginManagerImpl;
import com.android.systemui.shared.plugins.PluginPrefs;
+import com.android.systemui.shared.system.UncaughtExceptionPreHandlerManager;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Optional;
import java.util.Set;
public class PluginManagerWrapper {
@@ -48,6 +48,9 @@
public static final String PLUGIN_CHANGED = PluginManager.PLUGIN_CHANGED;
+ private static final UncaughtExceptionPreHandlerManager UNCAUGHT_EXCEPTION_PRE_HANDLER_MANAGER =
+ new UncaughtExceptionPreHandlerManager();
+
private final Context mContext;
private final PluginManager mPluginManager;
private final PluginEnablerImpl mPluginEnabler;
@@ -67,7 +70,7 @@
mPluginManager = new PluginManagerImpl(c, instanceManagerFactory,
Utilities.IS_DEBUG_DEVICE,
- Optional.ofNullable(Thread.getDefaultUncaughtExceptionHandler()), mPluginEnabler,
+ UNCAUGHT_EXCEPTION_PRE_HANDLER_MANAGER, mPluginEnabler,
new PluginPrefs(c), privilegedPlugins);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index 8f89d30..a74774c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -20,10 +20,10 @@
import android.content.Context;
+import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.util.Themes;
/**
@@ -31,28 +31,26 @@
*/
public class AllAppsState extends LauncherState {
- private static final int STATE_FLAGS = FLAG_WORKSPACE_INACCESSIBLE | FLAG_CLOSE_POPUPS;
+ private static final float WORKSPACE_SCALE_FACTOR = 0.97f;
- private static final PageAlphaProvider PAGE_ALPHA_PROVIDER = new PageAlphaProvider(DEACCEL_2) {
- @Override
- public float getPageAlpha(int pageIndex) {
- return 0;
- }
- };
+ private static final int STATE_FLAGS =
+ FLAG_WORKSPACE_INACCESSIBLE | FLAG_CLOSE_POPUPS | FLAG_HOTSEAT_INACCESSIBLE;
public AllAppsState(int id) {
super(id, LAUNCHER_STATE_ALLAPPS, STATE_FLAGS);
}
@Override
- public int getTransitionDuration(Context context) {
- return 320;
+ public <DEVICE_PROFILE_CONTEXT extends Context & DeviceProfileListenable>
+ int getTransitionDuration(DEVICE_PROFILE_CONTEXT context, boolean isToState) {
+ return !context.getDeviceProfile().isTablet && isToState
+ ? 600
+ : isToState ? 500 : 300;
}
@Override
public String getDescription(Launcher launcher) {
- AllAppsContainerView appsView = launcher.getAppsView();
- return appsView.getDescription();
+ return launcher.getAppsView().getDescription();
}
@Override
@@ -62,15 +60,21 @@
@Override
public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
- ScaleAndTranslation scaleAndTranslation = LauncherState.OVERVIEW
- .getWorkspaceScaleAndTranslation(launcher);
- scaleAndTranslation.scale = 1;
- return scaleAndTranslation;
+ return new ScaleAndTranslation(WORKSPACE_SCALE_FACTOR, NO_OFFSET, NO_OFFSET);
}
@Override
- public boolean isTaskbarStashed(Launcher launcher) {
- return true;
+ public ScaleAndTranslation getHotseatScaleAndTranslation(Launcher launcher) {
+ if (launcher.getDeviceProfile().isTablet) {
+ return getWorkspaceScaleAndTranslation(launcher);
+ } else {
+ ScaleAndTranslation overviewScaleAndTranslation = LauncherState.OVERVIEW
+ .getWorkspaceScaleAndTranslation(launcher);
+ return new ScaleAndTranslation(
+ WORKSPACE_SCALE_FACTOR,
+ overviewScaleAndTranslation.translationX,
+ overviewScaleAndTranslation.translationY);
+ }
}
@Override
@@ -82,12 +86,22 @@
@Override
public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
- return PAGE_ALPHA_PROVIDER;
+ PageAlphaProvider superPageAlphaProvider = super.getWorkspacePageAlphaProvider(launcher);
+ return new PageAlphaProvider(DEACCEL_2) {
+ @Override
+ public float getPageAlpha(int pageIndex) {
+ return launcher.getDeviceProfile().isTablet
+ ? superPageAlphaProvider.getPageAlpha(pageIndex)
+ : 0;
+ }
+ };
}
@Override
public int getVisibleElements(Launcher launcher) {
- return ALL_APPS_CONTENT;
+ // Don't add HOTSEAT_ICONS for non-tablets in ALL_APPS state.
+ return launcher.getDeviceProfile().isTablet ? ALL_APPS_CONTENT | HOTSEAT_ICONS
+ : ALL_APPS_CONTENT;
}
@Override
@@ -97,6 +111,8 @@
@Override
public int getWorkspaceScrimColor(Launcher launcher) {
- return Themes.getAttrColor(launcher, R.attr.allAppsScrimColor);
+ return launcher.getDeviceProfile().isTablet
+ ? launcher.getResources().getColor(R.color.widgets_picker_scrim)
+ : Themes.getAttrColor(launcher, R.attr.allAppsScrimColor);
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
index 6f084a1..0c49e5f 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
@@ -40,7 +40,7 @@
}
@Override
- public int getTransitionDuration(Context launcher) {
+ public int getTransitionDuration(Context launcher, boolean isToState) {
return 300;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 08d0a80..6427e09 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -22,12 +22,14 @@
import android.graphics.Rect;
import android.os.SystemProperties;
+import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
+import com.android.launcher3.taskbar.LauncherTaskbarUIController;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.Themes;
-import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -56,17 +58,17 @@
}
@Override
- public int getTransitionDuration(Context context) {
+ public int getTransitionDuration(Context context, boolean isToState) {
// In gesture modes, overview comes in all the way from the side, so give it more time.
- return SysUINavigationMode.INSTANCE.get(context).getMode().hasGestures ? 380 : 250;
+ return DisplayController.getNavigationMode(context).hasGestures ? 380 : 250;
}
@Override
public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
RecentsView recentsView = launcher.getOverviewPanel();
- float workspacePageWidth = launcher.getDeviceProfile().getWorkspaceWidth();
+ float workspacePageHeight = launcher.getDeviceProfile().getCellLayoutHeight();
recentsView.getTaskSize(sTempRect);
- float scale = (float) sTempRect.width() / workspacePageWidth;
+ float scale = (float) sTempRect.height() / workspacePageHeight;
float parallaxFactor = 0.5f;
return new ScaleAndTranslation(scale, 0, -getDefaultSwipeHeight(launcher) * parallaxFactor);
}
@@ -93,7 +95,13 @@
@Override
public boolean isTaskbarStashed(Launcher launcher) {
- return true;
+ if (launcher instanceof BaseQuickstepLauncher) {
+ LauncherTaskbarUIController uiController =
+ ((BaseQuickstepLauncher) launcher).getTaskbarUIController();
+
+ return uiController != null && uiController.supportsVisualStashing();
+ }
+ return super.isTaskbarStashed(launcher);
}
@Override
@@ -103,7 +111,7 @@
@Override
public boolean displayOverviewTasksAsGrid(DeviceProfile deviceProfile) {
- return deviceProfile.overviewShowAsGrid;
+ return deviceProfile.isTablet;
}
@Override
@@ -123,9 +131,14 @@
@Override
public void onBackPressed(Launcher launcher) {
- TaskView taskView = launcher.<RecentsView>getOverviewPanel().getRunningTaskView();
+ RecentsView recentsView = launcher.getOverviewPanel();
+ TaskView taskView = recentsView.getRunningTaskView();
if (taskView != null) {
- taskView.launchTaskAnimated();
+ if (recentsView.isTaskViewFullyVisible(taskView)) {
+ taskView.launchTasks();
+ } else {
+ recentsView.snapToPage(recentsView.indexOfChild(taskView));
+ }
} else {
super.onBackPressed(launcher);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index 75cf5cb..2d7fe69 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -22,7 +22,7 @@
import static com.android.launcher3.LauncherState.HINT_STATE_TWO_BUTTON;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.WorkspaceStateTransitionAnimation.getSpringScaleAnimator;
+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;
@@ -42,6 +42,7 @@
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
@@ -50,6 +51,8 @@
import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_SCRIM_OPAQUE_THRESHOLD;
import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_SCRIM_VISIBLE_THRESHOLD;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
+import static com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE;
+import static com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE;
import android.animation.ValueAnimator;
@@ -60,7 +63,7 @@
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.uioverrides.QuickstepLauncher;
-import com.android.quickstep.SysUINavigationMode;
+import com.android.launcher3.util.DisplayController;
import com.android.quickstep.util.RecentsAtomicAnimationFactory;
import com.android.quickstep.views.RecentsView;
@@ -97,7 +100,7 @@
config.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
- if (SysUINavigationMode.getMode(mActivity).hasGestures
+ if (DisplayController.getNavigationMode(mActivity).hasGestures
&& overview.getTaskViewCount() > 0) {
// Overview is going offscreen, so keep it at its current scale and opacity.
config.setInterpolator(ANIM_OVERVIEW_SCALE, FINAL_FRAME);
@@ -118,7 +121,7 @@
config.duration = Math.max(config.duration, scrollDuration);
overview.snapToPage(DEFAULT_PAGE, Math.toIntExact(config.duration));
- Workspace workspace = mActivity.getWorkspace();
+ Workspace<?> workspace = mActivity.getWorkspace();
// Start from a higher workspace scale, but only if we're invisible so we don't jump.
boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE;
if (isWorkspaceVisible) {
@@ -139,7 +142,7 @@
}
} else if ((fromState == NORMAL || fromState == HINT_STATE
|| fromState == HINT_STATE_TWO_BUTTON) && toState == OVERVIEW) {
- if (SysUINavigationMode.getMode(mActivity).hasGestures) {
+ if (DisplayController.getNavigationMode(mActivity).hasGestures) {
config.setInterpolator(ANIM_WORKSPACE_SCALE,
fromState == NORMAL ? ACCEL : OVERSHOOT_1_2);
config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
@@ -172,18 +175,30 @@
} else if (fromState == HINT_STATE && toState == NORMAL) {
config.setInterpolator(ANIM_DEPTH, DEACCEL_3);
if (mHintToNormalDuration == -1) {
- ValueAnimator va = getSpringScaleAnimator(mActivity, mActivity.getWorkspace(),
+ ValueAnimator va = getWorkspaceSpringScaleAnimator(mActivity,
+ mActivity.getWorkspace(),
toState.getWorkspaceScaleAndTranslation(mActivity).scale);
mHintToNormalDuration = (int) va.getDuration();
}
config.duration = Math.max(config.duration, mHintToNormalDuration);
} else if (fromState == ALL_APPS && toState == NORMAL) {
- config.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL,
- 1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD,
- 1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD));
- config.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(DEACCEL,
+ boolean isTablet = mActivity.getDeviceProfile().isTablet;
+ config.setInterpolator(ANIM_ALL_APPS_FADE,
+ isTablet ? FINAL_FRAME : Interpolators.clampToProgress(LINEAR,
+ 1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD,
+ 1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD));
+ config.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(LINEAR,
1 - ALL_APPS_SCRIM_OPAQUE_THRESHOLD,
1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD));
+ config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED_ACCELERATE);
+ if (!isTablet) {
+ config.setInterpolator(ANIM_WORKSPACE_FADE, INSTANT);
+ }
+ } else if (fromState == NORMAL && toState == ALL_APPS) {
+ if (mActivity.getDeviceProfile().isTablet) {
+ config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED_DECELERATE);
+ }
+ // TODO(b/231682175): centralize this setup in AllAppsSwipeController
}
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index 86c42ca..34a6821 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -21,7 +21,8 @@
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.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
+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.config.FeatureFlags.ENABLE_ALL_APPS_EDU;
@@ -40,16 +41,14 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.AllAppsTransitionController;
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.config.FeatureFlags;
-import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.util.TouchController;
import com.android.quickstep.TaskUtils;
+import com.android.quickstep.TopTaskTracker;
import com.android.quickstep.util.AnimatorControllerWithResistance;
-import com.android.quickstep.util.AssistantUtilities;
import com.android.quickstep.util.OverviewToHomeAnim;
import com.android.quickstep.views.RecentsView;
@@ -112,7 +111,8 @@
return true;
}
if (FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS.get()
- && AssistantUtilities.isExcludedAssistantRunning()) {
+ && TopTaskTracker.INSTANCE.get(mLauncher).getCachedTopTask(false)
+ .isExcludedAssistant()) {
return true;
}
return false;
@@ -147,16 +147,10 @@
AbstractFloatingView.closeOpenContainer(mLauncher, AbstractFloatingView.TYPE_TASK_MENU);
} else if (mStartState == ALL_APPS) {
AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
- builder.setFloat(allAppsController, ALL_APPS_PROGRESS,
- -mPullbackDistance / allAppsController.getShiftRange(), PULLBACK_INTERPOLATOR);
-
- // Slightly fade out all apps content to further distinguish from scrolling.
- StateAnimationConfig config = new StateAnimationConfig();
- config.duration = accuracy;
- config.setInterpolator(StateAnimationConfig.ANIM_ALL_APPS_FADE, Interpolators
- .mapToProgress(PULLBACK_INTERPOLATOR, 0, 0.5f));
-
- allAppsController.setAlphas(mEndState, config, builder);
+ builder.setFloat(allAppsController, ALL_APPS_PULL_BACK_TRANSLATION,
+ -mPullbackDistance, PULLBACK_INTERPOLATOR);
+ builder.setFloat(allAppsController, ALL_APPS_PULL_BACK_ALPHA,
+ 0.5f, PULLBACK_INTERPOLATOR);
}
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mLauncher);
if (topView != null) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index ef6f53e..8faabc9 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -18,6 +18,7 @@
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;
@@ -33,11 +34,13 @@
import android.view.MotionEvent;
import android.view.ViewConfiguration;
+import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.taskbar.LauncherTaskbarUIController;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.MotionPauseDetector;
@@ -83,7 +86,7 @@
@Override
protected boolean canInterceptTouch(MotionEvent ev) {
mDidTouchStartInNavBar = (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0;
- return super.canInterceptTouch(ev);
+ return super.canInterceptTouch(ev) && !mLauncher.isInState(HINT_STATE);
}
@Override
@@ -109,6 +112,14 @@
@Override
public void onDragStart(boolean start, float startDisplacement) {
+ if (mLauncher.isInState(ALL_APPS)) {
+ LauncherTaskbarUIController controller =
+ ((BaseQuickstepLauncher) mLauncher).getTaskbarUIController();
+ if (controller != null) {
+ controller.setShouldDelayLauncherStateAnim(true);
+ }
+ }
+
super.onDragStart(start, startDisplacement);
mMotionPauseDetector.clear();
@@ -139,6 +150,12 @@
@Override
public void onDragEnd(float velocity) {
+ LauncherTaskbarUIController controller =
+ ((BaseQuickstepLauncher) mLauncher).getTaskbarUIController();
+ if (controller != null) {
+ controller.setShouldDelayLauncherStateAnim(false);
+ }
+
if (mStartedOverview) {
goToOverviewOrHomeOnDragEnd(velocity);
} else {
@@ -163,7 +180,7 @@
// Normally we compute the duration based on the velocity and distance to the given
// 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));
+ animator.setDuration(HINT_STATE.getTransitionDuration(mLauncher, true /* isToState */));
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index dadc706..53dc9dd 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -27,6 +27,7 @@
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;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEUP;
import static com.android.launcher3.logging.StatsLogManager.getLauncherAtomEvent;
@@ -41,7 +42,7 @@
import static com.android.launcher3.testing.TestProtocol.BAD_STATE;
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT;
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP;
-import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
+import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
import static com.android.quickstep.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
@@ -451,9 +452,11 @@
.withSrcState(LAUNCHER_STATE_HOME)
.withDstState(targetState.statsLogOrdinal)
.log(getLauncherAtomEvent(mStartState.statsLogOrdinal, targetState.statsLogOrdinal,
- targetState.ordinal > mStartState.ordinal
- ? LAUNCHER_UNKNOWN_SWIPEUP
- : LAUNCHER_UNKNOWN_SWIPEDOWN));
+ targetState == QUICK_SWITCH
+ ? LAUNCHER_QUICKSWITCH_RIGHT
+ : targetState.ordinal > mStartState.ordinal
+ ? LAUNCHER_UNKNOWN_SWIPEUP
+ : LAUNCHER_UNKNOWN_SWIPEDOWN));
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 59ade49..e56c90c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -21,12 +21,21 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.anim.Interpolators.ACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL;
+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_ALL_APPS_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;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
import android.view.MotionEvent;
+import android.view.animation.Interpolator;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
@@ -69,6 +78,33 @@
*/
public static final float ALL_APPS_SCRIM_OPAQUE_THRESHOLD = .5f;
+ // Custom timing for NORMAL -> ALL_APPS on phones only.
+ private static final float ALL_APPS_STATE_TRANSITION = 0.4f;
+ private static final float ALL_APPS_FULL_DEPTH_PROGRESS = 0.5f;
+
+ // Custom interpolators for NORMAL -> ALL_APPS on phones only.
+ private static final Interpolator LINEAR_EARLY =
+ Interpolators.clampToProgress(LINEAR, 0f, ALL_APPS_STATE_TRANSITION);
+ private static final Interpolator STEP_TRANSITION =
+ Interpolators.clampToProgress(FINAL_FRAME, 0f, ALL_APPS_STATE_TRANSITION);
+ // The blur to and from All Apps is set to be complete when the interpolator is at 0.5.
+ public static final Interpolator BLUR =
+ Interpolators.clampToProgress(
+ Interpolators.mapToProgress(LINEAR, 0f, ALL_APPS_FULL_DEPTH_PROGRESS),
+ 0f, ALL_APPS_STATE_TRANSITION);
+ public static final Interpolator WORKSPACE_FADE = STEP_TRANSITION;
+ public static final Interpolator WORKSPACE_SCALE = LINEAR_EARLY;
+ public static final Interpolator HOTSEAT_FADE = STEP_TRANSITION;
+ public static final Interpolator HOTSEAT_SCALE = LINEAR_EARLY;
+ public static final Interpolator HOTSEAT_TRANSLATE = STEP_TRANSITION;
+ public static final Interpolator SCRIM_FADE = LINEAR_EARLY;
+ public static final Interpolator ALL_APPS_FADE =
+ Interpolators.clampToProgress(LINEAR, ALL_APPS_STATE_TRANSITION, 1f);
+ public static final Interpolator ALL_APPS_VERTICAL_PROGRESS =
+ Interpolators.clampToProgress(
+ Interpolators.mapToProgress(LINEAR, ALL_APPS_STATE_TRANSITION, 1f),
+ ALL_APPS_STATE_TRANSITION, 1f);
+
private final PortraitOverviewStateTouchHelper mOverviewPortraitStateTouchHelper;
public PortraitStatesTouchController(Launcher l) {
@@ -126,23 +162,51 @@
private StateAnimationConfig getNormalToAllAppsAnimation() {
StateAnimationConfig builder = new StateAnimationConfig();
- builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(ACCEL,
- ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD,
- ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD));
- builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(ACCEL,
- ALL_APPS_SCRIM_VISIBLE_THRESHOLD,
- ALL_APPS_SCRIM_OPAQUE_THRESHOLD));
+ if (mLauncher.getDeviceProfile().isTablet) {
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, INSTANT);
+ builder.setInterpolator(ANIM_SCRIM_FADE,
+ Interpolators.clampToProgress(LINEAR,
+ ALL_APPS_SCRIM_VISIBLE_THRESHOLD,
+ ALL_APPS_SCRIM_OPAQUE_THRESHOLD));
+ } else {
+ // TODO(b/231682175): centralize this setup in AllAppsSwipeController.
+ builder.setInterpolator(ANIM_DEPTH, BLUR);
+ builder.setInterpolator(ANIM_WORKSPACE_FADE, WORKSPACE_FADE);
+ builder.setInterpolator(ANIM_WORKSPACE_SCALE, WORKSPACE_SCALE);
+ builder.setInterpolator(ANIM_HOTSEAT_FADE, HOTSEAT_FADE);
+ builder.setInterpolator(ANIM_HOTSEAT_SCALE, HOTSEAT_SCALE);
+ builder.setInterpolator(ANIM_HOTSEAT_TRANSLATE, HOTSEAT_TRANSLATE);
+ builder.setInterpolator(ANIM_SCRIM_FADE, SCRIM_FADE);
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, ALL_APPS_FADE);
+ builder.setInterpolator(ANIM_VERTICAL_PROGRESS, ALL_APPS_VERTICAL_PROGRESS);
+ }
return builder;
}
private StateAnimationConfig getAllAppsToNormalAnimation() {
StateAnimationConfig builder = new StateAnimationConfig();
- builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL,
- 1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD,
- 1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD));
- builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(DEACCEL,
- 1 - ALL_APPS_SCRIM_OPAQUE_THRESHOLD,
- 1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD));
+ if (mLauncher.getDeviceProfile().isTablet) {
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, FINAL_FRAME);
+ builder.setInterpolator(ANIM_SCRIM_FADE,
+ Interpolators.clampToProgress(LINEAR,
+ 1 - ALL_APPS_SCRIM_OPAQUE_THRESHOLD,
+ 1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD));
+ } else {
+ // These interpolators are the reverse of the ones used above, so swiping out of All
+ // Apps feels the same as swiping into it.
+ // TODO(b/231682175): centralize this setup in AllAppsSwipeController.
+ builder.setInterpolator(ANIM_DEPTH, Interpolators.reverse(BLUR));
+ builder.setInterpolator(ANIM_WORKSPACE_FADE, Interpolators.reverse(WORKSPACE_FADE));
+ builder.setInterpolator(ANIM_WORKSPACE_SCALE, Interpolators.reverse(WORKSPACE_SCALE));
+ builder.setInterpolator(ANIM_HOTSEAT_FADE, Interpolators.reverse(HOTSEAT_FADE));
+ builder.setInterpolator(ANIM_HOTSEAT_SCALE, Interpolators.reverse(HOTSEAT_SCALE));
+ builder.setInterpolator(ANIM_HOTSEAT_TRANSLATE,
+ Interpolators.reverse(HOTSEAT_TRANSLATE));
+ builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.reverse(SCRIM_FADE));
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.reverse(ALL_APPS_FADE));
+ builder.setInterpolator(ANIM_VERTICAL_PROGRESS,
+ Interpolators.reverse(ALL_APPS_VERTICAL_PROGRESS));
+ }
return builder;
}
@@ -221,13 +285,9 @@
* @return true if the event is over the hotseat
*/
static boolean isTouchOverHotseat(Launcher launcher, MotionEvent ev) {
- return (ev.getY() >= getHotseatTop(launcher));
- }
-
- public static int getHotseatTop(Launcher launcher) {
DeviceProfile dp = launcher.getDeviceProfile();
int hotseatHeight = dp.hotseatBarSizePx + dp.getInsets().bottom;
- return launcher.getDragLayer().getHeight() - hotseatHeight;
+ return (ev.getY() >= (launcher.getDragLayer().getHeight() - hotseatHeight));
}
@Override
@@ -258,7 +318,7 @@
@Override
protected void onReachedFinalState(LauncherState toState) {
- super.onReinitToState(toState);
+ super.onReachedFinalState(toState);
if (toState == ALL_APPS) {
InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_OPEN_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 59c2859..d1b0a9c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -46,8 +46,8 @@
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.touch.AbstractStateChangeTouchController;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
-import com.android.quickstep.SysUINavigationMode;
-import com.android.quickstep.SysUINavigationMode.Mode;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.views.RecentsView;
@@ -128,7 +128,7 @@
private void setupInterpolators(StateAnimationConfig stateAnimationConfig) {
stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_2);
stateAnimationConfig.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_2);
- if (SysUINavigationMode.getMode(mLauncher) == Mode.NO_BUTTON) {
+ 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);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index 308bca6..ca7f633 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -38,10 +38,10 @@
import com.android.launcher3.touch.BaseSwipeDetector;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.FlingBlockCheck;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
-import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.util.VibratorWrapper;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -177,7 +177,7 @@
// - It's the focused task if in grid view
// - The task is snapped
mAllowGoingDown = i == mRecentsView.getCurrentPage()
- && SysUINavigationMode.getMode(mActivity).hasGestures
+ && DisplayController.getNavigationMode(mActivity).hasGestures
&& (!mRecentsView.showAsGrid() || mTaskBeingDragged.isFocusedTask())
&& mRecentsView.isTaskInExpectedScrollPosition(i);
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 2f52c9d..76f7718 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -22,6 +22,7 @@
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.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;
@@ -32,10 +33,10 @@
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.util.DisplayController.getSingleFrameMs;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
+import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
import static com.android.quickstep.GestureState.GestureEndTarget.HOME;
import static com.android.quickstep.GestureState.GestureEndTarget.LAST_TASK;
import static com.android.quickstep.GestureState.GestureEndTarget.NEW_TASK;
@@ -66,6 +67,7 @@
import android.os.Build;
import android.os.IBinder;
import android.os.SystemClock;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnApplyWindowInsetsListener;
@@ -102,7 +104,6 @@
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.InputConsumerProxy;
import com.android.quickstep.util.InputProxyHandlerFactory;
-import com.android.quickstep.util.LauncherSplitScreenListener;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.ProtoTracer;
import com.android.quickstep.util.RecentsOrientedState;
@@ -114,6 +115,7 @@
import com.android.quickstep.util.VibratorWrapper;
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.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
@@ -149,6 +151,7 @@
// Null if the recents animation hasn't started yet or has been canceled or finished.
protected @Nullable RecentsAnimationController mRecentsAnimationController;
+ protected @Nullable RecentsAnimationController mDeferredCleanupRecentsAnimationController;
protected RecentsAnimationTargets mRecentsAnimationTargets;
protected T mActivity;
protected Q mRecentsView;
@@ -429,6 +432,9 @@
mRecentsView.switchToScreenshot(snapshots, () -> {
if (mRecentsAnimationController != null) {
mRecentsAnimationController.cleanupScreenshot();
+ } else if (mDeferredCleanupRecentsAnimationController != null) {
+ mDeferredCleanupRecentsAnimationController.cleanupScreenshot();
+ mDeferredCleanupRecentsAnimationController = null;
}
});
mRecentsView.onRecentsAnimationComplete();
@@ -564,26 +570,14 @@
}
protected void notifyGestureAnimationStartToRecents() {
- ActivityManager.RunningTaskInfo[] runningTasks;
+ Task[] runningTasks;
if (mIsSwipeForStagedSplit) {
- int[] splitTaskIds =
- LauncherSplitScreenListener.INSTANCE.getNoCreate().getRunningSplitTaskIds();
- runningTasks = new ActivityManager.RunningTaskInfo[splitTaskIds.length];
- for (int i = 0; i < splitTaskIds.length; i++) {
- int taskId = splitTaskIds[i];
- // Order matters here, we want first indexed RunningTaskInfo to be leftTop task
- for (ActivityManager.RunningTaskInfo rti : mGestureState.getRunningTasks()) {
- if (taskId == rti.taskId) {
- runningTasks[i] = rti;
- break;
- }
-
- }
- }
+ int[] splitTaskIds = TopTaskTracker.INSTANCE.get(mContext).getRunningSplitTaskIds();
+ runningTasks = mGestureState.getRunningTask().getPlaceholderTasks(splitTaskIds);
} else {
- runningTasks = new ActivityManager.RunningTaskInfo[]{mGestureState.getRunningTask()};
+ runningTasks = mGestureState.getRunningTask().getPlaceholderTasks();
}
- mRecentsView.onGestureAnimationStart(runningTasks);
+ mRecentsView.onGestureAnimationStart(runningTasks, mDeviceState.getRotationTouchHelper());
}
private void launcherFrameDrawn() {
@@ -782,7 +776,7 @@
// We will handle the sysui flags based on the centermost task view.
mRecentsAnimationController.setUseLauncherSystemBarFlags(swipeUpThresholdPassed
|| (quickswitchThresholdPassed && centermostTaskFlags != 0));
- mRecentsAnimationController.setSplitScreenMinimized(swipeUpThresholdPassed);
+ mRecentsAnimationController.setSplitScreenMinimized(mContext, swipeUpThresholdPassed);
// Provide a hint to WM the direction that we will be settling in case the animation
// needs to be canceled
mRecentsAnimationController.setWillFinishToHome(swipeUpThresholdPassed);
@@ -801,7 +795,7 @@
RecentsAnimationTargets targets) {
super.onRecentsAnimationStart(controller, targets);
ActiveGestureLog.INSTANCE.addLog("startRecentsAnimationCallback", targets.apps.length);
- mRemoteTargetHandles = mTargetGluer.assignTargetsForSplitScreen(targets);
+ mRemoteTargetHandles = mTargetGluer.assignTargetsForSplitScreen(mContext, targets);
mRecentsAnimationController = controller;
mRecentsAnimationTargets = targets;
@@ -833,12 +827,9 @@
// Notify when the animation starts
flushOnRecentsAnimationAndLauncherBound();
- // Start hiding the divider
- setDividerShown(false, false /* immediate */);
-
// Only add the callback to enable the input consumer after we actually have the controller
mStateCallback.runOnceAtState(STATE_APP_CONTROLLER_RECEIVED | STATE_GESTURE_STARTED,
- mRecentsAnimationController::enableInputConsumer);
+ this::startInterceptingTouchesForGesture);
mStateCallback.setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
mPassedOverviewThreshold = false;
@@ -848,10 +839,13 @@
public void onRecentsAnimationCanceled(HashMap<Integer, ThumbnailData> thumbnailDatas) {
ActiveGestureLog.INSTANCE.addLog("cancelRecentsAnimation");
mActivityInitListener.unregister();
+ // Cache the recents animation controller so we can defer its cleanup to after having
+ // properly cleaned up the screenshot without accidentally using it.
+ mDeferredCleanupRecentsAnimationController = mRecentsAnimationController;
mStateCallback.setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
if (mRecentsAnimationTargets != null) {
- setDividerShown(true, false /* immediate */);
+ setDividerShown(true /* shown */, false /* immediate */);
}
// Defer clearing the controller and the targets until after we've updated the state
@@ -937,7 +931,13 @@
mLogDirectionUpOrLeft = velocity.x < 0;
}
mDownPos = downPos;
- handleNormalGestureEnd(endVelocity, isFling, velocity, false /* isCancel */);
+ Runnable handleNormalGestureEndCallback = () ->
+ handleNormalGestureEnd(endVelocity, isFling, velocity, /* isCancel= */ false);
+ if (mRecentsView != null) {
+ mRecentsView.runOnPageScrollsInitialized(handleNormalGestureEndCallback);
+ } else {
+ handleNormalGestureEndCallback.run();
+ }
}
private void endRunningWindowAnim(boolean cancel) {
@@ -984,7 +984,6 @@
mStateCallback.setState(STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT);
// Notify swipe-to-home (recents animation) is finished
SystemUiProxy.INSTANCE.get(mContext).notifySwipeToHomeFinished();
- LauncherSplitScreenListener.INSTANCE.getNoCreate().notifySwipingToHome();
break;
case RECENTS:
mStateCallback.setState(STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
@@ -1001,7 +1000,7 @@
mStateCallback.setState(STATE_RESUME_LAST_TASK);
}
if (mRecentsAnimationTargets != null) {
- setDividerShown(true, true /* immediate */);
+ setDividerShown(true /* shown */, true /* immediate */);
}
break;
}
@@ -1022,8 +1021,8 @@
return false;
}
- private GestureEndTarget calculateEndTarget(PointF velocity, float endVelocity, boolean isFling,
- boolean isCancel) {
+ private GestureEndTarget calculateEndTarget(PointF velocity, float endVelocity,
+ boolean isFlingY, boolean isCancel) {
if (mGestureState.isHandlingAtomicEvent()) {
// Button mode, this is only used to go to recents
return RECENTS;
@@ -1044,11 +1043,17 @@
goingToNewTask = false;
}
final boolean reachedOverviewThreshold = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW;
- if (!isFling) {
+ final boolean isFlingX = Math.abs(velocity.x) > mContext.getResources()
+ .getDimension(R.dimen.quickstep_fling_threshold_speed);
+ if (!isFlingY) {
if (isCancel) {
endTarget = LAST_TASK;
} else if (mDeviceState.isFullyGesturalNavMode()) {
- if (mIsMotionPaused) {
+ if (goingToNewTask && isFlingX) {
+ // Flinging towards new task takes precedence over mIsMotionPaused (which only
+ // checks y-velocity).
+ endTarget = NEW_TASK;
+ } else if (mIsMotionPaused) {
endTarget = RECENTS;
} else if (goingToNewTask) {
endTarget = NEW_TASK;
@@ -1140,6 +1145,13 @@
} else if (endTarget == RECENTS) {
if (mRecentsView != null) {
int nearestPage = mRecentsView.getDestinationPage();
+ if (nearestPage == INVALID_PAGE) {
+ // Allow the snap to invalid page to catch future error cases.
+ Log.e(TAG,
+ "RecentsView destination page is invalid",
+ new IllegalStateException());
+ }
+
boolean isScrolling = false;
if (mRecentsView.getNextPage() != nearestPage) {
// We shouldn't really scroll to the next page when swiping up to recents.
@@ -1170,6 +1182,11 @@
}
private void doLogGesture(GestureEndTarget endTarget, @Nullable TaskView targetTask) {
+ if (mDp == null || !mDp.isGestureMode || mDownPos == null) {
+ // We probably never received an animation controller, skip logging.
+ return;
+ }
+
StatsLogManager.EventEnum event;
switch (endTarget) {
case HOME:
@@ -1193,15 +1210,10 @@
logger.withItemInfo(targetTask.getItemInfo());
}
- DeviceProfile dp = mDp;
- if (dp == null || mDownPos == null) {
- // We probably never received an animation controller, skip logging.
- return;
- }
- int pageIndex = endTarget == LAST_TASK
+ int pageIndex = endTarget == LAST_TASK || mRecentsView == null
? LOG_NO_OP_PAGE_INDEX
: mRecentsView.getNextPage();
- // TODO: set correct container using the pageIndex
+ logger.withRank(pageIndex);
logger.log(event);
}
@@ -1276,8 +1288,7 @@
HomeAnimationFactory homeAnimFactory =
createHomeAnimationFactory(cookies, duration, isTranslucent, appCanEnterPip,
runningTaskTarget);
- mIsSwipingPipToHome = !mIsSwipeForStagedSplit
- && homeAnimFactory.supportSwipePipToHome() && appCanEnterPip;
+ mIsSwipingPipToHome = !mIsSwipeForStagedSplit && appCanEnterPip;
final RectFSpringAnim[] windowAnim;
if (mIsSwipingPipToHome) {
mSwipePipToHomeAnimator = createWindowAnimationToPip(
@@ -1385,7 +1396,7 @@
private SwipePipToHomeAnimator createWindowAnimationToPip(HomeAnimationFactory homeAnimFactory,
RemoteAnimationTargetCompat runningTaskTarget, float startProgress) {
// Directly animate the app to PiP (picture-in-picture) mode
- final ActivityManager.RunningTaskInfo taskInfo = mGestureState.getRunningTask();
+ final ActivityManager.RunningTaskInfo taskInfo = runningTaskTarget.taskInfo;
final RecentsOrientedState orientationState = mRemoteTargetHandles[0].getTaskViewSimulator()
.getOrientationState();
final int windowRotation = calculateWindowRotation(runningTaskTarget, orientationState);
@@ -1410,7 +1421,7 @@
.setContext(mContext)
.setTaskId(runningTaskTarget.taskId)
.setComponentName(taskInfo.topActivity)
- .setLeash(runningTaskTarget.leash.getSurfaceControl())
+ .setLeash(runningTaskTarget.leash)
.setSourceRectHint(
runningTaskTarget.taskInfo.pictureInPictureParams.getSourceRectHint())
.setAppBounds(taskInfo.configuration.windowConfiguration.getBounds())
@@ -1418,6 +1429,7 @@
.setStartBounds(startRect)
.setDestinationBounds(destinationBounds)
.setCornerRadius(mRecentsView.getPipCornerRadius())
+ .setShadowRadius(mRecentsView.getPipShadowRadius())
.setAttachedView(mRecentsView);
// We would assume home and app window always in the same rotation While homeRotation
// is not ROTATION_0 (which implies the rotation is turned on in launcher settings).
@@ -1457,6 +1469,17 @@
return swipePipToHomeAnimator;
}
+ private void startInterceptingTouchesForGesture() {
+ if (mRecentsAnimationController == null) {
+ return;
+ }
+
+ mRecentsAnimationController.enableInputConsumer();
+
+ // Start hiding the divider
+ setDividerShown(false /* shown */, true /* immediate */);
+ }
+
private void computeRecentsScrollIfInvisible() {
if (mRecentsView != null && mRecentsView.getVisibility() != View.VISIBLE) {
// Views typically don't compute scroll when invisible as an optimization,
@@ -1653,7 +1676,7 @@
mActivityInterface.onTransitionCancelled(wasVisible, mGestureState.getEndTarget());
if (mRecentsAnimationTargets != null) {
- setDividerShown(true, true /* immediate */);
+ setDividerShown(true /* shown */, true /* immediate */);
}
// Leave the pending invisible flag, as it may be used by wallpaper open animation.
@@ -1760,6 +1783,7 @@
private void maybeFinishSwipeToHome() {
if (mIsSwipingPipToHome && mSwipePipToHomeAnimators[0] != null) {
SystemUiProxy.INSTANCE.get(mContext).stopSwipePipToHome(
+ mSwipePipToHomeAnimator.getTaskId(),
mSwipePipToHomeAnimator.getComponentName(),
mSwipePipToHomeAnimator.getDestinationBounds(),
mSwipePipToHomeAnimator.getContentOverlay());
@@ -1774,8 +1798,7 @@
new PictureInPictureSurfaceTransaction.Builder()
.setAlpha(0f)
.build();
- int[] taskIds =
- LauncherSplitScreenListener.INSTANCE.getNoCreate().getRunningSplitTaskIds();
+ int[] taskIds = TopTaskTracker.INSTANCE.get(mContext).getRunningSplitTaskIds();
for (int taskId : taskIds) {
mRecentsAnimationController.setFinishTaskTransaction(taskId,
tx, null /* overlay */);
@@ -1919,7 +1942,7 @@
@Override
public void onRecentsAnimationFinished(RecentsAnimationController controller) {
if (!controller.getFinishTargetIsLauncher()) {
- setDividerShown(true, false /* immediate */);
+ setDividerShown(true /* shown */, false /* immediate */);
}
mRecentsAnimationController = null;
mRecentsAnimationTargets = null;
@@ -1972,9 +1995,11 @@
* Applies the transform on the recents animation
*/
protected void applyScrollAndTransform() {
- // No need to apply any transform if there is ongoing swipe-pip-to-home animator since
- // that animator handles the leash solely.
- boolean notSwipingPipToHome = mRecentsAnimationTargets != null && !mIsSwipingPipToHome;
+ // No need to apply any transform if there is ongoing swipe-to-home animator
+ // swipe-to-pip handles the leash solely
+ // swipe-to-icon animation is handled by RectFSpringAnim anim
+ boolean notSwipingToHome = mRecentsAnimationTargets != null
+ && mGestureState.getEndTarget() != HOME;
boolean setRecentsScroll = mRecentsViewScrollLinked && mRecentsView != null;
for (RemoteTargetHandle remoteHandle : mRemoteTargetHandles) {
AnimatorControllerWithResistance playbackController =
@@ -1984,7 +2009,7 @@
getScaleProgressDueToScroll()), mDragLengthFactor);
}
- if (notSwipingPipToHome) {
+ if (notSwipingToHome) {
TaskViewSimulator taskViewSimulator = remoteHandle.getTaskViewSimulator();
if (setRecentsScroll) {
taskViewSimulator.setScroll(mRecentsView.getScrollOffset());
diff --git a/quickstep/src/com/android/quickstep/AnimatedFloat.java b/quickstep/src/com/android/quickstep/AnimatedFloat.java
index 6a7d066..6c7a885 100644
--- a/quickstep/src/com/android/quickstep/AnimatedFloat.java
+++ b/quickstep/src/com/android/quickstep/AnimatedFloat.java
@@ -98,6 +98,15 @@
}
}
+ /**
+ * Starts the animation.
+ */
+ public void startAnimation() {
+ if (mValueAnimator != null) {
+ mValueAnimator.start();
+ }
+ }
+
public void cancelAnimation() {
if (mValueAnimator != null) {
mValueAnimator.cancel();
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 1d4ed4c..2fcd286 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -21,7 +21,6 @@
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.AbsSwipeUpHandler.RECENTS_ATTACH_DURATION;
import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
-import static com.android.quickstep.SysUINavigationMode.getMode;
import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM;
import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_TRANSLATE_X_ANIM;
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET;
@@ -55,19 +54,20 @@
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.taskbar.TaskbarUIController;
import com.android.launcher3.touch.PagedOrientationHandler;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.launcher3.util.WindowBounds;
import com.android.launcher3.views.ScrimView;
-import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.SplitScreenBounds;
-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.ThumbnailData;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.HashMap;
+import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -84,6 +84,8 @@
private STATE_TYPE mTargetState;
+ @Nullable private Runnable mOnInitBackgroundStateUICallback = null;
+
protected BaseActivityInterface(boolean rotationSupportedByActivity,
STATE_TYPE overviewState, STATE_TYPE backgroundState) {
this.rotationSupportedByActivity = rotationSupportedByActivity;
@@ -167,7 +169,7 @@
public abstract boolean allowMinimizeSplitScreen();
public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) {
- return deviceState.isInDeferredGestureRegion(ev);
+ return deviceState.isInDeferredGestureRegion(ev) || deviceState.isImeRenderingNavButtons();
}
/**
@@ -192,7 +194,12 @@
activity.getStateManager().moveToRestState();
}
- public void closeOverlay() { }
+ /**
+ * Closes any overlays.
+ */
+ public void closeOverlay() {
+ Optional.ofNullable(getTaskbarController()).ifPresent(TaskbarUIController::hideAllApps);
+ }
public void switchRunningTaskViewToScreenshot(HashMap<Integer, ThumbnailData> thumbnailDatas,
Runnable runnable) {
@@ -215,32 +222,27 @@
*/
public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect) {
Resources res = context.getResources();
- if (dp.overviewShowAsGrid) {
+ float maxScale = res.getFloat(R.dimen.overview_max_scale);
+ if (dp.isTablet) {
Rect gridRect = new Rect();
- calculateGridSize(context, dp, gridRect);
+ calculateGridSize(dp, gridRect);
- PointF taskDimension = getTaskDimension(context, dp);
- float scale = gridRect.height() / taskDimension.y;
- scale = Math.min(scale, res.getFloat(R.dimen.overview_max_scale));
- int outWidth = Math.round(scale * taskDimension.x);
- int outHeight = Math.round(scale * taskDimension.y);
-
- int gravity = Gravity.CENTER;
- Gravity.apply(gravity, outWidth, outHeight, gridRect, outRect);
+ calculateTaskSizeInternal(context, dp, gridRect, maxScale, Gravity.CENTER, outRect);
} else {
int taskMargin = dp.overviewTaskMarginPx;
calculateTaskSizeInternal(context, dp,
dp.overviewTaskThumbnailTopMarginPx,
- getOverviewActionsHeight(context, dp),
+ dp.getOverviewActionsClaimedSpace(),
res.getDimensionPixelSize(R.dimen.overview_minimum_next_prev_size) + taskMargin,
+ maxScale,
+ Gravity.CENTER,
outRect);
}
}
- private void calculateTaskSizeInternal(Context context, DeviceProfile dp,
- int claimedSpaceAbove, int claimedSpaceBelow, int minimumHorizontalPadding,
+ private void calculateTaskSizeInternal(Context context, DeviceProfile dp, int claimedSpaceAbove,
+ int claimedSpaceBelow, int minimumHorizontalPadding, float maxScale, int gravity,
Rect outRect) {
- PointF taskDimension = getTaskDimension(context, dp);
Rect insets = dp.getInsets();
Rect potentialTaskRect = new Rect(0, 0, dp.widthPx, dp.heightPx);
@@ -251,13 +253,21 @@
minimumHorizontalPadding,
claimedSpaceBelow);
+ calculateTaskSizeInternal(context, dp, potentialTaskRect, maxScale, gravity, outRect);
+ }
+
+ private void calculateTaskSizeInternal(Context context, DeviceProfile dp,
+ Rect potentialTaskRect, float maxScale, int gravity, Rect outRect) {
+ PointF taskDimension = getTaskDimension(context, dp);
+
float scale = Math.min(
potentialTaskRect.width() / taskDimension.x,
potentialTaskRect.height() / taskDimension.y);
+ scale = Math.min(scale, maxScale);
int outWidth = Math.round(scale * taskDimension.x);
int outHeight = Math.round(scale * taskDimension.y);
- Gravity.apply(Gravity.CENTER, outWidth, outHeight, potentialTaskRect, outRect);
+ Gravity.apply(gravity, outWidth, outHeight, potentialTaskRect, outRect);
}
private static PointF getTaskDimension(Context context, DeviceProfile dp) {
@@ -307,10 +317,10 @@
/**
* Calculates the overview grid size for the provided device configuration.
*/
- public final void calculateGridSize(Context context, DeviceProfile dp, Rect outRect) {
+ public final void calculateGridSize(DeviceProfile dp, Rect outRect) {
Rect insets = dp.getInsets();
int topMargin = dp.overviewTaskThumbnailTopMarginPx;
- int bottomMargin = getOverviewActionsHeight(context, dp);
+ int bottomMargin = dp.getOverviewActionsClaimedSpace();
int sideMargin = dp.overviewGridSideMargin;
outRect.set(0, 0, dp.widthPx, dp.heightPx);
@@ -345,22 +355,18 @@
* Calculates the modal taskView size for the provided device configuration
*/
public final void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect) {
+ calculateTaskSize(context, dp, outRect);
+ float maxScale = context.getResources().getFloat(R.dimen.overview_modal_max_scale);
calculateTaskSizeInternal(
context, dp,
dp.overviewTaskMarginPx,
- getOverviewActionsHeight(context, dp),
- dp.overviewTaskMarginPx,
+ dp.heightPx - outRect.bottom - dp.getInsets().bottom,
+ Math.round((dp.availableWidthPx - outRect.width() * maxScale) / 2),
+ 1f /*maxScale*/,
+ Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM,
outRect);
}
- /** Gets the space that the overview actions will take, including bottom margin. */
- private int getOverviewActionsHeight(Context context, DeviceProfile dp) {
- Resources res = context.getResources();
- return OverviewActionsView.getOverviewActionsBottomMarginPx(getMode(context), dp)
- + OverviewActionsView.getOverviewActionsTopMarginPx(getMode(context), dp)
- + res.getDimensionPixelSize(R.dimen.overview_actions_height);
- }
-
/**
* Called when the gesture ends and the animation starts towards the given target. Used to add
* an optional additional animation with the same duration.
@@ -408,6 +414,21 @@
return null;
}
+ protected void runOnInitBackgroundStateUI(Runnable callback) {
+ mOnInitBackgroundStateUICallback = callback;
+ ACTIVITY_TYPE activity = getCreatedActivity();
+ if (activity != null && activity.getStateManager().getState() == mBackgroundState) {
+ onInitBackgroundStateUI();
+ }
+ }
+
+ private void onInitBackgroundStateUI() {
+ if (mOnInitBackgroundStateUICallback != null) {
+ mOnInitBackgroundStateUICallback.run();
+ mOnInitBackgroundStateUICallback = null;
+ }
+ }
+
public interface AnimationFactory {
void createActivityInterface(long transitionLength);
@@ -447,13 +468,14 @@
mStartState = mActivity.getStateManager().getState();
}
- protected ACTIVITY_TYPE initUI() {
+ protected ACTIVITY_TYPE initBackgroundStateUI() {
STATE_TYPE resetState = mStartState;
if (mStartState.shouldDisableRestore()) {
resetState = mActivity.getStateManager().getRestState();
}
mActivity.getStateManager().setRestState(resetState);
mActivity.getStateManager().goToState(mBackgroundState, false);
+ onInitBackgroundStateUI();
return mActivity;
}
@@ -480,7 +502,7 @@
// Creating the activity controller animation sometimes reapplies the launcher state
// (because we set the animation as the current state animation), so we reapply the
// attached state here as well to ensure recents is shown/hidden appropriately.
- if (SysUINavigationMode.getMode(mActivity) == Mode.NO_BUTTON) {
+ if (DisplayController.getNavigationMode(mActivity) == NavigationMode.NO_BUTTON) {
setRecentsAttachedToAppWindow(mIsAttachedToWindow, false);
}
}
diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
index ffdfa43..ba61574 100644
--- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
@@ -16,7 +16,7 @@
package com.android.quickstep;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
+import static com.android.launcher3.util.DisplayController.NavigationMode.NO_BUTTON;
import static com.android.quickstep.fallback.RecentsState.BACKGROUND_APP;
import static com.android.quickstep.fallback.RecentsState.DEFAULT;
import static com.android.quickstep.fallback.RecentsState.HOME;
@@ -33,6 +33,7 @@
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.taskbar.FallbackTaskbarUIController;
import com.android.launcher3.touch.PagedOrientationHandler;
+import com.android.launcher3.util.DisplayController;
import com.android.quickstep.GestureState.GestureEndTarget;
import com.android.quickstep.fallback.RecentsState;
import com.android.quickstep.util.ActivityInitListener;
@@ -62,8 +63,7 @@
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect,
PagedOrientationHandler orientationHandler) {
calculateTaskSize(context, dp, outRect);
- if (dp.isVerticalBarLayout()
- && SysUINavigationMode.INSTANCE.get(context).getMode() != NO_BUTTON) {
+ if (dp.isVerticalBarLayout() && DisplayController.getNavigationMode(context) != NO_BUTTON) {
return dp.isSeascape() ? outRect.left : (dp.widthPx - outRect.right);
} else {
return dp.heightPx - outRect.bottom;
@@ -89,7 +89,7 @@
boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback) {
notifyRecentsOfOrientation(deviceState.getRotationTouchHelper());
DefaultAnimationFactory factory = new DefaultAnimationFactory(callback);
- factory.initUI();
+ factory.initBackgroundStateUI();
return factory;
}
diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
index a82137e..ee5bb44 100644
--- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -21,14 +21,16 @@
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.Utilities.createHomeIntent;
+import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
-import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityOptions;
import android.content.ActivityNotFoundException;
import android.content.Context;
@@ -44,25 +46,29 @@
import android.os.Message;
import android.os.Messenger;
import android.os.ParcelUuid;
+import android.os.RemoteException;
import android.os.UserHandle;
+import android.util.Log;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.SpringAnimationBuilder;
+import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.util.DisplayController;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.fallback.RecentsState;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.util.TransformParams.BuilderProxy;
import com.android.systemui.shared.recents.model.Task.TaskKey;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
@@ -79,6 +85,8 @@
public class FallbackSwipeHandler extends
AbsSwipeUpHandler<RecentsActivity, FallbackRecentsView, RecentsState> {
+ private static final String TAG = "FallbackSwipeHandler";
+
/**
* Message used for receiving gesture nav contract information. We use a static messenger to
* avoid leaking too make binders in case the receiving launcher does not handle the contract
@@ -92,13 +100,15 @@
private final Matrix mTmpMatrix = new Matrix();
private float mMaxLauncherScale = 1;
+ private boolean mAppCanEnterPip;
+
public FallbackSwipeHandler(Context context, RecentsAnimationDeviceState deviceState,
TaskAnimationManager taskAnimationManager, GestureState gestureState, long touchTimeMs,
boolean continuingLastGesture, InputConsumerController inputConsumer) {
super(context, deviceState, taskAnimationManager, gestureState, touchTimeMs,
continuingLastGesture, inputConsumer);
- mRunningOverHome = ActivityManagerWrapper.isHomeTask(mGestureState.getRunningTask());
+ mRunningOverHome = mGestureState.getRunningTask().isHomeTask();
if (mRunningOverHome) {
runActionOnRemoteHandles(remoteTargetHandle ->
remoteTargetHandle.getTransformParams().setHomeBuilderProxy(
@@ -134,16 +144,28 @@
protected HomeAnimationFactory createHomeAnimationFactory(ArrayList<IBinder> launchCookies,
long duration, boolean isTargetTranslucent, boolean appCanEnterPip,
RemoteAnimationTargetCompat runningTaskTarget) {
+ mAppCanEnterPip = appCanEnterPip;
+ if (appCanEnterPip) {
+ return new FallbackPipToHomeAnimationFactory();
+ }
mActiveAnimationFactory = new FallbackHomeAnimationFactory(duration);
+ startHomeIntent(mActiveAnimationFactory, runningTaskTarget);
+ return mActiveAnimationFactory;
+ }
+
+ private void startHomeIntent(
+ @Nullable FallbackHomeAnimationFactory gestureContractAnimationFactory,
+ @Nullable RemoteAnimationTargetCompat runningTaskTarget) {
ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
Intent intent = new Intent(mGestureState.getHomeIntent());
- mActiveAnimationFactory.addGestureContract(intent);
+ if (gestureContractAnimationFactory != null && runningTaskTarget != null) {
+ gestureContractAnimationFactory.addGestureContract(intent, runningTaskTarget.taskInfo);
+ }
try {
mContext.startActivity(intent, options.toBundle());
} catch (NullPointerException | ActivityNotFoundException | SecurityException e) {
mContext.startActivity(createHomeIntent());
}
- return mActiveAnimationFactory;
}
@Override
@@ -159,8 +181,21 @@
@Override
protected void finishRecentsControllerToHome(Runnable callback) {
+ final Runnable recentsCallback;
+ if (mAppCanEnterPip) {
+ // Make sure Launcher is resumed after auto-enter-pip transition to actually trigger
+ // the PiP task appearing.
+ recentsCallback = () -> {
+ callback.run();
+ startHomeIntent(
+ null /* gestureContractAnimationFactory */, null /* runningTaskTarget */);
+ };
+ } else {
+ recentsCallback = callback;
+ }
+ mRecentsView.cleanupRemoteTargets();
mRecentsAnimationController.finish(
- false /* toRecents */, callback, true /* sendUserLeaveHint */);
+ mAppCanEnterPip /* toRecents */, recentsCallback, true /* sendUserLeaveHint */);
}
@Override
@@ -176,16 +211,29 @@
@Override
protected void notifyGestureAnimationStartToRecents() {
if (mRunningOverHome) {
- if (SysUINavigationMode.getMode(mContext).hasGestures) {
+ if (DisplayController.getNavigationMode(mContext).hasGestures) {
mRecentsView.onGestureAnimationStartOnHome(
- new ActivityManager.RunningTaskInfo[]{mGestureState.getRunningTask()});
+ mGestureState.getRunningTask().getPlaceholderTasks(),
+ mDeviceState.getRotationTouchHelper());
}
} else {
super.notifyGestureAnimationStartToRecents();
}
}
- private class FallbackHomeAnimationFactory extends HomeAnimationFactory {
+ private class FallbackPipToHomeAnimationFactory extends HomeAnimationFactory {
+ @NonNull
+ @Override
+ public AnimatorPlaybackController createActivityAnimationToHome() {
+ // copied from {@link LauncherSwipeHandlerV2.LauncherHomeAnimationFactory}
+ long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx);
+ return mActivity.getStateManager().createAnimationToNewWorkspace(
+ RecentsState.HOME, accuracy, StateAnimationConfig.SKIP_ALL_ANIMATIONS);
+ }
+ }
+
+ private class FallbackHomeAnimationFactory extends HomeAnimationFactory
+ implements Consumer<Message> {
private final Rect mTempRect = new Rect();
private final TransformParams mHomeAlphaParams = new TransformParams();
private final AnimatedFloat mHomeAlpha;
@@ -196,6 +244,9 @@
private final RectF mTargetRect = new RectF();
private SurfaceControl mSurfaceControl;
+ private boolean mAnimationFinished;
+ private Message mOnFinishCallback;
+
private final long mDuration;
private RectFSpringAnim mSpringAnim;
@@ -213,15 +264,13 @@
} else {
mHomeAlpha = new AnimatedFloat(this::updateHomeAlpha);
mHomeAlpha.value = 0;
- runActionOnRemoteHandles(remoteTargetHandle ->
- remoteTargetHandle.getTransformParams().setHomeBuilderProxy(
- FallbackHomeAnimationFactory.this
- ::updateHomeActivityTransformDuringHomeAnim));
+ mHomeAlphaParams.setHomeBuilderProxy(
+ this::updateHomeActivityTransformDuringHomeAnim);
}
mRecentsAlpha.value = 1;
runActionOnRemoteHandles(remoteTargetHandle ->
- remoteTargetHandle.getTransformParams().setHomeBuilderProxy(
+ remoteTargetHandle.getTransformParams().setBaseBuilderProxy(
FallbackHomeAnimationFactory.this
::updateRecentsActivityTransformDuringHomeAnim));
}
@@ -297,9 +346,26 @@
@Override
public void setAnimation(RectFSpringAnim anim) {
mSpringAnim = anim;
+ mSpringAnim.addAnimatorListener(forEndCallback(this::onRectAnimationEnd));
}
- private void onMessageReceived(Message msg) {
+ private void onRectAnimationEnd() {
+ mAnimationFinished = true;
+ maybeSendEndMessage();
+ }
+
+ private void maybeSendEndMessage() {
+ if (mAnimationFinished && mOnFinishCallback != null) {
+ try {
+ mOnFinishCallback.replyTo.send(mOnFinishCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error sending icon position", e);
+ }
+ }
+ }
+
+ @Override
+ public void accept(Message msg) {
try {
Bundle data = msg.getData();
RectF position = data.getParcelable(EXTRA_ICON_POSITION);
@@ -309,7 +375,9 @@
if (mSpringAnim != null) {
mSpringAnim.onTargetPositionChanged();
}
+ mOnFinishCallback = data.getParcelable(EXTRA_ON_FINISH_CALLBACK);
}
+ maybeSendEndMessage();
} catch (Exception e) {
// Ignore
}
@@ -329,12 +397,12 @@
}
}
- private void addGestureContract(Intent intent) {
- if (mRunningOverHome || mGestureState.getRunningTask() == null) {
+ private void addGestureContract(Intent intent, RunningTaskInfo runningTaskInfo) {
+ if (mRunningOverHome || runningTaskInfo == null) {
return;
}
- TaskKey key = new TaskKey(mGestureState.getRunningTask());
+ TaskKey key = new TaskKey(runningTaskInfo);
if (key.getComponent() != null) {
if (sMessageReceiver == null) {
sMessageReceiver = new StaticMessageReceiver();
@@ -343,8 +411,8 @@
Bundle gestureNavContract = new Bundle();
gestureNavContract.putParcelable(EXTRA_COMPONENT_NAME, key.getComponent());
gestureNavContract.putParcelable(EXTRA_USER, UserHandle.of(key.userId));
- gestureNavContract.putParcelable(EXTRA_REMOTE_CALLBACK,
- sMessageReceiver.newCallback(this::onMessageReceived));
+ gestureNavContract.putParcelable(
+ EXTRA_REMOTE_CALLBACK, sMessageReceiver.newCallback(this));
intent.putExtra(EXTRA_GESTURE_CONTRACT, gestureNavContract);
}
}
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index ed0623d..3b52e91 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -22,7 +22,6 @@
import android.annotation.Nullable;
import android.annotation.TargetApi;
-import android.app.ActivityManager;
import android.content.Intent;
import android.os.Build;
@@ -30,6 +29,7 @@
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.ActiveGestureLog;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -135,8 +135,7 @@
private final MultiStateCallback mStateCallback;
private final int mGestureId;
- private ActivityManager.RunningTaskInfo mRunningTask;
- private ActivityManager.RunningTaskInfo[] mRunningTasks;
+ private CachedTaskInfo mRunningTask;
private GestureEndTarget mEndTarget;
private RemoteAnimationTargetCompat mLastAppearedTaskTarget;
private Set<Integer> mPreviouslyAppearedTaskIds = new HashSet<>();
@@ -232,42 +231,25 @@
/**
* @return the running task for this gesture.
*/
- public ActivityManager.RunningTaskInfo getRunningTask() {
+ public CachedTaskInfo getRunningTask() {
return mRunningTask;
}
/**
- * This will array will contain the task returned by {@link #getRunningTask()}
- * @return the running tasks for this gesture.
- */
- public ActivityManager.RunningTaskInfo[] getRunningTasks() {
- return mRunningTasks;
- }
-
- /**
* @return the running task id for this gesture.
*/
public int getRunningTaskId() {
- return mRunningTask != null ? mRunningTask.taskId : -1;
+ return mRunningTask != null ? mRunningTask.getTaskId() : -1;
}
/**
* Updates the running task for the gesture to be the given {@param runningTask}.
*/
- public void updateRunningTask(ActivityManager.RunningTaskInfo runningTask) {
+ public void updateRunningTask(CachedTaskInfo runningTask) {
mRunningTask = runningTask;
}
/**
- * TODO(b/210903248) refactor to consolidate w/ method above
- * Updates the running task for the gesture to be the given {@param runningTask}.
- */
- public void updateRunningTasks(ActivityManager.RunningTaskInfo[] runningTasks) {
- mRunningTasks = runningTasks;
- updateRunningTask(runningTasks[0]);
- }
-
- /**
* Updates the last task that appeared during this gesture.
*/
public void updateLastAppearedTaskTarget(RemoteAnimationTargetCompat lastAppearedTaskTarget) {
@@ -339,7 +321,7 @@
* user controlled gesture.
*/
public void setHandlingAtomicEvent(boolean handlingAtomicEvent) {
- mHandlingAtomicEvent = true;
+ mHandlingAtomicEvent = handlingAtomicEvent;
}
/**
diff --git a/quickstep/src/com/android/quickstep/ImageActionsApi.java b/quickstep/src/com/android/quickstep/ImageActionsApi.java
index 8cb64c2..154848d 100644
--- a/quickstep/src/com/android/quickstep/ImageActionsApi.java
+++ b/quickstep/src/com/android/quickstep/ImageActionsApi.java
@@ -64,20 +64,23 @@
*/
@UiThread
public void shareWithExplicitIntent(@Nullable Rect crop, Intent intent) {
- addImageAndSendIntent(crop, intent, false);
+ addImageAndSendIntent(crop, intent, false, null /* exceptionCallback */);
}
/**
* Share the image this api was constructed with using the provided intent. The implementation
* should set the intent's data field to the URI pointing to the image.
+ * @param exceptionCallback An optional callback to be called when the intent can't be resolved
*/
@UiThread
- public void shareAsDataWithExplicitIntent(@Nullable Rect crop, Intent intent) {
- addImageAndSendIntent(crop, intent, true);
+ public void shareAsDataWithExplicitIntent(@Nullable Rect crop, Intent intent,
+ @Nullable Runnable exceptionCallback) {
+ addImageAndSendIntent(crop, intent, true, exceptionCallback);
}
@UiThread
- private void addImageAndSendIntent(@Nullable Rect crop, Intent intent, boolean setData) {
+ private void addImageAndSendIntent(@Nullable Rect crop, Intent intent, boolean setData,
+ @Nullable Runnable exceptionCallback) {
if (mBitmapSupplier.get() == null) {
Log.e(TAG, "No snapshot available, not starting share.");
return;
@@ -92,7 +95,7 @@
intentForUri.putExtra(EXTRA_STREAM, uri);
}
return new Intent[]{intentForUri};
- }, TAG));
+ }, TAG, exceptionCallback));
}
/**
diff --git a/quickstep/src/com/android/quickstep/KtR.java b/quickstep/src/com/android/quickstep/KtR.java
index a768ef5..758c6e0 100644
--- a/quickstep/src/com/android/quickstep/KtR.java
+++ b/quickstep/src/com/android/quickstep/KtR.java
@@ -31,6 +31,7 @@
public static final class dimen {
public static int task_menu_spacing = R.dimen.task_menu_spacing;
public static int task_menu_horizontal_padding = R.dimen.task_menu_horizontal_padding;
+ public static int taskbar_ime_size = R.dimen.taskbar_ime_size;
}
public static final class layout {
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 719c2ae..c13b95f 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -44,8 +44,9 @@
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.taskbar.LauncherTaskbarUIController;
import com.android.launcher3.touch.PagedOrientationHandler;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.quickstep.GestureState.GestureEndTarget;
-import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.LayoutUtils;
@@ -72,7 +73,8 @@
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect,
PagedOrientationHandler orientationHandler) {
calculateTaskSize(context, dp, outRect);
- if (dp.isVerticalBarLayout() && SysUINavigationMode.getMode(context) != Mode.NO_BUTTON) {
+ if (dp.isVerticalBarLayout()
+ && DisplayController.getNavigationMode(context) != NavigationMode.NO_BUTTON) {
return dp.isSeascape() ? outRect.left : (dp.widthPx - outRect.right);
} else {
return LayoutUtils.getShelfTrackingDistance(context, dp, orientationHandler);
@@ -133,7 +135,7 @@
}
};
- BaseQuickstepLauncher launcher = factory.initUI();
+ BaseQuickstepLauncher launcher = factory.initBackgroundStateUI();
// Since all apps is not visible, we can safely reset the scroll position.
// This ensures then the next swipe up to all-apps starts from scroll 0.
launcher.getAppsView().reset(false /* animate */);
@@ -278,6 +280,7 @@
@Override
public void closeOverlay() {
+ super.closeOverlay();
Launcher launcher = getCreatedActivity();
if (launcher == null) {
return;
@@ -326,7 +329,8 @@
if (uiController == null) {
return super.deferStartingActivity(deviceState, ev);
}
- return uiController.isEventOverAnyTaskbarItem(ev);
+ return uiController.isEventOverAnyTaskbarItem(ev)
+ || super.deferStartingActivity(deviceState, ev);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
new file mode 100644
index 0000000..fd9f922
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep;
+
+import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
+import static com.android.launcher3.BaseActivity.INVISIBLE_ALL;
+import static com.android.launcher3.BaseActivity.INVISIBLE_BY_PENDING_FLAGS;
+import static com.android.launcher3.BaseActivity.PENDING_INVISIBLE_BY_WALLPAPER_ANIMATION;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
+import android.graphics.Matrix;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.os.Handler;
+import android.util.Pair;
+import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.window.BackEvent;
+import android.window.IOnBackInvokedCallback;
+
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.BaseQuickstepLauncher;
+import com.android.launcher3.QuickstepTransitionManager;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.quickstep.util.RectFSpringAnim;
+import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
+
+/**
+ * Controls the animation of swiping back and returning to launcher.
+ *
+ * This is a two part animation. The first part is an animation that tracks gesture location to
+ * scale and move the leaving app window. Once the gesture is committed, the second part takes over
+ * the app window and plays the rest of app close transitions in one go.
+ *
+ * This animation is used only for apps that enable back dispatching via
+ * {@link android.window.OnBackInvokedDispatcher}. The controller registers
+ * an {@link IOnBackInvokedCallback} with WM Shell and receives back dispatches when a back
+ * navigation to launcher starts.
+ *
+ * Apps using the legacy back dispatching will keep triggering the WALLPAPER_OPEN remote
+ * transition registered in {@link QuickstepTransitionManager}.
+ *
+ */
+public class LauncherBackAnimationController {
+ private static final int CANCEL_TRANSITION_DURATION = 233;
+ private static final float MIN_WINDOW_SCALE = 0.7f;
+ private final QuickstepTransitionManager mQuickstepTransitionManager;
+ private final Matrix mTransformMatrix = new Matrix();
+ /** The window position at the beginning of the back animation. */
+ private final Rect mStartRect = new Rect();
+ /** The window position when the back gesture is cancelled. */
+ private final RectF mCancelRect = new RectF();
+ /** The current window position. */
+ private final RectF mCurrentRect = new RectF();
+ private final BaseQuickstepLauncher mLauncher;
+ private final int mWindowScaleMarginX;
+ /** Max window translation in the Y axis. */
+ private final int mWindowMaxDeltaY;
+ private final float mWindowScaleEndCornerRadius;
+ private final float mWindowScaleStartCornerRadius;
+ private final Interpolator mCancelInterpolator;
+ private final PointF mInitialTouchPos = new PointF();
+
+ private RemoteAnimationTargetCompat mBackTarget;
+ private SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
+ private boolean mSpringAnimationInProgress = false;
+ private boolean mAnimatorSetInProgress = false;
+ private float mBackProgress = 0;
+ private boolean mBackInProgress = false;
+ private IOnBackInvokedCallback mBackCallback;
+
+ public LauncherBackAnimationController(
+ BaseQuickstepLauncher launcher,
+ QuickstepTransitionManager quickstepTransitionManager) {
+ mLauncher = launcher;
+ mQuickstepTransitionManager = quickstepTransitionManager;
+ mWindowScaleEndCornerRadius = QuickStepContract.supportsRoundedCornersOnWindows(
+ mLauncher.getResources())
+ ? mLauncher.getResources().getDimensionPixelSize(
+ R.dimen.swipe_back_window_corner_radius)
+ : 0;
+ mWindowScaleStartCornerRadius = QuickStepContract.getWindowCornerRadius(mLauncher);
+ mWindowScaleMarginX = mLauncher.getResources().getDimensionPixelSize(
+ R.dimen.swipe_back_window_scale_x_margin);
+ mWindowMaxDeltaY = mLauncher.getResources().getDimensionPixelSize(
+ R.dimen.swipe_back_window_max_delta_y);
+ mCancelInterpolator =
+ AnimationUtils.loadInterpolator(mLauncher, R.interpolator.back_cancel);
+ }
+
+ /**
+ * Registers {@link IOnBackInvokedCallback} to receive back dispatches from shell.
+ * @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(() -> resetPositionAnimated());
+ }
+
+ @Override
+ public void onBackInvoked() {
+ handler.post(() -> startTransition());
+ }
+
+ @Override
+ public void onBackProgressed(BackEvent backEvent) {
+ mBackProgress = backEvent.getProgress();
+ // TODO: Update once the interpolation curve spec is finalized.
+ mBackProgress =
+ 1 - (1 - mBackProgress) * (1 - mBackProgress) * (1
+ - mBackProgress);
+ if (!mBackInProgress) {
+ startBack(backEvent);
+ } else {
+ updateBackProgress(mBackProgress, backEvent);
+ }
+ }
+
+ @Override
+ public void onBackStarted() { }
+ };
+ SystemUiProxy.INSTANCE.get(mLauncher).setBackToLauncherCallback(mBackCallback);
+ }
+
+ private void resetPositionAnimated() {
+ ValueAnimator cancelAnimator = ValueAnimator.ofFloat(0, 1);
+ mCancelRect.set(mCurrentRect);
+ cancelAnimator.setDuration(CANCEL_TRANSITION_DURATION);
+ cancelAnimator.setInterpolator(mCancelInterpolator);
+ cancelAnimator.addUpdateListener(
+ animation -> {
+ updateCancelProgress((float) animation.getAnimatedValue());
+ });
+ cancelAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ finishAnimation();
+ }
+ });
+ cancelAnimator.start();
+ }
+
+ /** Unregisters the back to launcher callback in shell. */
+ public void unregisterBackCallbacks() {
+ if (mBackCallback != null) {
+ SystemUiProxy.INSTANCE.get(mLauncher).clearBackToLauncherCallback(mBackCallback);
+ }
+ mBackCallback = null;
+ }
+
+ private void startBack(BackEvent backEvent) {
+ mBackInProgress = true;
+ RemoteAnimationTarget appTarget = backEvent.getDepartingAnimationTarget();
+
+ if (appTarget == null) {
+ return;
+ }
+
+ mTransaction.show(appTarget.leash).apply();
+ mTransaction.setAnimationTransaction();
+ mBackTarget = new RemoteAnimationTargetCompat(appTarget);
+ mInitialTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY());
+
+ // TODO(b/218916755): Offset start rectangle in multiwindow mode.
+ mStartRect.set(mBackTarget.windowConfiguration.getMaxBounds());
+ }
+
+ private void updateBackProgress(float progress, BackEvent event) {
+ if (mBackTarget == null) {
+ return;
+ }
+ float screenWidth = mStartRect.width();
+ float screenHeight = mStartRect.height();
+ float dX = Math.abs(event.getTouchX() - mInitialTouchPos.x);
+ // The 'follow width' is the width of the window if it completely matches
+ // the gesture displacement.
+ float followWidth = screenWidth - dX;
+ // The 'progress width' is the width of the window if it strictly linearly interpolates
+ // to minimum scale base on progress.
+ float progressWidth = Utilities.mapRange(progress, 1, MIN_WINDOW_SCALE) * screenWidth;
+ // The final width is derived from interpolating between the follow with and progress width
+ // using gesture progress.
+ float width = Utilities.mapRange(progress, followWidth, progressWidth);
+ float height = screenHeight / screenWidth * width;
+ float deltaYRatio = (event.getTouchY() - mInitialTouchPos.y) / screenHeight;
+ // Base the window movement in the Y axis on the touch movement in the Y axis.
+ float deltaY = (float) Math.sin(deltaYRatio * Math.PI * 0.5f) * mWindowMaxDeltaY;
+ // Move the window along the Y axis.
+ float top = (screenHeight - height) * 0.5f + deltaY;
+ // Move the window along the X axis.
+ float left = event.getSwipeEdge() == BackEvent.EDGE_RIGHT
+ ? progress * mWindowScaleMarginX
+ : screenWidth - progress * mWindowScaleMarginX - width;
+
+ mCurrentRect.set(left, top, left + width, top + height);
+ float cornerRadius = Utilities.mapRange(
+ progress, mWindowScaleStartCornerRadius, mWindowScaleEndCornerRadius);
+ applyTransform(mCurrentRect, cornerRadius);
+ }
+
+ private void updateCancelProgress(float progress) {
+ if (mBackTarget == null) {
+ return;
+ }
+ mCurrentRect.set(
+ Utilities.mapRange(progress, mCancelRect.left, mStartRect.left),
+ Utilities.mapRange(progress, mCancelRect.top, mStartRect.top),
+ Utilities.mapRange(progress, mCancelRect.right, mStartRect.right),
+ Utilities.mapRange(progress, mCancelRect.bottom, mStartRect.bottom));
+
+ float endCornerRadius = Utilities.mapRange(
+ mBackProgress, mWindowScaleStartCornerRadius, mWindowScaleEndCornerRadius);
+ float cornerRadius = Utilities.mapRange(
+ progress, endCornerRadius, mWindowScaleStartCornerRadius);
+ applyTransform(mCurrentRect, cornerRadius);
+ }
+
+ /** Transform the target window to match the target rect. */
+ private void applyTransform(RectF targetRect, float cornerRadius) {
+ SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder builder =
+ new SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder(mBackTarget.leash);
+ final float scale = targetRect.width() / mStartRect.width();
+ mTransformMatrix.reset();
+ mTransformMatrix.setScale(scale, scale);
+ mTransformMatrix.postTranslate(targetRect.left, targetRect.top);
+ builder.withMatrix(mTransformMatrix)
+ .withWindowCrop(mStartRect)
+ .withCornerRadius(cornerRadius);
+ SyncRtSurfaceTransactionApplierCompat.SurfaceParams surfaceParams = builder.build();
+
+ if (surfaceParams.surface.isValid()) {
+ surfaceParams.applyTo(mTransaction);
+ }
+ mTransaction.apply();
+ }
+
+ private void startTransition() {
+ if (mBackTarget == null) {
+ // Trigger transition system instead of custom transition animation.
+ finishAnimation();
+ return;
+ }
+ if (mLauncher.isDestroyed()) {
+ return;
+ }
+ // TODO: Catch the moment when launcher becomes visible after the top app un-occludes
+ // launcher and start animating afterwards. Currently we occasionally get a flicker from
+ // animating when launcher is still invisible.
+ if (mLauncher.hasSomeInvisibleFlag(PENDING_INVISIBLE_BY_WALLPAPER_ANIMATION)) {
+ mLauncher.addForceInvisibleFlag(INVISIBLE_BY_PENDING_FLAGS);
+ mLauncher.getStateManager().moveToRestState();
+ }
+
+ // Explicitly close opened floating views (which is typically called from
+ // Launcher#onResumed, but in the predictive back flow launcher is not resumed until
+ // the transition is fully finished.)
+ AbstractFloatingView.closeAllOpenViewsExcept(mLauncher, false, TYPE_REBIND_SAFE);
+ float cornerRadius = Utilities.mapRange(
+ mBackProgress, mWindowScaleStartCornerRadius, mWindowScaleEndCornerRadius);
+ Pair<RectFSpringAnim, AnimatorSet> pair =
+ mQuickstepTransitionManager.createWallpaperOpenAnimations(
+ new RemoteAnimationTargetCompat[]{mBackTarget},
+ new RemoteAnimationTargetCompat[]{},
+ false /* fromUnlock */,
+ mCurrentRect,
+ cornerRadius);
+ startTransitionAnimations(pair.first, pair.second);
+ mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL);
+ }
+
+ private void finishAnimation() {
+ mBackTarget = null;
+ mBackInProgress = false;
+ mBackProgress = 0;
+ mTransformMatrix.reset();
+ mCancelRect.setEmpty();
+ mCurrentRect.setEmpty();
+ mStartRect.setEmpty();
+ mInitialTouchPos.set(0, 0);
+ mAnimatorSetInProgress = false;
+ mSpringAnimationInProgress = false;
+ SystemUiProxy.INSTANCE.get(mLauncher).onBackToLauncherAnimationFinished();
+ }
+
+ private void startTransitionAnimations(RectFSpringAnim springAnim, AnimatorSet anim) {
+ mAnimatorSetInProgress = anim != null;
+ mSpringAnimationInProgress = springAnim != null;
+ if (springAnim != null) {
+ springAnim.addAnimatorListener(
+ new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mSpringAnimationInProgress = false;
+ tryFinishBackAnimation();
+ }
+ }
+ );
+ }
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mAnimatorSetInProgress = false;
+ tryFinishBackAnimation();
+ }
+ });
+ anim.start();
+ }
+
+ private void tryFinishBackAnimation() {
+ if (!mSpringAnimationInProgress && !mAnimatorSetInProgress) {
+ finishAnimation();
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index 4fb03c4..50d1244 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -15,10 +15,7 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
-import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.Utilities.dpToPx;
import static com.android.launcher3.Utilities.mapBoundToRange;
import static com.android.launcher3.anim.Interpolators.EXAGGERATED_EASE;
import static com.android.launcher3.anim.Interpolators.LINEAR;
@@ -26,10 +23,7 @@
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import static com.android.launcher3.views.FloatingIconView.getFloatingIconView;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
-import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -42,15 +36,9 @@
import androidx.annotation.Nullable;
import com.android.launcher3.BaseQuickstepLauncher;
-import com.android.launcher3.Hotseat;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.R;
-import com.android.launcher3.Workspace;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.SpringAnimationBuilder;
-import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.states.StateAnimationConfig;
-import com.android.launcher3.util.DynamicResource;
import com.android.launcher3.util.ObjectWrapper;
import com.android.launcher3.views.FloatingIconView;
import com.android.launcher3.views.FloatingView;
@@ -60,7 +48,6 @@
import com.android.quickstep.views.FloatingWidgetView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
-import com.android.systemui.plugins.ResourceProvider;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -252,67 +239,22 @@
@Override
protected void finishRecentsControllerToHome(Runnable callback) {
+ mRecentsView.cleanupRemoteTargets();
mRecentsAnimationController.finish(
true /* toRecents */, callback, true /* sendUserLeaveHint */);
}
private class FloatingViewHomeAnimationFactory extends LauncherHomeAnimationFactory {
- private final float mTransY;
private final FloatingView mFloatingView;
- private ValueAnimator mBounceBackAnimator;
FloatingViewHomeAnimationFactory(FloatingView floatingView) {
mFloatingView = floatingView;
-
- ResourceProvider rp = DynamicResource.provider(mActivity);
- mTransY = dpToPx(rp.getFloat(R.dimen.swipe_up_trans_y_dp));
- }
-
- @Override
- public boolean shouldPlayAtomicWorkspaceReveal() {
- return false;
- }
-
- protected void bounceBackToRestingPosition() {
- final float startValue = mTransY;
- final float endValue = 0;
- // Ensures the velocity is always aligned with the direction.
- float pixelPerSecond = Math.abs(mSwipeVelocity) * Math.signum(endValue - mTransY);
-
- DragLayer dl = mActivity.getDragLayer();
- Workspace workspace = mActivity.getWorkspace();
- Hotseat hotseat = mActivity.getHotseat();
-
- ResourceProvider rp = DynamicResource.provider(mActivity);
- ValueAnimator springTransY = new SpringAnimationBuilder(dl.getContext())
- .setStiffness(rp.getFloat(R.dimen.swipe_up_trans_y_stiffness))
- .setDampingRatio(rp.getFloat(R.dimen.swipe_up_trans_y_damping))
- .setMinimumVisibleChange(1f)
- .setStartValue(startValue)
- .setEndValue(endValue)
- .setStartVelocity(pixelPerSecond)
- .build(dl, VIEW_TRANSLATE_Y);
- springTransY.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- dl.setTranslationY(0f);
- dl.setAlpha(1f);
- SCALE_PROPERTY.set(workspace, 1f);
- SCALE_PROPERTY.set(hotseat, 1f);
- }
- });
-
- mBounceBackAnimator = springTransY;
- mBounceBackAnimator.start();
}
@Override
public void onCancel() {
mFloatingView.fastFinish();
- if (mBounceBackAnimator != null) {
- mBounceBackAnimator.cancel();
- }
}
}
@@ -343,10 +285,5 @@
getViewIgnoredInWorkspaceRevealAnimation())
.start();
}
-
- @Override
- public boolean supportSwipePipToHome() {
- return true;
- }
}
}
diff --git a/quickstep/src/com/android/quickstep/OrientationRectF.java b/quickstep/src/com/android/quickstep/OrientationRectF.java
index 59a202c..aa01b05 100644
--- a/quickstep/src/com/android/quickstep/OrientationRectF.java
+++ b/quickstep/src/com/android/quickstep/OrientationRectF.java
@@ -66,7 +66,7 @@
return applyTransform(event, deltaRotation(mRotation, currentRotation), forceTransform);
}
- private boolean applyTransform(MotionEvent event, int deltaRotation, boolean forceTransform) {
+ public boolean applyTransform(MotionEvent event, int deltaRotation, boolean forceTransform) {
mTmpMatrix.reset();
postDisplayRotation(deltaRotation, mHeight, mWidth, mTmpMatrix);
if (forceTransform) {
diff --git a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
index ecff4f1..895cf89 100644
--- a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
+++ b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
@@ -22,6 +22,8 @@
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_UP;
+import static com.android.launcher3.states.RotationHelper.deltaRotation;
+
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.RectF;
@@ -32,11 +34,12 @@
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.util.DisplayController.Info;
+import com.android.launcher3.util.DisplayController.NavigationMode;
+import com.android.launcher3.util.window.CachedDisplayInfo;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
-import java.util.Objects;
/**
* Maintains state for supporting nav bars and tracking their gestures in multiple orientations.
@@ -48,55 +51,17 @@
*/
class OrientationTouchTransformer {
- private static class CurrentDisplay {
- public Point size;
- public int rotation;
-
- CurrentDisplay() {
- this.size = new Point(0, 0);
- this.rotation = 0;
- }
-
- CurrentDisplay(Point size, int rotation) {
- this.size = size;
- this.rotation = rotation;
- }
-
- @Override
- public String toString() {
- return "CurrentDisplay:"
- + " rotation: " + rotation
- + " size: " + size;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- CurrentDisplay display = (CurrentDisplay) o;
- if (rotation != display.rotation) return false;
-
- return Objects.equals(size, display.size);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(size, rotation);
- }
- };
-
private static final String TAG = "OrientationTouchTransformer";
private static final boolean DEBUG = false;
private static final int QUICKSTEP_ROTATION_UNINITIALIZED = -1;
- private final Map<CurrentDisplay, OrientationRectF> mSwipeTouchRegions =
- new HashMap<CurrentDisplay, OrientationRectF>();
+ private final Map<CachedDisplayInfo, OrientationRectF> mSwipeTouchRegions =
+ new HashMap<CachedDisplayInfo, OrientationRectF>();
private final RectF mAssistantLeftRegion = new RectF();
private final RectF mAssistantRightRegion = new RectF();
private final RectF mOneHandedModeRegion = new RectF();
- private CurrentDisplay mCurrentDisplay = new CurrentDisplay();
+ private CachedDisplayInfo mCachedDisplayInfo = new CachedDisplayInfo();
private int mNavBarGesturalHeight;
private final int mNavBarLargerGesturalHeight;
private boolean mEnableMultipleRegions;
@@ -110,7 +75,7 @@
* mQuickstepStartingRotation only updates when device rotation matches touch rotation.
*/
private int mActiveTouchRotation;
- private SysUINavigationMode.Mode mMode;
+ private NavigationMode mMode;
private QuickStepContractInfo mContractInfo;
/**
@@ -133,7 +98,7 @@
}
- OrientationTouchTransformer(Resources resources, SysUINavigationMode.Mode mode,
+ OrientationTouchTransformer(Resources resources, NavigationMode mode,
QuickStepContractInfo contractInfo) {
mResources = resources;
mMode = mode;
@@ -153,7 +118,7 @@
resetSwipeRegions(info);
}
- void setNavigationMode(SysUINavigationMode.Mode newMode, Info info, Resources newRes) {
+ void setNavigationMode(NavigationMode newMode, Info info, Resources newRes) {
if (DEBUG) {
Log.d(TAG, "setNavigationMode new: " + newMode + " oldMode: " + mMode + " " + this);
}
@@ -181,22 +146,22 @@
* @see #enableMultipleRegions(boolean, Info)
*/
void createOrAddTouchRegion(Info info) {
- mCurrentDisplay = new CurrentDisplay(info.currentSize, info.rotation);
+ mCachedDisplayInfo = new CachedDisplayInfo(info.currentSize, info.rotation);
if (mQuickStepStartingRotation > QUICKSTEP_ROTATION_UNINITIALIZED
- && mCurrentDisplay.rotation == mQuickStepStartingRotation) {
+ && mCachedDisplayInfo.rotation == mQuickStepStartingRotation) {
// User already was swiping and the current screen is same rotation as the starting one
// Remove active nav bars in other rotations except for the one we started out in
resetSwipeRegions(info);
return;
}
- OrientationRectF region = mSwipeTouchRegions.get(mCurrentDisplay);
+ OrientationRectF region = mSwipeTouchRegions.get(mCachedDisplayInfo);
if (region != null) {
return;
}
if (mEnableMultipleRegions) {
- mSwipeTouchRegions.put(mCurrentDisplay, createRegionForDisplay(info));
+ mSwipeTouchRegions.put(mCachedDisplayInfo, createRegionForDisplay(info));
} else {
resetSwipeRegions(info);
}
@@ -210,8 +175,7 @@
* @param info The current displayInfo which will be the start of the quickswitch gesture
*/
void enableMultipleRegions(boolean enableMultipleRegions, Info info) {
- mEnableMultipleRegions = enableMultipleRegions &&
- mMode != SysUINavigationMode.Mode.TWO_BUTTONS;
+ mEnableMultipleRegions = enableMultipleRegions && mMode != NavigationMode.TWO_BUTTONS;
if (mEnableMultipleRegions) {
mQuickStepStartingRotation = info.rotation;
} else {
@@ -243,40 +207,39 @@
*/
private void resetSwipeRegions(Info region) {
if (DEBUG) {
- Log.d(TAG, "clearing all regions except rotation: " + mCurrentDisplay.rotation);
+ Log.d(TAG, "clearing all regions except rotation: " + mCachedDisplayInfo.rotation);
}
- mCurrentDisplay = new CurrentDisplay(region.currentSize, region.rotation);
- OrientationRectF regionToKeep = mSwipeTouchRegions.get(mCurrentDisplay);
+ mCachedDisplayInfo = new CachedDisplayInfo(region.currentSize, region.rotation);
+ OrientationRectF regionToKeep = mSwipeTouchRegions.get(mCachedDisplayInfo);
if (regionToKeep == null) {
regionToKeep = createRegionForDisplay(region);
}
mSwipeTouchRegions.clear();
- mSwipeTouchRegions.put(mCurrentDisplay, regionToKeep);
+ mSwipeTouchRegions.put(mCachedDisplayInfo, regionToKeep);
updateAssistantRegions(regionToKeep);
}
private void resetSwipeRegions() {
- OrientationRectF regionToKeep = mSwipeTouchRegions.get(mCurrentDisplay);
+ OrientationRectF regionToKeep = mSwipeTouchRegions.get(mCachedDisplayInfo);
mSwipeTouchRegions.clear();
if (regionToKeep != null) {
- mSwipeTouchRegions.put(mCurrentDisplay, regionToKeep);
+ mSwipeTouchRegions.put(mCachedDisplayInfo, regionToKeep);
updateAssistantRegions(regionToKeep);
}
}
private OrientationRectF createRegionForDisplay(Info display) {
if (DEBUG) {
- Log.d(TAG, "creating rotation region for: " + mCurrentDisplay.rotation
+ Log.d(TAG, "creating rotation region for: " + mCachedDisplayInfo.rotation
+ " with mode: " + mMode + " displayRotation: " + display.rotation);
}
Point size = display.currentSize;
int rotation = display.rotation;
int touchHeight = mNavBarGesturalHeight;
- OrientationRectF orientationRectF =
- new OrientationRectF(0, 0, size.x, size.y, rotation);
- if (mMode == SysUINavigationMode.Mode.NO_BUTTON) {
+ OrientationRectF orientationRectF = new OrientationRectF(0, 0, size.x, size.y, rotation);
+ if (mMode == NavigationMode.NO_BUTTON) {
orientationRectF.top = orientationRectF.bottom - touchHeight;
updateAssistantRegions(orientationRectF);
} else {
@@ -358,7 +321,18 @@
if (mLastRectTouched == null) {
return;
}
- mLastRectTouched.applyTransformFromRotation(event, mCurrentDisplay.rotation, true);
+ if (TaskAnimationManager.SHELL_TRANSITIONS_ROTATION) {
+ if (event.getSurfaceRotation() != mActiveTouchRotation) {
+ // With Shell transitions, we should rotated to the orientation at the start
+ // of the gesture not the current display rotation which will happen early
+ mLastRectTouched.applyTransform(event,
+ deltaRotation(event.getSurfaceRotation(), mActiveTouchRotation),
+ true);
+ }
+ } else {
+ mLastRectTouched.applyTransformFromRotation(event, mCachedDisplayInfo.rotation,
+ true);
+ }
break;
}
case ACTION_CANCEL:
@@ -366,7 +340,18 @@
if (mLastRectTouched == null) {
return;
}
- mLastRectTouched.applyTransformFromRotation(event, mCurrentDisplay.rotation, true);
+ if (TaskAnimationManager.SHELL_TRANSITIONS_ROTATION) {
+ if (event.getSurfaceRotation() != mActiveTouchRotation) {
+ // With Shell transitions, we should rotated to the orientation at the start
+ // of the gesture not the current display rotation which will happen early
+ mLastRectTouched.applyTransform(event,
+ deltaRotation(event.getSurfaceRotation(), mActiveTouchRotation),
+ true);
+ }
+ } else {
+ mLastRectTouched.applyTransformFromRotation(event, mCachedDisplayInfo.rotation,
+ true);
+ }
mLastRectTouched = null;
break;
}
@@ -380,11 +365,12 @@
if (rect == null) {
continue;
}
- if (rect.applyTransformFromRotation(event, mCurrentDisplay.rotation, false)) {
+ if (rect.applyTransformFromRotation(
+ event, mCachedDisplayInfo.rotation, false)) {
mLastRectTouched = rect;
mActiveTouchRotation = rect.getRotation();
if (mEnableMultipleRegions
- && mCurrentDisplay.rotation == mActiveTouchRotation) {
+ && mCachedDisplayInfo.rotation == mActiveTouchRotation) {
// TODO(b/154580671) might make this block unnecessary
// Start a touch session for the default nav region for the display
mQuickStepStartingRotation = mLastRectTouched.getRotation();
@@ -407,7 +393,7 @@
pw.println(" lastTouchedRegion=" + mLastRectTouched);
pw.println(" multipleRegionsEnabled=" + mEnableMultipleRegions);
StringBuilder regions = new StringBuilder(" currentTouchableRotations=");
- for (CurrentDisplay key: mSwipeTouchRegions.keySet()) {
+ for (CachedDisplayInfo key: mSwipeTouchRegions.keySet()) {
OrientationRectF rectF = mSwipeTouchRegions.get(key);
regions.append(rectF).append(" ");
}
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 17baa3a..dffdc5a 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -32,7 +32,6 @@
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.util.RunnableList;
import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
-import com.android.quickstep.util.LauncherSplitScreenListener;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -54,6 +53,12 @@
public static final int TYPE_TOGGLE = 4;
public static final int TYPE_HOME = 5;
+ /**
+ * Use case for needing a queue is double tapping recents button in 3 button nav.
+ * Size of 2 should be enough. We'll toss in one more because we're kind hearted.
+ */
+ private final static int MAX_QUEUE_SIZE = 3;
+
private static final String TRANSITION_NAME = "Transition:toOverview";
private final TouchInteractionService mService;
@@ -105,10 +110,15 @@
}
/**
- * Adds a command to be executed next, after all pending tasks are completed
+ * Adds a command to be executed next, after all pending tasks are completed.
+ * Max commands that can be queued is {@link #MAX_QUEUE_SIZE}.
+ * Requests after reaching that limit will be silently dropped.
*/
@BinderThread
public void addCommand(int type) {
+ if (mPendingCommands.size() > MAX_QUEUE_SIZE) {
+ return;
+ }
CommandInfo cmd = new CommandInfo(type);
MAIN_EXECUTOR.execute(() -> addCommand(cmd));
}
@@ -161,7 +171,6 @@
}
if (cmd.type == TYPE_HOME) {
mService.startActivity(mOverviewComponentObserver.getHomeIntent());
- LauncherSplitScreenListener.INSTANCE.getNoCreate().notifySwipingToHome();
return true;
}
} else {
@@ -180,7 +189,6 @@
return launchTask(recents, getNextTask(recents), cmd);
case TYPE_HOME:
recents.startHome();
- LauncherSplitScreenListener.INSTANCE.getNoCreate().notifySwipingToHome();
return true;
}
}
@@ -209,7 +217,8 @@
@Override
public void onRecentsAnimationStart(RecentsAnimationController controller,
RecentsAnimationTargets targets) {
- interactionHandler.onGestureEnded(0, new PointF(), new PointF());
+ activityInterface.runOnInitBackgroundStateUI(() ->
+ interactionHandler.onGestureEnded(0, new PointF(), new PointF()));
cmd.removeListener(this);
}
diff --git a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
index a551f55..5521020 100644
--- a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
+++ b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
@@ -16,16 +16,18 @@
package com.android.quickstep;
import android.annotation.TargetApi;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
+import android.os.RemoteException;
import android.os.UserManager;
import android.util.Log;
+import android.view.ThreadedRenderer;
import com.android.launcher3.BuildConfig;
import com.android.launcher3.MainProcessInitializer;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
-import com.android.systemui.shared.system.ThreadedRendererCompat;
@SuppressWarnings("unused")
@TargetApi(Build.VERSION_CODES.R)
@@ -58,7 +60,14 @@
super.init(context);
// Elevate GPU priority for Quickstep and Remote animations.
- ThreadedRendererCompat.setContextPriority(
- ThreadedRendererCompat.EGL_CONTEXT_PRIORITY_HIGH_IMG);
+ ThreadedRenderer.setContextPriority(
+ ThreadedRenderer.EGL_CONTEXT_PRIORITY_HIGH_IMG);
+
+ // Enable binder tracing on system server for calls originating from Launcher
+ try {
+ ActivityManager.getService().enableBinderTracing();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to enable binder tracing", e);
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
index 95ab62f..528fb97 100644
--- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -5,11 +5,11 @@
import android.graphics.Rect;
import android.os.Bundle;
-import com.android.launcher3.LauncherState;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.testing.TestInformationHandler;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.PagedOrientationHandler;
-import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController;
import com.android.quickstep.util.LayoutUtils;
public class QuickstepTestInformationHandler extends TestInformationHandler {
@@ -21,18 +21,9 @@
}
@Override
- public Bundle call(String method, String arg) {
+ public Bundle call(String method, String arg, @Nullable Bundle extras) {
final Bundle response = new Bundle();
switch (method) {
- case TestProtocol.REQUEST_ALL_APPS_TO_OVERVIEW_SWIPE_HEIGHT: {
- return getLauncherUIProperty(Bundle::putInt, l -> {
- final float progress = LauncherState.OVERVIEW.getVerticalProgress(l)
- - LauncherState.ALL_APPS.getVerticalProgress(l);
- final float distance = l.getAllAppsController().getShiftRange() * progress;
- return (int) distance;
- });
- }
-
case TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT: {
final float swipeHeight =
LayoutUtils.getDefaultSwipeHeight(mContext, mDeviceProfile);
@@ -48,11 +39,6 @@
return response;
}
- case TestProtocol.REQUEST_HOTSEAT_TOP: {
- return getLauncherUIProperty(
- Bundle::putInt, PortraitStatesTouchController::getHotseatTop);
- }
-
case TestProtocol.REQUEST_GET_FOCUSED_TASK_HEIGHT_FOR_TABLET: {
if (!mDeviceProfile.isTablet) {
return null;
@@ -74,9 +60,21 @@
response.putParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD, gridTaskRect);
return response;
}
+
+ case TestProtocol.REQUEST_GET_OVERVIEW_PAGE_SPACING: {
+ response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD,
+ mDeviceProfile.overviewPageSpacing);
+ return response;
+ }
+
+ case TestProtocol.REQUEST_HAS_TIS: {
+ response.putBoolean(
+ TestProtocol.REQUEST_HAS_TIS, true);
+ return response;
+ }
}
- return super.call(method, arg);
+ return super.call(method, arg, extras);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index e6424d7..4f0b976 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -137,8 +137,8 @@
SYSUI_PROGRESS.set(getRootView().getSysUiScrim(), 0f);
SplitSelectStateController controller =
- new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this),
- getStateManager(), null /*depthController*/);
+ new SplitSelectStateController(this, mHandler, getStateManager(),
+ null /* depthController */);
mDragLayer.recreateControllers();
mFallbackRecentsView.init(mActionsView, controller);
@@ -276,7 +276,10 @@
final ActivityOptionsWrapper activityOptions = new ActivityOptionsWrapper(
ActivityOptionsCompat.makeRemoteAnimation(adapterCompat),
onEndCallback);
- activityOptions.options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+ activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+ activityOptions.options.setLaunchDisplayId(
+ (v != null && v.getDisplay() != null) ? v.getDisplay().getDisplayId()
+ : Display.DEFAULT_DISPLAY);
mHandler.postDelayed(mAnimationStartTimeoutRunnable, RECENTS_ANIMATION_TIMEOUT);
return activityOptions;
}
@@ -442,7 +445,7 @@
RemoteAnimationTargets targets = new RemoteAnimationTargets(
appTargets, wallpaperTargets, nonAppTargets, MODE_OPENING);
for (RemoteAnimationTargetCompat app : targets.apps) {
- new Transaction().setAlpha(app.leash.getSurfaceControl(), 1).apply();
+ new Transaction().setAlpha(app.leash, 1).apply();
}
AnimatorSet anim = new AnimatorSet();
anim.play(controller.getAnimationPlayer());
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
index b502676..51ae56b 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
@@ -104,8 +104,7 @@
.map(RemoteAnimationTargetCompat::unwrap)
.toArray(RemoteAnimationTarget[]::new);
- RemoteAnimationTarget[] nonAppTargets =
- mSystemUiProxy.onGoingToRecentsLegacy(mCancelled, nonHomeApps);
+ RemoteAnimationTarget[] nonAppTargets = mSystemUiProxy.onGoingToRecentsLegacy(nonHomeApps);
RecentsAnimationTargets targets = new RecentsAnimationTargets(appTargets,
wallpaperTargets, RemoteAnimationTargetCompat.wrap(nonAppTargets),
@@ -145,6 +144,18 @@
});
}
+ @BinderThread
+ @Override
+ public boolean onSwitchToScreenshot(Runnable onFinished) {
+ Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
+ for (RecentsAnimationListener listener : getListeners()) {
+ if (listener.onSwitchToScreenshot(onFinished)) return;
+ }
+ onFinished.run();
+ });
+ return true;
+ }
+
private final void onAnimationFinished(RecentsAnimationController controller) {
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
for (RecentsAnimationListener listener : getListeners()) {
@@ -180,5 +191,12 @@
* Callback made when a task started from the recents is ready for an app transition.
*/
default void onTasksAppeared(@NonNull RemoteAnimationTargetCompat[] appearedTaskTarget) {}
+
+ /**
+ * @return whether this will call onFinished or not (onFinished should only be called once).
+ */
+ default boolean onSwitchToScreenshot(Runnable onFinished) {
+ return false;
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
index f343485..2007ee1 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
@@ -17,9 +17,14 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Log;
import android.view.IRecentsAnimationController;
import android.view.SurfaceControl;
+import android.view.WindowManagerGlobal;
import android.window.PictureInPictureSurfaceTransaction;
import androidx.annotation.NonNull;
@@ -39,6 +44,7 @@
*/
public class RecentsAnimationController {
+ private static final String TAG = "RecentsAnimationController";
private final RecentsAnimationControllerCompat mController;
private final Consumer<RecentsAnimationController> mOnFinishedListener;
private final boolean mAllowMinimizeSplitScreen;
@@ -74,7 +80,16 @@
if (mUseLauncherSysBarFlags != useLauncherSysBarFlags) {
mUseLauncherSysBarFlags = useLauncherSysBarFlags;
UI_HELPER_EXECUTOR.execute(() -> {
- mController.setAnimationTargetsBehindSystemBars(!useLauncherSysBarFlags);
+ if (!ENABLE_SHELL_TRANSITIONS) {
+ mController.setAnimationTargetsBehindSystemBars(!useLauncherSysBarFlags);
+ } else {
+ try {
+ WindowManagerGlobal.getWindowManagerService().setRecentsAppBehindSystemBars(
+ useLauncherSysBarFlags);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to reach window manager", e);
+ }
+ }
});
}
}
@@ -83,24 +98,20 @@
* Indicates that the gesture has crossed the window boundary threshold and we should minimize
* if we are in splitscreen.
*/
- public void setSplitScreenMinimized(boolean splitScreenMinimized) {
+ public void setSplitScreenMinimized(Context context, boolean splitScreenMinimized) {
if (!mAllowMinimizeSplitScreen) {
return;
}
if (mSplitScreenMinimized != splitScreenMinimized) {
mSplitScreenMinimized = splitScreenMinimized;
- UI_HELPER_EXECUTOR.execute(() -> {
- SystemUiProxy p = SystemUiProxy.INSTANCE.getNoCreate();
- if (p != null) {
- p.setSplitScreenMinimized(splitScreenMinimized);
- }
- });
+ UI_HELPER_EXECUTOR.execute(() -> SystemUiProxy.INSTANCE.get(context)
+ .setSplitScreenMinimized(splitScreenMinimized));
}
}
/**
* Remove task remote animation target from
- * {@link RecentsAnimationCallbacks#onTaskAppeared(RemoteAnimationTargetCompat)}}.
+ * {@link RecentsAnimationCallbacks#onTasksAppeared}}.
*/
@UiThread
public void removeTaskTarget(@NonNull RemoteAnimationTargetCompat target) {
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 8d17cf4..bb9fa5e 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -21,19 +21,21 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
+import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
+import static com.android.launcher3.util.DisplayController.NavigationMode.NO_BUTTON;
+import static com.android.launcher3.util.DisplayController.NavigationMode.THREE_BUTTONS;
+import static com.android.launcher3.util.DisplayController.NavigationMode.TWO_BUTTONS;
import static com.android.launcher3.util.SettingsCache.ONE_HANDED_ENABLED;
import static com.android.launcher3.util.SettingsCache.ONE_HANDED_SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED;
-import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
-import static com.android.quickstep.SysUINavigationMode.Mode.THREE_BUTTONS;
-import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_GLOBAL_ACTIONS_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DIALOG_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
@@ -44,35 +46,30 @@
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 android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Resources;
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.text.TextUtils;
import android.view.MotionEvent;
-import android.view.Surface;
import androidx.annotation.BinderThread;
-import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
import com.android.launcher3.util.DisplayController.Info;
+import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.launcher3.util.SettingsCache;
-import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
-import com.android.quickstep.SysUINavigationMode.OneHandedModeChangeListener;
+import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
import com.android.quickstep.util.NavBarPosition;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
@@ -83,30 +80,27 @@
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.List;
/**
* Manages the state of the system during a swipe up gesture.
*/
-public class RecentsAnimationDeviceState implements
- NavigationModeChangeListener,
- DisplayInfoChangeListener,
- OneHandedModeChangeListener {
+public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
private final Context mContext;
- private final SysUINavigationMode mSysUiNavMode;
private final DisplayController mDisplayController;
private final int mDisplayId;
private final RotationTouchHelper mRotationTouchHelper;
private final TaskStackChangeListener mPipListener;
- private final List<ComponentName> mGestureBlockedActivities;
+ // Cache for better performance since it doesn't change at runtime.
+ private final boolean mCanImeRenderGesturalNavButtons =
+ InputMethodService.canImeRenderGesturalNavButtons();
private final ArrayList<Runnable> mOnDestroyActions = new ArrayList<>();
private @SystemUiStateFlags int mSystemUiStateFlags;
- private SysUINavigationMode.Mode mMode = THREE_BUTTONS;
+ private NavigationMode mMode = THREE_BUTTONS;
private NavBarPosition mNavBarPosition;
private final Region mDeferredGestureRegion = new Region();
@@ -130,6 +124,7 @@
}
};
+ private int mGestureBlockingTaskId = -1;
private Region mExclusionRegion;
private SystemGestureExclusionListenerCompat mExclusionListener;
@@ -144,10 +139,8 @@
public RecentsAnimationDeviceState(Context context, boolean isInstanceForTouches) {
mContext = context;
mDisplayController = DisplayController.INSTANCE.get(context);
- mSysUiNavMode = SysUINavigationMode.INSTANCE.get(context);
mDisplayId = DEFAULT_DISPLAY;
mIsOneHandedModeSupported = SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false);
- runOnDestroy(() -> mDisplayController.removeChangeListener(this));
mRotationTouchHelper = RotationTouchHelper.INSTANCE.get(context);
if (isInstanceForTouches) {
// rotationTouchHelper doesn't get initialized after being destroyed, so only destroy
@@ -176,25 +169,10 @@
};
runOnDestroy(mExclusionListener::unregister);
- // Register for navigation mode changes
- onNavigationModeChanged(mSysUiNavMode.addModeChangeListener(this));
- runOnDestroy(() -> mSysUiNavMode.removeModeChangeListener(this));
-
- // Add any blocked activities
- String[] blockingActivities;
- try {
- blockingActivities =
- context.getResources().getStringArray(R.array.gesture_blocking_activities);
- } catch (Resources.NotFoundException e) {
- blockingActivities = new String[0];
- }
- mGestureBlockedActivities = new ArrayList<>(blockingActivities.length);
- for (String blockingActivity : blockingActivities) {
- if (!TextUtils.isEmpty(blockingActivity)) {
- mGestureBlockedActivities.add(
- ComponentName.unflattenFromString(blockingActivity));
- }
- }
+ // Register for display changes changes
+ mDisplayController.addChangeListener(this);
+ onDisplayInfoChanged(context, mDisplayController.getInfo(), CHANGE_ALL);
+ runOnDestroy(() -> mDisplayController.removeChangeListener(this));
SettingsCache settingsCache = SettingsCache.INSTANCE.get(mContext);
if (mIsOneHandedModeSupported) {
@@ -263,56 +241,36 @@
* Adds a listener for the nav mode change, guaranteed to be called after the device state's
* mode has changed.
*/
- public void addNavigationModeChangedCallback(NavigationModeChangeListener listener) {
- listener.onNavigationModeChanged(mSysUiNavMode.addModeChangeListener(listener));
- runOnDestroy(() -> mSysUiNavMode.removeModeChangeListener(listener));
- }
-
- /**
- * Adds a listener for the one handed mode change,
- * guaranteed to be called after the device state's mode has changed.
- */
- public void addOneHandedModeChangedCallback(OneHandedModeChangeListener listener) {
- listener.onOneHandedModeChanged(mSysUiNavMode.addOneHandedOverlayChangeListener(listener));
- runOnDestroy(() -> mSysUiNavMode.removeOneHandedOverlayChangeListener(listener));
- }
-
- @Override
- public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) {
- mDisplayController.removeChangeListener(this);
- mDisplayController.addChangeListener(this);
- onDisplayInfoChanged(mContext, mDisplayController.getInfo(), CHANGE_ALL);
-
- if (newMode == NO_BUTTON) {
- mExclusionListener.register();
- } else {
- mExclusionListener.unregister();
- }
-
- mNavBarPosition = new NavBarPosition(newMode, mDisplayController.getInfo());
- mMode = newMode;
+ public void addNavigationModeChangedCallback(Runnable callback) {
+ DisplayController.DisplayInfoChangeListener listener = (context, info, flags) -> {
+ if ((flags & CHANGE_NAVIGATION_MODE) != 0) {
+ callback.run();
+ }
+ };
+ mDisplayController.addChangeListener(listener);
+ callback.run();
+ runOnDestroy(() -> mDisplayController.removeChangeListener(listener));
}
@Override
public void onDisplayInfoChanged(Context context, Info info, int flags) {
- if ((flags & CHANGE_ROTATION) != 0) {
+ if ((flags & (CHANGE_ROTATION | CHANGE_NAVIGATION_MODE)) != 0) {
+ mMode = info.navigationMode;
mNavBarPosition = new NavBarPosition(mMode, info);
+
+ if (mMode == NO_BUTTON) {
+ mExclusionListener.register();
+ } else {
+ mExclusionListener.unregister();
+ }
}
}
- @Override
public void onOneHandedModeChanged(int newGesturalHeight) {
mRotationTouchHelper.setGesturalHeight(newGesturalHeight);
}
/**
- * @return the current navigation mode for the device.
- */
- public SysUINavigationMode.Mode getNavMode() {
- return mMode;
- }
-
- /**
* @return the nav bar position for the current nav bar mode and display rotation.
*/
public NavBarPosition getNavBarPosition() {
@@ -389,11 +347,17 @@
}
/**
- * @return whether the given running task info matches the gesture-blocked activity.
+ * Sets the task id where gestures should be blocked
*/
- public boolean isGestureBlockedActivity(ActivityManager.RunningTaskInfo runningTaskInfo) {
- return runningTaskInfo != null
- && mGestureBlockedActivities.contains(runningTaskInfo.topActivity);
+ public void setGestureBlockingTaskId(int taskId) {
+ mGestureBlockingTaskId = taskId;
+ }
+
+ /**
+ * @return whether the given running task info matches the gesture-blocked task.
+ */
+ public boolean isGestureBlockedTask(CachedTaskInfo taskInfo) {
+ return taskInfo != null && taskInfo.getTaskId() == mGestureBlockingTaskId;
}
/**
@@ -457,10 +421,17 @@
}
/**
+ * @return whether notification panel is expanded
+ */
+ public boolean isNotificationPanelExpanded() {
+ return (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0;
+ }
+
+ /**
* @return whether the global actions dialog is showing
*/
- public boolean isGlobalActionsShowing() {
- return (mSystemUiStateFlags & SYSUI_STATE_GLOBAL_ACTIONS_SHOWING) != 0;
+ public boolean isSystemUiDialogShowing() {
+ return (mSystemUiStateFlags & SYSUI_STATE_DIALOG_SHOWING) != 0;
}
/**
@@ -579,8 +550,7 @@
if (mIsOneHandedModeEnabled) {
final Info displayInfo = mDisplayController.getInfo();
return (mRotationTouchHelper.touchInOneHandedModeRegion(ev)
- && displayInfo.rotation != Surface.ROTATION_90
- && displayInfo.rotation != Surface.ROTATION_270);
+ && (displayInfo.currentSize.x < displayInfo.currentSize.y));
}
return false;
}
@@ -601,6 +571,12 @@
return mRotationTouchHelper;
}
+ /** Returns whether IME is rendering nav buttons, and IME is currently showing. */
+ public boolean isImeRenderingNavButtons() {
+ return mCanImeRenderGesturalNavButtons && mMode == NO_BUTTON
+ && ((mSystemUiStateFlags & SYSUI_STATE_IME_SHOWING) != 0);
+ }
+
public void dump(PrintWriter pw) {
pw.println("DeviceState:");
pw.println(" canStartSystemGesture=" + canStartSystemGesture());
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index 5d77a6e..1634c08 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -54,7 +54,7 @@
* Singleton class to load and manage recents model.
*/
@TargetApi(Build.VERSION_CODES.O)
-public class RecentsModel extends TaskStackChangeListener implements IconChangeListener {
+public class RecentsModel implements IconChangeListener, TaskStackChangeListener {
// We do not need any synchronization for this variable as its only written on UI thread.
public static final MainThreadInitializedObject<RecentsModel> INSTANCE =
@@ -165,7 +165,7 @@
}
@Override
- public void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) {
+ public boolean onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) {
mThumbnailCache.updateTaskSnapShot(taskId, snapshot);
for (int i = mThumbnailChangeListeners.size() - 1; i >= 0; i--) {
@@ -174,6 +174,7 @@
task.thumbnail = snapshot;
}
}
+ return true;
}
@Override
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index ed1a06d..c3ea256 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -22,11 +22,12 @@
import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
import com.android.quickstep.util.AnimatorControllerWithResistance;
-import com.android.quickstep.util.LauncherSplitScreenListener;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import java.util.ArrayList;
+
/**
* Glues together the necessary components to animate a remote target using a
* {@link TaskViewSimulator}
@@ -48,8 +49,7 @@
* running tasks
*/
public RemoteTargetGluer(Context context, BaseActivityInterface sizingStrategy) {
- int[] splitIds = LauncherSplitScreenListener.INSTANCE.getNoCreate()
- .getRunningSplitTaskIds();
+ int[] splitIds = TopTaskTracker.INSTANCE.get(context).getRunningSplitTaskIds();
mRemoteTargetHandles = createHandles(context, sizingStrategy, splitIds.length == 2 ? 2 : 1);
}
@@ -71,7 +71,7 @@
* Length of targets.apps should match that of {@link #mRemoteTargetHandles}.
*
* If split screen may be active when this is called, you might want to use
- * {@link #assignTargetsForSplitScreen(RemoteAnimationTargets)}
+ * {@link #assignTargetsForSplitScreen(Context, RemoteAnimationTargets)}
*/
public RemoteTargetHandle[] assignTargets(RemoteAnimationTargets targets) {
for (int i = 0; i < mRemoteTargetHandles.length; i++) {
@@ -88,9 +88,9 @@
* apps in targets.apps to that of the _active_ split screened tasks.
* See {@link #assignTargetsForSplitScreen(RemoteAnimationTargets, int[])}
*/
- public RemoteTargetHandle[] assignTargetsForSplitScreen(RemoteAnimationTargets targets) {
- int[] splitIds = LauncherSplitScreenListener.INSTANCE.getNoCreate()
- .getRunningSplitTaskIds();
+ public RemoteTargetHandle[] assignTargetsForSplitScreen(
+ Context context, RemoteAnimationTargets targets) {
+ int[] splitIds = TopTaskTracker.INSTANCE.get(context).getRunningSplitTaskIds();
return assignTargetsForSplitScreen(targets, splitIds);
}
@@ -119,8 +119,8 @@
// remoteTargetHandle[0] denotes topLeft task, so we pass in the bottomRight to exclude,
// vice versa
mStagedSplitBounds = new StagedSplitBounds(
- topLeftTarget.screenSpaceBounds,
- bottomRightTarget.screenSpaceBounds, splitIds[0], splitIds[1]);
+ topLeftTarget.startScreenSpaceBounds,
+ bottomRightTarget.startScreenSpaceBounds, splitIds[0], splitIds[1]);
mRemoteTargetHandles[0].mTransformParams.setTargetSet(
createRemoteAnimationTargetsForTarget(targets, bottomRightTarget));
mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(topLeftTarget,
@@ -144,20 +144,29 @@
*/
private RemoteAnimationTargets createRemoteAnimationTargetsForTarget(
RemoteAnimationTargets targets,
- @Nullable RemoteAnimationTargetCompat targetToExclude) {
- int finalLength = targets.unfilteredApps.length - (targetToExclude == null ? 0 : 1);
- RemoteAnimationTargetCompat[] targetsWithoutExcluded =
- new RemoteAnimationTargetCompat[finalLength];
- int i = 0;
+ RemoteAnimationTargetCompat targetToExclude) {
+ ArrayList<RemoteAnimationTargetCompat> targetsWithoutExcluded =
+ new ArrayList<RemoteAnimationTargetCompat>();
+
for (RemoteAnimationTargetCompat targetCompat : targets.unfilteredApps) {
if (targetCompat == targetToExclude) {
continue;
}
- targetsWithoutExcluded[i] = targetCompat;
- i++;
+ if (targetToExclude != null
+ && targetToExclude.taskInfo != null
+ && targetCompat.taskInfo != null
+ && targetToExclude.taskInfo.parentTaskId == targetCompat.taskInfo.taskId) {
+ // Also exclude corresponding parent task
+ continue;
+ }
+
+ targetsWithoutExcluded.add(targetCompat);
}
- return new RemoteAnimationTargets(targetsWithoutExcluded,
- targets.wallpapers, targets.nonApps, targets.targetMode);
+ final RemoteAnimationTargetCompat[] filteredApps =
+ targetsWithoutExcluded.toArray(
+ new RemoteAnimationTargetCompat[targetsWithoutExcluded.size()]);
+ return new RemoteAnimationTargets(
+ filteredApps, targets.wallpapers, targets.nonApps, targets.targetMode);
}
public RemoteTargetHandle[] getRemoteTargetHandles() {
diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
index 35efddf..f1e20db 100644
--- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java
+++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
@@ -20,9 +20,11 @@
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;
import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
+import static com.android.launcher3.util.DisplayController.CHANGE_SUPPORTED_BOUNDS;
+import static com.android.launcher3.util.DisplayController.NavigationMode.THREE_BUTTONS;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-import static com.android.quickstep.SysUINavigationMode.Mode.THREE_BUTTONS;
import android.content.Context;
import android.content.res.Resources;
@@ -33,6 +35,7 @@
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.DisplayController.NavigationMode;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.systemui.shared.system.QuickStepContract;
@@ -42,22 +45,22 @@
import java.io.PrintWriter;
import java.util.ArrayList;
-public class RotationTouchHelper implements
- SysUINavigationMode.NavigationModeChangeListener,
- DisplayInfoChangeListener {
+/**
+ * Helper class for transforming touch events
+ */
+public class RotationTouchHelper implements DisplayInfoChangeListener {
public static final MainThreadInitializedObject<RotationTouchHelper> INSTANCE =
new MainThreadInitializedObject<>(RotationTouchHelper::new);
private OrientationTouchTransformer mOrientationTouchTransformer;
private DisplayController mDisplayController;
- private SysUINavigationMode mSysUiNavMode;
private int mDisplayId;
private int mDisplayRotation;
private final ArrayList<Runnable> mOnDestroyActions = new ArrayList<>();
- private SysUINavigationMode.Mode mMode = THREE_BUTTONS;
+ private NavigationMode mMode = THREE_BUTTONS;
private TaskStackChangeListener mFrozenTaskListener = new TaskStackChangeListener() {
@Override
@@ -71,7 +74,6 @@
@Override
public void onActivityRotation(int displayId) {
- super.onActivityRotation(displayId);
// This always gets called before onDisplayInfoChanged() so we know how to process
// the rotation in that method. This is done to avoid having a race condition between
// the sensor readings and onDisplayInfoChanged() call
@@ -144,16 +146,16 @@
}
mDisplayController = DisplayController.INSTANCE.get(mContext);
Resources resources = mContext.getResources();
- mSysUiNavMode = SysUINavigationMode.INSTANCE.get(mContext);
mDisplayId = DEFAULT_DISPLAY;
mOrientationTouchTransformer = new OrientationTouchTransformer(resources, mMode,
() -> QuickStepContract.getWindowCornerRadius(mContext));
// Register for navigation mode changes
- SysUINavigationMode.Mode newMode = mSysUiNavMode.addModeChangeListener(this);
- onNavModeChangedInternal(newMode, newMode.hasGestures);
- runOnDestroy(() -> mSysUiNavMode.removeModeChangeListener(this));
+ mDisplayController.addChangeListener(this);
+ DisplayController.Info info = mDisplayController.getInfo();
+ onDisplayInfoChangedInternal(info, CHANGE_ALL, info.navigationMode.hasGestures);
+ runOnDestroy(() -> mDisplayController.removeChangeListener(this));
mOrientationListener = new OrientationEventListener(mContext) {
@Override
@@ -242,66 +244,57 @@
event.getY(pointerIndex));
}
-
@Override
- public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) {
- onNavModeChangedInternal(newMode, false);
+ public void onDisplayInfoChanged(Context context, Info info, int flags) {
+ onDisplayInfoChangedInternal(info, flags, false);
}
- /**
- * @param forceRegister if {@code true}, this will register {@link #mFrozenTaskListener} via
- * {@link #setupOrientationSwipeHandler()}
- */
- private void onNavModeChangedInternal(SysUINavigationMode.Mode newMode, boolean forceRegister) {
- mDisplayController.removeChangeListener(this);
- mDisplayController.addChangeListener(this);
- onDisplayInfoChanged(mContext, mDisplayController.getInfo(), CHANGE_ALL);
+ private void onDisplayInfoChangedInternal(Info info, int flags, boolean forceRegister) {
+ if ((flags & (CHANGE_ROTATION | CHANGE_ACTIVE_SCREEN | CHANGE_NAVIGATION_MODE
+ | CHANGE_SUPPORTED_BOUNDS)) != 0) {
+ mDisplayRotation = info.rotation;
- mOrientationTouchTransformer.setNavigationMode(newMode, mDisplayController.getInfo(),
- mContext.getResources());
+ if (mMode.hasGestures) {
+ updateGestureTouchRegions();
+ mOrientationTouchTransformer.createOrAddTouchRegion(info);
+ mCurrentAppRotation = mDisplayRotation;
- if (forceRegister || (!mMode.hasGestures && newMode.hasGestures)) {
- setupOrientationSwipeHandler();
- } else if (mMode.hasGestures && !newMode.hasGestures){
- destroyOrientationSwipeHandlerCallback();
+ /* Update nav bars on the following:
+ * a) if this is coming from an activity rotation OR
+ * aa) we launch an app in the orientation that user is already in
+ * b) We're not in overview, since overview will always be portrait (w/o home
+ * rotation)
+ * c) We're actively in quickswitch mode
+ */
+ if ((mPrioritizeDeviceRotation
+ || mCurrentAppRotation == mSensorRotation)
+ // switch to an app of orientation user is in
+ && !mInOverview
+ && mTaskListFrozen) {
+ toggleSecondaryNavBarsForRotation();
+ }
+ }
}
- mMode = newMode;
+ if ((flags & CHANGE_NAVIGATION_MODE) != 0) {
+ NavigationMode newMode = info.navigationMode;
+ mOrientationTouchTransformer.setNavigationMode(newMode, mDisplayController.getInfo(),
+ mContext.getResources());
+
+ if (forceRegister || (!mMode.hasGestures && newMode.hasGestures)) {
+ setupOrientationSwipeHandler();
+ } else if (mMode.hasGestures && !newMode.hasGestures) {
+ destroyOrientationSwipeHandlerCallback();
+ }
+
+ mMode = newMode;
+ }
}
public int getDisplayRotation() {
return mDisplayRotation;
}
- @Override
- public void onDisplayInfoChanged(Context context, Info info, int flags) {
- if ((flags & (CHANGE_ROTATION | CHANGE_ACTIVE_SCREEN)) == 0) {
- return;
- }
-
- mDisplayRotation = info.rotation;
-
- if (!mMode.hasGestures) {
- return;
- }
- updateGestureTouchRegions();
- mOrientationTouchTransformer.createOrAddTouchRegion(info);
- mCurrentAppRotation = mDisplayRotation;
-
- /* Update nav bars on the following:
- * a) if this is coming from an activity rotation OR
- * aa) we launch an app in the orientation that user is already in
- * b) We're not in overview, since overview will always be portrait (w/o home rotation)
- * c) We're actively in quickswitch mode
- */
- if ((mPrioritizeDeviceRotation
- || mCurrentAppRotation == mSensorRotation) // switch to an app of orientation user is in
- && !mInOverview
- && mTaskListFrozen) {
- toggleSecondaryNavBarsForRotation();
- }
- }
-
/**
* Sets the gestural height.
*/
diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
index 8e9b668..9667108 100644
--- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -37,7 +37,6 @@
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
import com.android.quickstep.util.AnimatorControllerWithResistance;
-import com.android.quickstep.util.LauncherSplitScreenListener;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
@@ -82,8 +81,7 @@
mGestureState = gestureState;
mIsSwipeForStagedSplit = ENABLE_SPLIT_SELECT.get() &&
- LauncherSplitScreenListener.INSTANCE.getNoCreate()
- .getRunningSplitTaskIds().length > 1;
+ TopTaskTracker.INSTANCE.get(context).getRunningSplitTaskIds().length > 1;
mTargetGluer = new RemoteTargetGluer(mContext, mGestureState.getActivityInterface());
mRemoteTargetHandles = mTargetGluer.getRemoteTargetHandles();
@@ -177,10 +175,6 @@
// No-op
}
- public boolean shouldPlayAtomicWorkspaceReveal() {
- return true;
- }
-
public void setAnimation(RectFSpringAnim anim) { }
public void update(RectF currentRect, float progress, float radius) { }
@@ -188,14 +182,6 @@
public void onCancel() { }
/**
- * @return {@code true} if this factory supports animating an Activity to PiP window on
- * swiping up to home.
- */
- public boolean supportSwipePipToHome() {
- return false;
- }
-
- /**
* @param progress The progress of the animation to the home screen.
* @return The current alpha to set on the animating app window.
*/
@@ -280,6 +266,13 @@
RectF cropRectF = new RectF(taskViewSimulator.getCurrentCropRect());
// Move the startRect to Launcher space as floatingIconView runs in Launcher
Matrix windowToHomePositionMap = new Matrix();
+
+ // If the start rect ends up overshooting too much to the left/right offscreen, bring it
+ // back to fullscreen. This can happen when the recentsScroll value isn't aligned with
+ // the pageScroll value for a given taskView, see b/228829958#comment12
+ mRemoteTargetHandles[0].getTaskViewSimulator().getOrientationState().getOrientationHandler()
+ .fixBoundsForHomeAnimStartRect(startRect, mDp);
+
homeToWindowPositionMap.invert(windowToHomePositionMap);
windowToHomePositionMap.mapRect(startRect);
diff --git a/quickstep/src/com/android/quickstep/SysUINavigationMode.java b/quickstep/src/com/android/quickstep/SysUINavigationMode.java
deleted file mode 100644
index 74f4bea..0000000
--- a/quickstep/src/com/android/quickstep/SysUINavigationMode.java
+++ /dev/null
@@ -1,202 +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;
-
-import static com.android.launcher3.ResourceUtils.INVALID_RESOURCE_HANDLE;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_2_BUTTON;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_3_BUTTON;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON;
-import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-import com.android.launcher3.ResourceUtils;
-import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
-import com.android.launcher3.util.MainThreadInitializedObject;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * Observer for the resource config that specifies the navigation bar mode.
- */
-public class SysUINavigationMode {
-
- public enum Mode {
- THREE_BUTTONS(false, 0, LAUNCHER_NAVIGATION_MODE_3_BUTTON),
- TWO_BUTTONS(true, 1, LAUNCHER_NAVIGATION_MODE_2_BUTTON),
- NO_BUTTON(true, 2, LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON);
-
- public final boolean hasGestures;
- public final int resValue;
- public final LauncherEvent launcherEvent;
-
- Mode(boolean hasGestures, int resValue, LauncherEvent launcherEvent) {
- this.hasGestures = hasGestures;
- this.resValue = resValue;
- this.launcherEvent = launcherEvent;
- }
- }
-
- public static Mode getMode(Context context) {
- return INSTANCE.get(context).getMode();
- }
-
- public static final MainThreadInitializedObject<SysUINavigationMode> INSTANCE =
- new MainThreadInitializedObject<>(SysUINavigationMode::new);
-
- private static final String TAG = "SysUINavigationMode";
- private static final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
- private static final String NAV_BAR_INTERACTION_MODE_RES_NAME =
- "config_navBarInteractionMode";
- private static final String TARGET_OVERLAY_PACKAGE = "android";
-
- private final Context mContext;
- private Mode mMode;
-
- private int mNavBarGesturalHeight;
- private int mNavBarLargerGesturalHeight;
-
- private final List<NavigationModeChangeListener> mChangeListeners =
- new CopyOnWriteArrayList<>();
- private final List<OneHandedModeChangeListener> mOneHandedOverlayChangeListeners =
- new ArrayList<>();
-
- public SysUINavigationMode(Context context) {
- mContext = context;
- initializeMode();
-
- mContext.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- updateMode();
- updateGesturalHeight();
- }
- }, getPackageFilter(TARGET_OVERLAY_PACKAGE, ACTION_OVERLAY_CHANGED));
- }
-
- /** Updates navigation mode when needed. */
- public void updateMode() {
- Mode oldMode = mMode;
- initializeMode();
- if (mMode != oldMode) {
- dispatchModeChange();
- }
- }
-
- private void updateGesturalHeight() {
- int newGesturalHeight = ResourceUtils.getDimenByName(
- ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, mContext.getResources(),
- INVALID_RESOURCE_HANDLE);
-
- if (newGesturalHeight == INVALID_RESOURCE_HANDLE) {
- Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
- return;
- }
-
- if (mNavBarGesturalHeight != newGesturalHeight) {
- mNavBarGesturalHeight = newGesturalHeight;
- }
-
- int newLargerGesturalHeight = ResourceUtils.getDimenByName(
- ResourceUtils.NAVBAR_BOTTOM_GESTURE_LARGER_SIZE, mContext.getResources(),
- INVALID_RESOURCE_HANDLE);
- if (newLargerGesturalHeight == INVALID_RESOURCE_HANDLE) {
- Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
- return;
- }
- if (mNavBarLargerGesturalHeight != newLargerGesturalHeight) {
- mNavBarLargerGesturalHeight = newLargerGesturalHeight;
- dispatchOneHandedOverlayChange();
- }
- }
-
- private void initializeMode() {
- int modeInt = ResourceUtils.getIntegerByName(NAV_BAR_INTERACTION_MODE_RES_NAME,
- mContext.getResources(), INVALID_RESOURCE_HANDLE);
- mNavBarGesturalHeight = ResourceUtils.getDimenByName(
- ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, mContext.getResources(),
- INVALID_RESOURCE_HANDLE);
- mNavBarLargerGesturalHeight = ResourceUtils.getDimenByName(
- ResourceUtils.NAVBAR_BOTTOM_GESTURE_LARGER_SIZE, mContext.getResources(),
- mNavBarGesturalHeight);
-
- if (modeInt == INVALID_RESOURCE_HANDLE) {
- Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
- return;
- }
-
- for (Mode m : Mode.values()) {
- if (m.resValue == modeInt) {
- mMode = m;
- }
- }
- }
-
- private void dispatchModeChange() {
- for (NavigationModeChangeListener listener : mChangeListeners) {
- listener.onNavigationModeChanged(mMode);
- }
- }
-
- private void dispatchOneHandedOverlayChange() {
- for (OneHandedModeChangeListener listener : mOneHandedOverlayChangeListeners) {
- listener.onOneHandedModeChanged(mNavBarLargerGesturalHeight);
- }
- }
-
- public Mode addModeChangeListener(NavigationModeChangeListener listener) {
- mChangeListeners.add(listener);
- return mMode;
- }
-
- public void removeModeChangeListener(NavigationModeChangeListener listener) {
- mChangeListeners.remove(listener);
- }
-
- public int addOneHandedOverlayChangeListener(OneHandedModeChangeListener listener) {
- mOneHandedOverlayChangeListeners.add(listener);
- return mNavBarLargerGesturalHeight;
- }
-
- public void removeOneHandedOverlayChangeListener(OneHandedModeChangeListener listener) {
- mOneHandedOverlayChangeListeners.remove(listener);
- }
-
- public Mode getMode() {
- return mMode;
- }
-
- public void dump(PrintWriter pw) {
- pw.println("SysUINavigationMode:");
- pw.println(" mode=" + mMode.name());
- pw.println(" mNavBarGesturalHeight=:" + mNavBarGesturalHeight);
- }
-
- public interface NavigationModeChangeListener {
- void onNavigationModeChanged(Mode newMode);
- }
-
- public interface OneHandedModeChangeListener {
- void onOneHandedModeChanged(int newGesturalHeight);
- }
-}
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 67e7f88..39d8b54 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -17,6 +17,7 @@
import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
+import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.app.PendingIntent;
@@ -38,14 +39,19 @@
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
+import android.window.IOnBackInvokedCallback;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.RemoteTransitionCompat;
-import com.android.systemui.shared.system.smartspace.ISmartspaceCallback;
-import com.android.systemui.shared.system.smartspace.ISmartspaceTransitionController;
+import com.android.systemui.shared.system.smartspace.ILauncherUnlockAnimationController;
+import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
+import com.android.systemui.shared.system.smartspace.SmartspaceState;
+import com.android.wm.shell.back.IBackAnimation;
import com.android.wm.shell.onehanded.IOneHanded;
import com.android.wm.shell.pip.IPip;
import com.android.wm.shell.pip.IPipAnimationListener;
@@ -64,8 +70,7 @@
/**
* Holds the reference to SystemUI.
*/
-public class SystemUiProxy implements ISystemUiProxy,
- SysUINavigationMode.NavigationModeChangeListener {
+public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayInfoChangeListener {
private static final String TAG = SystemUiProxy.class.getSimpleName();
public static final MainThreadInitializedObject<SystemUiProxy> INSTANCE =
@@ -73,12 +78,13 @@
private ISystemUiProxy mSystemUiProxy;
private IPip mPip;
- private ISmartspaceTransitionController mSmartspaceTransitionController;
+ private ISysuiUnlockAnimationController mSysuiUnlockAnimationController;
private ISplitScreen mSplitScreen;
private IOneHanded mOneHanded;
private IShellTransitions mShellTransitions;
private IStartingWindow mStartingWindow;
private IRecentTasks mRecentTasks;
+ private IBackAnimation mBackAnimation;
private final DeathRecipient mSystemUiProxyDeathRecipient = () -> {
MAIN_EXECUTOR.execute(() -> clearProxy());
};
@@ -90,9 +96,10 @@
private IPipAnimationListener mPipAnimationListener;
private ISplitScreenListener mSplitScreenListener;
private IStartingWindowListener mStartingWindowListener;
- private ISmartspaceCallback mSmartspaceCallback;
+ private ILauncherUnlockAnimationController mPendingLauncherUnlockAnimationController;
private IRecentTasksListener mRecentTasksListener;
private final ArrayList<RemoteTransitionCompat> mRemoteTransitions = new ArrayList<>();
+ private IOnBackInvokedCallback mBackToLauncherCallback;
// Used to dedupe calls to SystemUI
private int mLastShelfHeight;
@@ -106,13 +113,15 @@
private int mLastSystemUiStateFlags;
public SystemUiProxy(Context context) {
- SysUINavigationMode.INSTANCE.get(context).addModeChangeListener(this);
+ DisplayController.INSTANCE.get(context).addChangeListener(this);
}
@Override
- public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) {
- // Whenever the nav mode changes, force reset the nav button alpha
- setNavBarButtonAlpha(1f, false);
+ public void onDisplayInfoChanged(Context context, Info info, int flags) {
+ if ((flags & CHANGE_NAVIGATION_MODE) != 0) {
+ // Whenever the nav mode changes, force reset the nav button alpha
+ setNavBarButtonAlpha(1f, false);
+ }
}
@Override
@@ -157,7 +166,8 @@
public void setProxy(ISystemUiProxy proxy, IPip pip, ISplitScreen splitScreen,
IOneHanded oneHanded, IShellTransitions shellTransitions,
IStartingWindow startingWindow, IRecentTasks recentTasks,
- ISmartspaceTransitionController smartSpaceTransitionController) {
+ ISysuiUnlockAnimationController sysuiUnlockAnimationController,
+ IBackAnimation backAnimation) {
unlinkToDeath();
mSystemUiProxy = proxy;
mPip = pip;
@@ -165,8 +175,9 @@
mOneHanded = oneHanded;
mShellTransitions = shellTransitions;
mStartingWindow = startingWindow;
- mSmartspaceTransitionController = smartSpaceTransitionController;
+ mSysuiUnlockAnimationController = sysuiUnlockAnimationController;
mRecentTasks = recentTasks;
+ mBackAnimation = backAnimation;
linkToDeath();
// re-attach the listeners once missing due to setProxy has not been initialized yet.
if (mPipAnimationListener != null && mPip != null) {
@@ -178,8 +189,10 @@
if (mStartingWindowListener != null && mStartingWindow != null) {
setStartingWindowListener(mStartingWindowListener);
}
- if (mSmartspaceCallback != null && mSmartspaceTransitionController != null) {
- setSmartspaceCallback(mSmartspaceCallback);
+ if (mPendingLauncherUnlockAnimationController != null
+ && mSysuiUnlockAnimationController != null) {
+ setLauncherUnlockAnimationController(mPendingLauncherUnlockAnimationController);
+ mPendingLauncherUnlockAnimationController = null;
}
for (int i = mRemoteTransitions.size() - 1; i >= 0; --i) {
registerRemoteTransition(mRemoteTransitions.get(i));
@@ -187,6 +200,9 @@
if (mRecentTasksListener != null && mRecentTasks != null) {
registerRecentTasksListener(mRecentTasksListener);
}
+ if (mBackAnimation != null && mBackToLauncherCallback != null) {
+ setBackToLauncherCallback(mBackToLauncherCallback);
+ }
if (mPendingSetNavButtonAlpha != null) {
mPendingSetNavButtonAlpha.run();
@@ -195,7 +211,7 @@
}
public void clearProxy() {
- setProxy(null, null, null, null, null, null, null, null);
+ setProxy(null, null, null, null, null, null, null, null, null);
}
// TODO(141886704): Find a way to remove this
@@ -478,6 +494,17 @@
}
}
+ @Override
+ public void toggleNotificationPanel() {
+ if (mSystemUiProxy != null) {
+ try {
+ mSystemUiProxy.toggleNotificationPanel();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call toggleNotificationPanel", e);
+ }
+ }
+ }
+
//
// Pip
//
@@ -526,11 +553,16 @@
return null;
}
- public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds,
+ /**
+ * Notifies WM Shell that launcher has finished all the animation for swipe to home. WM Shell
+ * can choose to fade out the overlay when entering PIP is finished, and WM Shell should be
+ * responsible for cleaning up the overlay.
+ */
+ public void stopSwipePipToHome(int taskId, ComponentName componentName, Rect destinationBounds,
SurfaceControl overlay) {
if (mPip != null) {
try {
- mPip.stopSwipePipToHome(componentName, destinationBounds, overlay);
+ mPip.stopSwipePipToHome(taskId, componentName, destinationBounds, overlay);
} catch (RemoteException e) {
Log.w(TAG, "Failed call stopSwipePipToHome");
}
@@ -593,6 +625,20 @@
}
}
+ public void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent,
+ Intent fillInIntent, int taskId, Bundle mainOptions, Bundle sideOptions,
+ @SplitConfigurationOptions.StagePosition int sidePosition, float splitRatio,
+ RemoteAnimationAdapter adapter) {
+ if (mSystemUiProxy != null) {
+ try {
+ mSplitScreen.startIntentAndTaskWithLegacyTransition(pendingIntent, fillInIntent,
+ taskId, mainOptions, sideOptions, sidePosition, splitRatio, adapter);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call startTasksWithLegacyTransition");
+ }
+ }
+ }
+
public void startShortcut(String packageName, String shortcutId, int position,
Bundle options, UserHandle user) {
if (mSplitScreen != null) {
@@ -630,14 +676,12 @@
* Call this when going to recents so that shell can set-up and provide appropriate leashes
* for animation (eg. DividerBar).
*
- * @param cancel true if recents starting is being cancelled.
* @return RemoteAnimationTargets of windows that need to animate but only exist in shell.
*/
- public RemoteAnimationTarget[] onGoingToRecentsLegacy(boolean cancel,
- RemoteAnimationTarget[] apps) {
+ public RemoteAnimationTarget[] onGoingToRecentsLegacy(RemoteAnimationTarget[] apps) {
if (mSplitScreen != null) {
try {
- return mSplitScreen.onGoingToRecentsLegacy(cancel, apps);
+ return mSplitScreen.onGoingToRecentsLegacy(apps);
} catch (RemoteException e) {
Log.w(TAG, "Failed call onGoingToRecentsLegacy");
}
@@ -645,6 +689,17 @@
return null;
}
+ public RemoteAnimationTarget[] onStartingSplitLegacy(RemoteAnimationTarget[] apps) {
+ if (mSplitScreen != null) {
+ try {
+ return mSplitScreen.onStartingSplitLegacy(apps);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call onStartingSplitLegacy");
+ }
+ }
+ return null;
+ }
+
//
// One handed
//
@@ -720,15 +775,42 @@
// SmartSpace transitions
//
- public void setSmartspaceCallback(ISmartspaceCallback callback) {
- if (mSmartspaceTransitionController != null) {
+ /**
+ * Sets the instance of {@link ILauncherUnlockAnimationController} that System UI should use to
+ * control the launcher side of the unlock animation. This will also cause us to dispatch the
+ * current state of the smartspace to System UI (this will subsequently happen if the state
+ * changes).
+ */
+ public void setLauncherUnlockAnimationController(
+ ILauncherUnlockAnimationController controller) {
+ if (mSysuiUnlockAnimationController != null) {
try {
- mSmartspaceTransitionController.setSmartspace(callback);
+ mSysuiUnlockAnimationController.setLauncherUnlockController(controller);
+
+ if (controller != null) {
+ controller.dispatchSmartspaceStateToSysui();
+ }
} catch (RemoteException e) {
Log.w(TAG, "Failed call setStartingWindowListener", e);
}
+ } else {
+ mPendingLauncherUnlockAnimationController = controller;
}
- mSmartspaceCallback = callback;
+ }
+
+ /**
+ * Tells System UI that the Launcher's smartspace state has been updated, so that it can prepare
+ * the unlock animation accordingly.
+ */
+ public void notifySysuiSmartspaceStateUpdated(SmartspaceState state) {
+ if (mSysuiUnlockAnimationController != null) {
+ try {
+ mSysuiUnlockAnimationController.onLauncherSmartspaceStateUpdated(state);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call notifySysuiSmartspaceStateUpdated", e);
+ e.printStackTrace();
+ }
+ }
}
//
@@ -757,11 +839,65 @@
mRecentTasksListener = null;
}
+ //
+ // Back navigation transitions
+ //
+
+ /** Sets the launcher {@link android.window.IOnBackInvokedCallback} to shell */
+ public void setBackToLauncherCallback(IOnBackInvokedCallback callback) {
+ mBackToLauncherCallback = callback;
+ if (mBackAnimation == null) {
+ return;
+ }
+ try {
+ mBackAnimation.setBackToLauncherCallback(callback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed call setBackToLauncherCallback", e);
+ }
+ }
+
+ /** Clears the previously registered {@link IOnBackInvokedCallback}.
+ *
+ * @param callback The previously registered callback instance.
+ */
+ public void clearBackToLauncherCallback(IOnBackInvokedCallback callback) {
+ if (mBackToLauncherCallback != callback) {
+ return;
+ }
+ mBackToLauncherCallback = null;
+ if (mBackAnimation == null) {
+ return;
+ }
+ try {
+ mBackAnimation.clearBackToLauncherCallback();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed call clearBackToLauncherCallback", e);
+ }
+ }
+
+ /**
+ * Notifies shell that all back to launcher animations have finished (including the transition
+ * that plays after the gesture is committed and before the app is closed.
+ */
+ public void onBackToLauncherAnimationFinished() {
+ if (mBackAnimation != null) {
+ try {
+ mBackAnimation.onBackToLauncherAnimationFinished();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call onBackAnimationFinished", e);
+ }
+ }
+ }
+
public ArrayList<GroupedRecentTaskInfo> getRecentTasks(int numTasks, int userId) {
if (mRecentTasks != null) {
try {
- return new ArrayList<>(Arrays.asList(mRecentTasks.getRecentTasks(numTasks,
- RECENT_IGNORE_UNAVAILABLE, userId)));
+ final GroupedRecentTaskInfo[] rawTasks = mRecentTasks.getRecentTasks(numTasks,
+ RECENT_IGNORE_UNAVAILABLE, userId);
+ if (rawTasks == null) {
+ return new ArrayList<>();
+ }
+ return new ArrayList<>(Arrays.asList(rawTasks));
} catch (RemoteException e) {
Log.w(TAG, "Failed call getRecentTasks", e);
}
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 82c7c08..54f457d 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -23,9 +23,9 @@
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
import android.app.ActivityManager;
+import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
-import android.os.Bundle;
import android.os.SystemProperties;
import android.util.Log;
import android.view.RemoteAnimationTarget;
@@ -35,6 +35,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
+import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -44,12 +45,14 @@
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
-import java.util.Arrays;
+import java.util.ArrayList;
import java.util.HashMap;
public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener {
public static final boolean ENABLE_SHELL_TRANSITIONS =
- SystemProperties.getBoolean("persist.debug.shell_transit", false);
+ SystemProperties.getBoolean("persist.wm.debug.shell_transit", false);
+ public static final boolean SHELL_TRANSITIONS_ROTATION = ENABLE_SHELL_TRANSITIONS
+ && SystemProperties.getBoolean("persist.wm.debug.shell_transit_rotate", false);
private RecentsAnimationController mController;
private RecentsAnimationCallbacks mCallbacks;
@@ -154,15 +157,29 @@
RemoteAnimationTargetCompat appearedTaskTarget = appearedTaskTargets[0];
BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
// Convert appTargets to type RemoteAnimationTarget for all apps except Home app
- RemoteAnimationTarget[] nonHomeApps = Arrays.stream(appearedTaskTargets)
- .filter(remoteAnimationTarget ->
- remoteAnimationTarget.activityType != ACTIVITY_TYPE_HOME)
+ final ArrayList<RemoteAnimationTargetCompat> tmpNonHomeApps = new ArrayList<>();
+ final ArrayList<RemoteAnimationTargetCompat> tmpHomeApps = new ArrayList<>();
+ for (RemoteAnimationTargetCompat compat : appearedTaskTargets) {
+ if (compat.activityType != ACTIVITY_TYPE_HOME) {
+ tmpNonHomeApps.add(compat);
+ } else {
+ tmpHomeApps.add(compat);
+ }
+ }
+ RemoteAnimationTarget[] nonHomeApps = tmpNonHomeApps.stream()
.map(RemoteAnimationTargetCompat::unwrap)
.toArray(RemoteAnimationTarget[]::new);
+ RemoteAnimationTarget[] homeApps = tmpHomeApps.stream()
+ .map(RemoteAnimationTargetCompat::unwrap)
+ .toArray(RemoteAnimationTarget[]::new);
+ if (homeApps.length > 0
+ && activityInterface.getCreatedActivity() instanceof RecentsActivity) {
+ ((RecentsActivity) activityInterface.getCreatedActivity()).startHome();
+ return;
+ }
RemoteAnimationTarget[] nonAppTargets =
- SystemUiProxy.INSTANCE.getNoCreate()
- .onGoingToRecentsLegacy(false, nonHomeApps);
+ SystemUiProxy.INSTANCE.getNoCreate().onStartingSplitLegacy(nonHomeApps);
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode()
&& activityInterface.getCreatedActivity() != null) {
@@ -175,6 +192,10 @@
RemoteAnimationTargetCompat.wrap(nonAppTargets) /* nonApps */);
return;
}
+ } else if (nonAppTargets != null && nonAppTargets.length > 0) {
+ TaskViewUtils.createSplitAuxiliarySurfacesAnimator(
+ RemoteAnimationTargetCompat.wrap(nonAppTargets) /* nonApps */,
+ true /*shown*/, dividerAnimator -> dividerAnimator.start());
}
if (mController != null) {
if (mLastAppearedTaskTarget == null
@@ -187,6 +208,24 @@
}
}
}
+
+ @Override
+ public boolean onSwitchToScreenshot(Runnable onFinished) {
+ if (!ENABLE_QUICKSTEP_LIVE_TILE.get() || !activityInterface.isInLiveTileMode()
+ || activityInterface.getCreatedActivity() == null) {
+ // No need to switch since tile is already a screenshot.
+ onFinished.run();
+ } else {
+ final RecentsView recentsView =
+ activityInterface.getCreatedActivity().getOverviewPanel();
+ if (recentsView != null) {
+ recentsView.switchToScreenshot(onFinished);
+ } else {
+ onFinished.run();
+ }
+ }
+ return true;
+ }
});
final long eventTime = gestureState.getSwipeUpStartTimeMs();
mCallbacks.addListener(gestureState);
@@ -196,9 +235,17 @@
RemoteTransitionCompat transition = new RemoteTransitionCompat(mCallbacks,
mController != null ? mController.getController() : null,
mCtx.getIApplicationThread());
- Bundle options = ActivityOptionsCompat.makeRemoteTransition(transition)
- .setTransientLaunch().toBundle();
- mCtx.startActivity(intent, options);
+ final ActivityOptions options = ActivityOptionsCompat.makeRemoteTransition(transition);
+ // Allowing to pause Home if Home is top activity and Recents is not Home. So when user
+ // start home when recents animation is playing, the home activity can be resumed again
+ // to let the transition controller collect Home activity.
+ CachedTaskInfo cti = gestureState.getRunningTask();
+ boolean homeIsOnTop = cti != null && cti.isHomeTask();
+ if (!homeIsOnTop) {
+ options.setTransientLaunch();
+ }
+ options.setSourceInfo(ActivityOptions.SourceInfo.TYPE_RECENTS_ANIMATION, eventTime);
+ UI_HELPER_EXECUTOR.execute(() -> mCtx.startActivity(intent, options.toBundle()));
} else {
UI_HELPER_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
.startRecentsActivity(intent, eventTime, mCallbacks, null, null));
diff --git a/quickstep/src/com/android/quickstep/TaskIconCache.java b/quickstep/src/com/android/quickstep/TaskIconCache.java
index fa61fff..3803f03 100644
--- a/quickstep/src/com/android/quickstep/TaskIconCache.java
+++ b/quickstep/src/com/android/quickstep/TaskIconCache.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.uioverrides.QuickstepLauncher.GO_LOW_RAM_RECENTS_ENABLED;
import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
+import android.app.ActivityManager;
import android.app.ActivityManager.TaskDescription;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -26,7 +27,6 @@
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.SparseArray;
@@ -37,6 +37,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.BaseIconFactory;
+import com.android.launcher3.icons.BaseIconFactory.IconOptions;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.IconProvider;
import com.android.launcher3.util.DisplayController;
@@ -48,7 +49,6 @@
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.system.PackageManagerWrapper;
-import com.android.systemui.shared.system.TaskDescriptionCompat;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -64,6 +64,8 @@
private final Context mContext;
private final TaskKeyLruCache<TaskCacheEntry> mIconCache;
private final SparseArray<BitmapInfo> mDefaultIcons = new SparseArray<>();
+ private BitmapInfo mDefaultIconBase = null;
+
private final IconProvider mIconProvider;
private BaseIconFactory mIconFactory;
@@ -152,9 +154,8 @@
// Load icon
// TODO: Load icon resource (b/143363444)
- Bitmap icon = TaskDescriptionCompat.getIcon(desc, key.userId);
+ Bitmap icon = getIcon(desc, key.userId);
if (icon != null) {
- /* isInstantApp */
entry.icon = getBitmapInfo(
new BitmapDrawable(mContext.getResources(), icon),
key.userId,
@@ -192,6 +193,14 @@
return entry;
}
+ private Bitmap getIcon(ActivityManager.TaskDescription desc, int userId) {
+ if (desc.getInMemoryIcon() != null) {
+ return desc.getInMemoryIcon();
+ }
+ return ActivityManager.TaskDescription.loadTaskDescriptionIcon(
+ desc.getIconFilename(), userId);
+ }
+
private String getBadgedContentDescription(ActivityInfo info, int userId, TaskDescription td) {
PackageManager pm = mContext.getPackageManager();
String taskLabel = td == null ? null : Utilities.trim(td.getLabel());
@@ -210,14 +219,23 @@
@WorkerThread
private Drawable getDefaultIcon(int userId) {
synchronized (mDefaultIcons) {
- BitmapInfo info = mDefaultIcons.get(userId);
- if (info == null) {
+ if (mDefaultIconBase == null) {
try (BaseIconFactory bif = getIconFactory()) {
- info = bif.makeDefaultIcon(UserHandle.of(userId));
+ mDefaultIconBase = bif.makeDefaultIcon();
}
- mDefaultIcons.put(userId, info);
}
- return info.newIcon(mContext);
+
+ int index;
+ if ((index = mDefaultIcons.indexOfKey(userId)) >= 0) {
+ return mDefaultIcons.valueAt(index).newIcon(mContext);
+ } else {
+ try (BaseIconFactory li = getIconFactory()) {
+ BitmapInfo info = mDefaultIconBase.withFlags(
+ li.getBitmapFlagOp(new IconOptions().setUser(UserHandle.of(userId))));
+ mDefaultIcons.put(userId, info);
+ return info.newIcon(mContext);
+ }
+ }
}
}
@@ -229,8 +247,8 @@
bif.setWrapperBackgroundColor(primaryColor);
// User version code O, so that the icon is always wrapped in an adaptive icon container
- return bif.createBadgedIconBitmap(drawable, UserHandle.of(userId),
- Build.VERSION_CODES.O, isInstantApp);
+ return bif.createBadgedIconBitmap(drawable,
+ new IconOptions().setUser(UserHandle.of(userId)).setInstantApp(isInstantApp));
}
}
@@ -238,7 +256,7 @@
private BaseIconFactory getIconFactory() {
if (mIconFactory == null) {
mIconFactory = new BaseIconFactory(mContext,
- DisplayController.INSTANCE.get(mContext).getInfo().densityDpi,
+ DisplayController.INSTANCE.get(mContext).getInfo().getDensityDpi(),
mContext.getResources().getDimensionPixelSize(R.dimen.taskbar_icon_size));
}
return mIconFactory;
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 276e1c2..3ef1332 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -46,6 +46,7 @@
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.ResourceBasedOverride;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
+import com.android.launcher3.views.ActivityContext;
import com.android.quickstep.TaskShortcutFactory.SplitSelectSystemShortcut;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.views.OverviewActionsView;
@@ -55,7 +56,6 @@
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;
import java.util.ArrayList;
import java.util.List;
@@ -119,8 +119,8 @@
* * There aren't at least 2 tasks in overview to show split options for
* * Device is in "Lock task mode"
* * The taskView to show split options for is the focused task AND we haven't started
- * scrolling in overview (if we haven't scrolled, there's a split overview action button so
- * we don't need this menu option)
+ * scrolling in overview (if we haven't scrolled, there's a split overview action button so
+ * we don't need this menu option)
*/
private static void addSplitOptions(List<SystemShortcut> outShortcuts,
BaseDraggingActivity activity, TaskView taskView, DeviceProfile deviceProfile) {
@@ -130,7 +130,7 @@
boolean taskViewHasMultipleTasks = taskViewTaskIds[0] != -1 &&
taskViewTaskIds[1] != -1;
boolean notEnoughTasksToSplit = recentsView.getTaskViewCount() < 2;
- boolean isFocusedTask = deviceProfile.overviewShowAsGrid && taskView.isFocusedTask();
+ boolean isFocusedTask = deviceProfile.isTablet && taskView.isFocusedTask();
boolean isTaskInExpectedScrollPosition =
recentsView.isTaskInExpectedScrollPosition(recentsView.indexOfChild(taskView));
ActivityManager activityManager =
@@ -157,13 +157,15 @@
* Subclasses can attach any system listeners in this method, must be paired with
* {@link #removeListeners()}
*/
- public void initListeners() { }
+ public void initListeners() {
+ }
/**
* Subclasses should remove any system listeners in this method, must be paired with
* {@link #initListeners()}
*/
- public void removeListeners() { }
+ public void removeListeners() {
+ }
/** 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[]{
@@ -190,7 +192,7 @@
mApplicationContext = taskThumbnailView.getContext().getApplicationContext();
mThumbnailView = taskThumbnailView;
mImageApi = new ImageActionsApi(
- mApplicationContext, mThumbnailView::getThumbnail);
+ mApplicationContext, mThumbnailView::getThumbnail);
}
protected T getActionsView() {
@@ -264,7 +266,8 @@
/**
* Gets the modal state system shortcut.
*/
- public SystemShortcut getModalStateSystemShortcut(WorkspaceItemInfo itemInfo) {
+ public SystemShortcut getModalStateSystemShortcut(WorkspaceItemInfo itemInfo,
+ View original) {
return null;
}
@@ -278,9 +281,10 @@
* Gets the system shortcut for the screenshot that will be added to the task menu.
*/
public SystemShortcut getScreenshotShortcut(BaseDraggingActivity activity,
- ItemInfo iteminfo) {
- return new ScreenshotSystemShortcut(activity, iteminfo);
+ ItemInfo iteminfo, View originalView) {
+ return new ScreenshotSystemShortcut(activity, iteminfo, originalView);
}
+
/**
* Gets the task snapshot as it is displayed on the screen.
*
@@ -311,18 +315,29 @@
}
protected void showBlockedByPolicyMessage() {
+ ActivityContext activityContext = ActivityContext.lookupContext(
+ mThumbnailView.getContext());
+ String message = activityContext.getStringCache() != null
+ ? activityContext.getStringCache().disabledByAdminMessage
+ : mThumbnailView.getContext().getString(R.string.blocked_by_policy);
Toast.makeText(
mThumbnailView.getContext(),
- R.string.blocked_by_policy,
+ message,
Toast.LENGTH_LONG).show();
}
+ /** Called when the snapshot has updated its full screen drawing parameters. */
+ public void setFullscreenParams(TaskView.FullscreenDrawParams fullscreenParams) {
+ }
+
private class ScreenshotSystemShortcut extends SystemShortcut {
private final BaseDraggingActivity mActivity;
- ScreenshotSystemShortcut(BaseDraggingActivity activity, ItemInfo itemInfo) {
- super(R.drawable.ic_screenshot, R.string.action_screenshot, activity, itemInfo);
+ ScreenshotSystemShortcut(BaseDraggingActivity activity, ItemInfo itemInfo,
+ View originalView) {
+ super(R.drawable.ic_screenshot, R.string.action_screenshot, activity, itemInfo,
+ originalView);
mActivity = activity;
}
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index f507ea3..e807e26 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -49,7 +49,6 @@
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
import com.android.systemui.shared.recents.view.RecentsTransition;
-import com.android.systemui.shared.system.ActivityCompat;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -78,7 +77,7 @@
TaskUtils.getTitle(taskView.getContext(), taskContainer.getTask()),
taskContainer.getA11yNodeId()
);
- return new AppInfo(activity, taskContainer.getItemInfo(), accessibilityInfo);
+ return new AppInfo(activity, taskContainer.getItemInfo(), taskView, accessibilityInfo);
}
@Override
@@ -123,7 +122,7 @@
private final SplitPositionOption mSplitPositionOption;
public SplitSelectSystemShortcut(BaseDraggingActivity target, TaskView taskView,
SplitPositionOption option) {
- super(option.iconResId, option.textResId, target, taskView.getItemInfo());
+ super(option.iconResId, option.textResId, target, taskView.getItemInfo(), taskView);
mTaskView = taskView;
mSplitPositionOption = option;
}
@@ -147,7 +146,8 @@
public MultiWindowSystemShortcut(int iconRes, int textRes, BaseDraggingActivity activity,
TaskIdAttributeContainer taskContainer, MultiWindowFactory factory,
LauncherEvent launcherEvent) {
- super(iconRes, textRes, activity, taskContainer.getItemInfo());
+ super(iconRes, textRes, activity, taskContainer.getItemInfo(),
+ taskContainer.getTaskView());
mLauncherEvent = launcherEvent;
mHandler = new Handler(Looper.getMainLooper());
mTaskView = taskContainer.getTaskView();
@@ -190,7 +190,7 @@
ActivityOptions options = mFactory.makeLaunchOptions(mTarget);
if (options != null) {
- options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+ options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
}
if (options != null
&& ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId,
@@ -258,9 +258,8 @@
@Override
protected ActivityOptions makeLaunchOptions(Activity activity) {
- final ActivityCompat act = new ActivityCompat(activity);
final int navBarPosition = WindowManagerWrapper.getInstance().getNavBarPosition(
- act.getDisplayId());
+ activity.getDisplayId());
if (navBarPosition == WindowManagerWrapper.NAV_BAR_POS_INVALID) {
return null;
}
@@ -321,7 +320,7 @@
public PinSystemShortcut(BaseDraggingActivity target,
TaskIdAttributeContainer taskContainer) {
super(R.drawable.ic_pin, R.string.recent_task_option_pin, target,
- taskContainer.getItemInfo());
+ taskContainer.getItemInfo(), taskContainer.getTaskView());
mTaskView = taskContainer.getTaskView();
}
@@ -338,20 +337,23 @@
TaskShortcutFactory INSTALL = (activity, taskContainer) ->
InstantAppResolver.newInstance(activity).isInstantApp(activity,
- taskContainer.getTask().getTopComponent().getPackageName())
- ? new SystemShortcut.Install(activity, taskContainer.getItemInfo()) : null;
+ taskContainer.getTask().getTopComponent().getPackageName())
+ ? new SystemShortcut.Install(activity, taskContainer.getItemInfo(),
+ taskContainer.getTaskView()) : null;
TaskShortcutFactory WELLBEING = (activity, taskContainer) ->
- WellbeingModel.SHORTCUT_FACTORY.getShortcut(activity, taskContainer.getItemInfo());
+ WellbeingModel.SHORTCUT_FACTORY.getShortcut(activity, taskContainer.getItemInfo(),
+ taskContainer.getTaskView());
TaskShortcutFactory SCREENSHOT = (activity, taskContainer) ->
taskContainer.getThumbnailView().getTaskOverlay()
- .getScreenshotShortcut(activity, taskContainer.getItemInfo());
+ .getScreenshotShortcut(activity, taskContainer.getItemInfo(),
+ taskContainer.getTaskView());
TaskShortcutFactory MODAL = (activity, taskContainer) -> {
if (ENABLE_OVERVIEW_SELECTIONS.get()) {
- return taskContainer.getThumbnailView()
- .getTaskOverlay().getModalStateSystemShortcut(taskContainer.getItemInfo());
+ return taskContainer.getThumbnailView().getTaskOverlay().getModalStateSystemShortcut(
+ taskContainer.getItemInfo(), taskContainer.getTaskView());
}
return null;
};
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index dbf8acf..db402af 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -15,6 +15,7 @@
*/
package com.android.quickstep;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
@@ -37,7 +38,6 @@
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
import static com.android.launcher3.testing.TestProtocol.BAD_STATE;
-import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
@@ -47,6 +47,7 @@
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
+import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Matrix;
@@ -168,11 +169,9 @@
boolean isQuickSwitch = v.isEndQuickswitchCuj();
v.setEndQuickswitchCuj(false);
- boolean inLiveTileMode =
- ENABLE_QUICKSTEP_LIVE_TILE.get() && v.getRecentsView().getRunningTaskIndex() != -1;
final RemoteAnimationTargets targets =
new RemoteAnimationTargets(appTargets, wallpaperTargets, nonAppTargets,
- inLiveTileMode ? MODE_CLOSING : MODE_OPENING);
+ MODE_OPENING);
final RemoteAnimationTargetCompat navBarTarget = targets.getNavBarRemoteAnimationTarget();
SurfaceTransactionApplier applier = new SurfaceTransactionApplier(v);
@@ -199,7 +198,7 @@
int taskIndex = recentsView.indexOfChild(v);
Context context = v.getContext();
DeviceProfile dp = BaseActivity.fromContext(context).getDeviceProfile();
- boolean showAsGrid = dp.overviewShowAsGrid;
+ boolean showAsGrid = dp.isTablet;
boolean parallaxCenterAndAdjacentTask =
taskIndex != recentsView.getCurrentPage() && !showAsGrid;
int taskRectTranslationPrimary = recentsView.getScrollOffset(taskIndex);
@@ -274,7 +273,7 @@
}
}
});
- } else if (inLiveTileMode) {
+ } else {
// There is no transition animation for app launch from recent in live tile mode so
// we have to trigger the navigation bar animation from system here.
final RecentsAnimationController controller =
@@ -286,7 +285,8 @@
topMostSimulators = remoteTargetHandles;
}
- if (!skipViewChanges && parallaxCenterAndAdjacentTask && topMostSimulators.length > 0) {
+ if (!skipViewChanges && parallaxCenterAndAdjacentTask && topMostSimulators != null
+ && topMostSimulators.length > 0) {
out.addFloat(v, VIEW_ALPHA, 1, 0, clampToProgress(LINEAR, 0.2f, 0.4f));
RemoteTargetHandle[] simulatorCopies = topMostSimulators;
@@ -391,18 +391,20 @@
* device is considered in multiWindowMode and things like insets and stuff change
* and calculations have to be adjusted in the animations for that
*/
- public static void composeRecentsSplitLaunchAnimator(@NonNull Task initalTask,
- @NonNull Task secondTask, @NonNull TransitionInfo transitionInfo,
- SurfaceControl.Transaction t, @NonNull Runnable finishCallback) {
-
- final TransitionInfo.Change[] splitRoots = new TransitionInfo.Change[2];
+ public static void composeRecentsSplitLaunchAnimator(int initialTaskId,
+ @Nullable PendingIntent initialTaskPendingIntent, int secondTaskId,
+ @NonNull TransitionInfo transitionInfo, SurfaceControl.Transaction t,
+ @NonNull Runnable finishCallback) {
+ // TODO: consider initialTaskPendingIntent
+ TransitionInfo.Change splitRoot1 = null;
+ TransitionInfo.Change splitRoot2 = null;
for (int i = 0; i < transitionInfo.getChanges().size(); ++i) {
final TransitionInfo.Change change = transitionInfo.getChanges().get(i);
final int taskId = change.getTaskInfo() != null ? change.getTaskInfo().taskId : -1;
final int mode = change.getMode();
// Find the target tasks' root tasks since those are the split stages that need to
// be animated (the tasks themselves are children and thus inherit animation).
- if (taskId == initalTask.key.id || taskId == secondTask.key.id) {
+ if (taskId == initialTaskId || taskId == secondTaskId) {
if (!(mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT)) {
throw new IllegalStateException(
"Expected task to be showing, but it is " + mode);
@@ -411,16 +413,18 @@
throw new IllegalStateException("Initiating multi-split launch but the split"
+ "root of " + taskId + " is already visible or has broken hierarchy.");
}
- splitRoots[taskId == initalTask.key.id ? 0 : 1] =
- transitionInfo.getChange(change.getParent());
+ }
+ if (taskId == initialTaskId && initialTaskId != INVALID_TASK_ID) {
+ splitRoot1 = transitionInfo.getChange(change.getParent());
+ }
+ if (taskId == secondTaskId) {
+ splitRoot2 = transitionInfo.getChange(change.getParent());
}
}
// This is where we should animate the split roots. For now, though, just make them visible.
- for (int i = 0; i < 2; ++i) {
- t.show(splitRoots[i].getLeash());
- t.setAlpha(splitRoots[i].getLeash(), 1.f);
- }
+ animateSplitRoot(t, splitRoot1);
+ animateSplitRoot(t, splitRoot2);
// This contains the initial state (before animation), so apply this at the beginning of
// the animation.
@@ -430,6 +434,14 @@
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);
+ }
+ }
+
/**
* Legacy version (until shell transitions are enabled)
*
@@ -442,9 +454,9 @@
* 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 composeRecentsSplitLaunchAnimatorLegacy(
- @Nullable GroupedTaskView launchingTaskView,
- @NonNull Task initialTask,
- @NonNull Task secondTask, @NonNull RemoteAnimationTargetCompat[] appTargets,
+ @Nullable GroupedTaskView launchingTaskView, int initialTaskId,
+ @Nullable PendingIntent initialTaskPendingIntent, int secondTaskId,
+ @NonNull RemoteAnimationTargetCompat[] appTargets,
@NonNull RemoteAnimationTargetCompat[] wallpaperTargets,
@NonNull RemoteAnimationTargetCompat[] nonAppTargets,
@NonNull StateManager stateManager,
@@ -473,14 +485,14 @@
for (RemoteAnimationTargetCompat appTarget : appTargets) {
final int taskId = appTarget.taskInfo != null ? appTarget.taskInfo.taskId : -1;
final int mode = appTarget.mode;
- final SurfaceControl leash = appTarget.leash.getSurfaceControl();
+ final SurfaceControl leash = appTarget.leash;
if (leash == null) {
continue;
}
if (mode == MODE_OPENING) {
openingTargets.add(leash);
- } else if (taskId == initialTask.key.id || taskId == secondTask.key.id) {
+ } else if (taskId == initialTaskId || taskId == secondTaskId) {
throw new IllegalStateException("Expected task to be opening, but it is " + mode);
} else if (mode == MODE_CLOSING) {
closingTargets.add(leash);
@@ -488,7 +500,7 @@
}
for (int i = 0; i < nonAppTargets.length; ++i) {
- final SurfaceControl leash = appTargets[i].leash.getSurfaceControl();
+ final SurfaceControl leash = nonAppTargets[i].leash;
if (nonAppTargets[i].windowType == TYPE_DOCK_DIVIDER && leash != null) {
openingTargets.add(leash);
}
@@ -502,9 +514,6 @@
for (SurfaceControl leash: openingTargets) {
t.setAlpha(leash, progress);
}
- for (SurfaceControl leash: closingTargets) {
- t.setAlpha(leash, 1 - progress);
- }
t.apply();
});
animator.addListener(new AnimatorListenerAdapter() {
@@ -561,7 +570,7 @@
if (launcherClosing) {
Context context = v.getContext();
DeviceProfile dp = BaseActivity.fromContext(context).getDeviceProfile();
- launcherAnim = dp.overviewShowAsGrid
+ launcherAnim = dp.isTablet
? ObjectAnimator.ofFloat(recentsView, RecentsView.CONTENT_ALPHA, 0)
: recentsView.createAdjacentPageAnimForTaskLaunch(taskView);
if (dp.isTablet) {
@@ -647,7 +656,7 @@
boolean hasSurfaceToAnimate = false;
for (int i = 0; i < nonApps.length; ++i) {
final RemoteAnimationTargetCompat targ = nonApps[i];
- final SurfaceControl leash = targ.leash.getSurfaceControl();
+ final SurfaceControl leash = targ.leash;
if (targ.windowType == TYPE_DOCK_DIVIDER && leash != null) {
auxiliarySurfaces.add(leash);
hasSurfaceToAnimate = true;
diff --git a/quickstep/src/com/android/quickstep/TopTaskTracker.java b/quickstep/src/com/android/quickstep/TopTaskTracker.java
new file mode 100644
index 0000000..723dc72
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/TopTaskTracker.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.content.Intent.ACTION_CHOOSER;
+import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
+
+import android.app.ActivityManager.RunningTaskInfo;
+import android.content.Context;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+
+import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.SplitConfigurationOptions;
+import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
+import com.android.launcher3.util.SplitConfigurationOptions.StageType;
+import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitTaskPosition;
+import com.android.launcher3.util.TraceHelper;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.Task.TaskKey;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.shared.system.TaskStackChangeListeners;
+import com.android.wm.shell.splitscreen.ISplitScreenListener;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * This class tracked the top-most task and some 'approximate' task history to allow faster
+ * system state estimation during touch interaction
+ */
+public class TopTaskTracker extends ISplitScreenListener.Stub implements TaskStackChangeListener {
+
+ public static MainThreadInitializedObject<TopTaskTracker> INSTANCE =
+ new MainThreadInitializedObject<>(TopTaskTracker::new);
+
+ private static final int HISTORY_SIZE = 5;
+
+ // Ordered list with first item being the most recent task.
+ private final LinkedList<RunningTaskInfo> mOrderedTaskList = new LinkedList<>();
+
+ private final StagedSplitTaskPosition mMainStagePosition = new StagedSplitTaskPosition();
+ private final StagedSplitTaskPosition mSideStagePosition = new StagedSplitTaskPosition();
+ private int mPinnedTaskId = INVALID_TASK_ID;
+
+ private TopTaskTracker(Context context) {
+ mMainStagePosition.stageType = SplitConfigurationOptions.STAGE_TYPE_MAIN;
+ mSideStagePosition.stageType = SplitConfigurationOptions.STAGE_TYPE_SIDE;
+
+ TaskStackChangeListeners.getInstance().registerTaskStackListener(this);
+ SystemUiProxy.INSTANCE.get(context).registerSplitScreenListener(this);
+ }
+
+ @Override
+ public void onTaskRemoved(int taskId) {
+ mOrderedTaskList.removeIf(rto -> rto.taskId == taskId);
+ }
+
+ @Override
+ public void onTaskMovedToFront(RunningTaskInfo taskInfo) {
+ mOrderedTaskList.removeIf(rto -> rto.taskId == taskInfo.taskId);
+ mOrderedTaskList.addFirst(taskInfo);
+ if (mOrderedTaskList.size() >= HISTORY_SIZE) {
+ // If we grow in size, remove the last taskInfo which is not part of the split task.
+ Iterator<RunningTaskInfo> itr = mOrderedTaskList.descendingIterator();
+ while (itr.hasNext()) {
+ RunningTaskInfo info = itr.next();
+ if (info.taskId != taskInfo.taskId
+ && info.taskId != mMainStagePosition.taskId
+ && info.taskId != mSideStagePosition.taskId) {
+ itr.remove();
+ return;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onStagePositionChanged(@StageType int stage, @StagePosition int position) {
+ if (stage == SplitConfigurationOptions.STAGE_TYPE_MAIN) {
+ mMainStagePosition.stagePosition = position;
+ } else {
+ mSideStagePosition.stagePosition = position;
+ }
+ }
+
+ @Override
+ public void onTaskStageChanged(int taskId, @StageType int stage, boolean visible) {
+ // If task is not visible but we are tracking it, stop tracking it
+ if (!visible) {
+ if (mMainStagePosition.taskId == taskId) {
+ resetTaskId(mMainStagePosition);
+ } else if (mSideStagePosition.taskId == taskId) {
+ resetTaskId(mSideStagePosition);
+ } // else it's an un-tracked child
+ return;
+ }
+
+ // If stage has moved to undefined, stop tracking the task
+ if (stage == SplitConfigurationOptions.STAGE_TYPE_UNDEFINED) {
+ resetTaskId(taskId == mMainStagePosition.taskId
+ ? mMainStagePosition : mSideStagePosition);
+ return;
+ }
+
+ if (stage == SplitConfigurationOptions.STAGE_TYPE_MAIN) {
+ mMainStagePosition.taskId = taskId;
+ } else {
+ mSideStagePosition.taskId = taskId;
+ }
+ }
+
+ @Override
+ public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
+ mPinnedTaskId = taskId;
+ }
+
+ @Override
+ public void onActivityUnpinned() {
+ mPinnedTaskId = INVALID_TASK_ID;
+ }
+
+ private void resetTaskId(StagedSplitTaskPosition taskPosition) {
+ taskPosition.taskId = INVALID_TASK_ID;
+ }
+
+ /**
+ * @return index 0 will be task in left/top position, index 1 in right/bottom position.
+ * Will return empty array if device is not in staged split
+ */
+ public int[] getRunningSplitTaskIds() {
+ if (mMainStagePosition.taskId == INVALID_TASK_ID
+ || mSideStagePosition.taskId == INVALID_TASK_ID) {
+ return new int[]{};
+ }
+ int[] out = new int[2];
+ if (mMainStagePosition.stagePosition == STAGE_POSITION_TOP_OR_LEFT) {
+ out[0] = mMainStagePosition.taskId;
+ out[1] = mSideStagePosition.taskId;
+ } else {
+ out[1] = mMainStagePosition.taskId;
+ out[0] = mSideStagePosition.taskId;
+ }
+ return out;
+ }
+
+
+ /**
+ * Returns the CachedTaskInfo for the top most task
+ */
+ @UiThread
+ public CachedTaskInfo getCachedTopTask(boolean filterOnlyVisibleRecents) {
+ if (filterOnlyVisibleRecents) {
+ // Since we only know about the top most task, any filtering may not be applied on the
+ // cache. The second to top task may change while the top task is still the same.
+ RunningTaskInfo[] tasks = TraceHelper.allowIpcs("getCachedTopTask.true", () ->
+ ActivityManagerWrapper.getInstance().getRunningTasks(true));
+ return new CachedTaskInfo(Arrays.asList(tasks));
+ }
+
+ if (mOrderedTaskList.isEmpty()) {
+ RunningTaskInfo[] tasks = TraceHelper.allowIpcs("getCachedTopTask.false", () ->
+ ActivityManagerWrapper.getInstance().getRunningTasks(
+ false /* filterOnlyVisibleRecents */));
+ Collections.addAll(mOrderedTaskList, tasks);
+ }
+
+ // Strip the pinned task
+ ArrayList<RunningTaskInfo> tasks = new ArrayList<>(mOrderedTaskList);
+ tasks.removeIf(t -> t.taskId == mPinnedTaskId);
+ return new CachedTaskInfo(tasks);
+ }
+
+ /**
+ * Class to provide information about a task which can be safely cached and do not change
+ * during the lifecycle of the task.
+ */
+ public static class CachedTaskInfo {
+
+ @Nullable
+ private final RunningTaskInfo mTopTask;
+ private final List<RunningTaskInfo> mAllCachedTasks;
+
+ CachedTaskInfo(List<RunningTaskInfo> allCachedTasks) {
+ mAllCachedTasks = allCachedTasks;
+ mTopTask = allCachedTasks.isEmpty() ? null : allCachedTasks.get(0);
+ }
+
+ public int getTaskId() {
+ return mTopTask == null ? INVALID_TASK_ID : mTopTask.taskId;
+ }
+
+ /**
+ * Returns true if the root of the task chooser activity
+ */
+ public boolean isRootChooseActivity() {
+ return mTopTask != null && ACTION_CHOOSER.equals(mTopTask.baseIntent.getAction());
+ }
+
+ /**
+ * Returns true if the given task holds an Assistant activity that is excluded from recents
+ */
+ public boolean isExcludedAssistant() {
+ return mTopTask != null && mTopTask.configuration.windowConfiguration
+ .getActivityType() == ACTIVITY_TYPE_ASSISTANT
+ && (mTopTask.baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
+ }
+
+ /**
+ * Returns true if this represents the HOME task
+ */
+ public boolean isHomeTask() {
+ return mTopTask != null && mTopTask.configuration.windowConfiguration
+ .getActivityType() == ACTIVITY_TYPE_HOME;
+ }
+
+ /**
+ * Returns {@link Task} array which can be used as a placeholder until the true object
+ * is loaded by the model
+ */
+ public Task[] getPlaceholderTasks() {
+ return mTopTask == null ? new Task[0]
+ : new Task[] {Task.from(new TaskKey(mTopTask), mTopTask, false)};
+ }
+
+ /**
+ * Returns {@link Task} array corresponding to the provided task ids which can be used as a
+ * placeholder until the true object is loaded by the model
+ */
+ public Task[] getPlaceholderTasks(int[] taskIds) {
+ if (mTopTask == null) {
+ return new Task[0];
+ }
+ Task[] result = new Task[taskIds.length];
+ for (int i = 0; i < taskIds.length; i++) {
+ final int index = i;
+ int taskId = taskIds[i];
+ mAllCachedTasks.forEach(rti -> {
+ if (rti.taskId == taskId) {
+ result[index] = Task.from(new TaskKey(rti), rti, false);
+ }
+ });
+ }
+ return result;
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index af8fec2..61d36fb 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -15,7 +15,6 @@
*/
package com.android.quickstep;
-import static android.content.Intent.ACTION_CHOOSER;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_UP;
@@ -26,13 +25,14 @@
import static com.android.quickstep.GestureState.DEFAULT_STATE;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_RECENT_TASKS;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_BACK_ANIMATION;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_ONE_HANDED;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_PIP;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SHELL_TRANSITIONS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SPLIT_SCREEN;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_STARTING_WINDOW;
-import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SMARTSPACE_TRANSITION_CONTROLLER;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
@@ -40,27 +40,21 @@
import android.app.PendingIntent;
import android.app.RemoteAction;
import android.app.Service;
-import android.content.ComponentName;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
-import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.drawable.Icon;
-import android.hardware.display.DisplayManager;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Looper;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.util.Log;
import android.view.Choreographer;
-import android.view.Display;
import android.view.InputEvent;
import android.view.MotionEvent;
-import android.view.Surface;
import android.view.accessibility.AccessibilityManager;
import androidx.annotation.BinderThread;
@@ -75,12 +69,14 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.provider.RestoreDbTask;
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.TestProtocol;
import com.android.launcher3.tracing.LauncherTraceProto;
import com.android.launcher3.tracing.TouchInteractionServiceProto;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.WindowBounds;
@@ -97,20 +93,18 @@
import com.android.quickstep.inputconsumers.SysUiOverlayInputConsumer;
import com.android.quickstep.inputconsumers.TaskbarStashInputConsumer;
import com.android.quickstep.util.ActiveGestureLog;
-import com.android.quickstep.util.AssistantUtilities;
-import com.android.quickstep.util.LauncherSplitScreenListener;
import com.android.quickstep.util.ProtoTracer;
import com.android.quickstep.util.ProxyScreenStatusProvider;
import com.android.quickstep.util.SplitScreenBounds;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InputMonitorCompat;
-import com.android.systemui.shared.system.smartspace.ISmartspaceTransitionController;
+import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
import com.android.systemui.shared.tracing.ProtoTraceable;
+import com.android.wm.shell.back.IBackAnimation;
import com.android.wm.shell.onehanded.IOneHanded;
import com.android.wm.shell.pip.IPip;
import com.android.wm.shell.recents.IRecentTasks;
@@ -144,9 +138,6 @@
*/
private static final int SYSTEM_ACTION_ID_ALL_APPS = 14;
- public static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION =
- SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false);
-
private int mBackGestureNotificationCounter = -1;
private final TISBinder mTISBinder = new TISBinder();
@@ -156,6 +147,8 @@
*/
public class TISBinder extends IOverviewProxy.Stub {
+ @Nullable private Runnable mOnOverviewTargetChangeListener = null;
+
@BinderThread
public void onInitialize(Bundle bundle) {
ISystemUiProxy proxy = ISystemUiProxy.Stub.asInterface(
@@ -169,16 +162,18 @@
bundle.getBinder(KEY_EXTRA_SHELL_SHELL_TRANSITIONS));
IStartingWindow startingWindow = IStartingWindow.Stub.asInterface(
bundle.getBinder(KEY_EXTRA_SHELL_STARTING_WINDOW));
- ISmartspaceTransitionController smartspaceTransitionController =
- ISmartspaceTransitionController.Stub.asInterface(
- bundle.getBinder(KEY_EXTRA_SMARTSPACE_TRANSITION_CONTROLLER));
+ ISysuiUnlockAnimationController launcherUnlockAnimationController =
+ ISysuiUnlockAnimationController.Stub.asInterface(
+ bundle.getBinder(KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER));
IRecentTasks recentTasks = IRecentTasks.Stub.asInterface(
bundle.getBinder(KEY_EXTRA_RECENT_TASKS));
+ IBackAnimation backAnimation = IBackAnimation.Stub.asInterface(
+ bundle.getBinder(KEY_EXTRA_SHELL_BACK_ANIMATION));
MAIN_EXECUTOR.execute(() -> {
SystemUiProxy.INSTANCE.get(TouchInteractionService.this).setProxy(proxy, pip,
splitscreen, onehanded, shellTransitions, startingWindow, recentTasks,
- smartspaceTransitionController);
- TouchInteractionService.this.initInputMonitor();
+ launcherUnlockAnimationController, backAnimation);
+ TouchInteractionService.this.initInputMonitor("TISBinder#onInitialize()");
preloadOverview(true /* fromInit */);
});
sIsInitialized = true;
@@ -271,6 +266,16 @@
MAIN_EXECUTOR.execute(ProxyScreenStatusProvider.INSTANCE::onScreenTurnedOn);
}
+ /**
+ * Preloads the Overview activity.
+ *
+ * This method should only be used when the All Set page of the SUW is reached to safely
+ * preload the Launcher for the SUW first reveal.
+ */
+ public void preloadOverviewForSUWAllSet() {
+ preloadOverview(false, true);
+ }
+
@Override
public void onRotationProposal(int rotation, boolean isValid) {
executeForTaskbarManager(() -> mTaskbarManager.onRotationProposal(rotation, isValid));
@@ -317,6 +322,25 @@
public void setSwipeUpProxy(Function<GestureState, AnimatedFloat> proxy) {
mSwipeUpProxyProvider = proxy != null ? proxy : (i -> null);
}
+
+ /**
+ * Sets the task id where gestures should be blocked
+ */
+ public void setGestureBlockedTaskId(int taskId) {
+ mDeviceState.setGestureBlockingTaskId(taskId);
+ }
+
+ /** Sets a listener to be run on Overview Target updates. */
+ public void setOverviewTargetChangeListener(@Nullable Runnable listener) {
+ mOnOverviewTargetChangeListener = listener;
+ }
+
+ protected void onOverviewTargetChange() {
+ if (mOnOverviewTargetChangeListener != null) {
+ mOnOverviewTargetChangeListener.run();
+ mOnOverviewTargetChangeListener = null;
+ }
+ }
}
private static boolean sConnected = false;
@@ -352,8 +376,6 @@
private InputMonitorCompat mInputMonitorCompat;
private InputEventReceiver mInputEventReceiver;
- private DisplayManager mDisplayManager;
-
private TaskbarManager mTaskbarManager;
private Function<GestureState, AnimatedFloat> mSwipeUpProxyProvider = i -> null;
@@ -365,7 +387,6 @@
mMainChoreographer = Choreographer.getInstance();
mAM = ActivityManagerWrapper.getInstance();
mDeviceState = new RecentsAnimationDeviceState(this, true);
- mDisplayManager = getSystemService(DisplayManager.class);
mTaskbarManager = new TaskbarManager(this);
mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
@@ -373,14 +394,13 @@
mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
mDeviceState.runOnUserUnlocked(mTaskbarManager::onUserUnlocked);
mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
- mDeviceState.addOneHandedModeChangedCallback(this::onOneHandedModeOverlayChanged);
ProtoTracer.INSTANCE.get(this).add(this);
- LauncherSplitScreenListener.INSTANCE.get(this).init();
sConnected = true;
}
- private void disposeEventHandlers() {
+ private void disposeEventHandlers(String reason) {
+ Log.d(TAG, "disposeEventHandlers: Reason: " + reason);
if (mInputEventReceiver != null) {
mInputEventReceiver.dispose();
mInputEventReceiver = null;
@@ -391,8 +411,8 @@
}
}
- private void initInputMonitor() {
- disposeEventHandlers();
+ private void initInputMonitor(String reason) {
+ disposeEventHandlers("Initializing input monitor due to: " + reason);
if (mDeviceState.isButtonNavMode()) {
return;
@@ -408,18 +428,11 @@
/**
* Called when the navigation mode changes, guaranteed to be after the device state has updated.
*/
- private void onNavigationModeChanged(SysUINavigationMode.Mode mode) {
- initInputMonitor();
+ private void onNavigationModeChanged() {
+ initInputMonitor("onNavigationModeChanged()");
resetHomeBounceSeenOnQuickstepEnabledFirstTime();
}
- /**
- * Called when the one handed mode overlay package changes, to recreate touch region.
- */
- private void onOneHandedModeOverlayChanged(int newGesturalHeight) {
- initInputMonitor();
- }
-
@UiThread
public void onUserUnlocked() {
mTaskAnimationManager = new TaskAnimationManager(this);
@@ -432,6 +445,9 @@
onSystemUiFlagsChanged(mDeviceState.getSystemUiStateFlags());
onAssistantVisibilityChanged();
+ // Initialize the task tracker
+ TopTaskTracker.INSTANCE.get(this);
+
// Temporarily disable model preload
// new ModelPreload().start(this);
mBackGestureNotificationCounter = Math.max(0, Utilities.getDevicePrefs(this)
@@ -485,6 +501,7 @@
if (newOverviewActivity != null) {
mTaskbarManager.setActivity(newOverviewActivity);
}
+ mTISBinder.onOverviewTargetChange();
}
@UiThread
@@ -535,7 +552,7 @@
mInputConsumer.unregisterInputConsumer();
mOverviewComponentObserver.onDestroy();
}
- disposeEventHandlers();
+ disposeEventHandlers("TouchInteractionService onDestroy()");
mDeviceState.destroy();
SystemUiProxy.INSTANCE.get(this).clearProxy();
ProtoTracer.INSTANCE.get(this).stop();
@@ -544,7 +561,6 @@
getSystemService(AccessibilityManager.class)
.unregisterSystemAction(SYSTEM_ACTION_ID_ALL_APPS);
- LauncherSplitScreenListener.INSTANCE.get(this).destroy();
mTaskbarManager.destroy();
sConnected = false;
super.onDestroy();
@@ -562,15 +578,6 @@
return;
}
MotionEvent event = (MotionEvent) ev;
- if (ENABLE_PER_WINDOW_INPUT_ROTATION) {
- final Display display = mDisplayManager.getDisplay(mDeviceState.getDisplayId());
- int rotation = display.getRotation();
- Point sz = new Point();
- display.getRealSize(sz);
- if (rotation != Surface.ROTATION_0) {
- event.transform(InputChannelCompat.createRotationMatrix(rotation, sz.x, sz.y));
- }
- }
TestLogging.recordMotionEvent(
TestProtocol.SEQUENCE_TIS, "TouchInteractionService.onInputEvent", event);
@@ -655,7 +662,7 @@
private InputConsumer tryCreateAssistantInputConsumer(InputConsumer base,
GestureState gestureState, MotionEvent motionEvent) {
- return mDeviceState.isGestureBlockedActivity(gestureState.getRunningTask())
+ return mDeviceState.isGestureBlockedTask(gestureState.getRunningTask())
? base
: new AssistantInputConsumer(this, gestureState, base, mInputMonitorCompat,
mDeviceState, motionEvent);
@@ -670,8 +677,8 @@
gestureState.updatePreviouslyAppearedTaskIds(
previousGestureState.getPreviouslyAppearedTaskIds());
} else {
- gestureState.updateRunningTasks(TraceHelper.allowIpcs("getRunningTask.0",
- () -> mAM.getRunningTasks(false /* filterOnlyVisibleRecents */)));
+ gestureState.updateRunningTask(
+ TopTaskTracker.INSTANCE.get(this).getCachedTopTask(false));
}
return gestureState;
}
@@ -711,16 +718,17 @@
}
// If Taskbar is present, we listen for long press to unstash it.
- BaseActivityInterface activityInterface = newGestureState.getActivityInterface();
- StatefulActivity activity = activityInterface.getCreatedActivity();
- if (activity != null && activity.getDeviceProfile().isTaskbarPresent) {
- base = new TaskbarStashInputConsumer(this, base, mInputMonitorCompat,
- mTaskbarManager.getCurrentActivityContext());
+ TaskbarActivityContext tac = mTaskbarManager.getCurrentActivityContext();
+ if (tac != null) {
+ base = new TaskbarStashInputConsumer(this, base, mInputMonitorCompat, tac);
}
// If Bubbles is expanded, use the overlay input consumer, which will close Bubbles
// instead of going all the way home when a swipe up is detected.
- if (mDeviceState.isBubblesExpanded() || mDeviceState.isGlobalActionsShowing()) {
+ // Notification panel can be expanded on top of expanded bubbles. Bubbles remain
+ // expanded in the back. Make sure swipe up is not passed to bubbles in this case.
+ if ((mDeviceState.isBubblesExpanded() && !mDeviceState.isNotificationPanelExpanded())
+ || mDeviceState.isSystemUiDialogShowing()) {
base = new SysUiOverlayInputConsumer(
getBaseContext(), mDeviceState, mInputMonitorCompat);
}
@@ -767,17 +775,14 @@
// Use overview input consumer for sharesheets on top of home.
boolean forceOverviewInputConsumer = gestureState.getActivityInterface().isStarted()
&& gestureState.getRunningTask() != null
- && ACTION_CHOOSER.equals(gestureState.getRunningTask().baseIntent.getAction());
- if (AssistantUtilities.isExcludedAssistant(gestureState.getRunningTask())) {
+ && gestureState.getRunningTask().isRootChooseActivity();
+ if (gestureState.getRunningTask() != null
+ && gestureState.getRunningTask().isExcludedAssistant()) {
// In the case where we are in the excluded assistant state, ignore it and treat the
// running activity as the task behind the assistant
- gestureState.updateRunningTask(TraceHelper.allowIpcs("getRunningTask.assistant",
- () -> mAM.getRunningTask(true /* filterOnlyVisibleRecents */)));
- ComponentName homeComponent = mOverviewComponentObserver.getHomeIntent().getComponent();
- ComponentName runningComponent =
- gestureState.getRunningTask().baseIntent.getComponent();
- forceOverviewInputConsumer =
- runningComponent != null && runningComponent.equals(homeComponent);
+ gestureState.updateRunningTask(TopTaskTracker.INSTANCE.get(this)
+ .getCachedTopTask(true /* filterOnlyVisibleRecents */));
+ forceOverviewInputConsumer = gestureState.getRunningTask().isHomeTask();
}
if (ENABLE_QUICKSTEP_LIVE_TILE.get()
@@ -787,11 +792,14 @@
} else if (gestureState.getRunningTask() == null) {
return getDefaultInputConsumer();
} else if (previousGestureState.isRunningAnimationToLauncher()
- || gestureState.getActivityInterface().isResumed()
+ || (gestureState.getActivityInterface().isResumed()
+ // with shell-transitions, home is resumed during recents animation, so
+ // explicitly check against recents animation too.
+ && !previousGestureState.isRecentsAnimationRunning())
|| forceOverviewInputConsumer) {
return createOverviewInputConsumer(
previousGestureState, gestureState, event, forceOverviewInputConsumer);
- } else if (mDeviceState.isGestureBlockedActivity(gestureState.getRunningTask())) {
+ } else if (mDeviceState.isGestureBlockedTask(gestureState.getRunningTask())) {
return getDefaultInputConsumer();
} else {
return createOtherActivityInputConsumer(gestureState, event);
@@ -882,6 +890,10 @@
}
private void preloadOverview(boolean fromInit) {
+ preloadOverview(fromInit, false);
+ }
+
+ private void preloadOverview(boolean fromInit, boolean forSUWAllSet) {
if (!mDeviceState.isUserUnlocked()) {
return;
}
@@ -891,7 +903,8 @@
return;
}
- if (RestoreDbTask.isPending(this) || !mDeviceState.isUserSetupComplete()) {
+ if ((RestoreDbTask.isPending(this) && !forSUWAllSet)
+ || !mDeviceState.isUserSetupComplete()) {
// Preloading while a restore is pending may cause launcher to start the restore
// too early.
return;
@@ -970,7 +983,7 @@
pw.println("Input state:");
pw.println(" mInputMonitorCompat=" + mInputMonitorCompat);
pw.println(" mInputEventReceiver=" + mInputEventReceiver);
- SysUINavigationMode.INSTANCE.get(this).dump(pw);
+ DisplayController.INSTANCE.get(this).dump(pw);
pw.println("TouchState:");
BaseDraggingActivity createdOverviewActivity = mOverviewComponentObserver == null ? null
: mOverviewComponentObserver.getActivityInterface().getCreatedActivity();
@@ -983,6 +996,10 @@
RecentsModel.INSTANCE.get(this).dump("", pw);
pw.println("ProtoTrace:");
pw.println(" file=" + ProtoTracer.INSTANCE.get(this).getTraceFile());
+ if (createdOverviewActivity != null) {
+ createdOverviewActivity.getDeviceProfile().dump("", pw);
+ }
+ mTaskbarManager.dumpLogs("", pw);
}
}
diff --git a/quickstep/src/com/android/quickstep/ViewUtils.java b/quickstep/src/com/android/quickstep/ViewUtils.java
index e290be8..1fef544 100644
--- a/quickstep/src/com/android/quickstep/ViewUtils.java
+++ b/quickstep/src/com/android/quickstep/ViewUtils.java
@@ -21,10 +21,8 @@
import android.view.ViewRootImpl;
import com.android.launcher3.Utilities;
-import com.android.systemui.shared.system.ViewRootImplCompat;
import java.util.function.BooleanSupplier;
-import java.util.function.LongConsumer;
/**
* Utility class for helpful methods related to {@link View} objects.
@@ -85,7 +83,7 @@
}
private boolean schedule() {
- if (mViewRoot.getView() != null) {
+ if (mViewRoot != null && mViewRoot.getView() != null) {
mViewRoot.registerRtFrameCallback(this);
mViewRoot.getView().invalidate();
return true;
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
index 9d9ef94..3e01ed0 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
@@ -22,9 +22,9 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.launcher3.util.TouchController;
import com.android.quickstep.RecentsActivity;
-import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.util.NavBarPosition;
import com.android.quickstep.util.TriggerSwipeUpTouchTracker;
@@ -40,8 +40,8 @@
public FallbackNavBarTouchController(RecentsActivity activity) {
mActivity = activity;
- SysUINavigationMode.Mode sysUINavigationMode = SysUINavigationMode.getMode(mActivity);
- if (sysUINavigationMode == SysUINavigationMode.Mode.NO_BUTTON) {
+ NavigationMode sysUINavigationMode = DisplayController.getNavigationMode(mActivity);
+ if (sysUINavigationMode == NavigationMode.NO_BUTTON) {
NavBarPosition navBarPosition = new NavBarPosition(sysUINavigationMode,
DisplayController.INSTANCE.get(mActivity).getInfo());
mTriggerSwipeUpTracker = new TriggerSwipeUpTouchTracker(mActivity,
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index ff175f1..f68bbbc 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -111,7 +111,8 @@
RecentsState currentState = mActivity.getStateManager().getState();
if (isSplitSelectionState(state) && !isSplitSelectionState(currentState)) {
- setter.add(mRecentsView.createSplitSelectInitAnimation().buildAnim());
+ setter.add(mRecentsView.createSplitSelectInitAnimation(
+ state.getTransitionDuration(mActivity, true /* isToState */)).buildAnim());
}
Pair<FloatProperty, FloatProperty> taskViewsFloat =
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index d7da74b..ab3201a 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -24,7 +24,6 @@
import android.animation.AnimatorSet;
import android.annotation.TargetApi;
-import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
@@ -36,11 +35,13 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.popup.QuickstepSystemShortcut;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.quickstep.FallbackActivityInterface;
import com.android.quickstep.GestureState;
import com.android.quickstep.RecentsActivity;
+import com.android.quickstep.RotationTouchHelper;
import com.android.quickstep.util.GroupTask;
import com.android.quickstep.util.SplitSelectStateController;
import com.android.quickstep.util.TaskViewSimulator;
@@ -48,7 +49,6 @@
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.recents.model.Task.TaskKey;
import java.util.ArrayList;
@@ -56,7 +56,8 @@
public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsState>
implements StateListener<RecentsState> {
- private RunningTaskInfo mHomeTaskInfo;
+ @Nullable
+ private Task mHomeTask;
public FallbackRecentsView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -85,11 +86,12 @@
* to the home task. This allows us to handle quick-switch similarly to a quick-switching
* from a foreground task.
*/
- public void onGestureAnimationStartOnHome(RunningTaskInfo[] homeTaskInfo) {
+ public void onGestureAnimationStartOnHome(Task[] homeTask,
+ RotationTouchHelper rotationTouchHelper) {
// TODO(b/195607777) General fallback love, but this might be correct
// Home task should be defined as the front-most task info I think?
- mHomeTaskInfo = homeTaskInfo[0];
- onGestureAnimationStart(homeTaskInfo);
+ mHomeTask = homeTask.length > 0 ? homeTask[0] : null;
+ onGestureAnimationStart(homeTask, rotationTouchHelper);
}
/**
@@ -102,8 +104,8 @@
@Nullable AnimatorSet animatorSet, GestureState.GestureEndTarget endTarget,
TaskViewSimulator[] taskViewSimulators) {
super.onPrepareGestureEndAnimation(animatorSet, endTarget, taskViewSimulators);
- if (mHomeTaskInfo != null && endTarget == RECENTS && animatorSet != null) {
- TaskView tv = getTaskViewByTaskId(mHomeTaskInfo.taskId);
+ if (mHomeTask != null && endTarget == RECENTS && animatorSet != null) {
+ TaskView tv = getTaskViewByTaskId(mHomeTask.key.id);
if (tv != null) {
PendingAnimation pa = createTaskDismissAnimation(tv, true, false, 150,
false /* dismissingForSplitSelection*/);
@@ -128,8 +130,8 @@
public void setCurrentTask(int runningTaskViewId) {
super.setCurrentTask(runningTaskViewId);
int runningTaskId = getTaskIdsForRunningTaskView()[0];
- if (mHomeTaskInfo != null && mHomeTaskInfo.taskId != runningTaskId) {
- mHomeTaskInfo = null;
+ if (mHomeTask != null && mHomeTask.key.id != runningTaskId) {
+ mHomeTask = null;
setRunningTaskHidden(false);
}
}
@@ -137,26 +139,26 @@
@Nullable
@Override
protected TaskView getHomeTaskView() {
- return mHomeTaskInfo != null ? getTaskViewByTaskId(mHomeTaskInfo.taskId) : null;
+ return mHomeTask != null ? getTaskViewByTaskId(mHomeTask.key.id) : null;
}
@Override
- protected boolean shouldAddStubTaskView(RunningTaskInfo[] runningTaskInfos) {
- if (runningTaskInfos.length > 1) {
+ protected boolean shouldAddStubTaskView(Task[] runningTasks) {
+ if (runningTasks.length > 1) {
// can't be in split screen w/ home task
- return super.shouldAddStubTaskView(runningTaskInfos);
+ return super.shouldAddStubTaskView(runningTasks);
}
- RunningTaskInfo runningTaskInfo = runningTaskInfos[0];
- if (mHomeTaskInfo != null && runningTaskInfo != null &&
- mHomeTaskInfo.taskId == runningTaskInfo.taskId
+ Task runningTask = runningTasks[0];
+ if (mHomeTask != null && runningTask != null
+ && mHomeTask.key.id == runningTask.key.id
&& getTaskViewCount() == 0 && mLoadPlanEverApplied) {
// Do not add a stub task if we are running over home with empty recents, so that we
// show the empty recents message instead of showing a stub task and later removing it.
// Ignore empty task signal if applyLoadPlan has never run.
return false;
}
- return super.shouldAddStubTaskView(runningTaskInfos);
+ return super.shouldAddStubTaskView(runningTasks);
}
@Override
@@ -166,7 +168,8 @@
// track the index of the next task appropriately, as if we are switching on any other app.
// TODO(b/195607777) Confirm home task info is front-most task and not mixed in with others
int runningTaskId = getTaskIdsForRunningTaskView()[0];
- if (mHomeTaskInfo != null && mHomeTaskInfo.taskId == runningTaskId && !taskGroups.isEmpty()) {
+ if (mHomeTask != null && mHomeTask.key.id == runningTaskId
+ && !taskGroups.isEmpty()) {
// Check if the task list has running task
boolean found = false;
for (GroupTask group : taskGroups) {
@@ -178,9 +181,7 @@
if (!found) {
ArrayList<GroupTask> newList = new ArrayList<>(taskGroups.size() + 1);
newList.addAll(taskGroups);
- newList.add(new GroupTask(
- Task.from(new TaskKey(mHomeTaskInfo), mHomeTaskInfo, false),
- null, null));
+ newList.add(new GroupTask(mHomeTask, null, null));
taskGroups = newList;
}
}
@@ -189,7 +190,7 @@
@Override
public void setRunningTaskHidden(boolean isHidden) {
- if (mHomeTaskInfo != null) {
+ if (mHomeTask != null) {
// Always keep the home task hidden
isHidden = true;
}
@@ -221,6 +222,9 @@
setOverviewStateEnabled(true);
setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mActivity.getDeviceProfile()));
setOverviewFullscreenEnabled(toState.isFullScreen());
+ if (toState == MODAL_TASK) {
+ setOverviewSelectEnabled(true);
+ }
Log.d(BAD_STATE, "FRV onStateTransitionStart setFreezeVisibility=true, toState=" + toState);
setFreezeViewVisibility(true);
}
@@ -236,6 +240,9 @@
Log.d(BAD_STATE, "FRV onStateTransitionComplete setFreezeVisibility=false, finalState="
+ finalState);
setFreezeViewVisibility(false);
+ if (finalState != MODAL_TASK) {
+ setOverviewSelectEnabled(false);
+ }
if (isOverlayEnabled) {
runActionOnRemoteHandles(remoteTargetHandle ->
@@ -258,4 +265,15 @@
// Do not let touch escape to siblings below this view.
return result || mActivity.getStateManager().getState().overviewUi();
}
+
+ @Override
+ public void initiateSplitSelect(QuickstepSystemShortcut.SplitSelectSource splitSelectSource) {
+ super.initiateSplitSelect(splitSelectSource);
+ mActivity.getStateManager().goToState(OVERVIEW_SPLIT_SELECT);
+ }
+
+ @Override
+ protected boolean canLaunchFullscreenTask() {
+ return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsState.java b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
index 15feb18..77db6b7 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsState.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
@@ -77,7 +77,7 @@
}
@Override
- public int getTransitionDuration(Context context) {
+ public int getTransitionDuration(Context context, boolean isToState) {
return 250;
}
@@ -135,7 +135,7 @@
* For this state, whether tasks should layout as a grid rather than a list.
*/
public boolean displayOverviewTasksAsGrid(DeviceProfile deviceProfile) {
- return hasFlag(FLAG_SHOW_AS_GRID) && deviceProfile.overviewShowAsGrid;
+ return hasFlag(FLAG_SHOW_AS_GRID) && deviceProfile.isTablet;
}
/**
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 0bd8832..e458c1f 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -36,12 +36,10 @@
import android.content.ContextWrapper;
import android.content.Intent;
import android.graphics.PointF;
-import android.hardware.display.DisplayManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
-import android.view.Display;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
@@ -63,7 +61,6 @@
import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.quickstep.RotationTouchHelper;
import com.android.quickstep.TaskAnimationManager;
-import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.CachedEventDispatcher;
import com.android.quickstep.util.MotionPauseDetector;
@@ -87,6 +84,9 @@
public static final float QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON = 9;
public static final float QUICKSTEP_TOUCH_SLOP_RATIO_GESTURAL = 2;
+ // Minimum angle of a gesture's coordinate where a release goes to overview.
+ public static final int OVERVIEW_MIN_DEGREES = 15;
+
private final RecentsAnimationDeviceState mDeviceState;
private final NavBarPosition mNavBarPosition;
private final TaskAnimationManager mTaskAnimationManager;
@@ -113,8 +113,6 @@
private final PointF mLastPos = new PointF();
private int mActivePointerId = INVALID_POINTER_ID;
- private int mLastRotation = -1;
-
// Distance after which we start dragging the window.
private final float mTouchSlop;
@@ -132,8 +130,6 @@
// Might be displacement in X or Y, depending on the direction we are swiping from the nav bar.
private float mStartDisplacement;
- private final DisplayManager mDisplayManager;
-
private Handler mMainThreadHandler;
private Runnable mCancelRecentsAnimationRunnable = () -> {
ActivityManagerWrapper.getInstance().cancelRecentsAnimation(
@@ -176,7 +172,6 @@
mPassedPilferInputSlop = mPassedWindowMoveSlop = continuingPreviousGesture;
mDisableHorizontalSwipe = !mPassedPilferInputSlop && disableHorizontalSwipe;
mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
- mDisplayManager = getSystemService(DisplayManager.class);
}
@Override
@@ -202,17 +197,6 @@
return;
}
- if (TouchInteractionService.ENABLE_PER_WINDOW_INPUT_ROTATION) {
- final Display display = mDisplayManager.getDisplay(mDeviceState.getDisplayId());
- final int rotation = display.getRotation();
- if (rotation != mLastRotation) {
- // If rotation changes, reset tracking to avoid degenerate velocities.
- mLastPos.set(ev.getX(), ev.getY());
- mVelocityTracker.clear();
- mLastRotation = rotation;
- }
- }
-
// Proxy events to recents view
if (mPassedWindowMoveSlop && mInteractionHandler != null
&& !mRecentsViewDispatcher.hasConsumer()) {
@@ -310,8 +294,9 @@
// the gesture (in which case mPassedPilferInputSlop starts as true).
boolean haveNotPassedSlopOnContinuedGesture =
!mPassedSlopOnThisGesture && mPassedPilferInputSlop;
+ double degrees = Math.toDegrees(Math.atan(upDist / horizontalDist));
boolean isLikelyToStartNewTask = haveNotPassedSlopOnContinuedGesture
- || horizontalDist > upDist;
+ || degrees <= OVERVIEW_MIN_DEGREES;
if (!mPassedPilferInputSlop) {
if (passedSlop) {
@@ -440,12 +425,18 @@
mMainThreadHandler.removeCallbacks(mCancelRecentsAnimationRunnable);
mMainThreadHandler.postDelayed(mCancelRecentsAnimationRunnable, 100);
}
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- mMotionPauseDetector.clear();
+ cleanupAfterGesture();
TraceHelper.INSTANCE.endSection(traceToken);
}
+ private void cleanupAfterGesture() {
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+ mMotionPauseDetector.clear();
+ }
+
@Override
public void notifyOrientationSetup() {
mRotationTouchHelper.onStartGesture();
@@ -468,6 +459,7 @@
Preconditions.assertUIThread();
removeListener();
mInteractionHandler = null;
+ cleanupAfterGesture();
mOnCompleteCallback.accept(this);
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java
index 3f833c0..878f132 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java
@@ -15,9 +15,11 @@
*/
package com.android.quickstep.inputconsumers;
+import android.app.ActivityManager;
import android.content.Context;
-import android.content.Intent;
import android.graphics.PointF;
+import android.os.RemoteException;
+import android.util.Log;
import android.view.MotionEvent;
import com.android.launcher3.testing.TestLogging;
@@ -36,6 +38,10 @@
*/
public class SysUiOverlayInputConsumer implements InputConsumer,
TriggerSwipeUpTouchTracker.OnSwipeUpListener {
+ private static final String TAG = "SysUiOverlayInputConsumer";
+
+ // Should match the values in PhoneWindowManager
+ private static final String SYSTEM_DIALOG_REASON_GESTURE_NAV = "gestureNav";
private final Context mContext;
private final InputMonitorCompat mInputMonitor;
@@ -76,7 +82,11 @@
@Override
public void onSwipeUp(boolean wasFling, PointF finalVelocity) {
// Close system dialogs when a swipe up is detected.
- mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+ try {
+ ActivityManager.getService().closeSystemDialogs(SYSTEM_DIALOG_REASON_GESTURE_NAV);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception calling closeSystemDialogs " + e.getMessage());
+ }
}
@Override
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
index dbe260a..3785de4 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
@@ -22,6 +22,7 @@
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
+import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.quickstep.InputConsumer;
@@ -36,14 +37,20 @@
private final GestureDetector mLongPressDetector;
private final float mSquaredTouchSlop;
+
private float mDownX, mDownY;
private boolean mCanceledUnstashHint;
+ private final float mUnstashArea;
+ private final float mScreenWidth;
public TaskbarStashInputConsumer(Context context, InputConsumer delegate,
InputMonitorCompat inputMonitor, TaskbarActivityContext taskbarActivityContext) {
super(delegate, inputMonitor);
mTaskbarActivityContext = taskbarActivityContext;
mSquaredTouchSlop = Utilities.squaredTouchSlop(context);
+ mScreenWidth = taskbarActivityContext.getDeviceProfile().widthPx;
+ mUnstashArea = context.getResources()
+ .getDimensionPixelSize(R.dimen.taskbar_unstash_input_area);
mLongPressDetector = new GestureDetector(context, new SimpleOnGestureListener() {
@Override
@@ -69,11 +76,13 @@
final float y = ev.getRawY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
- mDownX = x;
- mDownY = y;
- mTaskbarActivityContext.startTaskbarUnstashHint(
- /* animateForward = */ true);
- mCanceledUnstashHint = false;
+ if (isInArea(x)) {
+ mDownX = x;
+ mDownY = y;
+ mTaskbarActivityContext.startTaskbarUnstashHint(
+ /* animateForward = */ true);
+ mCanceledUnstashHint = false;
+ }
break;
case MotionEvent.ACTION_MOVE:
if (!mCanceledUnstashHint
@@ -95,10 +104,18 @@
}
}
+ private boolean isInArea(float x) {
+ float areaFromMiddle = mUnstashArea / 2.0f;
+ float distFromMiddle = Math.abs(mScreenWidth / 2.0f - x);
+ return distFromMiddle < areaFromMiddle;
+ }
+
private void onLongPressDetected(MotionEvent motionEvent) {
- if (mTaskbarActivityContext != null
- && mTaskbarActivityContext.onLongPressToUnstashTaskbar()) {
- setActive(motionEvent);
+ if (mTaskbarActivityContext != null && isInArea(motionEvent.getRawX())) {
+ boolean taskBarPressed = mTaskbarActivityContext.onLongPressToUnstashTaskbar();
+ if (taskBarPressed) {
+ setActive(motionEvent);
+ }
}
}
}
diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
index 1c3e784..5680170 100644
--- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -17,11 +17,11 @@
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 android.animation.Animator;
import android.app.Activity;
-import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
@@ -52,8 +52,11 @@
import androidx.annotation.Nullable;
import androidx.core.graphics.ColorUtils;
+import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.util.Executors;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.GestureState;
import com.android.quickstep.TouchInteractionService.TISBinder;
@@ -77,6 +80,8 @@
private static final float HINT_BOTTOM_FACTOR = 1 - .94f;
+ private static final int MAX_SWIPE_DURATION = 350;
+
private TISBindHelper mTISBindHelper;
private TISBinder mBinder;
@@ -89,6 +94,8 @@
private LottieAnimationView mAnimatedBackground;
private Animator.AnimatorListener mBackgroundAnimatorListener;
+ private AnimatorPlaybackController mLauncherStartAnim = null;
+
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -110,6 +117,12 @@
mContentView = findViewById(R.id.content_view);
mSwipeUpShift = getResources().getDimension(R.dimen.allset_swipe_up_shift);
+ boolean isTablet = InvariantDeviceProfile.INSTANCE.get(getApplicationContext())
+ .getDeviceProfile(this).isTablet;
+ TextView subtitle = findViewById(R.id.subtitle);
+ subtitle.setText(isTablet
+ ? R.string.allset_description_tablet : R.string.allset_description);
+
TextView tv = findViewById(R.id.navigation_settings);
tv.setTextColor(accentColor);
tv.setOnClickListener(v -> {
@@ -130,6 +143,10 @@
startBackgroundAnimation();
}
+ private void runOnUiHelperThread(Runnable runnable) {
+ Executors.UI_HELPER_EXECUTOR.execute(runnable);
+ }
+
private void startBackgroundAnimation() {
if (Utilities.ATLEAST_S && mVibrator != null && mVibrator.areAllPrimitivesSupported(
VibrationEffect.Composition.PRIMITIVE_THUD)) {
@@ -138,22 +155,22 @@
new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
- mVibrator.vibrate(getVibrationEffect());
+ runOnUiHelperThread(() -> mVibrator.vibrate(getVibrationEffect()));
}
@Override
public void onAnimationRepeat(Animator animation) {
- mVibrator.vibrate(getVibrationEffect());
+ runOnUiHelperThread(() -> mVibrator.vibrate(getVibrationEffect()));
}
@Override
public void onAnimationEnd(Animator animation) {
- mVibrator.cancel();
+ runOnUiHelperThread(mVibrator::cancel);
}
@Override
public void onAnimationCancel(Animator animation) {
- mVibrator.cancel();
+ runOnUiHelperThread(mVibrator::cancel);
}
};
}
@@ -185,6 +202,8 @@
mBinder = binder;
mBinder.getTaskbarManager().setSetupUIVisible(isResumed());
mBinder.setSwipeUpProxy(isResumed() ? this::createSwipeUpProxy : null);
+ mBinder.setOverviewTargetChangeListener(mBinder::preloadOverviewForSUWAllSet);
+ mBinder.preloadOverviewForSUWAllSet();
}
@Override
@@ -200,6 +219,7 @@
if (mBinder != null) {
mBinder.getTaskbarManager().setSetupUIVisible(false);
mBinder.setSwipeUpProxy(null);
+ mBinder.setOverviewTargetChangeListener(null);
}
}
@@ -217,8 +237,7 @@
if (!state.getHomeIntent().getComponent().getPackageName().equals(getPackageName())) {
return null;
}
- RunningTaskInfo rti = state.getRunningTask();
- if (rti == null || !rti.topActivity.equals(getComponentName())) {
+ if (state.getRunningTaskId() != getTaskId()) {
return null;
}
mSwipeProgress.updateValue(0);
@@ -227,11 +246,20 @@
private void onSwipeProgressUpdate() {
mBackground.setProgress(mSwipeProgress.value);
- float alpha = Utilities.mapBoundToRange(mSwipeProgress.value, 0, HINT_BOTTOM_FACTOR,
- 1, 0, LINEAR);
+ float alpha = Utilities.mapBoundToRange(
+ mSwipeProgress.value, 0, HINT_BOTTOM_FACTOR, 1, 0, LINEAR);
mContentView.setAlpha(alpha);
mContentView.setTranslationY((alpha - 1) * mSwipeUpShift);
+ if (mLauncherStartAnim == null) {
+ mLauncherStartAnim = mBinder.getTaskbarManager().createLauncherStartFromSuwAnim(
+ MAX_SWIPE_DURATION);
+ }
+ if (mLauncherStartAnim != null) {
+ mLauncherStartAnim.setPlayFraction(Utilities.mapBoundToRange(
+ mSwipeProgress.value, 0, 1, 0, 1, FAST_OUT_SLOW_IN));
+ }
+
if (alpha == 0f) {
mAnimatedBackground.pauseAnimation();
} else if (!mAnimatedBackground.isAnimating()) {
diff --git a/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialFragment.java
index b797f0c..f440638 100644
--- a/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/AssistantGestureTutorialFragment.java
@@ -18,10 +18,16 @@
import android.view.MotionEvent;
import android.view.View;
+import androidx.annotation.NonNull;
+
+import com.android.launcher3.logging.StatsLogManager;
import com.android.quickstep.interaction.TutorialController.TutorialType;
/** Shows the Home gesture interactive tutorial. */
public class AssistantGestureTutorialFragment extends TutorialFragment {
+
+ public AssistantGestureTutorialFragment() {}
+
@Override
TutorialController createController(TutorialType type) {
return new AssistantGestureTutorialController(this, type);
@@ -39,4 +45,14 @@
}
return super.onTouch(view, motionEvent);
}
+
+ @Override
+ void logTutorialStepShown(@NonNull StatsLogManager statsLogManager) {
+ // No-Op: tutorial step not currently shown to users
+ }
+
+ @Override
+ void logTutorialStepCompleted(@NonNull StatsLogManager statsLogManager) {
+ // No-Op: tutorial step not currently shown to users
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
index 49d8203..35d9f22 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
@@ -33,17 +33,22 @@
}
@Override
- public Integer getIntroductionTitle() {
+ public int getIntroductionTitle() {
return R.string.back_gesture_intro_title;
}
@Override
- public Integer getIntroductionSubtitle() {
+ public int getIntroductionSubtitle() {
return R.string.back_gesture_intro_subtitle;
}
@Override
- public Integer getSuccessFeedbackSubtitle() {
+ public int getSpokenIntroductionSubtitle() {
+ return R.string.back_gesture_spoken_intro_subtitle;
+ }
+
+ @Override
+ public int getSuccessFeedbackSubtitle() {
return mTutorialFragment.isAtFinalStep()
? R.string.back_gesture_feedback_complete_without_follow_up
: R.string.back_gesture_feedback_complete_with_overview_follow_up;
@@ -57,14 +62,14 @@
@LayoutRes
int getMockAppTaskCurrentPageLayoutResId() {
return mTutorialFragment.isLargeScreen()
- ? R.layout.gesture_tutorial_foldable_mock_conversation
+ ? R.layout.gesture_tutorial_tablet_mock_conversation
: R.layout.gesture_tutorial_mock_conversation;
}
@LayoutRes
int getMockAppTaskPreviousPageLayoutResId() {
return mTutorialFragment.isLargeScreen()
- ? R.layout.gesture_tutorial_foldable_mock_conversation_list
+ ? R.layout.gesture_tutorial_tablet_mock_conversation_list
: R.layout.gesture_tutorial_mock_conversation_list;
}
@@ -117,7 +122,22 @@
mTutorialFragment.closeTutorial();
}
} else if (mTutorialType == BACK_NAVIGATION) {
- showFeedback(R.string.back_gesture_feedback_swipe_in_nav_bar);
+ switch (result) {
+ case HOME_NOT_STARTED_TOO_FAR_FROM_EDGE:
+ case OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE:
+ case HOME_OR_OVERVIEW_CANCELLED:
+ showFeedback(R.string.back_gesture_feedback_swipe_too_far_from_edge);
+ break;
+ case HOME_GESTURE_COMPLETED:
+ case OVERVIEW_GESTURE_COMPLETED:
+ case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION:
+ case ASSISTANT_COMPLETED:
+ case ASSISTANT_NOT_STARTED_BAD_ANGLE:
+ case ASSISTANT_NOT_STARTED_SWIPE_TOO_SHORT:
+ default:
+ showFeedback(R.string.back_gesture_feedback_swipe_in_nav_bar);
+
+ }
}
}
}
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java
index f54734d..37253e2 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java
@@ -22,9 +22,11 @@
import android.view.MotionEvent;
import android.view.View;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.R;
+import com.android.launcher3.logging.StatsLogManager;
import com.android.quickstep.interaction.TutorialController.TutorialType;
import java.util.ArrayList;
@@ -32,6 +34,8 @@
/** Shows the Back gesture interactive tutorial. */
public class BackGestureTutorialFragment extends TutorialFragment {
+ public BackGestureTutorialFragment() {}
+
@Nullable
@Override
Integer getEdgeAnimationResId() {
@@ -117,4 +121,16 @@
}
return super.onTouch(view, motionEvent);
}
+
+ @Override
+ void logTutorialStepShown(@NonNull StatsLogManager statsLogManager) {
+ statsLogManager.logger().log(
+ StatsLogManager.LauncherEvent.LAUNCHER_GESTURE_TUTORIAL_BACK_STEP_SHOWN);
+ }
+
+ @Override
+ void logTutorialStepCompleted(@NonNull StatsLogManager statsLogManager) {
+ statsLogManager.logger().log(
+ StatsLogManager.LauncherEvent.LAUNCHER_GESTURE_TUTORIAL_BACK_STEP_COMPLETED);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java
index c532f8e..d059d82 100644
--- a/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java
+++ b/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java
@@ -31,6 +31,7 @@
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.Utilities;
+import com.android.launcher3.util.DisplayController;
/**
* Utility class to handle edge swipes for back gestures.
@@ -115,10 +116,9 @@
// Add a nav bar panel window.
mEdgeBackPanel = new EdgeBackGesturePanel(mContext, parent, createLayoutParams());
mEdgeBackPanel.setBackCallback(mBackCallback);
- if (mContext.getDisplay() != null) {
- mContext.getDisplay().getRealSize(mDisplaySize);
- mEdgeBackPanel.setDisplaySize(mDisplaySize);
- }
+ Point currentSize = DisplayController.INSTANCE.get(mContext).getInfo().currentSize;
+ mDisplaySize.set(currentSize.x, currentSize.y);
+ mEdgeBackPanel.setDisplaySize(mDisplaySize);
}
}
diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
index c2524b1..bf7023c 100644
--- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
@@ -15,6 +15,7 @@
*/
package com.android.quickstep.interaction;
+import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
@@ -28,9 +29,13 @@
import androidx.fragment.app.FragmentActivity;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.logging.StatsLogManager;
+import com.android.quickstep.TouchInteractionService.TISBinder;
import com.android.quickstep.interaction.TutorialController.TutorialType;
+import com.android.quickstep.util.TISBindHelper;
-import java.util.List;
+import java.util.Arrays;
/** Shows the gesture interactive sandbox in full screen mode. */
public class GestureSandboxActivity extends FragmentActivity {
@@ -46,12 +51,21 @@
private int mCurrentStep;
private int mNumSteps;
+ private SharedPreferences mSharedPrefs;
+ private StatsLogManager mStatsLogManager;
+
+ private TISBindHelper mTISBindHelper;
+ private TISBinder mBinder;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.gesture_tutorial_activity);
+ mSharedPrefs = Utilities.getPrefs(this);
+ mStatsLogManager = StatsLogManager.newInstance(getApplicationContext());
+
Bundle args = savedInstanceState == null ? getIntent().getExtras() : savedInstanceState;
mTutorialSteps = getTutorialSteps(args);
mCurrentTutorialStep = mTutorialSteps[mCurrentStep - 1];
@@ -60,6 +74,8 @@
getSupportFragmentManager().beginTransaction()
.add(R.id.gesture_tutorial_fragment_container, mFragment)
.commit();
+
+ mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
}
@Override
@@ -91,6 +107,14 @@
super.onSaveInstanceState(savedInstanceState);
}
+ protected SharedPreferences getSharedPrefs() {
+ return mSharedPrefs;
+ }
+
+ protected StatsLogManager getStatsLogManager() {
+ return mStatsLogManager;
+ }
+
/** Returns true iff there aren't anymore tutorial types to display to the user. */
public boolean isTutorialComplete() {
return mCurrentStep >= mNumSteps;
@@ -105,13 +129,6 @@
}
/**
- * Closes the tutorial and this activity.
- */
- public void closeTutorial() {
- mFragment.closeTutorial();
- }
-
- /**
* Replaces the current TutorialFragment, continuing to the next tutorial step if there is one.
*
* If there is no following step, the tutorial is closed.
@@ -122,7 +139,8 @@
return;
}
mCurrentTutorialStep = mTutorialSteps[mCurrentStep];
- mFragment = TutorialFragment.newInstance(mCurrentTutorialStep, false);
+ mFragment = TutorialFragment.newInstance(
+ mCurrentTutorialStep, /* gestureComplete= */ false);
getSupportFragmentManager().beginTransaction()
.replace(R.id.gesture_tutorial_fragment_container, mFragment)
.runOnCommit(() -> mFragment.onAttachedToWindow())
@@ -195,7 +213,37 @@
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
getWindow().setSystemGestureExclusionRects(
- List.of(new Rect(0, 0, metrics.widthPixels, metrics.heightPixels)));
+ Arrays.asList(new Rect(0, 0, metrics.widthPixels, metrics.heightPixels)));
}
}
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ updateServiceState(true);
+ }
+
+ private void onTISConnected(TISBinder binder) {
+ mBinder = binder;
+ updateServiceState(isResumed());
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ updateServiceState(false);
+ }
+
+ private void updateServiceState(boolean isEnabled) {
+ if (mBinder != null) {
+ mBinder.setGestureBlockedTaskId(isEnabled ? getTaskId() : -1);
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mTISBindHelper.onDestroy();
+ updateServiceState(false);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
index 0bc3691..f519d50 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
@@ -32,17 +32,22 @@
}
@Override
- public Integer getIntroductionTitle() {
+ public int getIntroductionTitle() {
return R.string.home_gesture_intro_title;
}
@Override
- public Integer getIntroductionSubtitle() {
+ public int getIntroductionSubtitle() {
return R.string.home_gesture_intro_subtitle;
}
@Override
- public Integer getSuccessFeedbackSubtitle() {
+ public int getSpokenIntroductionSubtitle() {
+ return R.string.home_gesture_spoken_intro_subtitle;
+ }
+
+ @Override
+ public int getSuccessFeedbackSubtitle() {
return mTutorialFragment.isAtFinalStep()
? R.string.home_gesture_feedback_complete_without_follow_up
: R.string.home_gesture_feedback_complete_with_follow_up;
@@ -51,7 +56,7 @@
@Override
protected int getMockAppTaskLayoutResId() {
return mTutorialFragment.isLargeScreen()
- ? R.layout.gesture_tutorial_foldable_mock_webpage
+ ? R.layout.gesture_tutorial_tablet_mock_webpage
: R.layout.gesture_tutorial_mock_webpage;
}
diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java
index 423e66f..95eafda 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java
@@ -21,9 +21,11 @@
import android.view.MotionEvent;
import android.view.View;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.R;
+import com.android.launcher3.logging.StatsLogManager;
import com.android.quickstep.interaction.TutorialController.TutorialType;
import java.util.ArrayList;
@@ -31,6 +33,8 @@
/** Shows the Home gesture interactive tutorial. */
public class HomeGestureTutorialFragment extends TutorialFragment {
+ public HomeGestureTutorialFragment() {}
+
@Nullable
@Override
Integer getEdgeAnimationResId() {
@@ -99,4 +103,16 @@
releaseFeedbackAnimation();
return super.onTouch(view, motionEvent);
}
+
+ @Override
+ void logTutorialStepShown(@NonNull StatsLogManager statsLogManager) {
+ statsLogManager.logger().log(
+ StatsLogManager.LauncherEvent.LAUNCHER_GESTURE_TUTORIAL_HOME_STEP_SHOWN);
+ }
+
+ @Override
+ void logTutorialStepCompleted(@NonNull StatsLogManager statsLogManager) {
+ statsLogManager.logger().log(
+ StatsLogManager.LauncherEvent.LAUNCHER_GESTURE_TUTORIAL_HOME_STEP_COMPLETED);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
index 851cccf..f981860 100644
--- a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
+++ b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
@@ -37,7 +37,6 @@
import android.view.Display;
import android.view.GestureDetector;
import android.view.MotionEvent;
-import android.view.Surface;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
@@ -47,7 +46,8 @@
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.anim.Interpolators;
-import com.android.quickstep.SysUINavigationMode.Mode;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.NavBarPosition;
import com.android.quickstep.util.TriggerSwipeUpTouchTracker;
@@ -92,16 +92,13 @@
NavBarGestureHandler(Context context) {
mContext = context;
final Display display = mContext.getDisplay();
- final int displayRotation;
- if (display == null) {
- displayRotation = Surface.ROTATION_0;
- } else {
- displayRotation = display.getRotation();
- display.getRealSize(mDisplaySize);
- }
+ 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(Mode.NO_BUTTON, displayRotation),
+ new NavBarPosition(NavigationMode.NO_BUTTON, displayRotation),
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 f308f27..6b016ce 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
@@ -42,17 +42,22 @@
}
@Override
- public Integer getIntroductionTitle() {
+ public int getIntroductionTitle() {
return R.string.overview_gesture_intro_title;
}
@Override
- public Integer getIntroductionSubtitle() {
+ public int getIntroductionSubtitle() {
return R.string.overview_gesture_intro_subtitle;
}
@Override
- public Integer getSuccessFeedbackSubtitle() {
+ public int getSpokenIntroductionSubtitle() {
+ return R.string.overview_gesture_spoken_intro_subtitle;
+ }
+
+ @Override
+ public int getSuccessFeedbackSubtitle() {
return mTutorialFragment.getNumSteps() > 1 && mTutorialFragment.isAtFinalStep()
? R.string.overview_gesture_feedback_complete_with_follow_up
: R.string.overview_gesture_feedback_complete_without_follow_up;
@@ -61,7 +66,7 @@
@Override
protected int getMockAppTaskLayoutResId() {
return mTutorialFragment.isLargeScreen()
- ? R.layout.gesture_tutorial_foldable_mock_conversation_list
+ ? R.layout.gesture_tutorial_tablet_mock_conversation_list
: R.layout.gesture_tutorial_mock_conversation_list;
}
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
index f63a945..4e1521f 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
@@ -21,9 +21,11 @@
import android.view.MotionEvent;
import android.view.View;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.R;
+import com.android.launcher3.logging.StatsLogManager;
import com.android.quickstep.interaction.TutorialController.TutorialType;
import java.util.ArrayList;
@@ -31,6 +33,8 @@
/** Shows the Overview gesture interactive tutorial. */
public class OverviewGestureTutorialFragment extends TutorialFragment {
+ public OverviewGestureTutorialFragment() {}
+
@Nullable
@Override
Integer getEdgeAnimationResId() {
@@ -111,4 +115,16 @@
releaseFeedbackAnimation();
return super.onTouch(view, motionEvent);
}
+
+ @Override
+ void logTutorialStepShown(@NonNull StatsLogManager statsLogManager) {
+ statsLogManager.logger().log(
+ StatsLogManager.LauncherEvent.LAUNCHER_GESTURE_TUTORIAL_OVERVIEW_STEP_SHOWN);
+ }
+
+ @Override
+ void logTutorialStepCompleted(@NonNull StatsLogManager statsLogManager) {
+ statsLogManager.logger().log(
+ StatsLogManager.LauncherEvent.LAUNCHER_GESTURE_TUTORIAL_OVERVIEW_STEP_COMPLETED);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialFragment.java
index 955a2f7..5183e2c 100644
--- a/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialFragment.java
@@ -18,11 +18,16 @@
import android.view.MotionEvent;
import android.view.View;
+import androidx.annotation.NonNull;
+
+import com.android.launcher3.logging.StatsLogManager;
import com.android.quickstep.interaction.TutorialController.TutorialType;
/** Shows the general navigation gesture sandbox environment. */
public class SandboxModeTutorialFragment extends TutorialFragment {
+ public SandboxModeTutorialFragment() {}
+
@Override
TutorialController createController(TutorialType type) {
return new SandboxModeTutorialController(this, type);
@@ -40,4 +45,14 @@
}
return super.onTouch(view, motionEvent);
}
+
+ @Override
+ void logTutorialStepShown(@NonNull StatsLogManager statsLogManager) {
+ // No-Op: tutorial step not currently shown to users
+ }
+
+ @Override
+ void logTutorialStepCompleted(@NonNull StatsLogManager statsLogManager) {
+ // No-Op: tutorial step not currently shown to users
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index 672687d..b70c411 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -16,7 +16,7 @@
package com.android.quickstep.interaction;
import static com.android.launcher3.anim.Interpolators.ACCEL;
-import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
+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;
import static com.android.quickstep.interaction.TutorialController.TutorialType.HOME_NAVIGATION_COMPLETE;
@@ -280,6 +280,15 @@
super(context, deviceState, gestureState);
mRemoteTargetHandles[0] = new RemoteTargetGluer.RemoteTargetHandle(
mRemoteTargetHandles[0].getTaskViewSimulator(), new FakeTransformParams());
+
+ for (RemoteTargetGluer.RemoteTargetHandle handle
+ : mTargetGluer.getRemoteTargetHandles()) {
+ // Override home screen rotation preference so that home and overview animations
+ // work properly
+ handle.getTaskViewSimulator()
+ .getOrientationState()
+ .ignoreAllowHomeRotationPreference();
+ }
}
void initDp(DeviceProfile dp) {
@@ -336,8 +345,7 @@
1f - SHAPE_PROGRESS_DURATION /* shapeProgressStart */,
radius, 255,
false, /* isOpening */
- mFakeIconView, mDp,
- false /* isVerticalBarLayout */);
+ mFakeIconView, mDp);
mFakeIconView.setAlpha(1);
mFakeTaskView.setAlpha(getWindowAlpha(progress));
mFakePreviousTaskView.setAlpha(getWindowAlpha(progress));
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index 4145393..fa7d848 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -49,6 +49,7 @@
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.content.res.AppCompatResources;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorListeners;
@@ -61,9 +62,9 @@
abstract class TutorialController implements BackGestureAttemptCallback,
NavBarGestureAttemptCallback {
- private static final String TAG = "TutorialController";
+ private static final String LOG_TAG = "TutorialController";
- private static final float FINGER_DOT_VISIBLE_ALPHA = 0.6f;
+ private static final float FINGER_DOT_VISIBLE_ALPHA = 0.7f;
private static final float FINGER_DOT_SMALL_SCALE = 0.7f;
private static final int FINGER_DOT_ANIMATION_DURATION_MILLIS = 500;
@@ -73,14 +74,15 @@
private static final int FEEDBACK_ANIMATION_MS = 133;
private static final int RIPPLE_VISIBLE_MS = 300;
private static final int GESTURE_ANIMATION_DELAY_MS = 1500;
- private static final int ADVANCE_TUTORIAL_TIMEOUT_MS = 4000;
+ private static final int ADVANCE_TUTORIAL_TIMEOUT_MS = 2000;
private static final long GESTURE_ANIMATION_PAUSE_DURATION_MILLIS = 1000;
final TutorialFragment mTutorialFragment;
TutorialType mTutorialType;
final Context mContext;
- final TextView mCloseButton;
+ final TextView mSkipButton;
+ final Button mDoneButton;
final ViewGroup mFeedbackView;
final TextView mFeedbackTitleView;
final ImageView mEdgeGestureVideoView;
@@ -93,7 +95,6 @@
final AnimatedTaskView mFakePreviousTaskView;
final View mRippleView;
final RippleDrawable mRippleDrawable;
- final Button mActionButton;
final TutorialStepIndicator mTutorialStepView;
final ImageView mFingerDotView;
private final AlertDialog mSkipTutorialDialog;
@@ -114,8 +115,8 @@
mContext = mTutorialFragment.getContext();
RootSandboxLayout rootView = tutorialFragment.getRootView();
- mCloseButton = rootView.findViewById(R.id.gesture_tutorial_fragment_close_button);
- mCloseButton.setOnClickListener(button -> showSkipTutorialDialog());
+ mSkipButton = rootView.findViewById(R.id.gesture_tutorial_fragment_close_button);
+ mSkipButton.setOnClickListener(button -> showSkipTutorialDialog());
mFeedbackView = rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_view);
mFeedbackTitleView = mFeedbackView.findViewById(
R.id.gesture_tutorial_fragment_feedback_title);
@@ -129,7 +130,7 @@
rootView.findViewById(R.id.gesture_tutorial_fake_previous_task_view);
mRippleView = rootView.findViewById(R.id.gesture_tutorial_ripple_view);
mRippleDrawable = (RippleDrawable) mRippleView.getBackground();
- mActionButton = rootView.findViewById(R.id.gesture_tutorial_fragment_action_button);
+ mDoneButton = rootView.findViewById(R.id.gesture_tutorial_fragment_action_button);
mTutorialStepView =
rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_tutorial_step);
mFingerDotView = rootView.findViewById(R.id.gesture_tutorial_finger_dot);
@@ -185,7 +186,9 @@
@LayoutRes
protected int getMockHotseatResId() {
return mTutorialFragment.isLargeScreen()
- ? R.layout.gesture_tutorial_foldable_mock_hotseat
+ ? (mTutorialFragment.isFoldable()
+ ? R.layout.gesture_tutorial_foldable_mock_hotseat
+ : R.layout.gesture_tutorial_tablet_mock_hotseat)
: R.layout.gesture_tutorial_mock_hotseat;
}
@@ -214,18 +217,23 @@
}
@StringRes
- public Integer getIntroductionTitle() {
- return null;
+ public int getIntroductionTitle() {
+ return NO_ID;
}
@StringRes
- public Integer getIntroductionSubtitle() {
- return null;
+ public int getIntroductionSubtitle() {
+ return NO_ID;
}
@StringRes
- public Integer getSuccessFeedbackSubtitle() {
- return null;
+ public int getSpokenIntroductionSubtitle() {
+ return NO_ID;
+ }
+
+ @StringRes
+ public int getSuccessFeedbackSubtitle() {
+ return NO_ID;
}
void showFeedback() {
@@ -244,7 +252,16 @@
* Show feedback reflecting a successful gesture attempt.
**/
void showSuccessFeedback() {
- showFeedback(getSuccessFeedbackSubtitle(), true);
+ int successSubtitleResId = getSuccessFeedbackSubtitle();
+ if (successSubtitleResId == NO_ID) {
+ // Allow crash since this should never be reached with a tutorial controller used in
+ // production.
+ Log.e(LOG_TAG,
+ "Cannot show success feedback for tutorial step: " + mTutorialType
+ + ", no success feedback subtitle",
+ new IllegalStateException());
+ }
+ showFeedback(successSubtitleResId, true);
}
/**
@@ -266,6 +283,7 @@
isGestureSuccessful
? R.string.gesture_tutorial_nice : R.string.gesture_tutorial_try_again,
subtitleResId,
+ NO_ID,
isGestureSuccessful,
false);
}
@@ -273,6 +291,7 @@
void showFeedback(
int titleResId,
int subtitleResId,
+ int spokenSubtitleResId,
boolean isGestureSuccessful,
boolean useGestureAnimationDelay) {
mFeedbackTitleView.removeCallbacks(mTitleViewCallback);
@@ -284,7 +303,10 @@
mFeedbackTitleView.setText(titleResId);
TextView subtitle =
mFeedbackView.findViewById(R.id.gesture_tutorial_fragment_feedback_subtitle);
- subtitle.setText(subtitleResId);
+ subtitle.setText(spokenSubtitleResId == NO_ID
+ ? mContext.getText(subtitleResId)
+ : Utilities.wrapForTts(
+ mContext.getText(subtitleResId), mContext.getString(spokenSubtitleResId)));
if (isGestureSuccessful) {
if (mTutorialFragment.isAtFinalStep()) {
showActionButton();
@@ -319,6 +341,9 @@
}
void hideFeedback() {
+ if (mFeedbackView.getVisibility() != View.VISIBLE) {
+ return;
+ }
cancelQueuedGestureAnimation();
mFeedbackView.clearAnimation();
mFeedbackView.setVisibility(View.INVISIBLE);
@@ -425,22 +450,22 @@
}
void updateCloseButton() {
- mCloseButton.setTextAppearance(Utilities.isDarkTheme(mContext)
+ mSkipButton.setTextAppearance(Utilities.isDarkTheme(mContext)
? R.style.TextAppearance_GestureTutorial_Feedback_Subtext
: R.style.TextAppearance_GestureTutorial_Feedback_Subtext_Dark);
}
void hideActionButton() {
- mCloseButton.setVisibility(View.VISIBLE);
+ mSkipButton.setVisibility(View.VISIBLE);
// Invisible to maintain the layout.
- mActionButton.setVisibility(View.INVISIBLE);
- mActionButton.setOnClickListener(null);
+ mDoneButton.setVisibility(View.INVISIBLE);
+ mDoneButton.setOnClickListener(null);
}
void showActionButton() {
- mCloseButton.setVisibility(GONE);
- mActionButton.setVisibility(View.VISIBLE);
- mActionButton.setOnClickListener(this::onActionButtonClicked);
+ mSkipButton.setVisibility(GONE);
+ mDoneButton.setVisibility(View.VISIBLE);
+ mDoneButton.setOnClickListener(this::onActionButtonClicked);
}
void hideFakeTaskbar(boolean animateToHotseat) {
@@ -515,20 +540,45 @@
}
private void updateLayout() {
- if (mContext != null) {
- RelativeLayout.LayoutParams feedbackLayoutParams =
- (RelativeLayout.LayoutParams) mFeedbackView.getLayoutParams();
- feedbackLayoutParams.setMarginStart(mContext.getResources().getDimensionPixelSize(
- mTutorialFragment.isLargeScreen()
- ? R.dimen.gesture_tutorial_foldable_feedback_margin_start_end
- : R.dimen.gesture_tutorial_feedback_margin_start_end));
- feedbackLayoutParams.setMarginEnd(mContext.getResources().getDimensionPixelSize(
- mTutorialFragment.isLargeScreen()
- ? R.dimen.gesture_tutorial_foldable_feedback_margin_start_end
- : R.dimen.gesture_tutorial_feedback_margin_start_end));
-
- mFakeTaskbarView.setVisibility(mTutorialFragment.isLargeScreen() ? View.VISIBLE : GONE);
+ if (mContext == null) {
+ return;
}
+ RelativeLayout.LayoutParams feedbackLayoutParams =
+ (RelativeLayout.LayoutParams) mFeedbackView.getLayoutParams();
+ feedbackLayoutParams.setMarginStart(mContext.getResources().getDimensionPixelSize(
+ mTutorialFragment.isLargeScreen()
+ ? R.dimen.gesture_tutorial_tablet_feedback_margin_start_end
+ : R.dimen.gesture_tutorial_feedback_margin_start_end));
+ feedbackLayoutParams.setMarginEnd(mContext.getResources().getDimensionPixelSize(
+ mTutorialFragment.isLargeScreen()
+ ? R.dimen.gesture_tutorial_tablet_feedback_margin_start_end
+ : R.dimen.gesture_tutorial_feedback_margin_start_end));
+ feedbackLayoutParams.topMargin = mContext.getResources().getDimensionPixelSize(
+ mTutorialFragment.isLargeScreen()
+ ? R.dimen.gesture_tutorial_tablet_feedback_margin_top
+ : R.dimen.gesture_tutorial_feedback_margin_top);
+
+ mFakeTaskbarView.setVisibility(mTutorialFragment.isLargeScreen() ? View.VISIBLE : GONE);
+
+ RelativeLayout.LayoutParams hotseatLayoutParams =
+ (RelativeLayout.LayoutParams) mFakeHotseatView.getLayoutParams();
+ if (!mTutorialFragment.isLargeScreen()) {
+ DeviceProfile dp = mTutorialFragment.getDeviceProfile();
+ dp.updateIsSeascape(mContext);
+
+ hotseatLayoutParams.addRule(dp.isLandscape
+ ? (dp.isSeascape()
+ ? RelativeLayout.ALIGN_PARENT_START
+ : RelativeLayout.ALIGN_PARENT_END)
+ : RelativeLayout.ALIGN_PARENT_BOTTOM);
+ } else {
+ hotseatLayoutParams.width = RelativeLayout.LayoutParams.MATCH_PARENT;
+ hotseatLayoutParams.height = RelativeLayout.LayoutParams.WRAP_CONTENT;
+ hotseatLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+ hotseatLayoutParams.removeRule(RelativeLayout.ALIGN_PARENT_START);
+ hotseatLayoutParams.removeRule(RelativeLayout.ALIGN_PARENT_END);
+ }
+ mFakeHotseatView.setLayoutParams(hotseatLayoutParams);
}
private AlertDialog createSkipTutorialDialog() {
@@ -549,7 +599,7 @@
packageManager.getApplicationInfo(
PIXEL_TIPS_APP_PACKAGE_NAME, PackageManager.GET_META_DATA));
} catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG,
+ Log.e(LOG_TAG,
"Could not find app label for package name: "
+ PIXEL_TIPS_APP_PACKAGE_NAME
+ ". Defaulting to 'Pixel Tips.'",
@@ -562,7 +612,7 @@
subtitleTextView.setText(
mContext.getString(R.string.skip_tutorial_dialog_subtitle, tipsAppName));
} else {
- Log.w(TAG, "No subtitle view in the skip tutorial dialog to update.");
+ Log.w(LOG_TAG, "No subtitle view in the skip tutorial dialog to update.");
}
Button cancelButton = (Button) contentView.findViewById(
@@ -571,18 +621,18 @@
cancelButton.setOnClickListener(
v -> tutorialDialog.dismiss());
} else {
- Log.w(TAG, "No cancel button in the skip tutorial dialog to update.");
+ Log.w(LOG_TAG, "No cancel button in the skip tutorial dialog to update.");
}
Button confirmButton = contentView.findViewById(
R.id.gesture_tutorial_dialog_confirm_button);
if (confirmButton != null) {
confirmButton.setOnClickListener(v -> {
- sandboxActivity.closeTutorial();
+ mTutorialFragment.closeTutorial(true);
tutorialDialog.dismiss();
});
} else {
- Log.w(TAG, "No confirm button in the skip tutorial dialog to update.");
+ Log.w(LOG_TAG, "No confirm button in the skip tutorial dialog to update.");
}
tutorialDialog.getWindow().setBackgroundDrawable(
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index 2fd7cde..1599c8c 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -15,17 +15,20 @@
*/
package com.android.quickstep.interaction;
+import static android.view.View.NO_ID;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ActivityInfo;
+import android.content.SharedPreferences;
import android.graphics.Insets;
import android.graphics.drawable.Animatable2;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.util.ArraySet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -41,16 +44,24 @@
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.R;
+import com.android.launcher3.logging.StatsLogManager;
import com.android.quickstep.interaction.TutorialController.TutorialType;
+import java.util.Set;
+
abstract class TutorialFragment extends Fragment implements OnTouchListener {
private static final String LOG_TAG = "TutorialFragment";
static final String KEY_TUTORIAL_TYPE = "tutorial_type";
static final String KEY_GESTURE_COMPLETE = "gesture_complete";
+ private static final String TUTORIAL_SKIPPED_PREFERENCE_KEY = "pref_gestureTutorialSkipped";
+ private static final String COMPLETED_TUTORIAL_STEPS_PREFERENCE_KEY =
+ "pref_completedTutorialSteps";
+
TutorialType mTutorialType;
boolean mGestureComplete = false;
@Nullable TutorialController mTutorialController = null;
@@ -67,9 +78,12 @@
private boolean mFragmentStopped = false;
+ private DeviceProfile mDeviceProfile;
private boolean mIsLargeScreen;
+ private boolean mIsFoldable;
- public static TutorialFragment newInstance(TutorialType tutorialType, boolean gestureComplete) {
+ public static TutorialFragment newInstance(
+ TutorialType tutorialType, boolean gestureComplete) {
TutorialFragment fragment = getFragmentForTutorialType(tutorialType);
if (fragment == null) {
fragment = new BackGestureTutorialFragment();
@@ -139,22 +153,24 @@
mEdgeBackGestureHandler = new EdgeBackGestureHandler(getContext());
mNavBarGestureHandler = new NavBarGestureHandler(getContext());
- mIsLargeScreen = InvariantDeviceProfile.INSTANCE.get(getContext())
- .getDeviceProfile(getContext()).isTablet;
-
- if (mIsLargeScreen) {
- ((Activity) getContext()).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
- } else {
- // Temporary until UI mocks for landscape mode for phones are created.
- ((Activity) getContext()).setRequestedOrientation(
- ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
- }
+ mDeviceProfile = InvariantDeviceProfile.INSTANCE.get(getContext())
+ .getDeviceProfile(getContext());
+ mIsLargeScreen = mDeviceProfile.isTablet;
+ mIsFoldable = mDeviceProfile.isTwoPanels;
}
public boolean isLargeScreen() {
return mIsLargeScreen;
}
+ public boolean isFoldable() {
+ return mIsFoldable;
+ }
+
+ DeviceProfile getDeviceProfile() {
+ return mDeviceProfile;
+ }
+
@Override
public void onDestroy() {
super.onDestroy();
@@ -197,13 +213,31 @@
if (isGestureComplete()) {
mTutorialController.showSuccessFeedback();
} else if (!mIntroductionShown) {
- Integer introTileStringResId = mTutorialController.getIntroductionTitle();
- Integer introSubtitleResId = mTutorialController.getIntroductionSubtitle();
- if (introTileStringResId != null && introSubtitleResId != null) {
- mTutorialController.showFeedback(
- introTileStringResId, introSubtitleResId, false, true);
- mIntroductionShown = true;
+ int introTitleResId = mTutorialController.getIntroductionTitle();
+ int introSubtitleResId = mTutorialController.getIntroductionSubtitle();
+ if (introTitleResId == NO_ID) {
+ // Allow crash since this should never be reached with a tutorial controller used in
+ // production.
+ Log.e(LOG_TAG,
+ "Cannot show introduction feedback for tutorial step: " + mTutorialType
+ + ", no introduction feedback title",
+ new IllegalStateException());
}
+ if (introTitleResId == NO_ID) {
+ // Allow crash since this should never be reached with a tutorial controller used in
+ // production.
+ Log.e(LOG_TAG,
+ "Cannot show introduction feedback for tutorial step: " + mTutorialType
+ + ", no introduction feedback subtitle",
+ new IllegalStateException());
+ }
+ mTutorialController.showFeedback(
+ introTitleResId,
+ introSubtitleResId,
+ mTutorialController.getSpokenIntroductionSubtitle(),
+ false,
+ true);
+ mIntroductionShown = true;
}
}
@@ -296,6 +330,9 @@
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
+ if (mTutorialController != null && !isGestureComplete()) {
+ mTutorialController.hideFeedback();
+ }
// Note: Using logical-or to ensure both functions get called.
return mEdgeBackGestureHandler.onTouch(view, motionEvent)
| mNavBarGestureHandler.onTouch(view, motionEvent);
@@ -308,6 +345,10 @@
}
void onAttachedToWindow() {
+ StatsLogManager statsLogManager = getStatsLogManager();
+ if (statsLogManager != null) {
+ logTutorialStepShown(statsLogManager);
+ }
mEdgeBackGestureHandler.setViewGroupParent(getRootView());
}
@@ -341,8 +382,22 @@
}
void continueTutorial() {
- GestureSandboxActivity gestureSandboxActivity = getGestureSandboxActivity();
+ SharedPreferences sharedPrefs = getSharedPreferences();
+ if (sharedPrefs != null) {
+ Set<String> updatedCompletedSteps = new ArraySet<>(sharedPrefs.getStringSet(
+ COMPLETED_TUTORIAL_STEPS_PREFERENCE_KEY, new ArraySet<>()));
+ updatedCompletedSteps.add(mTutorialType.toString());
+
+ sharedPrefs.edit().putStringSet(
+ COMPLETED_TUTORIAL_STEPS_PREFERENCE_KEY, updatedCompletedSteps).apply();
+ }
+ StatsLogManager statsLogManager = getStatsLogManager();
+ if (statsLogManager != null) {
+ logTutorialStepCompleted(statsLogManager);
+ }
+
+ GestureSandboxActivity gestureSandboxActivity = getGestureSandboxActivity();
if (gestureSandboxActivity == null) {
closeTutorial();
return;
@@ -351,6 +406,21 @@
}
void closeTutorial() {
+ closeTutorial(false);
+ }
+
+ void closeTutorial(boolean tutorialSkipped) {
+ if (tutorialSkipped) {
+ SharedPreferences sharedPrefs = getSharedPreferences();
+ if (sharedPrefs != null) {
+ sharedPrefs.edit().putBoolean(TUTORIAL_SKIPPED_PREFERENCE_KEY, true).apply();
+ }
+ StatsLogManager statsLogManager = getStatsLogManager();
+ if (statsLogManager != null) {
+ statsLogManager.logger().log(
+ StatsLogManager.LauncherEvent.LAUNCHER_GESTURE_TUTORIAL_SKIPPED);
+ }
+ }
FragmentActivity activity = getActivity();
if (activity != null) {
activity.setResult(Activity.RESULT_OK);
@@ -383,10 +453,28 @@
|| (mTutorialController != null && mTutorialController.isGestureCompleted());
}
+ abstract void logTutorialStepShown(@NonNull StatsLogManager statsLogManager);
+
+ abstract void logTutorialStepCompleted(@NonNull StatsLogManager statsLogManager);
+
@Nullable
private GestureSandboxActivity getGestureSandboxActivity() {
Context context = getContext();
return context instanceof GestureSandboxActivity ? (GestureSandboxActivity) context : null;
}
+
+ @Nullable
+ private StatsLogManager getStatsLogManager() {
+ GestureSandboxActivity activity = getGestureSandboxActivity();
+
+ return activity != null ? activity.getStatsLogManager() : null;
+ }
+
+ @Nullable
+ private SharedPreferences getSharedPreferences() {
+ GestureSandboxActivity activity = getGestureSandboxActivity();
+
+ return activity != null ? activity.getSharedPrefs() : null;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialStepIndicator.java b/quickstep/src/com/android/quickstep/interaction/TutorialStepIndicator.java
index d880d74..ae0e725 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialStepIndicator.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialStepIndicator.java
@@ -23,7 +23,6 @@
import android.widget.LinearLayout;
import androidx.appcompat.content.res.AppCompatResources;
-import androidx.core.graphics.ColorUtils;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -87,8 +86,10 @@
for (int i = mTotalSteps; i < getChildCount(); i++) {
removeViewAt(i);
}
- int stepIndicatorColor = GraphicsUtils.getAttrColor(
+ int activeStepIndicatorColor = GraphicsUtils.getAttrColor(
getContext(), android.R.attr.textColorPrimary);
+ int inactiveStepIndicatorColor = GraphicsUtils.getAttrColor(
+ getContext(), android.R.attr.textColorSecondaryInverse);
for (int i = 0; i < mTotalSteps; i++) {
Drawable pageIndicatorPillDrawable = AppCompatResources.getDrawable(
getContext(), R.drawable.tutorial_step_indicator_pill);
@@ -107,10 +108,9 @@
}
if (pageIndicatorPillDrawable != null) {
if (i < mCurrentStep) {
- pageIndicatorPillDrawable.setTint(stepIndicatorColor);
+ pageIndicatorPillDrawable.setTint(activeStepIndicatorColor);
} else {
- pageIndicatorPillDrawable.setTint(
- ColorUtils.setAlphaComponent(stepIndicatorColor, 0x22));
+ pageIndicatorPillDrawable.setTint(inactiveStepIndicatorColor);
}
}
}
diff --git a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
index a0cd0d7..bd0250d 100644
--- a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
+++ b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
@@ -26,6 +26,7 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_THEMED_ICON_ENABLED;
import static com.android.launcher3.model.DeviceGridState.KEY_WORKSPACE_SIZE;
import static com.android.launcher3.model.QuickstepModelDelegate.LAST_PREDICTION_ENABLED_STATE;
+import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI;
import static com.android.launcher3.util.Themes.KEY_THEMED_ICONS;
@@ -44,11 +45,11 @@
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
import com.android.launcher3.model.DeviceGridState;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.DisplayController.Info;
+import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.SettingsCache;
-import com.android.quickstep.SysUINavigationMode;
-import com.android.quickstep.SysUINavigationMode.Mode;
-import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -60,8 +61,8 @@
* Utility class to log launcher settings changes
*/
public class SettingsChangeLogger implements
- NavigationModeChangeListener, OnSharedPreferenceChangeListener {
-
+ DisplayController.DisplayInfoChangeListener, OnSharedPreferenceChangeListener {
+
/**
* Singleton instance
*/
@@ -76,7 +77,7 @@
private final ArrayMap<String, LoggablePref> mLoggablePrefs;
private final StatsLogManager mStatsLogManager;
- private Mode mNavMode;
+ private NavigationMode mNavMode;
private StatsLogManager.LauncherEvent mNotificationDotsEvent;
private StatsLogManager.LauncherEvent mHomeScreenSuggestionEvent;
@@ -84,7 +85,8 @@
mContext = context;
mStatsLogManager = StatsLogManager.newInstance(mContext);
mLoggablePrefs = loadPrefKeys(context);
- mNavMode = SysUINavigationMode.INSTANCE.get(context).addModeChangeListener(this);
+ DisplayController.INSTANCE.get(context).addChangeListener(this);
+ mNavMode = DisplayController.getNavigationMode(context);
getPrefs(context).registerOnSharedPreferenceChangeListener(this);
getDevicePrefs(context).registerOnSharedPreferenceChangeListener(this);
@@ -141,9 +143,11 @@
}
@Override
- public void onNavigationModeChanged(Mode newMode) {
- mNavMode = newMode;
- mStatsLogManager.logger().log(newMode.launcherEvent);
+ public void onDisplayInfoChanged(Context context, Info info, int flags) {
+ if ((flags & CHANGE_NAVIGATION_MODE) != 0) {
+ mNavMode = info.navigationMode;
+ mStatsLogManager.logger().log(mNavMode.launcherEvent);
+ }
}
@Override
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 676161e..45c8036 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -19,6 +19,8 @@
import static androidx.core.util.Preconditions.checkNotNull;
import static androidx.core.util.Preconditions.checkState;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_NON_ACTIONABLE;
+import static com.android.launcher3.logger.LauncherAtom.ContainerInfo.ContainerCase.ALL_APPS_CONTAINER;
import static com.android.launcher3.logger.LauncherAtom.ContainerInfo.ContainerCase.EXTENDED_CONTAINERS;
import static com.android.launcher3.logger.LauncherAtom.ContainerInfo.ContainerCase.FOLDER;
import static com.android.launcher3.logger.LauncherAtom.ContainerInfo.ContainerCase.SEARCH_RESULT_CONTAINER;
@@ -42,12 +44,15 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.Utilities;
import com.android.launcher3.logger.LauncherAtom;
+import com.android.launcher3.logger.LauncherAtom.Attribute;
import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
import com.android.launcher3.logger.LauncherAtom.FolderContainer.ParentContainerCase;
import com.android.launcher3.logger.LauncherAtom.FolderIcon;
import com.android.launcher3.logger.LauncherAtom.FromState;
+import com.android.launcher3.logger.LauncherAtom.LauncherAttributes;
import com.android.launcher3.logger.LauncherAtom.ToState;
import com.android.launcher3.logger.LauncherAtomExtensions.DeviceSearchResultContainer;
+import com.android.launcher3.logger.LauncherAtomExtensions.DeviceSearchResultContainer.SearchAttributes;
import com.android.launcher3.logger.LauncherAtomExtensions.ExtendedContainers;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.StatsLogManager;
@@ -79,6 +84,7 @@
public class StatsLogCompatManager extends StatsLogManager {
private static final String TAG = "StatsLog";
+ private static final String LATENCY_TAG = "StatsLatencyLog";
private static final boolean IS_VERBOSE = Utilities.isPropertyEnabled(LogConfig.STATSLOG);
private static final InstanceId DEFAULT_INSTANCE_ID = InstanceId.fakeInstanceId(0);
// LauncherAtom.ItemInfo.getDefaultInstance() should be used but until launcher proto migrates
@@ -87,7 +93,15 @@
private static final int FOLDER_HIERARCHY_OFFSET = 100;
private static final int SEARCH_RESULT_HIERARCHY_OFFSET = 200;
private static final int EXTENDED_CONTAINERS_HIERARCHY_OFFSET = 300;
- private static final int ATTRIBUTE_MULTIPLIER = 100;
+ private static final int ALL_APPS_HIERARCHY_OFFSET = 400;
+
+ /**
+ * Flags for converting SearchAttribute to integer value.
+ */
+ private static final int SEARCH_ATTRIBUTES_CORRECTED_QUERY = 1 << 0;
+ private static final int SEARCH_ATTRIBUTES_DIRECT_MATCH = 1 << 1;
+ private static final int SEARCH_ATTRIBUTES_ENTRY_STATE_ALL_APPS = 1 << 2;
+ private static final int SEARCH_ATTRIBUTES_ENTRY_STATE_QSB = 1 << 3;
public static final CopyOnWriteArrayList<StatsLogConsumer> LOGS_CONSUMER =
new CopyOnWriteArrayList<>();
@@ -103,6 +117,11 @@
return new StatsCompatLogger(mContext, mActivityContext);
}
+ @Override
+ protected StatsLatencyLogger createLatencyLogger() {
+ return new StatsCompatLatencyLogger(mContext, mActivityContext);
+ }
+
/**
* Synchronously writes an itemInfo to stats log
*/
@@ -111,13 +130,12 @@
if (IS_VERBOSE) {
Log.d(TAG, String.format("\nwriteSnapshot(%d):\n%s", instanceId.getId(), info));
}
- if (!Utilities.ATLEAST_R) {
+ if (!Utilities.ATLEAST_R || Utilities.IS_RUNNING_IN_TEST_HARNESS) {
return;
}
SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_SNAPSHOT,
LAUNCHER_WORKSPACE_SNAPSHOT.getId() /* event_id */,
- info.getAttribute().getNumber() * ATTRIBUTE_MULTIPLIER
- + info.getItemCase().getNumber() /* target_id */,
+ info.getItemCase().getNumber() /* target_id */,
instanceId.getId() /* instance_id */,
0 /* uid */,
getPackageName(info) /* package_name */,
@@ -130,11 +148,20 @@
getParentPageId(info) /* page_id_parent */,
getHierarchy(info) /* hierarchy */,
info.getIsWork() /* is_work_profile */,
- info.getAttribute().getNumber() /* origin */,
+ 0 /* origin */,
getCardinality(info) /* cardinality */,
info.getWidget().getSpanX(),
info.getWidget().getSpanY(),
- getFeatures(info));
+ getFeatures(info),
+ getAttributes(info) /* attributes */
+ );
+ }
+
+ private static byte[] getAttributes(LauncherAtom.ItemInfo itemInfo) {
+ LauncherAttributes.Builder responseBuilder = LauncherAttributes.newBuilder();
+ itemInfo.getItemAttributesList().stream().map(Attribute::getNumber).forEach(
+ responseBuilder::addItemAttributes);
+ return responseBuilder.build().toByteArray();
}
/**
@@ -146,8 +173,7 @@
return SysUiStatsLog.buildStatsEvent(
SysUiStatsLog.LAUNCHER_LAYOUT_SNAPSHOT, // atom ID,
LAUNCHER_WORKSPACE_SNAPSHOT.getId(), // event_id = 1;
- info.getAttribute().getNumber() * ATTRIBUTE_MULTIPLIER
- + info.getItemCase().getNumber(), // item_id = 2;
+ info.getItemCase().getNumber(), // item_id = 2;
instanceId == null ? 0 : instanceId.getId(), //instance_id = 3;
0, //uid = 4 [(is_uid) = true];
getPackageName(info), // package_name = 5;
@@ -160,10 +186,11 @@
getParentPageId(info), //page_id_parent = 12 [default = -2];
getHierarchy(info), // container_id = 13;
info.getIsWork(), // is_work_profile = 14;
- info.getAttribute().getNumber(), // attribute_id = 15;
+ 0, // attribute_id = 15;
getCardinality(info), // cardinality = 16;
info.getWidget().getSpanX(), // span_x = 17 [default = 1];
- info.getWidget().getSpanY() // span_y = 18 [default = 1];
+ info.getWidget().getSpanY(), // span_y = 18 [default = 1];
+ getAttributes(info) /* attributes */
);
}
@@ -173,7 +200,9 @@
private static class StatsCompatLogger implements StatsLogger {
private static final ItemInfo DEFAULT_ITEM_INFO = new ItemInfo();
-
+ static {
+ DEFAULT_ITEM_INFO.itemType = ITEM_TYPE_NON_ACTIONABLE;
+ }
private final Context mContext;
private final Optional<ActivityContext> mActivityContext;
private ItemInfo mItemInfo = DEFAULT_ITEM_INFO;
@@ -365,19 +394,31 @@
if (IS_VERBOSE) {
String name = (event instanceof Enum) ? ((Enum) event).name() :
event.getId() + "";
-
- Log.d(TAG, instanceId == DEFAULT_INSTANCE_ID
- ? String.format("\n%s (State:%s->%s)\n%s", name, getStateString(srcState),
- getStateString(dstState), atomInfo)
- : String.format("\n%s (State:%s->%s) (InstanceId:%s)\n%s", name,
- getStateString(srcState), getStateString(dstState), instanceId,
- atomInfo));
+ StringBuilder logStringBuilder = new StringBuilder("\n");
+ if (instanceId != DEFAULT_INSTANCE_ID) {
+ logStringBuilder.append(String.format("InstanceId:%s ", instanceId));
+ }
+ logStringBuilder.append(name);
+ if (srcState != LAUNCHER_STATE_UNSPECIFIED
+ || dstState != LAUNCHER_STATE_UNSPECIFIED) {
+ logStringBuilder.append(
+ String.format("(State:%s->%s)", getStateString(srcState),
+ getStateString(dstState)));
+ }
+ if (atomInfo.hasContainerInfo()) {
+ logStringBuilder.append("\n").append(atomInfo);
+ }
+ Log.d(TAG, logStringBuilder.toString());
}
for (StatsLogConsumer consumer : LOGS_CONSUMER) {
consumer.consume(event, atomInfo);
}
+ // TODO: remove this when b/231648228 is fixed.
+ if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ return;
+ }
SysUiStatsLog.write(
SysUiStatsLog.LAUNCHER_EVENT,
SysUiStatsLog.LAUNCHER_UICHANGED__ACTION__DEFAULT_ACTION /* deprecated */,
@@ -386,8 +427,7 @@
null /* launcher extensions, deprecated */,
false /* quickstep_enabled, deprecated */,
event.getId() /* event_id */,
- atomInfo.getAttribute().getNumber() * ATTRIBUTE_MULTIPLIER
- + atomInfo.getItemCase().getNumber() /* target_id */,
+ atomInfo.getItemCase().getNumber() /* target_id */,
instanceId.getId() /* instance_id TODO */,
0 /* uid TODO */,
getPackageName(atomInfo) /* package_name */,
@@ -405,11 +445,86 @@
atomInfo.getFolderIcon().getToLabelState().getNumber() /* toState */,
atomInfo.getFolderIcon().getLabelInfo() /* edittext */,
getCardinality(atomInfo) /* cardinality */,
- getFeatures(atomInfo) /* features */);
+ getFeatures(atomInfo) /* features */,
+ getSearchAttributes(atomInfo) /* searchAttributes */,
+ getAttributes(atomInfo) /* attributes */
+ );
+ }
+ }
+
+ /**
+ * Helps to construct and log statsd compatible latency events.
+ */
+ private static class StatsCompatLatencyLogger implements StatsLatencyLogger {
+ private final Context mContext;
+ private final Optional<ActivityContext> mActivityContext;
+ private InstanceId mInstanceId = DEFAULT_INSTANCE_ID;
+ private LatencyType mType = LatencyType.UNKNOWN;
+ private int mPackageId = 0;
+ private long mLatencyInMillis;
+ private int mQueryLength = -1;
+
+ StatsCompatLatencyLogger(Context context, ActivityContext activityContext) {
+ mContext = context;
+ mActivityContext = Optional.ofNullable(activityContext);
+ }
+
+ @Override
+ public StatsLatencyLogger withInstanceId(InstanceId instanceId) {
+ this.mInstanceId = instanceId;
+ return this;
+ }
+
+ @Override
+ public StatsLatencyLogger withType(LatencyType type) {
+ this.mType = type;
+ return this;
+ }
+
+ @Override
+ public StatsLatencyLogger withPackageId(int packageId) {
+ this.mPackageId = packageId;
+ return this;
+ }
+
+ @Override
+ public StatsLatencyLogger withLatency(long latencyInMillis) {
+ this.mLatencyInMillis = latencyInMillis;
+ return this;
+ }
+
+ @Override
+ public StatsLatencyLogger withQueryLength(int queryLength) {
+ this.mQueryLength = queryLength;
+ return this;
+ }
+
+ @Override
+ public void log(EventEnum event) {
+ 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("%s=%sms", name, mLatencyInMillis));
+ Log.d(LATENCY_TAG, logStringBuilder.toString());
+ }
+
+ SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_LATENCY,
+ event.getId(), // event_id
+ mInstanceId.getId(), // instance_id
+ mPackageId, // package_id
+ mLatencyInMillis, // latency_in_millis
+ mType.getId(), //type
+ mQueryLength // query_length
+ );
}
}
private static int getCardinality(LauncherAtom.ItemInfo info) {
+ if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ return 0;
+ }
switch (info.getContainerInfo().getContainerCase()) {
case PREDICTED_HOTSEAT_CONTAINER:
return info.getContainerInfo().getPredictedHotseatContainer().getCardinality();
@@ -467,14 +582,18 @@
}
private static int getGridX(LauncherAtom.ItemInfo info, boolean parent) {
- if (info.getContainerInfo().getContainerCase() == FOLDER) {
+ LauncherAtom.ContainerInfo containerInfo = info.getContainerInfo();
+ if (containerInfo.getContainerCase() == FOLDER) {
if (parent) {
- return info.getContainerInfo().getFolder().getWorkspace().getGridX();
+ return containerInfo.getFolder().getWorkspace().getGridX();
} else {
- return info.getContainerInfo().getFolder().getGridX();
+ return containerInfo.getFolder().getGridX();
}
+ } else if (containerInfo.getContainerCase() == EXTENDED_CONTAINERS) {
+ return containerInfo.getExtendedContainers()
+ .getDeviceSearchResultContainer().getGridX();
} else {
- return info.getContainerInfo().getWorkspace().getGridX();
+ return containerInfo.getWorkspace().getGridX();
}
}
@@ -525,6 +644,9 @@
}
private static int getHierarchy(LauncherAtom.ItemInfo info) {
+ if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ return 0;
+ }
if (info.getContainerInfo().getContainerCase() == FOLDER) {
return info.getContainerInfo().getFolder().getParentContainerCase().getNumber()
+ FOLDER_HIERARCHY_OFFSET;
@@ -534,6 +656,9 @@
} else if (info.getContainerInfo().getContainerCase() == EXTENDED_CONTAINERS) {
return info.getContainerInfo().getExtendedContainers().getContainerCase().getNumber()
+ EXTENDED_CONTAINERS_HIERARCHY_OFFSET;
+ } else if (info.getContainerInfo().getContainerCase() == ALL_APPS_CONTAINER) {
+ return info.getContainerInfo().getAllAppsContainer().getParentContainerCase()
+ .getNumber() + ALL_APPS_HIERARCHY_OFFSET;
} else {
return info.getContainerInfo().getContainerCase().getNumber();
}
@@ -561,6 +686,39 @@
return 0;
}
+ private static int getSearchAttributes(LauncherAtom.ItemInfo info) {
+ if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ return 0;
+ }
+ ContainerInfo containerInfo = info.getContainerInfo();
+ if (containerInfo.getContainerCase() == EXTENDED_CONTAINERS
+ && containerInfo.getExtendedContainers().getContainerCase()
+ == DEVICE_SEARCH_RESULT_CONTAINER
+ && containerInfo.getExtendedContainers()
+ .getDeviceSearchResultContainer().hasSearchAttributes()
+ ) {
+ return searchAttributesToInt(containerInfo.getExtendedContainers()
+ .getDeviceSearchResultContainer().getSearchAttributes());
+ }
+ return 0;
+ }
+
+ private static int searchAttributesToInt(SearchAttributes searchAttributes) {
+ int response = 0;
+ if (searchAttributes.getCorrectedQuery()) {
+ response = response | SEARCH_ATTRIBUTES_CORRECTED_QUERY;
+ }
+ if (searchAttributes.getDirectMatch()) {
+ response = response | SEARCH_ATTRIBUTES_DIRECT_MATCH;
+ }
+ if (searchAttributes.getEntryState() == SearchAttributes.EntryState.ALL_APPS) {
+ response = response | SEARCH_ATTRIBUTES_ENTRY_STATE_ALL_APPS;
+ } else if (searchAttributes.getEntryState() == SearchAttributes.EntryState.QSB) {
+ response = response | SEARCH_ATTRIBUTES_ENTRY_STATE_QSB;
+ }
+
+ return response;
+ }
/**
* Interface to get stats log while it is dispatched to the system
diff --git a/quickstep/src/com/android/quickstep/util/AssistantUtilities.java b/quickstep/src/com/android/quickstep/util/AssistantUtilities.java
deleted file mode 100644
index 336f7d1..0000000
--- a/quickstep/src/com/android/quickstep/util/AssistantUtilities.java
+++ /dev/null
@@ -1,46 +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.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT;
-
-import android.annotation.TargetApi;
-import android.app.TaskInfo;
-import android.content.Intent;
-import android.os.Build;
-
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-
-/**
- * Utility class for interacting with the Assistant.
- */
-@TargetApi(Build.VERSION_CODES.Q)
-public final class AssistantUtilities {
-
- /** Returns true if an Assistant activity that is excluded from recents is running. */
- public static boolean isExcludedAssistantRunning() {
- return isExcludedAssistant(ActivityManagerWrapper.getInstance().getRunningTask());
- }
-
- /** Returns true if the given task holds an Assistant activity that is excluded from recents. */
- public static boolean isExcludedAssistant(TaskInfo info) {
- return info != null
- && info.configuration.windowConfiguration.getActivityType() == ACTIVITY_TYPE_ASSISTANT
- && (info.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
- }
-
- private AssistantUtilities() {}
-}
diff --git a/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java b/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java
index 861ff96..143042f 100644
--- a/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java
@@ -36,6 +36,8 @@
private final Map<ViewGroup, Boolean> mOriginalClipToPadding = new HashMap<>();
private final Map<ViewGroup, Boolean> mOriginalClipChildren = new HashMap<>();
+ private boolean mAnimationInProgress = false;
+
public BaseUnfoldMoveFromCenterAnimator(WindowManager windowManager) {
mMoveFromCenterAnimation = new UnfoldMoveFromCenterAnimator(windowManager,
new LauncherViewsMoveFromCenterTranslationApplier());
@@ -44,6 +46,7 @@
@CallSuper
@Override
public void onTransitionStarted() {
+ mAnimationInProgress = true;
mMoveFromCenterAnimation.updateDisplayProperties();
onPrepareViewsForAnimation();
onTransitionProgress(0f);
@@ -58,7 +61,23 @@
@CallSuper
@Override
public void onTransitionFinished() {
+ mAnimationInProgress = false;
mMoveFromCenterAnimation.onTransitionFinished();
+ clearRegisteredViews();
+ }
+
+ /**
+ * Re-prepares views for animation. This is useful in case views are re-bound while the
+ * animation is in progress.
+ */
+ public void updateRegisteredViewsIfNeeded() {
+ if (mAnimationInProgress) {
+ clearRegisteredViews();
+ onPrepareViewsForAnimation();
+ }
+ }
+
+ private void clearRegisteredViews() {
mMoveFromCenterAnimation.clearRegisteredViews();
mOriginalClipChildren.clear();
diff --git a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
index de7dbd6..63d5b0d 100644
--- a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
+++ b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
@@ -48,10 +48,10 @@
import androidx.core.content.FileProvider;
import com.android.internal.app.ChooserActivity;
+import com.android.internal.util.ScreenshotHelper;
import com.android.launcher3.BuildConfig;
import com.android.quickstep.SystemUiProxy;
import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.utilities.BitmapUtil;
import java.io.File;
import java.io.FileOutputStream;
@@ -77,7 +77,8 @@
public static void saveScreenshot(SystemUiProxy systemUiProxy, Bitmap screenshot,
Rect screenshotBounds,
Insets visibleInsets, Task.TaskKey task) {
- systemUiProxy.handleImageBundleAsScreenshot(BitmapUtil.hardwareBitmapToBundle(screenshot),
+ systemUiProxy.handleImageBundleAsScreenshot(
+ ScreenshotHelper.HardwareBitmapBundler.hardwareBitmapToBundle(screenshot),
screenshotBounds, visibleInsets, task);
}
@@ -154,6 +155,18 @@
@WorkerThread
public static void persistBitmapAndStartActivity(Context context, Bitmap bitmap, Rect crop,
Intent intent, BiFunction<Uri, Intent, Intent[]> uriToIntentMap, String tag) {
+ persistBitmapAndStartActivity(context, bitmap, crop, intent, uriToIntentMap, tag,
+ (Runnable) null);
+ }
+
+ /**
+ * Starts activity based on given intent created from image uri.
+ * @param exceptionCallback An optional callback to be called when the intent can't be resolved
+ */
+ @WorkerThread
+ public static void persistBitmapAndStartActivity(Context context, Bitmap bitmap, Rect crop,
+ Intent intent, BiFunction<Uri, Intent, Intent[]> uriToIntentMap, String tag,
+ Runnable exceptionCallback) {
Intent[] intents = uriToIntentMap.apply(getImageUri(bitmap, crop, context, tag), intent);
try {
@@ -165,6 +178,9 @@
}
} catch (ActivityNotFoundException e) {
Log.e(TAG, "No activity found to receive image intent");
+ if (exceptionCallback != null) {
+ exceptionCallback.run();
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/util/LauncherSplitScreenListener.java b/quickstep/src/com/android/quickstep/util/LauncherSplitScreenListener.java
deleted file mode 100644
index 99efb39..0000000
--- a/quickstep/src/com/android/quickstep/util/LauncherSplitScreenListener.java
+++ /dev/null
@@ -1,163 +0,0 @@
-package com.android.quickstep.util;
-
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
-
-import android.content.Context;
-import android.os.IBinder;
-
-import com.android.launcher3.util.MainThreadInitializedObject;
-import com.android.launcher3.util.SplitConfigurationOptions;
-import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
-import com.android.launcher3.util.SplitConfigurationOptions.StageType;
-import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitTaskPosition;
-import com.android.quickstep.SystemUiProxy;
-import com.android.systemui.shared.system.TaskStackChangeListener;
-import com.android.systemui.shared.system.TaskStackChangeListeners;
-import com.android.wm.shell.splitscreen.ISplitScreenListener;
-
-/**
- * Listeners for system wide split screen position and stage changes.
- *
- * Use {@link #getRunningSplitTaskIds()} to determine which tasks, if any, are actively in
- * staged split.
- *
- * Use {@link #getPersistentSplitIds()} to know if tasks were in split screen before a quickswitch
- * gesture happened.
- */
-public class LauncherSplitScreenListener extends ISplitScreenListener.Stub {
-
- public static final MainThreadInitializedObject<LauncherSplitScreenListener> INSTANCE =
- new MainThreadInitializedObject<>(LauncherSplitScreenListener::new);
-
- private static final int[] EMPTY_ARRAY = {};
-
- private final StagedSplitTaskPosition mMainStagePosition = new StagedSplitTaskPosition();
- private final StagedSplitTaskPosition mSideStagePosition = new StagedSplitTaskPosition();
-
- private boolean mIsRecentsListFrozen = false;
- private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
- @Override
- public void onRecentTaskListFrozenChanged(boolean frozen) {
- super.onRecentTaskListFrozenChanged(frozen);
- mIsRecentsListFrozen = frozen;
-
- if (frozen) {
- mPersistentGroupedIds = getRunningSplitTaskIds();
- } else {
- mPersistentGroupedIds = EMPTY_ARRAY;
- }
- }
- };
-
- /**
- * Gets set to current split taskIDs whenever the task list is frozen, and set to empty array
- * whenever task list unfreezes. This also gets set to empty array whenever the user swipes to
- * home - in that case the task list does not unfreeze immediately after the gesture, so it's
- * done via {@link #notifySwipingToHome()}.
- *
- * When not empty, this indicates that we need to load a GroupedTaskView as the most recent
- * page, so user can quickswitch back to a grouped task.
- */
- private int[] mPersistentGroupedIds;
-
- public LauncherSplitScreenListener(Context context) {
- mMainStagePosition.stageType = SplitConfigurationOptions.STAGE_TYPE_MAIN;
- mSideStagePosition.stageType = SplitConfigurationOptions.STAGE_TYPE_SIDE;
- }
-
- /** Also call {@link #destroy()} when done. */
- public void init() {
- SystemUiProxy.INSTANCE.getNoCreate().registerSplitScreenListener(this);
- TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
- }
-
- public void destroy() {
- SystemUiProxy.INSTANCE.getNoCreate().unregisterSplitScreenListener(this);
- TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
- }
-
- /**
- * This method returns the active split taskIDs that were active if a user quickswitched from
- * split screen to a fullscreen app as long as the recents task list remains frozen.
- */
- public int[] getPersistentSplitIds() {
- if (mIsRecentsListFrozen) {
- return mPersistentGroupedIds;
- } else {
- return getRunningSplitTaskIds();
- }
- }
- /**
- * @return index 0 will be task in left/top position, index 1 in right/bottom position.
- * Will return empty array if device is not in staged split
- */
- public int[] getRunningSplitTaskIds() {
- if (mMainStagePosition.taskId == -1 || mSideStagePosition.taskId == -1) {
- return new int[]{};
- }
- int[] out = new int[2];
- if (mMainStagePosition.stagePosition == STAGE_POSITION_TOP_OR_LEFT) {
- out[0] = mMainStagePosition.taskId;
- out[1] = mSideStagePosition.taskId;
- } else {
- out[1] = mMainStagePosition.taskId;
- out[0] = mSideStagePosition.taskId;
- }
- return out;
- }
-
- @Override
- public void onStagePositionChanged(@StageType int stage, @StagePosition int position) {
- if (stage == SplitConfigurationOptions.STAGE_TYPE_MAIN) {
- mMainStagePosition.stagePosition = position;
- } else {
- mSideStagePosition.stagePosition = position;
- }
- }
-
- @Override
- public void onTaskStageChanged(int taskId, @StageType int stage, boolean visible) {
- // If task is not visible but we are tracking it, stop tracking it
- if (!visible) {
- if (mMainStagePosition.taskId == taskId) {
- resetTaskId(mMainStagePosition);
- } else if (mSideStagePosition.taskId == taskId) {
- resetTaskId(mSideStagePosition);
- } // else it's an un-tracked child
- return;
- }
-
- // If stage has moved to undefined, stop tracking the task
- if (stage == SplitConfigurationOptions.STAGE_TYPE_UNDEFINED) {
- resetTaskId(taskId == mMainStagePosition.taskId ?
- mMainStagePosition : mSideStagePosition);
- return;
- }
-
- if (stage == SplitConfigurationOptions.STAGE_TYPE_MAIN) {
- mMainStagePosition.taskId = taskId;
- } else {
- mSideStagePosition.taskId = taskId;
- }
- }
-
- /** Notifies SystemUi to remove any split screen state */
- public void notifySwipingToHome() {
- boolean hasSplitTasks = LauncherSplitScreenListener.INSTANCE.getNoCreate()
- .getPersistentSplitIds().length > 0;
- if (!hasSplitTasks) {
- return;
- }
-
- mPersistentGroupedIds = EMPTY_ARRAY;
- }
-
- private void resetTaskId(StagedSplitTaskPosition taskPosition) {
- taskPosition.taskId = -1;
- }
-
- @Override
- public IBinder asBinder() {
- return this;
- }
-}
diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
index 6b6bd6a..97be437 100644
--- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
+++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
@@ -15,9 +15,14 @@
*/
package com.android.quickstep.util;
+import static com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY;
+import static com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_UNFOLD_ANIMATION;
+import static com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY;
import static com.android.launcher3.Utilities.comp;
import android.annotation.Nullable;
+import android.util.FloatProperty;
+import android.util.MathUtils;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
@@ -25,6 +30,7 @@
import com.android.launcher3.Hotseat;
import com.android.launcher3.Launcher;
+import com.android.launcher3.Workspace;
import com.android.launcher3.util.HorizontalInsettableView;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
@@ -39,15 +45,20 @@
// Percentage of the width of the quick search bar that will be reduced
// from the both sides of the bar when progress is 0
private static final float MAX_WIDTH_INSET_FRACTION = 0.15f;
+ private static final FloatProperty<Workspace<?>> WORKSPACE_SCALE_PROPERTY =
+ WORKSPACE_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION);
+ private static final FloatProperty<Hotseat> HOTSEAT_SCALE_PROPERTY =
+ HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION);
private final Launcher mLauncher;
+ private final ScopedUnfoldTransitionProgressProvider mProgressProvider;
+ private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider;
+ private final UnfoldMoveFromCenterHotseatAnimator mUnfoldMoveFromCenterHotseatAnimator;
+ private final UnfoldMoveFromCenterWorkspaceAnimator mUnfoldMoveFromCenterWorkspaceAnimator;
@Nullable
private HorizontalInsettableView mQsbInsettable;
- private final ScopedUnfoldTransitionProgressProvider mProgressProvider;
- private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider;
-
public LauncherUnfoldAnimationController(
Launcher launcher,
WindowManager windowManager,
@@ -55,19 +66,21 @@
mLauncher = launcher;
mProgressProvider = new ScopedUnfoldTransitionProgressProvider(
unfoldTransitionProgressProvider);
+ mUnfoldMoveFromCenterHotseatAnimator = new UnfoldMoveFromCenterHotseatAnimator(launcher,
+ windowManager);
+ mUnfoldMoveFromCenterWorkspaceAnimator = new UnfoldMoveFromCenterWorkspaceAnimator(launcher,
+ windowManager);
mNaturalOrientationProgressProvider = new NaturalRotationUnfoldProgressProvider(launcher,
WindowManagerGlobal.getWindowManagerService(), mProgressProvider);
mNaturalOrientationProgressProvider.init();
// Animated in all orientations
- mProgressProvider.addCallback(new UnfoldMoveFromCenterWorkspaceAnimator(launcher,
- windowManager));
+ mProgressProvider.addCallback(mUnfoldMoveFromCenterWorkspaceAnimator);
+ mProgressProvider.addCallback(new LauncherScaleAnimationListener());
// Animated only in natural orientation
- mNaturalOrientationProgressProvider
- .addCallback(new QsbAnimationListener());
- mNaturalOrientationProgressProvider
- .addCallback(new UnfoldMoveFromCenterHotseatAnimator(launcher, windowManager));
+ mNaturalOrientationProgressProvider.addCallback(new QsbAnimationListener());
+ mNaturalOrientationProgressProvider.addCallback(mUnfoldMoveFromCenterHotseatAnimator);
}
/**
@@ -99,6 +112,12 @@
mNaturalOrientationProgressProvider.destroy();
}
+ /** Called when launcher finished binding its items. */
+ public void updateRegisteredViewsIfNeeded() {
+ mUnfoldMoveFromCenterHotseatAnimator.updateRegisteredViewsIfNeeded();
+ mUnfoldMoveFromCenterWorkspaceAnimator.updateRegisteredViewsIfNeeded();
+ }
+
private class QsbAnimationListener implements TransitionProgressListener {
@Override
@@ -120,4 +139,27 @@
}
}
}
+
+ private class LauncherScaleAnimationListener implements TransitionProgressListener {
+
+ @Override
+ public void onTransitionStarted() {
+ mLauncher.getWorkspace().setPivotToScaleWithSelf(mLauncher.getHotseat());
+ }
+
+ @Override
+ public void onTransitionFinished() {
+ setScale(1);
+ }
+
+ @Override
+ public void onTransitionProgress(float progress) {
+ setScale(MathUtils.constrainedMap(0.85f, 1, 0, 1, progress));
+ }
+
+ private void setScale(float value) {
+ WORKSPACE_SCALE_PROPERTY.setValue(mLauncher.getWorkspace(), value);
+ HOTSEAT_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value);
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index 302526d..d0856be 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -22,8 +22,9 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.touch.PagedOrientationHandler;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.quickstep.LauncherActivityInterface;
-import com.android.quickstep.SysUINavigationMode;
public class LayoutUtils {
@@ -32,7 +33,7 @@
*/
public static float getDefaultSwipeHeight(Context context, DeviceProfile dp) {
float swipeHeight = dp.allAppsCellHeightPx - dp.allAppsIconTextSizePx;
- if (SysUINavigationMode.getMode(context) == SysUINavigationMode.Mode.NO_BUTTON) {
+ if (DisplayController.getNavigationMode(context) == NavigationMode.NO_BUTTON) {
swipeHeight -= dp.getInsets().bottom;
}
return swipeHeight;
diff --git a/quickstep/src/com/android/quickstep/util/NavBarPosition.java b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
index 449dba8..527a6d2 100644
--- a/quickstep/src/com/android/quickstep/util/NavBarPosition.java
+++ b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
@@ -15,27 +15,27 @@
*/
package com.android.quickstep.util;
-import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
+import static com.android.launcher3.util.DisplayController.NavigationMode.NO_BUTTON;
import android.view.Surface;
import com.android.launcher3.util.DisplayController.Info;
-import com.android.quickstep.SysUINavigationMode;
+import com.android.launcher3.util.DisplayController.NavigationMode;
/**
* Utility class to check nav bar position.
*/
public class NavBarPosition {
- private final SysUINavigationMode.Mode mMode;
+ private final NavigationMode mMode;
private final int mDisplayRotation;
- public NavBarPosition(SysUINavigationMode.Mode mode, Info info) {
+ public NavBarPosition(NavigationMode mode, Info info) {
mMode = mode;
mDisplayRotation = info.rotation;
}
- public NavBarPosition(SysUINavigationMode.Mode mode, int displayRotation) {
+ public NavBarPosition(NavigationMode mode, int displayRotation) {
mMode = mode;
mDisplayRotation = displayRotation;
}
diff --git a/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java b/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java
index 5cf4f0b..3cec1a4 100644
--- a/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java
+++ b/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java
@@ -82,7 +82,7 @@
// WorkspaceRevealAnim handles the depth, so don't interfere.
config.animFlags |= StateAnimationConfig.SKIP_DEPTH_CONTROLLER;
}
- config.duration = startState.getTransitionDuration(mLauncher);
+ config.duration = startState.getTransitionDuration(mLauncher, false /* isToState */);
AnimatorSet stateAnim = stateManager.createAtomicAnimation(
startState, NORMAL, config);
stateAnim.addListener(new AnimationSuccessListener() {
diff --git a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
index 6d6e802..fb32581 100644
--- a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
+++ b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
@@ -21,20 +21,21 @@
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.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
+import static com.android.launcher3.util.DisplayController.NavigationMode.NO_BUTTON;
import android.content.SharedPreferences;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
+import com.android.launcher3.appprediction.AppsDividerView;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.hybridhotseat.HotseatPredictionController;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.OnboardingPrefs;
-import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.views.AllAppsEduView;
/**
@@ -50,8 +51,8 @@
stateManager.addStateListener(new StateListener<LauncherState>() {
@Override
public void onStateTransitionComplete(LauncherState finalState) {
- boolean swipeUpEnabled = SysUINavigationMode.INSTANCE
- .get(mLauncher).getMode().hasGestures;
+ boolean swipeUpEnabled =
+ DisplayController.getNavigationMode(mLauncher).hasGestures;
LauncherState prevState = stateManager.getLastState();
if (((swipeUpEnabled && finalState == OVERVIEW) || (!swipeUpEnabled
@@ -87,7 +88,7 @@
});
}
- if (SysUINavigationMode.getMode(launcher) == NO_BUTTON
+ if (DisplayController.getNavigationMode(launcher) == NO_BUTTON
&& FeatureFlags.ENABLE_ALL_APPS_EDU.get()) {
stateManager.addStateListener(new StateListener<LauncherState>() {
private static final int MAX_NUM_SWIPES_TO_TRIGGER_EDU = 3;
@@ -132,5 +133,24 @@
}
});
}
+
+ if (!hasReachedMaxCount(ALL_APPS_VISITED_COUNT)) {
+ mLauncher.getStateManager().addStateListener(new StateListener<LauncherState>() {
+ @Override
+ public void onStateTransitionComplete(LauncherState finalState) {
+ if (finalState == ALL_APPS) {
+ incrementEventCount(ALL_APPS_VISITED_COUNT);
+ return;
+ }
+
+ boolean hasReachedMaxCount = hasReachedMaxCount(ALL_APPS_VISITED_COUNT);
+ mLauncher.getAppsView().getFloatingHeaderView().findFixedRowByType(
+ AppsDividerView.class).setShowAllAppsLabel(!hasReachedMaxCount);
+ if (hasReachedMaxCount) {
+ mLauncher.getStateManager().removeStateListener(this);
+ }
+ }
+ });
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index 8ccab71..6038a22 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -52,6 +52,7 @@
import com.android.launcher3.util.SettingsCache;
import com.android.quickstep.BaseActivityInterface;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.TaskAnimationManager;
import com.android.quickstep.views.TaskView;
import java.lang.annotation.Retention;
@@ -101,6 +102,8 @@
// Whether the swipe gesture is running, so the recents would stay locked in the
// current orientation
private static final int FLAG_SWIPE_UP_NOT_RUNNING = 1 << 8;
+ // Ignore shared prefs for home rotation rotation, allowing it in if the activity supports it
+ private static final int FLAG_IGNORE_ALLOW_HOME_ROTATION_PREF = 1 << 9;
private static final int MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE =
FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY
@@ -304,6 +307,7 @@
private void initMultipleOrientationListeners() {
mSharedPrefs.registerOnSharedPreferenceChangeListener(this);
mSettingsCache.register(ROTATION_SETTING_URI, mRotationChangeListener);
+ updateAutoRotateSetting();
}
private void destroyMultipleOrientationListeners() {
@@ -340,6 +344,11 @@
@SurfaceRotation
public int getDisplayRotation() {
+ if (TaskAnimationManager.SHELL_TRANSITIONS_ROTATION) {
+ // When shell transitions are enabled, both the display and activity rotations should
+ // be the same once the gesture starts
+ return mRecentsActivityRotation;
+ }
return mDisplayRotation;
}
@@ -365,12 +374,17 @@
== MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE;
}
+ public void ignoreAllowHomeRotationPreference() {
+ setFlag(FLAG_IGNORE_ALLOW_HOME_ROTATION_PREF, true);
+ }
+
public boolean isRecentsActivityRotationAllowed() {
// Activity rotation is allowed if the multi-simulated-rotation is not supported
// (fallback recents or tablets) or activity rotation is enabled by various settings.
return ((mFlags & MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE)
!= MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE)
- || (mFlags & (FLAG_HOME_ROTATION_ALLOWED_IN_PREFS
+ || (mFlags & (FLAG_IGNORE_ALLOW_HOME_ROTATION_PREF
+ | FLAG_HOME_ROTATION_ALLOWED_IN_PREFS
| FLAG_MULTIWINDOW_ROTATION_ALLOWED
| FLAG_HOME_ROTATION_FORCE_ENABLED_FOR_TESTING)) != 0;
}
@@ -593,7 +607,7 @@
width = Math.min(currentSize.x, currentSize.y);
height = Math.max(currentSize.x, currentSize.y);
}
- return idp.getBestMatch(width, height);
+ return idp.getBestMatch(width, height, mRecentsActivityRotation);
}
private static String nameAndAddress(Object obj) {
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 5253e8c..2502359 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -16,17 +16,24 @@
package com.android.quickstep.util;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.app.PendingIntent.FLAG_MUTABLE;
+
import static com.android.launcher3.Utilities.postAsyncCallback;
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.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
+import android.annotation.NonNull;
import android.app.ActivityOptions;
import android.app.ActivityThread;
-import android.graphics.Rect;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
+import android.text.TextUtils;
import android.view.RemoteAnimationAdapter;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
@@ -57,23 +64,26 @@
*/
public class SplitSelectStateController {
+ private final Context mContext;
private final Handler mHandler;
private final SystemUiProxy mSystemUiProxy;
private final StateManager mStateManager;
private final DepthController mDepthController;
private @StagePosition int mStagePosition;
- private Task mInitialTask;
- private Task mSecondTask;
+ private Intent mInitialTaskIntent;
+ private int mInitialTaskId = INVALID_TASK_ID;
+ private int mSecondTaskId = INVALID_TASK_ID;
+ private String mSecondTaskPackageName;
private boolean mRecentsAnimationRunning;
/** If not null, this is the TaskView we want to launch from */
@Nullable
private GroupedTaskView mLaunchingTaskView;
- public SplitSelectStateController(Handler handler, SystemUiProxy systemUiProxy,
- StateManager stateManager,
+ public SplitSelectStateController(Context context, Handler handler, StateManager stateManager,
DepthController depthController) {
+ mContext = context;
mHandler = handler;
- mSystemUiProxy = systemUiProxy;
+ mSystemUiProxy = SystemUiProxy.INSTANCE.get(mContext);
mStateManager = stateManager;
mDepthController = depthController;
}
@@ -81,19 +91,50 @@
/**
* To be called after first task selected
*/
- public void setInitialTaskSelect(Task task, @StagePosition int stagePosition,
- Rect initialBounds) {
- mInitialTask = task;
+ public void setInitialTaskSelect(int taskId, @StagePosition int stagePosition) {
+ mInitialTaskId = taskId;
mStagePosition = stagePosition;
+ mInitialTaskIntent = null;
+ }
+
+ public void setInitialTaskSelect(Intent intent, @StagePosition int stagePosition) {
+ mInitialTaskIntent = intent;
+ mStagePosition = stagePosition;
+ mInitialTaskId = INVALID_TASK_ID;
}
/**
- * To be called after second task selected
+ * To be called when the actual tasks ({@link #mInitialTaskId}, {@link #mSecondTaskId}) are
+ * to be launched. Call after launcher side animations are complete.
*/
- public void setSecondTaskId(Task task, Consumer<Boolean> callback) {
- mSecondTask = task;
- launchTasks(mInitialTask, mSecondTask, mStagePosition, callback,
- false /* freezeTaskList */, DEFAULT_SPLIT_RATIO);
+ public void launchSplitTasks(Consumer<Boolean> callback) {
+ final Intent fillInIntent;
+ if (mInitialTaskIntent != null) {
+ fillInIntent = new Intent();
+ if (TextUtils.equals(mInitialTaskIntent.getComponent().getPackageName(),
+ mSecondTaskPackageName)) {
+ fillInIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+ }
+ } else {
+ fillInIntent = null;
+ }
+ final PendingIntent pendingIntent =
+ mInitialTaskIntent == null ? null : PendingIntent.getActivity(mContext, 0,
+ mInitialTaskIntent, FLAG_MUTABLE);
+ launchTasks(mInitialTaskId, pendingIntent, fillInIntent, mSecondTaskId, mStagePosition,
+ callback, false /* freezeTaskList */, DEFAULT_SPLIT_RATIO);
+ }
+
+
+ /**
+ * To be called as soon as user selects the second task (even if animations aren't complete)
+ * @param task The second task that will be launched.
+ */
+ public void setSecondTask(Task task) {
+ mSecondTaskId = task.key.id;
+ if (mInitialTaskIntent != null) {
+ mSecondTaskPackageName = task.getTopComponent().getPackageName();
+ }
}
/**
@@ -104,30 +145,49 @@
mLaunchingTaskView = groupedTaskView;
TaskView.TaskIdAttributeContainer[] taskIdAttributeContainers =
groupedTaskView.getTaskIdAttributeContainers();
- launchTasks(taskIdAttributeContainers[0].getTask(), taskIdAttributeContainers[1].getTask(),
+ launchTasks(taskIdAttributeContainers[0].getTask().key.id,
+ taskIdAttributeContainers[1].getTask().key.id,
taskIdAttributeContainers[0].getStagePosition(), callback, freezeTaskList,
groupedTaskView.getSplitRatio());
}
/**
+ * To be called when we want to launch split pairs from Overview when split is initiated from
+ * Overview.
+ */
+ public void launchTasks(int taskId1, int taskId2, @StagePosition int stagePosition,
+ Consumer<Boolean> callback, boolean freezeTaskList, float splitRatio) {
+ launchTasks(taskId1, null /* taskPendingIntent */, null /* fillInIntent */, taskId2,
+ stagePosition, callback, freezeTaskList, splitRatio);
+ }
+
+ /**
+ * 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 taskPendingIntent is null when split is initiated from Overview
* @param stagePosition representing location of task1
*/
- public void launchTasks(Task task1, Task task2, @StagePosition int stagePosition,
+ public void launchTasks(int taskId1, @Nullable PendingIntent taskPendingIntent,
+ @Nullable Intent fillInIntent, int taskId2, @StagePosition int stagePosition,
Consumer<Boolean> callback, boolean freezeTaskList, float splitRatio) {
// Assume initial task is for top/left part of screen
final int[] taskIds = stagePosition == STAGE_POSITION_TOP_OR_LEFT
- ? new int[]{task1.key.id, task2.key.id}
- : new int[]{task2.key.id, task1.key.id};
+ ? new int[]{taskId1, taskId2}
+ : new int[]{taskId2, taskId1};
if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
RemoteSplitLaunchTransitionRunner animationRunner =
- new RemoteSplitLaunchTransitionRunner(task1, task2);
+ new RemoteSplitLaunchTransitionRunner(taskId1, taskPendingIntent, taskId2,
+ callback);
mSystemUiProxy.startTasks(taskIds[0], null /* mainOptions */, taskIds[1],
null /* sideOptions */, STAGE_POSITION_BOTTOM_OR_RIGHT, splitRatio,
new RemoteTransitionCompat(animationRunner, MAIN_EXECUTOR,
ActivityThread.currentActivityThread().getApplicationThread()));
+ // TODO: handle intent + task with shell transition
} else {
RemoteSplitLaunchAnimationRunner animationRunner =
- new RemoteSplitLaunchAnimationRunner(task1, task2, callback);
+ new RemoteSplitLaunchAnimationRunner(taskId1, taskPendingIntent, taskId2,
+ callback);
final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
RemoteAnimationAdapterCompat.wrapRemoteAnimationRunner(animationRunner),
300, 150,
@@ -137,9 +197,15 @@
if (freezeTaskList) {
mainOpts.setFreezeRecentTasksReordering();
}
- mSystemUiProxy.startTasksWithLegacyTransition(taskIds[0], mainOpts.toBundle(),
- taskIds[1], null /* sideOptions */, STAGE_POSITION_BOTTOM_OR_RIGHT,
- splitRatio, adapter);
+ if (taskPendingIntent == null) {
+ mSystemUiProxy.startTasksWithLegacyTransition(taskIds[0], mainOpts.toBundle(),
+ taskIds[1], null /* sideOptions */, STAGE_POSITION_BOTTOM_OR_RIGHT,
+ splitRatio, adapter);
+ } else {
+ mSystemUiProxy.startIntentAndTaskWithLegacyTransition(taskPendingIntent,
+ fillInIntent, taskId2, mainOpts.toBundle(), null /* sideOptions */,
+ stagePosition, splitRatio, adapter);
+ }
}
}
@@ -156,19 +222,29 @@
*/
private class RemoteSplitLaunchTransitionRunner implements RemoteTransitionRunner {
- private final Task mInitialTask;
- private final Task mSecondTask;
+ private final int mInitialTaskId;
+ private final PendingIntent mInitialTaskPendingIntent;
+ private final int mSecondTaskId;
+ private final Consumer<Boolean> mSuccessCallback;
- RemoteSplitLaunchTransitionRunner(Task initialTask, Task secondTask) {
- mInitialTask = initialTask;
- mSecondTask = secondTask;
+ RemoteSplitLaunchTransitionRunner(int initialTaskId, PendingIntent initialTaskPendingIntent,
+ int secondTaskId, Consumer<Boolean> callback) {
+ mInitialTaskId = initialTaskId;
+ mInitialTaskPendingIntent = initialTaskPendingIntent;
+ mSecondTaskId = secondTaskId;
+ mSuccessCallback = callback;
}
@Override
- public void startAnimation(IBinder transition, TransitionInfo info,
- SurfaceControl.Transaction t, Runnable finishCallback) {
- TaskViewUtils.composeRecentsSplitLaunchAnimator(mInitialTask,
- mSecondTask, info, t, finishCallback);
+ public void startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction t, @NonNull Runnable finishCallback) {
+ TaskViewUtils.composeRecentsSplitLaunchAnimator(mInitialTaskId,
+ mInitialTaskPendingIntent, mSecondTaskId, info, t, () -> {
+ finishCallback.run();
+ if (mSuccessCallback != null) {
+ mSuccessCallback.accept(true);
+ }
+ });
// After successful launch, call resetState
resetState();
}
@@ -180,14 +256,16 @@
*/
private class RemoteSplitLaunchAnimationRunner implements RemoteAnimationRunnerCompat {
- private final Task mInitialTask;
- private final Task mSecondTask;
+ private final int mInitialTaskId;
+ private final PendingIntent mInitialTaskPendingIntent;
+ private final int mSecondTaskId;
private final Consumer<Boolean> mSuccessCallback;
- RemoteSplitLaunchAnimationRunner(Task initialTask, Task secondTask,
- Consumer<Boolean> successCallback) {
- mInitialTask = initialTask;
- mSecondTask = secondTask;
+ RemoteSplitLaunchAnimationRunner(int initialTaskId, PendingIntent initialTaskPendingIntent,
+ int secondTaskId, Consumer<Boolean> successCallback) {
+ mInitialTaskId = initialTaskId;
+ mInitialTaskPendingIntent = initialTaskPendingIntent;
+ mSecondTaskId = secondTaskId;
mSuccessCallback = successCallback;
}
@@ -197,8 +275,9 @@
Runnable finishedCallback) {
postAsyncCallback(mHandler,
() -> TaskViewUtils.composeRecentsSplitLaunchAnimatorLegacy(
- mLaunchingTaskView, mInitialTask, mSecondTask, apps, wallpapers,
- nonApps, mStateManager, mDepthController, () -> {
+ mLaunchingTaskView, mInitialTaskId, mInitialTaskPendingIntent,
+ mSecondTaskId, apps, wallpapers, nonApps, mStateManager,
+ mDepthController, () -> {
finishedCallback.run();
if (mSuccessCallback != null) {
mSuccessCallback.accept(true);
@@ -224,8 +303,9 @@
* To be called if split select was cancelled
*/
public void resetState() {
- mInitialTask = null;
- mSecondTask = null;
+ mInitialTaskId = INVALID_TASK_ID;
+ mInitialTaskIntent = null;
+ mSecondTaskId = INVALID_TASK_ID;
mStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
mRecentsAnimationRunning = false;
mLaunchingTaskView = null;
@@ -236,6 +316,18 @@
* chosen
*/
public boolean isSplitSelectActive() {
- return mInitialTask != null && mSecondTask == null;
+ return isInitialTaskIntentSet() && mSecondTaskId == INVALID_TASK_ID;
+ }
+
+ /**
+ * @return {@code true} if the first and second task have been chosen and split is waiting to
+ * be launched
+ */
+ public boolean isBothSplitAppsConfirmed() {
+ return isInitialTaskIntentSet() && mSecondTaskId != INVALID_TASK_ID;
+ }
+
+ private boolean isInitialTaskIntentSet() {
+ return (mInitialTaskId != INVALID_TASK_ID || mInitialTaskIntent != null);
}
}
diff --git a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index 44396fa..32e08ff 100644
--- a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -18,6 +18,7 @@
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;
@@ -92,7 +93,7 @@
if (staggerWorkspace) {
DeviceProfile grid = launcher.getDeviceProfile();
- Workspace workspace = launcher.getWorkspace();
+ Workspace<?> workspace = launcher.getWorkspace();
Hotseat hotseat = launcher.getHotseat();
// Hotseat and QSB takes up two additional rows.
@@ -148,6 +149,9 @@
});
}
+ launcher.pauseExpensiveViewUpdates();
+ mAnimators.addListener(forEndCallback(launcher::resumeExpensiveViewUpdates));
+
if (animateOverviewScrim) {
PendingAnimation pendingAnimation = new PendingAnimation(DURATION_MS);
launcher.getWorkspace().getStateTransitionAnimation()
diff --git a/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java b/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java
index 3b1c150..1200208 100644
--- a/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java
+++ b/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java
@@ -53,6 +53,7 @@
mTargetViewRootImpl = targetView.getViewRootImpl();
mBarrierSurfaceControl = mTargetViewRootImpl.getSurfaceControl();
mApplyHandler = new Handler(this::onApplyMessage);
+ setCanRelease(true);
}
protected boolean onApplyMessage(Message msg) {
@@ -74,6 +75,13 @@
if (view == null) {
return;
}
+ Transaction t = new Transaction();
+ for (int i = params.length - 1; i >= 0; i--) {
+ SurfaceParams surfaceParams = params[i];
+ if (surfaceParams.surface.isValid()) {
+ surfaceParams.applyTo(t);
+ }
+ }
mLastSequenceNumber++;
final int toApplySeqNo = mLastSequenceNumber;
@@ -84,13 +92,6 @@
.sendToTarget();
return;
}
- Transaction t = new Transaction();
- for (int i = params.length - 1; i >= 0; i--) {
- SurfaceParams surfaceParams = params[i];
- if (surfaceParams.surface.isValid()) {
- surfaceParams.applyTo(t);
- }
- }
mTargetViewRootImpl.mergeWithNextTransaction(t, frame);
Message.obtain(mApplyHandler, MSG_UPDATE_SEQUENCE_NUMBER, toApplySeqNo, 0)
.sendToTarget();
diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
index a534450..b222f51 100644
--- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
@@ -56,6 +56,7 @@
private final int mTaskId;
private final ComponentName mComponentName;
private final SurfaceControl mLeash;
+ private final Rect mSourceRectHint = new Rect();
private final Rect mAppBounds = new Rect();
private final Matrix mHomeToWindowPositionMap = new Matrix();
private final Rect mStartBounds = new Rect();
@@ -101,6 +102,7 @@
* @param fromRotation From rotation if different from final rotation, ROTATION_0 otherwise
* @param destinationBoundsTransformed Destination bounds in window space
* @param cornerRadius Corner radius in pixel value for PiP window
+ * @param shadowRadius Shadow radius in pixel value for PiP window
* @param view Attached view for logging purpose
*/
private SwipePipToHomeAnimator(@NonNull Context context,
@@ -115,6 +117,7 @@
@RecentsOrientedState.SurfaceRotation int fromRotation,
@NonNull Rect destinationBoundsTransformed,
int cornerRadius,
+ int shadowRadius,
@NonNull View view) {
super(startBounds, new RectF(destinationBoundsTransformed), context, null);
mTaskId = taskId;
@@ -126,7 +129,7 @@
mDestinationBounds.set(destinationBounds);
mFromRotation = fromRotation;
mDestinationBoundsTransformed.set(destinationBoundsTransformed);
- mSurfaceTransactionHelper = new PipSurfaceTransactionHelper(cornerRadius);
+ mSurfaceTransactionHelper = new PipSurfaceTransactionHelper(cornerRadius, shadowRadius);
if (sourceRectHint != null && (sourceRectHint.width() < destinationBounds.width()
|| sourceRectHint.height() < destinationBounds.height())) {
@@ -138,6 +141,7 @@
}
if (sourceRectHint == null) {
+ mSourceRectHint.setEmpty();
mSourceHintRectInsets = null;
// Create a new overlay layer
@@ -167,6 +171,7 @@
t.apply();
});
} else {
+ mSourceRectHint.set(sourceRectHint);
mSourceHintRectInsets = new Rect(sourceRectHint.left - appBounds.left,
sourceRectHint.top - appBounds.top,
appBounds.right - sourceRectHint.right,
@@ -247,7 +252,8 @@
return mSurfaceTransactionHelper.scaleAndRotate(tx, mLeash, mAppBounds, bounds, insets,
rotatedPosition.degree, rotatedPosition.positionX, rotatedPosition.positionY);
} else {
- return mSurfaceTransactionHelper.scaleAndCrop(tx, mLeash, mAppBounds, bounds, insets);
+ return mSurfaceTransactionHelper.scaleAndCrop(tx, mLeash, mSourceRectHint, mAppBounds,
+ bounds, insets);
}
}
@@ -278,7 +284,7 @@
private RotatedPosition getRotatedPosition(float progress) {
final float degree, positionX, positionY;
- if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
+ if (TaskAnimationManager.SHELL_TRANSITIONS_ROTATION) {
if (mFromRotation == Surface.ROTATION_90) {
degree = -90 * (1 - progress);
positionX = progress * (mDestinationBoundsTransformed.left - mStartBounds.left)
@@ -324,6 +330,7 @@
private RectF mStartBounds;
private Rect mDestinationBounds;
private int mCornerRadius;
+ private int mShadowRadius;
private View mAttachedView;
private @RecentsOrientedState.SurfaceRotation int mFromRotation = Surface.ROTATION_0;
private final Rect mDestinationBoundsTransformed = new Rect();
@@ -378,6 +385,11 @@
return this;
}
+ public Builder setShadowRadius(int shadowRadius) {
+ mShadowRadius = shadowRadius;
+ return this;
+ }
+
public Builder setAttachedView(View attachedView) {
mAttachedView = attachedView;
return this;
@@ -422,7 +434,7 @@
mSourceRectHint, mAppBounds,
mHomeToWindowPositionMap, mStartBounds, mDestinationBounds,
mFromRotation, mDestinationBoundsTransformed,
- mCornerRadius, mAttachedView);
+ mCornerRadius, mShadowRadius, mAttachedView);
}
}
diff --git a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
new file mode 100644
index 0000000..9bb3d56
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.view.Display;
+
+import com.android.launcher3.util.window.WindowManagerProxy;
+
+/**
+ * Extension of {@link WindowManagerProxy} with some assumption for the default system Launcher
+ */
+public class SystemWindowManagerProxy extends WindowManagerProxy {
+
+ public SystemWindowManagerProxy(Context context) {
+ super(true);
+ }
+
+ @Override
+ protected String getDisplayId(Display display) {
+ return display.getUniqueId();
+ }
+
+ @Override
+ public boolean isInternalDisplay(Display display) {
+ return display.getType() == Display.TYPE_INTERNAL;
+ }
+
+ @Override
+ public int getRotation(Context context) {
+ return context.getResources().getConfiguration().windowConfiguration.getRotation();
+ }
+
+ @Override
+ protected Display[] getDisplays(Context context) {
+ return context.getSystemService(DisplayManager.class).getDisplays(
+ DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index f676091..5212755 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -44,6 +44,7 @@
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.BaseActivityInterface;
+import com.android.quickstep.TaskAnimationManager;
import com.android.quickstep.views.TaskThumbnailView.PreviewPositionHelper;
import com.android.quickstep.views.TaskView.FullscreenDrawParams;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -170,7 +171,7 @@
* Sets the targets which the simulator will control
*/
public void setPreview(RemoteAnimationTargetCompat runningTarget) {
- setPreviewBounds(runningTarget.screenSpaceBounds, runningTarget.contentInsets);
+ setPreviewBounds(runningTarget.startScreenSpaceBounds, runningTarget.contentInsets);
}
/**
@@ -304,7 +305,13 @@
mOrientationStateId = mOrientationState.getStateId();
getFullScreenScale();
- mThumbnailData.rotation = mOrientationState.getDisplayRotation();
+ if (TaskAnimationManager.SHELL_TRANSITIONS_ROTATION) {
+ // With shell transitions, the display is rotated early so we need to actually use
+ // the rotation when the gesture starts
+ mThumbnailData.rotation = mOrientationState.getTouchRotation();
+ } else {
+ mThumbnailData.rotation = mOrientationState.getDisplayRotation();
+ }
// mIsRecentsRtl is the inverse of TaskView RTL.
boolean isRtlEnabled = !mIsRecentsRtl;
diff --git a/quickstep/src/com/android/quickstep/util/TransformParams.java b/quickstep/src/com/android/quickstep/util/TransformParams.java
index 03d7a37..75d6001 100644
--- a/quickstep/src/com/android/quickstep/util/TransformParams.java
+++ b/quickstep/src/com/android/quickstep/util/TransformParams.java
@@ -174,10 +174,10 @@
RemoteAnimationTargetCompat app = targets.unfilteredApps[i];
if (app.mode == targets.targetMode) {
if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_RECENTS) {
- return app.leash.getSurfaceControl();
+ return app.leash;
}
} else {
- return app.leash.getSurfaceControl();
+ return app.leash;
}
}
return null;
diff --git a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
index 3d72398..354d157 100644
--- a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
@@ -37,7 +37,7 @@
@Override
protected void onPrepareViewsForAnimation() {
- Workspace workspace = mLauncher.getWorkspace();
+ Workspace<?> workspace = mLauncher.getWorkspace();
// App icons and widgets
workspace
diff --git a/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java b/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
index 7ae6cb7..5eb543e 100644
--- a/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
+++ b/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
@@ -15,7 +15,9 @@
*/
package com.android.quickstep.util;
-import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+import static com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY;
+import static com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_REVEAL_ANIM;
+import static com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
@@ -27,9 +29,11 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
+import android.util.FloatProperty;
import android.view.View;
import com.android.launcher3.BaseQuickstepLauncher;
+import com.android.launcher3.Hotseat;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Workspace;
@@ -49,6 +53,11 @@
// Should be used for animations running alongside this WorkspaceRevealAnim.
public static final int DURATION_MS = 350;
+ private static final FloatProperty<Workspace<?>> WORKSPACE_SCALE_PROPERTY =
+ WORKSPACE_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_REVEAL_ANIM);
+
+ private static final FloatProperty<Hotseat> HOTSEAT_SCALE_PROPERTY =
+ HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_REVEAL_ANIM);
private final float mScaleStart;
private final AnimatorSet mAnimators = new AnimatorSet();
@@ -59,12 +68,12 @@
ResourceProvider rp = DynamicResource.provider(launcher);
mScaleStart = rp.getFloat(R.dimen.swipe_up_scale_start);
- Workspace workspace = launcher.getWorkspace();
+ Workspace<?> workspace = launcher.getWorkspace();
workspace.setPivotToScaleWithSelf(launcher.getHotseat());
// Add reveal animations.
- addRevealAnimatorsForView(workspace);
- addRevealAnimatorsForView(launcher.getHotseat());
+ addRevealAnimatorsForView(workspace, WORKSPACE_SCALE_PROPERTY);
+ addRevealAnimatorsForView(launcher.getHotseat(), HOTSEAT_SCALE_PROPERTY);
// Add overview scrim animation.
if (animateOverviewScrim) {
@@ -89,8 +98,8 @@
mAnimators.setInterpolator(Interpolators.DECELERATED_EASE);
}
- private void addRevealAnimatorsForView(View v) {
- ObjectAnimator scale = ObjectAnimator.ofFloat(v, SCALE_PROPERTY, mScaleStart, 1f);
+ private <T extends View> void addRevealAnimatorsForView(T v, FloatProperty<T> scaleProperty) {
+ ObjectAnimator scale = ObjectAnimator.ofFloat(v, scaleProperty, mScaleStart, 1f);
scale.setDuration(DURATION_MS);
scale.setInterpolator(Interpolators.DECELERATED_EASE);
mAnimators.play(scale);
@@ -103,7 +112,7 @@
mAnimators.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- SCALE_PROPERTY.set(v, 1f);
+ scaleProperty.set(v, 1f);
v.setAlpha(1f);
}
});
diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
index 4f2ed4c..50be5ea 100644
--- a/quickstep/src/com/android/quickstep/views/ClearAllButton.java
+++ b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
@@ -141,7 +141,10 @@
}
applyPrimaryTranslation();
applySecondaryTranslation();
- mScrollAlpha = 1 - shift / orientationSize;
+ float clearAllSpacing =
+ recentsView.getPageSpacing() + recentsView.getClearAllExtraPageSpacing();
+ clearAllSpacing = mIsRtl ? -clearAllSpacing : clearAllSpacing;
+ mScrollAlpha = Math.max((clearAllScroll + clearAllSpacing - scroll) / clearAllSpacing, 0);
updateAlpha();
}
@@ -247,7 +250,7 @@
*/
private float getOriginalTranslationY() {
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
- return deviceProfile.overviewShowAsGrid
+ return deviceProfile.isTablet
? deviceProfile.overviewRowSpacing
: deviceProfile.overviewTaskThumbnailTopMarginPx / 2.0f;
}
diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
index e5664c6..79b15c7 100644
--- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
+++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
@@ -17,9 +17,6 @@
package com.android.quickstep.views;
import static android.provider.Settings.ACTION_APP_USAGE_SETTINGS;
-import static android.view.Gravity.BOTTOM;
-import static android.view.Gravity.CENTER_HORIZONTAL;
-import static android.view.Gravity.START;
import static com.android.launcher3.Utilities.prefixTextWithIcon;
import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR;
@@ -147,12 +144,6 @@
public void initialize(Task task) {
mTask = task;
-
- if (task.key.userId != UserHandle.myUserId()) {
- setNoLimit();
- return;
- }
-
THREAD_POOL_EXECUTOR.execute(() -> {
final AppUsageLimit usageLimit = mLauncherApps.getAppUsageLimit(
task.getTopComponent().getPackageName(),
@@ -175,9 +166,9 @@
public void setSplitConfiguration(StagedSplitBounds stagedSplitBounds) {
mStagedSplitBounds = stagedSplitBounds;
- if (mStagedSplitBounds == null ||
- !mActivity.getDeviceProfile().overviewShowAsGrid ||
- mTaskView.isFocusedTask()) {
+ if (mStagedSplitBounds == null
+ || !mActivity.getDeviceProfile().isTablet
+ || mTaskView.isFocusedTask()) {
mSplitBannerConfig = SPLIT_BANNER_FULLSCREEN;
return;
}
@@ -315,7 +306,7 @@
private void setBanner(@Nullable View view) {
mBanner = view;
- if (view != null) {
+ if (view != null && mTaskView.getRecentsView() != null) {
setupAndAddBanner();
setBannerOutline();
}
@@ -329,7 +320,7 @@
mTaskView.getThumbnail().getLayoutParams()).bottomMargin;
PagedOrientationHandler orientationHandler = mTaskView.getPagedOrientationHandler();
Pair<Float, Float> translations = orientationHandler
- .setDwbLayoutParamsAndGetTranslations(mTaskView.getMeasuredWidth(),
+ .getDwbLayoutTranslations(mTaskView.getMeasuredWidth(),
mTaskView.getMeasuredHeight(), mStagedSplitBounds, deviceProfile,
mTaskView.getThumbnails(), mTask.key.id, mBanner);
mSplitOffsetTranslationX = translations.first;
diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskThumbnailView.java
new file mode 100644
index 0000000..d869fed
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/FloatingTaskThumbnailView.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+package com.android.quickstep.views;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Shader;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+/**
+ * A child view of {@link com.android.quickstep.views.FloatingTaskView} to draw the thumbnail in a
+ * rounded corner frame. While the purpose of this class sounds similar to
+ * {@link TaskThumbnailView}, it doesn't need a lot of complex logic in {@link TaskThumbnailView}
+ * in relation to moving with {@link RecentsView}.
+ */
+public class FloatingTaskThumbnailView extends View {
+
+ private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final Matrix mMatrix = new Matrix();
+
+ private @Nullable BitmapShader mBitmapShader;
+ private @Nullable Bitmap mBitmap;
+
+ public FloatingTaskThumbnailView(Context context) {
+ this(context, null);
+ }
+
+ public FloatingTaskThumbnailView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public FloatingTaskThumbnailView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (mBitmap == null) {
+ return;
+ }
+
+ // Scale down the bitmap to fix x, and crop in y.
+ float scale = 1.0f * getMeasuredWidth() / mBitmap.getWidth();
+ mMatrix.reset();
+ mMatrix.postScale(scale, scale);
+ mBitmapShader.setLocalMatrix(mMatrix);
+
+ FloatingTaskView parent = (FloatingTaskView) getParent();
+ parent.drawRoundedRect(canvas, mPaint);
+ }
+
+ public void setThumbnail(Bitmap bitmap) {
+ mBitmap = bitmap;
+ if (bitmap != null) {
+ mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
+ mPaint.setShader(mBitmapShader);
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
index 18ab3bb..c980d1e 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
@@ -3,22 +3,23 @@
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
import android.animation.ValueAnimator;
import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
-import android.widget.ImageView;
import androidx.annotation.Nullable;
import com.android.launcher3.BaseActivity;
-import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.R;
@@ -26,15 +27,19 @@
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.touch.PagedOrientationHandler;
+import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.util.MultiValueUpdateListener;
+import com.android.quickstep.util.TaskCornerRadius;
+import com.android.systemui.shared.system.QuickStepContract;
/**
- * Create an instance via {@link #getFloatingTaskView(StatefulActivity, TaskView, RectF)} to
+ * Create an instance via
+ * {@link #getFloatingTaskView(StatefulActivity, View, Bitmap, Drawable, RectF)} to
* which will have the thumbnail from the provided existing TaskView overlaying the taskview itself.
*
* Can then animate the taskview using
- * {@link #addAnimation(PendingAnimation, RectF, Rect, View, boolean)}
+ * {@link #addAnimation(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.
*
@@ -42,13 +47,15 @@
*/
public class FloatingTaskView extends FrameLayout {
+ private FloatingTaskThumbnailView mThumbnailView;
private SplitPlaceholderView mSplitPlaceholderView;
private RectF mStartingPosition;
- private final BaseDraggingActivity mActivity;
+ private final StatefulActivity mActivity;
private final boolean mIsRtl;
- private final Rect mOutline = new Rect();
+ private final FullscreenDrawParams mFullscreenParams;
private PagedOrientationHandler mOrientationHandler;
- private ImageView mImageView;
+ @SplitConfigurationOptions.StagePosition
+ private int mStagePosition;
public FloatingTaskView(Context context) {
this(context, null);
@@ -62,37 +69,38 @@
super(context, attrs, defStyleAttr);
mActivity = BaseActivity.fromContext(context);
mIsRtl = Utilities.isRtl(getResources());
+ mFullscreenParams = new FullscreenDrawParams(context);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mImageView = findViewById(R.id.thumbnail);
- mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
- mImageView.setLayerType(LAYER_TYPE_HARDWARE, null);
+ mThumbnailView = findViewById(R.id.thumbnail);
mSplitPlaceholderView = findViewById(R.id.split_placeholder);
mSplitPlaceholderView.setAlpha(0);
}
- private void init(StatefulActivity launcher, TaskView originalView, RectF positionOut) {
+ private void init(StatefulActivity launcher, View originalView, @Nullable Bitmap thumbnail,
+ Drawable icon, RectF positionOut) {
mStartingPosition = positionOut;
updateInitialPositionForView(originalView);
final InsettableFrameLayout.LayoutParams lp =
(InsettableFrameLayout.LayoutParams) getLayoutParams();
mSplitPlaceholderView.setLayoutParams(new FrameLayout.LayoutParams(lp.width, lp.height));
- positionOut.round(mOutline);
setPivotX(0);
setPivotY(0);
// Copy bounds of exiting thumbnail into ImageView
- TaskThumbnailView thumbnail = originalView.getThumbnail();
- mImageView.setImageBitmap(thumbnail.getThumbnail());
- mImageView.setVisibility(VISIBLE);
+ mThumbnailView.setThumbnail(thumbnail);
- mOrientationHandler = originalView.getRecentsView().getPagedOrientationHandler();
- mSplitPlaceholderView.setIconView(originalView.getIconView(),
- launcher.getDeviceProfile().overviewTaskIconDrawableSizePx);
+ mThumbnailView.setVisibility(VISIBLE);
+
+ RecentsView recentsView = launcher.getOverviewPanel();
+ mOrientationHandler = recentsView.getPagedOrientationHandler();
+ mStagePosition = recentsView.getSplitPlaceholder().getActiveSplitStagePosition();
+ mSplitPlaceholderView.setIcon(icon,
+ mContext.getResources().getDimensionPixelSize(R.dimen.split_placeholder_icon_size));
mSplitPlaceholderView.getIconView().setRotation(mOrientationHandler.getDegreesRotated());
}
@@ -101,24 +109,22 @@
* appearance of {@code originalView}.
*/
public static FloatingTaskView getFloatingTaskView(StatefulActivity launcher,
- TaskView originalView, RectF positionOut) {
+ View originalView, @Nullable Bitmap thumbnail, Drawable icon, RectF positionOut) {
final BaseDragLayer dragLayer = launcher.getDragLayer();
ViewGroup parent = (ViewGroup) dragLayer.getParent();
final FloatingTaskView floatingView = (FloatingTaskView) launcher.getLayoutInflater()
.inflate(R.layout.floating_split_select_view, parent, false);
- floatingView.init(launcher, originalView, positionOut);
+ floatingView.init(launcher, originalView, thumbnail, icon, positionOut);
parent.addView(floatingView);
return floatingView;
}
- public void updateInitialPositionForView(TaskView originalView) {
- View thumbnail = originalView.getThumbnail();
- Rect viewBounds = new Rect(0, 0, thumbnail.getWidth(), thumbnail.getHeight());
- Utilities.getBoundsForViewInDragLayer(mActivity.getDragLayer(), thumbnail, viewBounds,
- true /* ignoreTransform */, null /* recycle */,
+ public void updateInitialPositionForView(View originalView) {
+ Rect viewBounds = new Rect(0, 0, originalView.getWidth(), originalView.getHeight());
+ Utilities.getBoundsForViewInDragLayer(mActivity.getDragLayer(), originalView, viewBounds,
+ false /* ignoreTransform */, null /* recycle */,
mStartingPosition);
- mStartingPosition.offset(originalView.getTranslationX(), originalView.getTranslationY());
final InsettableFrameLayout.LayoutParams lp = new InsettableFrameLayout.LayoutParams(
Math.round(mStartingPosition.width()),
Math.round(mStartingPosition.height()));
@@ -126,27 +132,25 @@
setLayoutParams(lp);
}
- // TODO(194414938) set correct corner radii
- public void update(RectF position, float progress, float windowRadius) {
+ public void update(RectF bounds, float progress) {
MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
- float dX = position.left - mStartingPosition.left;
- float dY = position.top - lp.topMargin;
+ float dX = bounds.left - mStartingPosition.left;
+ float dY = bounds.top - lp.topMargin;
+ float scaleX = bounds.width() / lp.width;
+ float scaleY = bounds.height() / lp.height;
+
+ mFullscreenParams.updateParams(bounds, progress, scaleX, scaleY);
setTranslationX(dX);
setTranslationY(dY);
-
- float scaleX = position.width() / lp.width;
- float scaleY = position.height() / lp.height;
setScaleX(scaleX);
setScaleY(scaleY);
+ mSplitPlaceholderView.invalidate();
+ mThumbnailView.invalidate();
+
float childScaleX = 1f / scaleX;
float childScaleY = 1f / scaleY;
-
- invalidate();
- // TODO(194414938) seems like this scale value could be fine tuned, some stretchiness
- mImageView.setScaleX(1f / scaleX + scaleX * progress);
- mImageView.setScaleY(1f / scaleY + scaleY * progress);
mOrientationHandler.setPrimaryScale(mSplitPlaceholderView.getIconView(), childScaleX);
mOrientationHandler.setSecondaryScale(mSplitPlaceholderView.getIconView(), childScaleY);
}
@@ -174,39 +178,40 @@
}
public void addAnimation(PendingAnimation animation, RectF startingBounds, Rect endBounds,
- View viewToCover, boolean fadeWithThumbnail) {
+ boolean fadeWithThumbnail, boolean isStagedTask) {
+ mFullscreenParams.setIsStagedTask(isStagedTask);
final BaseDragLayer dragLayer = mActivity.getDragLayer();
int[] dragLayerBounds = new int[2];
dragLayer.getLocationOnScreen(dragLayerBounds);
SplitOverlayProperties prop = new SplitOverlayProperties(endBounds,
- startingBounds, viewToCover, dragLayerBounds[0],
- dragLayerBounds[1]);
+ startingBounds, dragLayerBounds[0], dragLayerBounds[1]);
ValueAnimator transitionAnimator = ValueAnimator.ofFloat(0, 1);
animation.add(transitionAnimator);
long animDuration = animation.getDuration();
- Rect crop = new Rect();
RectF floatingTaskViewBounds = new RectF();
- final float initialWindowRadius = supportsRoundedCornersOnWindows(getResources())
- ? Math.max(crop.width(), crop.height()) / 2f
- : 0f;
if (fadeWithThumbnail) {
animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ALPHA_FLOAT,
0, 1, ACCEL);
- animation.addFloat(mImageView, LauncherAnimUtils.VIEW_ALPHA,
+ animation.addFloat(mThumbnailView, LauncherAnimUtils.VIEW_ALPHA,
1, 0, DEACCEL_3);
+ } else if (isStagedTask) {
+ // Fade in the placeholder view when split is initiated from homescreen / all apps
+ // icons.
+ if (mSplitPlaceholderView.getAlpha() == 0) {
+ animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ALPHA_FLOAT,
+ 0.3f, 1, ACCEL);
+ }
}
MultiValueUpdateListener listener = new MultiValueUpdateListener() {
- final FloatProp mWindowRadius = new FloatProp(initialWindowRadius,
- initialWindowRadius, 0, animDuration, LINEAR);
final FloatProp mDx = new FloatProp(0, prop.dX, 0, animDuration, LINEAR);
final FloatProp mDy = new FloatProp(0, prop.dY, 0, animDuration, LINEAR);
- final FloatProp mTaskViewScaleX = new FloatProp(prop.initialTaskViewScaleX,
- prop.finalTaskViewScaleX, 0, animDuration, LINEAR);
- final FloatProp mTaskViewScaleY = new FloatProp(prop.initialTaskViewScaleY,
- prop.finalTaskViewScaleY, 0, animDuration, LINEAR);
+ final FloatProp mTaskViewScaleX = new FloatProp(1f, prop.finalTaskViewScaleX, 0,
+ animDuration, LINEAR);
+ final FloatProp mTaskViewScaleY = new FloatProp(1f, prop.finalTaskViewScaleY, 0,
+ animDuration, LINEAR);
@Override
public void onUpdate(float percent, boolean initOnly) {
// Calculate the icon position.
@@ -215,32 +220,54 @@
Utilities.scaleRectFAboutCenter(floatingTaskViewBounds, mTaskViewScaleX.value,
mTaskViewScaleY.value);
- update(floatingTaskViewBounds, percent, mWindowRadius.value * 1);
+ update(floatingTaskViewBounds, percent);
}
};
transitionAnimator.addUpdateListener(listener);
}
+ void drawRoundedRect(Canvas canvas, Paint paint) {
+ if (mFullscreenParams == null) {
+ return;
+ }
+
+ canvas.drawRoundRect(0, 0, getMeasuredWidth(), getMeasuredHeight(),
+ mFullscreenParams.mCurrentDrawnCornerRadius / mFullscreenParams.mScaleX,
+ mFullscreenParams.mCurrentDrawnCornerRadius / mFullscreenParams.mScaleY,
+ paint);
+ }
+
+ /**
+ * When a split is staged, center the icon in the staging area. Accounts for device insets.
+ * @param iconView The icon that should be centered.
+ * @param onScreenRectCenterX The x-center of the on-screen staging area (most of the Rect is
+ * offscreen).
+ * @param onScreenRectCenterY The y-center of the on-screen staging area (most of the Rect is
+ * offscreen).
+ */
+ void centerIconView(IconView iconView, float onScreenRectCenterX, float onScreenRectCenterY) {
+ mOrientationHandler.updateStagedSplitIconParams(iconView, onScreenRectCenterX,
+ onScreenRectCenterY, mFullscreenParams.mScaleX, mFullscreenParams.mScaleY,
+ iconView.getDrawableWidth(), iconView.getDrawableHeight(),
+ mActivity.getDeviceProfile(), mStagePosition);
+ }
+
private static class SplitOverlayProperties {
- private final float initialTaskViewScaleX;
- private final float initialTaskViewScaleY;
private final float finalTaskViewScaleX;
private final float finalTaskViewScaleY;
private final float dX;
private final float dY;
- SplitOverlayProperties(Rect endBounds, RectF startTaskViewBounds, View view,
+ SplitOverlayProperties(Rect endBounds, RectF startTaskViewBounds,
int dragLayerLeft, int dragLayerTop) {
float maxScaleX = endBounds.width() / startTaskViewBounds.width();
float maxScaleY = endBounds.height() / startTaskViewBounds.height();
- initialTaskViewScaleX = view.getScaleX();
- initialTaskViewScaleY = view.getScaleY();
finalTaskViewScaleX = maxScaleX;
finalTaskViewScaleY = maxScaleY;
- // Animate the app icon to the center of the window bounds in screen coordinates.
+ // Animate to the center of the window bounds in screen coordinates.
float centerX = endBounds.centerX() - dragLayerLeft;
float centerY = endBounds.centerY() - dragLayerTop;
@@ -248,4 +275,34 @@
dY = centerY - startTaskViewBounds.centerY();
}
}
+
+ public static class FullscreenDrawParams {
+
+ private final float mCornerRadius;
+ private final float mWindowCornerRadius;
+ public boolean mIsStagedTask;
+ public final RectF mBounds = new RectF();
+ public float mCurrentDrawnCornerRadius;
+ public float mScaleX = 1;
+ public float mScaleY = 1;
+
+ public FullscreenDrawParams(Context context) {
+ mCornerRadius = TaskCornerRadius.get(context);
+ mWindowCornerRadius = QuickStepContract.getWindowCornerRadius(context);
+
+ mCurrentDrawnCornerRadius = mCornerRadius;
+ }
+
+ public void updateParams(RectF bounds, float progress, float scaleX, float scaleY) {
+ mBounds.set(bounds);
+ mScaleX = scaleX;
+ mScaleY = scaleY;
+ mCurrentDrawnCornerRadius = mIsStagedTask ? mWindowCornerRadius :
+ Utilities.mapRange(progress, mCornerRadius, mWindowCornerRadius);
+ }
+
+ public void setIsStagedTask(boolean isStagedTask) {
+ mIsStagedTask = isStagedTask;
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java b/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
index c3b166f..adea1a4 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
@@ -136,7 +136,7 @@
}
/** Returns the maximum corner radius of {@param drawable}. */
- private static float getMaxRadius(Drawable drawable) {
+ private static float getMaxRadius(@Nullable Drawable drawable) {
if (!(drawable instanceof GradientDrawable)) return 0;
float[] cornerRadii = ((GradientDrawable) drawable).getCornerRadii();
float cornerRadius = ((GradientDrawable) drawable).getCornerRadius();
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index 7e4f9d0..244a794 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -5,14 +5,17 @@
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
import android.content.Context;
+import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.MotionEvent;
+import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
import com.android.launcher3.util.TransformingTouchDelegate;
@@ -23,6 +26,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.InteractionJankMonitorWrapper;
import java.util.HashMap;
import java.util.function.Consumer;
@@ -52,7 +56,6 @@
@Nullable private StagedSplitBounds mSplitBoundsConfig;
private final DigitalWellBeingToast mDigitalWellBeingToast2;
-
public GroupedTaskView(Context context) {
this(context, null);
}
@@ -169,8 +172,14 @@
RunnableList endCallback = new RunnableList();
RecentsView recentsView = getRecentsView();
// Callbacks run from remote animation when recents animation not currently running
+ InteractionJankMonitorWrapper.begin(this,
+ InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "Enter form GroupedTaskView");
recentsView.getSplitPlaceholder().launchTasks(this /*groupedTaskView*/,
- success -> endCallback.executeAllAndDestroy(),
+ success -> {
+ endCallback.executeAllAndDestroy();
+ InteractionJankMonitorWrapper.end(
+ InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
+ },
false /* freezeTaskList */);
// Callbacks get run from recentsView for case when recents animation already running
@@ -180,9 +189,8 @@
@Override
public void launchTask(@NonNull Consumer<Boolean> callback, boolean freezeTaskList) {
- getRecentsView().getSplitPlaceholder().launchTasks(mTask, mSecondaryTask,
- STAGE_POSITION_TOP_OR_LEFT, callback, freezeTaskList,
- getSplitRatio());
+ getRecentsView().getSplitPlaceholder().launchTasks(mTask.key.id, mSecondaryTask.key.id,
+ STAGE_POSITION_TOP_OR_LEFT, callback, freezeTaskList, getSplitRatio());
}
@Override
@@ -205,6 +213,20 @@
}
@Override
+ protected int getChildTaskIndexAtPosition(PointF position) {
+ if (isCoordInView(mIconView2, position) || isCoordInView(mSnapshotView2, position)) {
+ return 1;
+ }
+ return super.getChildTaskIndexAtPosition(position);
+ }
+
+ private boolean isCoordInView(View v, PointF position) {
+ float[] localPos = new float[]{position.x, position.y};
+ Utilities.mapCoordInSelfToDescendant(v, this, localPos);
+ return Utilities.pointInView(v, localPos[0], localPos[1], 0f /* slop */);
+ }
+
+ @Override
public void onRecycle() {
super.onRecycle();
mSnapshotView2.setThumbnail(mSecondaryTask, null);
@@ -222,7 +244,7 @@
}
getPagedOrientationHandler().measureGroupedTaskViewThumbnailBounds(mSnapshotView,
mSnapshotView2, widthSize, heightSize, mSplitBoundsConfig,
- mActivity.getDeviceProfile());
+ mActivity.getDeviceProfile(), getLayoutDirection() == LAYOUT_DIRECTION_RTL);
updateIconPlacement();
}
@@ -236,12 +258,13 @@
public void setOrientationState(RecentsOrientedState orientationState) {
super.setOrientationState(orientationState);
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
- boolean isGridTask = deviceProfile.overviewShowAsGrid && !isFocusedTask();
+ boolean isGridTask = deviceProfile.isTablet && !isFocusedTask();
int iconDrawableSize = isGridTask ? deviceProfile.overviewTaskIconDrawableSizeGridPx
: deviceProfile.overviewTaskIconDrawableSizePx;
mIconView2.setDrawableSize(iconDrawableSize, iconDrawableSize);
mIconView2.setRotation(getPagedOrientationHandler().getDegreesRotated());
updateIconPlacement();
+ updateSecondaryDwbPlacement();
}
private void updateIconPlacement() {
@@ -255,7 +278,15 @@
getPagedOrientationHandler().setSplitIconParams(mIconView, mIconView2,
taskIconHeight, mSnapshotView.getMeasuredWidth(), mSnapshotView.getMeasuredHeight(),
- isRtl, deviceProfile, mSplitBoundsConfig);
+ getMeasuredHeight(), getMeasuredWidth(), isRtl, deviceProfile,
+ mSplitBoundsConfig);
+ }
+
+ private void updateSecondaryDwbPlacement() {
+ if (mSecondaryTask == null) {
+ return;
+ }
+ mDigitalWellBeingToast2.initialize(mSecondaryTask);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 7e1d29e..306ebd7 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -36,6 +36,7 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.popup.QuickstepSystemShortcut;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.util.SplitConfigurationOptions;
@@ -99,6 +100,9 @@
setOverviewStateEnabled(toState.overviewUi);
setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mActivity.getDeviceProfile()));
setOverviewFullscreenEnabled(toState.getOverviewFullscreenProgress() == 1);
+ if (toState == OVERVIEW_MODAL_TASK) {
+ setOverviewSelectEnabled(true);
+ }
Log.d(BAD_STATE, "LRV onStateTransitionStart setFreezeVisibility=true, toState=" + toState);
setFreezeViewVisibility(true);
}
@@ -114,6 +118,9 @@
Log.d(BAD_STATE, "LRV onStateTransitionComplete setFreezeVisibility=false, finalState="
+ finalState);
setFreezeViewVisibility(false);
+ if (finalState != OVERVIEW_MODAL_TASK) {
+ setOverviewSelectEnabled(false);
+ }
if (isOverlayEnabled) {
runActionOnRemoteHandles(remoteTargetHandle ->
@@ -174,4 +181,15 @@
super.initiateSplitSelect(taskView, stagePosition);
mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
}
+
+ @Override
+ public void initiateSplitSelect(QuickstepSystemShortcut.SplitSelectSource splitSelectSource) {
+ super.initiateSplitSelect(splitSelectSource);
+ mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
+ }
+
+ @Override
+ protected boolean canLaunchFullscreenTask() {
+ return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 0294828..1c4e497 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -33,10 +33,11 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
+import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
-import com.android.quickstep.SysUINavigationMode;
-import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.TaskOverlayFactory.OverlayUICallbacks;
import com.android.quickstep.util.LayoutUtils;
@@ -55,7 +56,6 @@
HIDDEN_NON_ZERO_ROTATION,
HIDDEN_NO_TASKS,
HIDDEN_NO_RECENTS,
- HIDDEN_FOCUSED_SCROLL,
HIDDEN_SPLIT_SCREEN})
@Retention(RetentionPolicy.SOURCE)
public @interface ActionsHiddenFlags { }
@@ -63,8 +63,7 @@
public static final int HIDDEN_NON_ZERO_ROTATION = 1 << 0;
public static final int HIDDEN_NO_TASKS = 1 << 1;
public static final int HIDDEN_NO_RECENTS = 1 << 2;
- public static final int HIDDEN_FOCUSED_SCROLL = 1 << 3;
- public static final int HIDDEN_SPLIT_SCREEN = 1 << 4;
+ public static final int HIDDEN_SPLIT_SCREEN = 1 << 3;
@IntDef(flag = true, value = {
DISABLED_SCROLLING,
@@ -96,6 +95,7 @@
@Nullable
protected DeviceProfile mDp;
+ private final Rect mTaskSize = new Rect();
public OverviewActionsView(Context context) {
this(context, null);
@@ -145,14 +145,14 @@
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- updateVerticalMargin(SysUINavigationMode.getMode(getContext()));
+ updateVerticalMargin(DisplayController.getNavigationMode(getContext()));
}
@Override
public void setInsets(Rect insets) {
mInsets.set(insets);
- updateVerticalMargin(SysUINavigationMode.getMode(getContext()));
- updateHorizontalPadding();
+ updateVerticalMargin(DisplayController.getNavigationMode(getContext()));
+ updatePadding();
}
public void updateHiddenFlags(@ActionsHiddenFlags int visibilityFlags, boolean enable) {
@@ -195,28 +195,64 @@
return mMultiValueAlpha.getProperty(INDEX_FULLSCREEN_ALPHA);
}
- private void updateHorizontalPadding() {
- setPadding(mInsets.left, 0, mInsets.right, 0);
+ /**
+ * Offsets OverviewActionsView horizontal position based on 3 button nav container in taskbar.
+ */
+ private void updatePadding() {
+ if (mDp == null) {
+ return;
+ }
+ boolean alignFor3ButtonTaskbar = mDp.isTaskbarPresent && !mDp.isGestureMode;
+ if (alignFor3ButtonTaskbar) {
+ // Add extra horizontal spacing
+ int additionalPadding = ApiWrapper.getHotseatEndOffset(getContext());
+ if (isLayoutRtl()) {
+ setPadding(mInsets.left + additionalPadding, 0, mInsets.right, 0);
+ } else {
+ setPadding(mInsets.left, 0, mInsets.right + additionalPadding, 0);
+ }
+ } else {
+ setPadding(mInsets.left, 0, mInsets.right, 0);
+ }
}
/** Updates vertical margins for different navigation mode or configuration changes. */
- public void updateVerticalMargin(Mode mode) {
+ public void updateVerticalMargin(NavigationMode mode) {
if (mDp == null) {
return;
}
LayoutParams actionParams = (LayoutParams) findViewById(
R.id.action_buttons).getLayoutParams();
actionParams.setMargins(
- actionParams.leftMargin, getOverviewActionsTopMarginPx(mode, mDp),
- actionParams.rightMargin, getOverviewActionsBottomMarginPx(mode, mDp));
+ actionParams.leftMargin, mDp.overviewActionsTopMarginPx,
+ actionParams.rightMargin, getBottomMargin());
+ }
+
+ private int getBottomMargin() {
+ if (mDp == null) {
+ return 0;
+ }
+
+ if (mDp.isVerticalBarLayout()) {
+ return mDp.getInsets().bottom;
+ }
+
+ if (!mDp.isGestureMode && mDp.isTaskbarPresent) {
+ return mDp.getOverviewActionsClaimedSpaceBelow();
+ }
+
+ // Align to bottom of task Rect.
+ return mDp.heightPx - mTaskSize.bottom - mDp.overviewActionsTopMarginPx
+ - mDp.overviewActionsHeight;
}
/**
- * Set the device profile for this view to draw with.
+ * Updates device profile and task size for this view to draw with.
*/
- public void setDp(DeviceProfile dp) {
+ public void updateDimension(DeviceProfile dp, Rect taskSize) {
mDp = dp;
- updateVerticalMargin(SysUINavigationMode.getMode(getContext()));
+ mTaskSize.set(taskSize);
+ updateVerticalMargin(DisplayController.getNavigationMode(getContext()));
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
dp.isVerticalBarLayout() ? 0 : dp.overviewActionsButtonSpacing,
@@ -239,35 +275,4 @@
mSplitButton.setVisibility(visible ? VISIBLE : GONE);
findViewById(R.id.action_split_space).setVisibility(visible ? VISIBLE : GONE);
}
-
- /** Get the top margin associated with the action buttons in Overview. */
- public static int getOverviewActionsTopMarginPx(
- SysUINavigationMode.Mode mode, DeviceProfile dp) {
- // In vertical bar, use the smaller task margin for the top regardless of mode
- if (dp.isVerticalBarLayout()) {
- return dp.overviewTaskMarginPx;
- }
-
- if (mode == SysUINavigationMode.Mode.THREE_BUTTONS) {
- return dp.overviewActionsMarginThreeButtonPx;
- }
-
- return dp.overviewActionsTopMarginGesturePx;
- }
-
- /** Get the bottom margin associated with the action buttons in Overview. */
- public static int getOverviewActionsBottomMarginPx(
- SysUINavigationMode.Mode mode, DeviceProfile dp) {
- int inset = dp.getInsets().bottom;
-
- if (dp.isVerticalBarLayout()) {
- return inset;
- }
-
- if (mode == SysUINavigationMode.Mode.THREE_BUTTONS) {
- return dp.overviewActionsMarginThreeButtonPx + inset;
- }
-
- return dp.overviewActionsBottomMarginGesturePx + inset;
- }
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 7218cd7..2360396 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -43,7 +43,6 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
-import static com.android.launcher3.testing.TestProtocol.TASK_VIEW_ID_CRASH;
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;
@@ -65,8 +64,8 @@
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
+import android.annotation.SuppressLint;
import android.annotation.TargetApi;
-import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.LocusId;
import android.content.res.Configuration;
@@ -107,6 +106,7 @@
import android.widget.ListView;
import android.widget.OverScroller;
import android.widget.Toast;
+import android.window.PictureInPictureSurfaceTransaction;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -128,6 +128,7 @@
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.cache.HandlerRunnable;
+import com.android.launcher3.popup.QuickstepSystemShortcut;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StatefulActivity;
@@ -154,10 +155,12 @@
import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.RemoteTargetGluer;
import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
+import com.android.quickstep.RotationTouchHelper;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskViewUtils;
+import com.android.quickstep.TopTaskTracker;
import com.android.quickstep.ViewUtils;
import com.android.quickstep.util.GroupTask;
import com.android.quickstep.util.LayoutUtils;
@@ -170,9 +173,9 @@
import com.android.quickstep.util.VibratorWrapper;
import com.android.systemui.plugins.ResourceProvider;
import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.systemui.shared.system.PackageManagerWrapper;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
@@ -375,6 +378,8 @@
// OverScroll constants
private static final int OVERSCROLL_PAGE_SNAP_ANIMATION_DURATION = 270;
+ private static final int DEFAULT_ACTIONS_VIEW_ALPHA_ANIMATION_DURATION = 300;
+
private static final int DISMISS_TASK_DURATION = 300;
private static final int ADDITION_TASK_DURATION = 200;
private static final float INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.55f;
@@ -382,7 +387,7 @@
private static final float ANIMATION_DISMISS_PROGRESS_MIDPOINT = 0.5f;
private static final float END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.75f;
- private static final float SIGNIFICANT_MOVE_THRESHOLD_TABLET = 0.15f;
+ private static final float SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE = 0.15f;
protected final RecentsOrientedState mOrientationState;
protected final BaseActivityInterface<STATE_TYPE, ACTIVITY_TYPE> mSizeStrategy;
@@ -425,6 +430,7 @@
private final int mScrollHapticMinGapMillis;
private final RecentsModel mModel;
private final int mSplitPlaceholderSize;
+ private final int mSplitPlaceholderInset;
private final ClearAllButton mClearAllButton;
private final Rect mClearAllButtonDeadZoneRect = new Rect();
private final Rect mTaskViewDeadZoneRect = new Rect();
@@ -451,6 +457,7 @@
protected boolean mFreezeViewVisibility;
private boolean mOverviewGridEnabled;
private boolean mOverviewFullscreenEnabled;
+ private boolean mOverviewSelectEnabled;
private float mAdjacentPageHorizontalOffset = 0;
protected float mTaskViewsSecondaryTranslation = 0;
@@ -538,6 +545,7 @@
private final PinnedStackAnimationListener mIPipAnimationListener =
new PinnedStackAnimationListener();
private int mPipCornerRadius;
+ private int mPipShadowRadius;
// Used to keep track of the last requested task list id, so that we do not request to load the
// tasks again if we have already requested it and the task list has not changed
@@ -614,7 +622,7 @@
@Nullable
private TaskView mSplitHiddenTaskView;
@Nullable
- private TaskView mSecondSplitHiddenTaskView;
+ private View mSecondSplitHiddenView;
@Nullable
private StagedSplitBounds mSplitBoundsConfig;
private final Toast mSplitToast = Toast.makeText(getContext(),
@@ -622,6 +630,9 @@
private final Toast mSplitUnsupportedToast = Toast.makeText(getContext(),
R.string.toast_split_app_unsupported, Toast.LENGTH_SHORT);
+ @Nullable
+ private QuickstepSystemShortcut.SplitSelectSource mSplitSelectSource;
+
/**
* 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
@@ -643,6 +654,8 @@
private TaskView mMovingTaskView;
private OverviewActionsView mActionsView;
+ private ObjectAnimator mActionsViewAlphaAnimator;
+ private float mActionsViewAlphaAnimatorFinalValue;
private MultiWindowModeChangedListener mMultiWindowModeChangedListener =
new MultiWindowModeChangedListener() {
@@ -694,6 +707,8 @@
setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
mSplitPlaceholderSize = getResources().getDimensionPixelSize(
R.dimen.split_placeholder_size);
+ mSplitPlaceholderInset = getResources().getDimensionPixelSize(
+ R.dimen.split_placeholder_inset);
mSquaredTouchSlop = squaredTouchSlop(context);
mEmptyIcon = context.getDrawable(R.drawable.ic_empty_recents);
@@ -870,6 +885,14 @@
return mSplitSelectStateController.isSplitSelectActive();
}
+ /**
+ * See overridden implementations
+ * @return {@code true} if child TaskViews can be launched when user taps on them
+ */
+ protected boolean canLaunchFullscreenTask() {
+ return true;
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -923,7 +946,7 @@
mHasVisibleTaskData.delete(i);
}
if (child instanceof GroupedTaskView) {
- mGroupedTaskViewPool.recycle((GroupedTaskView)taskView);
+ mGroupedTaskViewPool.recycle((GroupedTaskView) taskView);
} else {
mTaskViewPool.recycle(taskView);
}
@@ -1075,10 +1098,15 @@
private int getSnapToLastTaskScrollDiff() {
// Snap to a position where ClearAll is just invisible.
int screenStart = mOrientationHandler.getPrimaryScroll(this);
- int clearAllWidth = mOrientationHandler.getPrimarySize(mClearAllButton);
int clearAllScroll = getScrollForPage(indexOfChild(mClearAllButton));
- int targetScroll = clearAllScroll + (mIsRtl ? clearAllWidth : -clearAllWidth);
- return screenStart - targetScroll;
+ int clearAllWidth = mOrientationHandler.getPrimarySize(mClearAllButton);
+ int lastTaskScroll = getLastTaskScroll(clearAllScroll, clearAllWidth);
+ return screenStart - lastTaskScroll;
+ }
+
+ private int getLastTaskScroll(int clearAllScroll, int clearAllWidth) {
+ int distance = clearAllWidth + getClearAllExtraPageSpacing();
+ return clearAllScroll + (mIsRtl ? distance : -distance);
}
private int getSnapToFocusedTaskScrollDiff(boolean isClearAllHidden) {
@@ -1121,6 +1149,11 @@
return getScrollForPage(taskIndex) == getPagedOrientationHandler().getPrimaryScroll(this);
}
+ private boolean isFocusedTaskInExpectedScrollPosition() {
+ TaskView focusedTask = getFocusedTaskView();
+ return focusedTask != null && isTaskInExpectedScrollPosition(indexOfChild(focusedTask));
+ }
+
/**
* Returns a {@link TaskView} that has taskId matching {@code taskId} or null if no match.
*/
@@ -1167,13 +1200,15 @@
@Override
protected void onPageBeginTransition() {
super.onPageBeginTransition();
- mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, true);
+ if (!mActivity.getDeviceProfile().isTablet) {
+ mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, true);
+ }
}
@Override
protected void onPageEndTransition() {
super.onPageEndTransition();
- if (isClearAllHidden()) {
+ if (isClearAllHidden() && !mActivity.getDeviceProfile().isTablet) {
mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false);
}
if (getNextPage() > 0) {
@@ -1182,9 +1217,14 @@
}
@Override
- protected float getSignificantMoveThreshold() {
- return mActivity.getDeviceProfile().isTablet ? SIGNIFICANT_MOVE_THRESHOLD_TABLET
- : super.getSignificantMoveThreshold();
+ protected boolean isSignificantMove(float absoluteDelta, int pageOrientedSize) {
+ DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+ if (!deviceProfile.isTablet) {
+ return super.isSignificantMove(absoluteDelta, pageOrientedSize);
+ }
+
+ return absoluteDelta
+ > deviceProfile.availableWidthPx * SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE;
}
@Override
@@ -1276,10 +1316,11 @@
return;
}
TaskView taskView = getTaskViewAt(mNextPage);
- // Only snap to fully visible focused task.
- if (taskView == null
- || !taskView.isFocusedTask()
- || !isTaskViewFullyVisible(taskView)) {
+ // Snap to fully visible focused task and clear all button.
+ boolean shouldSnapToFocusedTask = taskView != null && taskView.isFocusedTask()
+ && isTaskViewFullyVisible(taskView);
+ boolean shouldSnapToClearAll = mNextPage == indexOfChild(mClearAllButton);
+ if (!shouldSnapToFocusedTask && !shouldSnapToClearAll) {
return;
}
}
@@ -1326,7 +1367,7 @@
* required to focus the task in grid.
*/
public void moveFocusedTaskToFront() {
- if (!mActivity.getDeviceProfile().overviewShowAsGrid) {
+ if (!mActivity.getDeviceProfile().isTablet) {
return;
}
@@ -1367,6 +1408,9 @@
if (taskGroups == null || taskGroups.isEmpty()) {
removeTasksViewsAndClearAllButton();
onTaskStackUpdated();
+ // With all tasks removed, touch handling in PagedView is disabled and we need to reset
+ // touch state or otherwise values will be obsolete.
+ resetTouchState();
return;
}
@@ -1605,11 +1649,11 @@
// Propagate DeviceProfile change event.
runActionOnRemoteHandles(
remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().setDp(dp));
- mActionsView.setDp(dp);
mOrientationState.setDeviceProfile(dp);
// Update RecentsView and TaskView's DeviceProfile dependent layout.
updateOrientationHandler();
+ mActionsView.updateDimension(dp, mLastComputedTaskSize);
}
private void updateOrientationHandler() {
@@ -1674,7 +1718,7 @@
dp.widthPx - mInsets.right - mTempRect.right,
dp.heightPx - mInsets.bottom - mTempRect.bottom);
- mSizeStrategy.calculateGridSize(mActivity, mActivity.getDeviceProfile(),
+ mSizeStrategy.calculateGridSize(mActivity.getDeviceProfile(),
mLastComputedGridSize);
mSizeStrategy.calculateGridTaskSize(mActivity, mActivity.getDeviceProfile(),
mLastComputedGridTaskSize, mOrientationHandler);
@@ -1732,7 +1776,8 @@
* Returns the size of task selected to enter modal state.
*/
public Point getSelectedTaskSize() {
- mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), mTempRect);
+ mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(),
+ mTempRect);
return new Point(mTempRect.width(), mTempRect.height());
}
@@ -1774,16 +1819,24 @@
}
private void updateActionsViewFocusedScroll() {
- boolean hiddenFocusedScroll;
if (showAsGrid()) {
- TaskView focusedTaskView = getFocusedTaskView();
- hiddenFocusedScroll = focusedTaskView == null
- || !isTaskInExpectedScrollPosition(indexOfChild(focusedTaskView));
- } else {
- hiddenFocusedScroll = false;
+ float actionsViewAlphaValue = isFocusedTaskInExpectedScrollPosition() ? 1 : 0;
+ // If animation is already in progress towards the same end value, do not restart.
+ if (mActionsViewAlphaAnimator == null || !mActionsViewAlphaAnimator.isStarted()
+ || (mActionsViewAlphaAnimator.isStarted()
+ && mActionsViewAlphaAnimatorFinalValue != actionsViewAlphaValue)) {
+ animateActionsViewAlpha(actionsViewAlphaValue,
+ DEFAULT_ACTIONS_VIEW_ALPHA_ANIMATION_DURATION);
+ }
}
- mActionsView.updateHiddenFlags(OverviewActionsView.HIDDEN_FOCUSED_SCROLL,
- hiddenFocusedScroll);
+ }
+
+ private void animateActionsViewAlpha(float alphaValue, long duration) {
+ mActionsViewAlphaAnimator = ObjectAnimator.ofFloat(
+ mActionsView.getVisibilityAlpha(), MultiValueAlpha.VALUE, alphaValue);
+ mActionsViewAlphaAnimatorFinalValue = alphaValue;
+ mActionsViewAlphaAnimator.setDuration(duration);
+ mActionsViewAlphaAnimator.start();
}
/**
@@ -1799,20 +1852,21 @@
@Override
protected int getDestinationPage(int scaledScroll) {
- if (!mActivity.getDeviceProfile().overviewShowAsGrid) {
+ if (!mActivity.getDeviceProfile().isTablet) {
return super.getDestinationPage(scaledScroll);
}
-
- final int childCount = getChildCount();
- if (mPageScrolls == null || childCount != mPageScrolls.length) {
- return -1;
+ if (!pageScrollsInitialized()) {
+ Log.e(TAG,
+ "Cannot get destination page: RecentsView not properly initialized",
+ new IllegalStateException());
+ return INVALID_PAGE;
}
// When in tablet with variable task width, return the page which scroll is closest to
// screenStart instead of page nearest to center of screen.
int minDistanceFromScreenStart = Integer.MAX_VALUE;
- int minDistanceFromScreenStartIndex = -1;
- for (int i = 0; i < childCount; ++i) {
+ int minDistanceFromScreenStartIndex = INVALID_PAGE;
+ for (int i = 0; i < getChildCount(); ++i) {
int distanceFromScreenStart = Math.abs(mPageScrolls[i] - scaledScroll);
if (distanceFromScreenStart < minDistanceFromScreenStart) {
minDistanceFromScreenStart = distanceFromScreenStart;
@@ -2053,14 +2107,19 @@
/**
* Called when a gesture from an app is starting.
*/
- public void onGestureAnimationStart(RunningTaskInfo[] runningTaskInfo) {
+ public void onGestureAnimationStart(
+ Task[] runningTasks, RotationTouchHelper rotationTouchHelper) {
mGestureActive = true;
// This needs to be called before the other states are set since it can create the task view
if (mOrientationState.setGestureActive(true)) {
- updateOrientationHandler();
+ setLayoutRotation(rotationTouchHelper.getCurrentActiveRotation(),
+ rotationTouchHelper.getDisplayRotation());
+ // Force update to ensure the initial task size is computed even if the orientation has
+ // not changed.
+ updateSizeAndPadding();
}
- showCurrentTask(runningTaskInfo);
+ showCurrentTask(runningTasks);
setEnableFreeScroll(false);
setEnableDrawingLiveTile(false);
setRunningTaskHidden(true);
@@ -2176,10 +2235,10 @@
/**
* Returns true if we should add a stub taskView for the running task id
*/
- protected boolean shouldAddStubTaskView(RunningTaskInfo[] runningTaskInfos) {
- if (runningTaskInfos.length > 1) {
- TaskView primaryTaskView = getTaskViewByTaskId(runningTaskInfos[0].taskId);
- TaskView secondaryTaskView = getTaskViewByTaskId(runningTaskInfos[1].taskId);
+ protected boolean shouldAddStubTaskView(Task[] runningTasks) {
+ if (runningTasks.length > 1) {
+ TaskView primaryTaskView = getTaskViewByTaskId(runningTasks[0].key.id);
+ TaskView secondaryTaskView = getTaskViewByTaskId(runningTasks[1].key.id);
int leftTopTaskViewId =
(primaryTaskView == null) ? -1 : primaryTaskView.getTaskViewId();
int rightBottomTaskViewId =
@@ -2187,8 +2246,8 @@
// Add a new stub view if both taskIds don't match any taskViews
return leftTopTaskViewId != rightBottomTaskViewId || leftTopTaskViewId == -1;
}
- RunningTaskInfo runningTaskInfo = runningTaskInfos[0];
- return runningTaskInfo != null && getTaskViewByTaskId(runningTaskInfo.taskId) == null;
+ Task runningTaskInfo = runningTasks[0];
+ return runningTaskInfo != null && getTaskViewByTaskId(runningTaskInfo.key.id) == null;
}
/**
@@ -2197,21 +2256,19 @@
* All subsequent calls to reload will keep the task as the first item until {@link #reset()}
* is called. Also scrolls the view to this task.
*/
- private void showCurrentTask(RunningTaskInfo[] runningTaskInfo) {
+ private void showCurrentTask(Task[] runningTasks) {
+ if (runningTasks.length == 0) {
+ return;
+ }
int runningTaskViewId = -1;
- boolean needGroupTaskView = runningTaskInfo.length > 1;
- RunningTaskInfo taskInfo = runningTaskInfo[0];
- if (shouldAddStubTaskView(runningTaskInfo)) {
+ boolean needGroupTaskView = runningTasks.length > 1;
+ if (shouldAddStubTaskView(runningTasks)) {
boolean wasEmpty = getChildCount() == 0;
// Add an empty view for now until the task plan is loaded and applied
final TaskView taskView;
if (needGroupTaskView) {
taskView = getTaskViewFromPool(true);
- RunningTaskInfo secondaryTaskInfo = runningTaskInfo[1];
- mTmpRunningTasks = new Task[]{
- Task.from(new TaskKey(taskInfo), taskInfo, false),
- Task.from(new TaskKey(secondaryTaskInfo), secondaryTaskInfo, false)
- };
+ mTmpRunningTasks = new Task[]{runningTasks[0], runningTasks[1]};
addView(taskView, 0);
// When we create a placeholder task view mSplitBoundsConfig will be null, but with
// the actual app running we won't need to show the thumbnail until all the tasks
@@ -2223,7 +2280,7 @@
addView(taskView, 0);
// The temporary running task is only used for the duration between the start of the
// gesture and the task list is loaded and applied
- mTmpRunningTasks = new Task[]{Task.from(new TaskKey(taskInfo), taskInfo, false)};
+ mTmpRunningTasks = new Task[]{runningTasks[0]};
taskView.bind(mTmpRunningTasks[0], mOrientationState);
}
runningTaskViewId = taskView.getTaskViewId();
@@ -2236,8 +2293,8 @@
measure(makeMeasureSpec(getMeasuredWidth(), EXACTLY),
makeMeasureSpec(getMeasuredHeight(), EXACTLY));
layout(getLeft(), getTop(), getRight(), getBottom());
- } else if (getTaskViewByTaskId(taskInfo.taskId) != null) {
- runningTaskViewId = getTaskViewByTaskId(taskInfo.taskId).getTaskViewId();
+ } else if (getTaskViewByTaskId(runningTasks[0].key.id) != null) {
+ runningTaskViewId = getTaskViewByTaskId(runningTasks[0].key.id).getTaskViewId();
}
boolean runningTaskTileHidden = mRunningTaskTileHidden;
@@ -2258,8 +2315,6 @@
* Sets the running task id, cleaning up the old running task if necessary.
*/
public void setCurrentTask(int runningTaskViewId) {
- Log.d(TASK_VIEW_ID_CRASH, "currentRunningTaskViewId: " + mRunningTaskViewId
- + " requestedTaskViewId: " + runningTaskViewId);
if (mRunningTaskViewId == runningTaskViewId) {
return;
}
@@ -2314,10 +2369,9 @@
}
private void animateActionsViewIn() {
- ObjectAnimator anim = ObjectAnimator.ofFloat(
- mActionsView.getVisibilityAlpha(), MultiValueAlpha.VALUE, 0, 1);
- anim.setDuration(TaskView.SCALE_ICON_DURATION);
- anim.start();
+ if (!showAsGrid() || isFocusedTaskInExpectedScrollPosition()) {
+ animateActionsViewAlpha(1, TaskView.SCALE_ICON_DURATION);
+ }
}
public void animateUpTaskIconScale() {
@@ -2654,13 +2708,6 @@
PendingAnimation anim) {
// 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
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && taskView.isRunningTask()) {
- runActionOnRemoteHandles(remoteTargetHandle -> {
- TransformParams params = remoteTargetHandle.getTransformParams();
- anim.setFloat(params, TransformParams.TARGET_ALPHA, 0,
- clampToProgress(FINAL_FRAME, 0, 0.5f));
- });
- }
anim.setFloat(taskView, VIEW_ALPHA, 0,
clampToProgress(isOnGridBottomRow(taskView) ? ACCEL : FINAL_FRAME, 0, 0.5f));
FloatProperty<TaskView> secondaryViewTranslate =
@@ -2696,19 +2743,37 @@
*/
private void createInitialSplitSelectAnimation(PendingAnimation anim) {
mOrientationHandler.getInitialSplitPlaceholderBounds(mSplitPlaceholderSize,
- mActivity.getDeviceProfile(),
+ mSplitPlaceholderInset, mActivity.getDeviceProfile(),
mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);
RectF startingTaskRect = new RectF();
- mSplitHiddenTaskView.setVisibility(INVISIBLE);
- mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
- mSplitHiddenTaskView, startingTaskRect);
- mFirstFloatingTaskView.setAlpha(1);
- mFirstFloatingTaskView.addAnimation(anim, startingTaskRect,
- mTempRect, mSplitHiddenTaskView, true /*fadeWithThumbnail*/);
+ if (mSplitHiddenTaskView != null) {
+ mSplitHiddenTaskView.setVisibility(INVISIBLE);
+ mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
+ mSplitHiddenTaskView.getThumbnail(),
+ mSplitHiddenTaskView.getThumbnail().getThumbnail(),
+ mSplitHiddenTaskView.getIconView().getDrawable(), startingTaskRect);
+ mFirstFloatingTaskView.setAlpha(1);
+ mFirstFloatingTaskView.addAnimation(anim, startingTaskRect, mTempRect,
+ true /* fadeWithThumbnail */, true /* isStagedTask */);
+ } else {
+ mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
+ mSplitSelectSource.view, null /* thumbnail */,
+ mSplitSelectSource.drawable, startingTaskRect);
+ mFirstFloatingTaskView.setAlpha(1);
+ mFirstFloatingTaskView.addAnimation(anim, startingTaskRect, mTempRect,
+ false /* fadeWithThumbnail */, true /* isStagedTask */);
+ }
+ InteractionJankMonitorWrapper.begin(this,
+ InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "First tile selected");
anim.addEndListener(success -> {
if (success) {
mSplitToast.show();
+ InteractionJankMonitorWrapper.end(
+ InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
+ } else {
+ InteractionJankMonitorWrapper.cancel(
+ InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
}
});
}
@@ -3241,7 +3306,7 @@
// Update various scroll-dependent UI.
dispatchScrollChanged();
updateActionsViewFocusedScroll();
- if (isClearAllHidden()) {
+ if (isClearAllHidden() && !mActivity.getDeviceProfile().isTablet) {
mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING,
false);
}
@@ -3268,7 +3333,7 @@
return;
}
mActionsView.setSplitButtonVisible(
- mActivity.getDeviceProfile().overviewShowAsGrid && getTaskViewCount() > 1);
+ mActivity.getDeviceProfile().isTablet && getTaskViewCount() > 1);
}
/**
@@ -3640,10 +3705,7 @@
// Update the pivots such that when the task is scaled, it fills the full page
getTaskSize(mTempRect);
- getPagedViewOrientedState().getFullScreenScaleAndPivot(mTempRect,
- mActivity.getDeviceProfile(), mTempPointF);
- setPivotX(mTempPointF.x);
- setPivotY(mTempPointF.y);
+ updatePivots();
setTaskModalness(mTaskModalness);
mLastComputedTaskStartPushOutDistance = null;
mLastComputedTaskEndPushOutDistance = null;
@@ -3655,6 +3717,18 @@
: IMPORTANT_FOR_ACCESSIBILITY_AUTO);
}
+ private void updatePivots() {
+ if (mOverviewSelectEnabled) {
+ setPivotX(mLastComputedTaskSize.centerX());
+ setPivotY(mLastComputedTaskSize.bottom);
+ } else {
+ getPagedViewOrientedState().getFullScreenScaleAndPivot(mTempRect,
+ mActivity.getDeviceProfile(), mTempPointF);
+ setPivotX(mTempPointF.x);
+ setPivotY(mTempPointF.y);
+ }
+ }
+
private void updatePageOffsets() {
float offset = mAdjacentPageHorizontalOffset;
float modalOffset = ACCEL_0_75.getInterpolation(mTaskModalness);
@@ -3859,9 +3933,10 @@
float taskSplitScrollOffsetPrimary = 0f;
float clearAllSplitScrollOffsetPrimar = 0f;
if (isSplitPlaceholderFirstInGrid()) {
- taskSplitScrollOffsetPrimary = mSplitPlaceholderSize;
+ taskSplitScrollOffsetPrimary = mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
} else if (isSplitPlaceholderLastInGrid()) {
- clearAllSplitScrollOffsetPrimar = -mSplitPlaceholderSize;
+ clearAllSplitScrollOffsetPrimar =
+ mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
}
for (int i = 0; i < getTaskViewCount(); i++) {
@@ -3928,35 +4003,60 @@
public void initiateSplitSelect(TaskView taskView, @StagePosition int stagePosition) {
mSplitHiddenTaskView = taskView;
- Rect initialBounds = new Rect(taskView.getLeft(), taskView.getTop(), taskView.getRight(),
- taskView.getBottom());
- mSplitSelectStateController.setInitialTaskSelect(taskView.getTask(),
- stagePosition, initialBounds);
+ mSplitSelectStateController.setInitialTaskSelect(taskView.getTask().key.id,
+ stagePosition);
mSplitHiddenTaskViewIndex = indexOfChild(taskView);
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
finishRecentsAnimation(true, null);
}
}
- public PendingAnimation createSplitSelectInitAnimation() {
- int duration = mActivity.getStateManager().getState().getTransitionDuration(getContext());
- return createTaskDismissAnimation(mSplitHiddenTaskView, true, false, duration,
- true /* dismissingForSplitSelection*/);
+ public void initiateSplitSelect(QuickstepSystemShortcut.SplitSelectSource splitSelectSource) {
+ mSplitSelectSource = splitSelectSource;
+ mSplitSelectStateController.setInitialTaskSelect(splitSelectSource.intent,
+ splitSelectSource.position.stagePosition);
}
- public void confirmSplitSelect(TaskView taskView) {
+ public PendingAnimation createSplitSelectInitAnimation(int duration) {
+ if (mSplitHiddenTaskView != null) {
+ return createTaskDismissAnimation(mSplitHiddenTaskView, true, false, duration,
+ true /* dismissingForSplitSelection*/);
+ } else {
+ PendingAnimation anim = new PendingAnimation(duration);
+ createInitialSplitSelectAnimation(anim);
+ return anim;
+ }
+ }
+
+ /**
+ * Confirms the selection of the next split task. The extra data is passed through because the
+ * user may be selecting a subtask in a group.
+ *
+ * @return true if waiting for confirmation of second app or if split animations are running,
+ * false otherwise
+ */
+ public boolean confirmSplitSelect(TaskView containerTaskView, Task task, IconView iconView,
+ TaskThumbnailView thumbnailView) {
+ if (canLaunchFullscreenTask()) {
+ return false;
+ }
+ if (mSplitSelectStateController.isBothSplitAppsConfirmed()) {
+ return true;
+ }
mSplitToast.cancel();
- if (!taskView.getTask().isDockable) {
+ if (!task.isDockable) {
// Task not split screen supported
mSplitUnsupportedToast.show();
- return;
+ return true;
}
+ mSplitSelectStateController.setSecondTask(task);
RectF secondTaskStartingBounds = new RectF();
Rect secondTaskEndingBounds = new Rect();
// TODO(194414938) starting bounds seem slightly off, investigate
Rect firstTaskStartingBounds = new Rect();
Rect firstTaskEndingBounds = mTempRect;
- int duration = mActivity.getStateManager().getState().getTransitionDuration(getContext());
+ int duration = mActivity.getStateManager().getState().getTransitionDuration(mActivity,
+ false /* isToState */);
PendingAnimation pendingAnimation = new PendingAnimation(duration);
int halfDividerSize = getResources()
@@ -3968,29 +4068,54 @@
mFirstFloatingTaskView.getBoundsOnScreen(firstTaskStartingBounds);
mFirstFloatingTaskView.addAnimation(pendingAnimation,
- new RectF(firstTaskStartingBounds), firstTaskEndingBounds, mFirstFloatingTaskView,
- false /*fadeWithThumbnail*/);
+ new RectF(firstTaskStartingBounds), firstTaskEndingBounds,
+ false /* fadeWithThumbnail */, true /* isStagedTask */);
mSecondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
- taskView, secondTaskStartingBounds);
+ thumbnailView, thumbnailView.getThumbnail(),
+ iconView.getDrawable(), secondTaskStartingBounds);
mSecondFloatingTaskView.setAlpha(1);
mSecondFloatingTaskView.addAnimation(pendingAnimation, secondTaskStartingBounds,
- secondTaskEndingBounds, taskView.getThumbnail(),
- true /*fadeWithThumbnail*/);
- pendingAnimation.addEndListener(aBoolean ->
- mSplitSelectStateController.setSecondTaskId(taskView.getTask(),
- aBoolean1 -> RecentsView.this.resetFromSplitSelectionState()));
- mSecondSplitHiddenTaskView = taskView;
- taskView.setVisibility(INVISIBLE);
+ secondTaskEndingBounds, true /* fadeWithThumbnail */, false /* isStagedTask */);
+ pendingAnimation.addEndListener(aBoolean -> {
+ mSplitSelectStateController.launchSplitTasks(
+ aBoolean1 -> RecentsView.this.resetFromSplitSelectionState());
+ InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
+ });
+ if (containerTaskView.containsMultipleTasks()) {
+ // If we are launching from a child task, then only hide the thumbnail itself
+ mSecondSplitHiddenView = thumbnailView;
+ } else {
+ mSecondSplitHiddenView = containerTaskView;
+ }
+ mSecondSplitHiddenView.setVisibility(INVISIBLE);
+ InteractionJankMonitorWrapper.begin(this,
+ InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "Second tile selected");
pendingAnimation.buildAnim().start();
+ return true;
}
/** TODO(b/181707736) More gracefully handle exiting split selection state */
+ @SuppressLint("WrongCall")
protected void resetFromSplitSelectionState() {
+ if (mSplitSelectSource != null || mSplitHiddenTaskViewIndex != -1) {
+ if (mFirstFloatingTaskView != null) {
+ mActivity.getRootView().removeView(mFirstFloatingTaskView);
+ mFirstFloatingTaskView = null;
+ }
+ if (mSecondFloatingTaskView != null) {
+ mActivity.getRootView().removeView(mSecondFloatingTaskView);
+ mSecondFloatingTaskView = null;
+ mSecondSplitHiddenView.setVisibility(VISIBLE);
+ mSecondSplitHiddenView = null;
+ }
+ mSplitSelectSource = null;
+ }
+
if (mSplitHiddenTaskViewIndex == -1) {
return;
}
- if (!mActivity.getDeviceProfile().overviewShowAsGrid) {
+ if (!mActivity.getDeviceProfile().isTablet) {
int pageToSnapTo = mCurrentPage;
if (mSplitHiddenTaskViewIndex <= pageToSnapTo) {
pageToSnapTo += 1;
@@ -4006,16 +4131,6 @@
mSplitHiddenTaskView.setVisibility(VISIBLE);
mSplitHiddenTaskView = null;
}
- if (mFirstFloatingTaskView != null) {
- mActivity.getRootView().removeView(mFirstFloatingTaskView);
- mFirstFloatingTaskView = null;
- }
- if (mSecondFloatingTaskView != null) {
- mActivity.getRootView().removeView(mSecondFloatingTaskView);
- mSecondFloatingTaskView = null;
- mSecondSplitHiddenTaskView.setVisibility(VISIBLE);
- mSecondSplitHiddenTaskView = null;
- }
}
/**
@@ -4035,12 +4150,11 @@
protected void onRotateInSplitSelectionState() {
mOrientationHandler.getInitialSplitPlaceholderBounds(mSplitPlaceholderSize,
- mActivity.getDeviceProfile(),
+ mSplitPlaceholderInset, mActivity.getDeviceProfile(),
mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);
mTempRectF.set(mTempRect);
- // TODO(194414938) set correct corner radius
mFirstFloatingTaskView.updateOrientationHandler(mOrientationHandler);
- mFirstFloatingTaskView.update(mTempRectF, /*progress=*/1f, /*windowRadius=*/0f);
+ mFirstFloatingTaskView.update(mTempRectF, /*progress=*/1f);
PagedOrientationHandler orientationHandler = getPagedOrientationHandler();
Pair<FloatProperty, FloatProperty> taskViewsFloat =
@@ -4239,7 +4353,7 @@
}
mPendingAnimation.addEndListener(isSuccess -> {
if (isSuccess) {
- if (tv.getTaskIds()[1] != -1) {
+ if (tv.getTaskIds()[1] != -1 && mRemoteTargetHandles != null) {
// TODO(b/194414938): make this part of the animations instead.
TaskViewUtils.createSplitAuxiliarySurfacesAnimator(
mRemoteTargetHandles[0].getTransformParams().getTargetSet().nonApps,
@@ -4357,7 +4471,8 @@
}
RemoteTargetGluer gluer = new RemoteTargetGluer(getContext(), getSizeStrategy());
- mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(recentsAnimationTargets);
+ mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(
+ getContext(), recentsAnimationTargets);
mSplitBoundsConfig = gluer.getStagedSplitBounds();
// Add release check to the targets from the RemoteTargetGluer and not the targets
// passed in because in the event we're in split screen, we use the passed in targets
@@ -4412,10 +4527,7 @@
// Reset the minimized state since we force-toggled the minimized state when entering
// overview, but never actually finished the recents animation. This is a catch all for
// cases where we haven't already reset it.
- SystemUiProxy p = SystemUiProxy.INSTANCE.getNoCreate();
- if (p != null) {
- p.setSplitScreenMinimized(false);
- }
+ SystemUiProxy.INSTANCE.get(getContext()).setSplitScreenMinimized(false);
}
if (mRecentsAnimationController == null) {
@@ -4431,6 +4543,17 @@
final SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.get(getContext());
systemUiProxy.notifySwipeToHomeFinished();
systemUiProxy.setShelfHeight(true, mActivity.getDeviceProfile().hotseatBarSizePx);
+ // Transaction to hide the task to avoid flicker for entering PiP from split-screen.
+ // See also {@link AbsSwipeUpHandler#maybeFinishSwipeToHome}.
+ PictureInPictureSurfaceTransaction tx =
+ new PictureInPictureSurfaceTransaction.Builder()
+ .setAlpha(0f)
+ .build();
+ int[] taskIds = TopTaskTracker.INSTANCE.get(getContext()).getRunningSplitTaskIds();
+ for (int taskId : taskIds) {
+ mRecentsAnimationController.setFinishTaskTransaction(taskId,
+ tx, null /* overlay */);
+ }
}
mRecentsAnimationController.finish(toRecents, () -> {
if (onFinishComplete != null) {
@@ -4468,6 +4591,7 @@
/**
* Updates page scroll synchronously after measure and layout child views.
*/
+ @SuppressLint("WrongCall")
public void updateScrollSynchronously() {
// onMeasure is needed to update child's measured width which is used in scroll calculation,
// in case TaskView sizes has changed when being focused/unfocused.
@@ -4478,6 +4602,19 @@
}
@Override
+ protected int getChildGap(int fromIndex, int toIndex) {
+ int clearAllIndex = indexOfChild(mClearAllButton);
+ return fromIndex == clearAllIndex || toIndex == clearAllIndex
+ ? getClearAllExtraPageSpacing() : 0;
+ }
+
+ protected int getClearAllExtraPageSpacing() {
+ return showAsGrid()
+ ? Math.max(mActivity.getDeviceProfile().overviewGridSideMargin - mPageSpacing, 0)
+ : 0;
+ }
+
+ @Override
protected void updateMinAndMaxScrollX() {
super.updateMinAndMaxScrollX();
if (DEBUG) {
@@ -4559,9 +4696,10 @@
TaskView taskView = requireTaskViewAt(i);
float scrollDiff = taskView.getScrollAdjustment(showAsFullscreen, showAsGrid);
int pageScroll = newPageScrolls[i] + (int) scrollDiff;
- if ((mIsRtl && pageScroll < clearAllScroll + clearAllWidth)
- || (!mIsRtl && pageScroll > clearAllScroll - clearAllWidth)) {
- pageScroll = clearAllScroll + (mIsRtl ? clearAllWidth : -clearAllWidth);
+ int lastTaskScroll = getLastTaskScroll(clearAllScroll, clearAllWidth);
+ if ((mIsRtl && pageScroll < lastTaskScroll)
+ || (!mIsRtl && pageScroll > lastTaskScroll)) {
+ pageScroll = lastTaskScroll;
}
if (outPageScrolls[i] != pageScroll) {
pageScrollChanged = true;
@@ -4754,6 +4892,17 @@
}
/**
+ * Update whether RecentsView is in select mode. Should be enabled before transitioning to
+ * select mode, and only disabled after transitioning from select mode.
+ */
+ public void setOverviewSelectEnabled(boolean overviewSelectEnabled) {
+ if (mOverviewSelectEnabled != overviewSelectEnabled) {
+ mOverviewSelectEnabled = overviewSelectEnabled;
+ updatePivots();
+ }
+ }
+
+ /**
* Switch the current running task view to static snapshot mode,
* capturing the snapshot at the same time.
*/
@@ -4946,6 +5095,14 @@
return mPipCornerRadius;
}
+ /**
+ * @return Shadow radius in pixel value for PiP window, which is updated via
+ * {@link #mIPipAnimationListener}
+ */
+ public int getPipShadowRadius() {
+ return mPipShadowRadius;
+ }
+
@Override
public boolean scrollLeft() {
if (!showAsGrid()) {
@@ -5041,11 +5198,25 @@
}
@Override
- public void onPipCornerRadiusChanged(int cornerRadius) {
+ public void onPipResourceDimensionsChanged(int cornerRadius, int shadowRadius) {
if (mRecentsView != null) {
mRecentsView.mPipCornerRadius = cornerRadius;
+ mRecentsView.mPipShadowRadius = shadowRadius;
}
}
+
+ @Override
+ public void onExpandPip() {
+ MAIN_EXECUTOR.execute(() -> {
+ if (mRecentsView == null
+ || mRecentsView.mSizeStrategy.getTaskbarController() == null) {
+ return;
+ }
+ // Hide the task bar when leaving PiP to prevent it from flickering once
+ // the app settles in full-screen mode.
+ mRecentsView.mSizeStrategy.getTaskbarController().onExpandPip();
+ });
+ }
}
/** Get the color used for foreground scrimming the RecentsView for sharing. */
diff --git a/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java b/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
index 04a5761..28080d4 100644
--- a/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
+++ b/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
@@ -17,15 +17,22 @@
package com.android.quickstep.views;
import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.FloatProperty;
-import android.view.Gravity;
+import android.util.TypedValue;
import android.widget.FrameLayout;
import androidx.annotation.Nullable;
public class SplitPlaceholderView extends FrameLayout {
+ private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final Rect mTempRect = new Rect();
+
public static final FloatProperty<SplitPlaceholderView> ALPHA_FLOAT =
new FloatProperty<SplitPlaceholderView>("SplitViewAlpha") {
@Override
@@ -45,6 +52,24 @@
public SplitPlaceholderView(Context context, AttributeSet attrs) {
super(context, attrs);
+
+ mPaint.setColor(getThemeBackgroundColor(context));
+ setWillNotDraw(false);
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ // Call this before super call to draw below the children.
+ drawBackground(canvas);
+
+ super.dispatchDraw(canvas);
+
+ if (mIconView != null) {
+ // Center the icon view in the visible area.
+ getLocalVisibleRect(mTempRect);
+ FloatingTaskView parent = (FloatingTaskView) getParent();
+ parent.centerIconView(mIconView, mTempRect.centerX(), mTempRect.centerY());
+ }
}
@Nullable
@@ -52,15 +77,25 @@
return mIconView;
}
- public void setIconView(IconView iconView, int iconSize) {
+ public void setIcon(Drawable drawable, int iconSize) {
if (mIconView == null) {
mIconView = new IconView(getContext());
addView(mIconView);
}
- mIconView.setDrawable(iconView.getDrawable());
+ mIconView.setDrawable(drawable);
mIconView.setDrawableSize(iconSize, iconSize);
- FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(iconView.getLayoutParams());
- params.gravity = Gravity.CENTER;
+ FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(iconSize, iconSize);
mIconView.setLayoutParams(params);
}
+
+ private void drawBackground(Canvas canvas) {
+ FloatingTaskView parent = (FloatingTaskView) getParent();
+ parent.drawRoundedRect(canvas, mPaint);
+ }
+
+ private static int getThemeBackgroundColor(Context context) {
+ final TypedValue value = new TypedValue();
+ context.getTheme().resolveAttribute(android.R.attr.colorBackground, value, true);
+ return value.data;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index 853a023..3803f1b 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -146,7 +146,7 @@
// NOTE: Changing the pivots means the rotated view gets rotated about the new pivots set,
// which would render the X and Y position set here incorrect
setPivotX(0);
- if (deviceProfile.overviewShowAsGrid) {
+ if (deviceProfile.isTablet) {
// In tablet, set pivotY to original position without mThumbnailTopMargin adjustment.
setPivotY(-taskTopMargin);
} else {
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index d833877..d8120ff 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -19,7 +19,6 @@
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
-import static com.android.launcher3.Utilities.comp;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN;
@@ -284,6 +283,7 @@
public void setFullscreenParams(TaskView.FullscreenDrawParams fullscreenParams) {
mFullscreenParams = fullscreenParams;
+ getTaskOverlay().setFullscreenParams(fullscreenParams);
invalidate();
}
@@ -291,17 +291,8 @@
float cornerRadius) {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (mTask != null && getTaskView().isRunningTask() && !getTaskView().showScreenshot()) {
- // TODO(b/189265196): Temporary fix to align the surface with the cutout perfectly.
- // Round up only when the live tile task is displayed in Overview.
- float rounding = comp(mFullscreenParams.mFullscreenProgress);
- float left = x + rounding / 2;
- float top = y + rounding / 2;
- float right = width - rounding;
- float bottom = height - rounding;
-
- canvas.drawRoundRect(left, top, right, bottom, cornerRadius, cornerRadius,
- mClearPaint);
- canvas.drawRoundRect(left, top, right, bottom, cornerRadius, cornerRadius,
+ canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mClearPaint);
+ canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius,
mDimmingPaintAfterClearing);
return;
}
@@ -310,7 +301,8 @@
// Always draw the background since the snapshots might be translucent or partially empty
// (For example, tasks been reparented out of dismissing split root when drag-to-dismiss
// split screen).
- canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mBackgroundPaint);
+ canvas.drawRoundRect(x, y + 1, width, height - 1, cornerRadius,
+ cornerRadius, mBackgroundPaint);
final boolean drawBackgroundOnly = mTask == null || mTask.isLocked || mBitmapShader == null
|| mThumbnailData == null;
@@ -461,7 +453,7 @@
// Note: Disable rotation in grid layout.
boolean windowingModeSupportsRotation = !dp.isMultiWindowMode
&& thumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN
- && !dp.overviewShowAsGrid;
+ && !dp.isTablet;
isOrientationDifferent = isOrientationChange(deltaRotate)
&& windowingModeSupportsRotation;
if (canvasWidth == 0 || canvasHeight == 0 || scale == 0) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index d046fef..d58bb7c 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -16,10 +16,10 @@
package com.android.quickstep.views;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.widget.Toast.LENGTH_SHORT;
import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
-import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
import static com.android.launcher3.Utilities.comp;
import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
@@ -44,6 +44,7 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.Outline;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
@@ -51,6 +52,7 @@
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.util.Log;
+import android.view.Display;
import android.view.MotionEvent;
import android.view.TouchDelegate;
import android.view.View;
@@ -424,8 +426,11 @@
private final float[] mIconCenterCoords = new float[2];
+ private final PointF mLastTouchDownPosition = new PointF();
+
private boolean mIsClickableAsLiveTile = true;
+
public TaskView(Context context) {
this(context, null);
}
@@ -598,6 +603,14 @@
return mIconView;
}
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ mLastTouchDownPosition.set(ev.getX(), ev.getY());
+ }
+ return super.dispatchTouchEvent(ev);
+ }
+
private void onClick(View view) {
if (getTask() == null) {
return;
@@ -605,72 +618,7 @@
if (confirmSecondSplitSelectApp()) {
return;
}
- RecentsView recentsView = getRecentsView();
- RemoteTargetHandle[] remoteTargetHandles = recentsView.mRemoteTargetHandles;
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask() && remoteTargetHandles != null) {
- if (!mIsClickableAsLiveTile) {
- return;
- }
-
- // Reset the minimized state since we force-toggled the minimized state when entering
- // overview, but never actually finished the recents animation
- SystemUiProxy p = SystemUiProxy.INSTANCE.getNoCreate();
- if (p != null) {
- p.setSplitScreenMinimized(false);
- }
-
- mIsClickableAsLiveTile = false;
- RemoteAnimationTargets targets;
- if (remoteTargetHandles.length == 1) {
- targets = remoteTargetHandles[0].getTransformParams().getTargetSet();
- } else {
- TransformParams topLeftParams = remoteTargetHandles[0].getTransformParams();
- TransformParams rightBottomParams = remoteTargetHandles[1].getTransformParams();
- RemoteAnimationTargetCompat[] apps = Stream.concat(
- Arrays.stream(topLeftParams.getTargetSet().apps),
- Arrays.stream(rightBottomParams.getTargetSet().apps))
- .toArray(RemoteAnimationTargetCompat[]::new);
- RemoteAnimationTargetCompat[] wallpapers = Stream.concat(
- Arrays.stream(topLeftParams.getTargetSet().wallpapers),
- Arrays.stream(rightBottomParams.getTargetSet().wallpapers))
- .toArray(RemoteAnimationTargetCompat[]::new);
- targets = new RemoteAnimationTargets(apps, wallpapers,
- topLeftParams.getTargetSet().nonApps,
- topLeftParams.getTargetSet().targetMode);
- }
- if (targets == null) {
- // If the recents animation is cancelled somehow between the parent if block and
- // here, try to launch the task as a non live tile task.
- launchTaskAnimated();
- return;
- }
-
- AnimatorSet anim = new AnimatorSet();
- TaskViewUtils.composeRecentsLaunchAnimator(
- anim, this, targets.apps,
- targets.wallpapers, targets.nonApps, true /* launcherClosing */,
- mActivity.getStateManager(), recentsView,
- recentsView.getDepthController());
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- recentsView.runActionOnRemoteHandles(
- (Consumer<RemoteTargetHandle>) remoteTargetHandle ->
- remoteTargetHandle
- .getTaskViewSimulator()
- .setDrawsBelowRecents(false));
- }
-
- @Override
- public void onAnimationEnd(Animator animator) {
- mIsClickableAsLiveTile = true;
- }
- });
- anim.start();
- recentsView.onTaskLaunchedInLiveTileMode();
- } else {
- launchTaskAnimated();
- }
+ launchTasks();
mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo())
.log(LAUNCHER_TASK_LAUNCH_TAP);
}
@@ -680,11 +628,17 @@
* second app. {@code false} otherwise
*/
private boolean confirmSecondSplitSelectApp() {
- boolean isSelectingSecondSplitApp = getRecentsView().isSplitSelectionActive();
- if (isSelectingSecondSplitApp) {
- getRecentsView().confirmSplitSelect(this);
- }
- return isSelectingSecondSplitApp;
+ int index = getChildTaskIndexAtPosition(mLastTouchDownPosition);
+ TaskIdAttributeContainer container = mTaskIdAttributeContainer[index];
+ return getRecentsView().confirmSplitSelect(this, container.getTask(),
+ container.getIconView(), container.getThumbnailView());
+ }
+
+ /**
+ * Returns the task under the given position in the local coordinates of this task view.
+ */
+ protected int getChildTaskIndexAtPosition(PointF position) {
+ return 0;
}
/**
@@ -697,7 +651,8 @@
TestLogging.recordEvent(
TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", mTask);
ActivityOptionsWrapper opts = mActivity.getActivityLaunchOptions(this, null);
- opts.options.setLaunchDisplayId(getRootViewDisplayId());
+ opts.options.setLaunchDisplayId(
+ getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId());
if (ActivityManagerWrapper.getInstance()
.startActivityFromRecents(mTask.key, opts.options)) {
RecentsView recentsView = getRecentsView();
@@ -738,7 +693,8 @@
// Indicate success once the system has indicated that the transition has started
ActivityOptions opts = ActivityOptionsCompat.makeCustomAnimation(
getContext(), 0, 0, () -> callback.accept(true), MAIN_EXECUTOR.getHandler());
- opts.setLaunchDisplayId(getRootViewDisplayId());
+ opts.setLaunchDisplayId(
+ getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId());
if (freezeTaskList) {
ActivityOptionsCompat.setFreezeRecentTasksList(opts);
}
@@ -760,6 +716,79 @@
}
/**
+ * Launch of the current task (both live and inactive tasks) with an animation.
+ */
+ public void launchTasks() {
+ RecentsView recentsView = getRecentsView();
+ RemoteTargetHandle[] remoteTargetHandles = recentsView.mRemoteTargetHandles;
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask() && remoteTargetHandles != null) {
+ if (!mIsClickableAsLiveTile) {
+ return;
+ }
+
+ // Reset the minimized state since we force-toggled the minimized state when entering
+ // overview, but never actually finished the recents animation
+ SystemUiProxy.INSTANCE.get(getContext()).setSplitScreenMinimized(false);
+
+ mIsClickableAsLiveTile = false;
+ RemoteAnimationTargets targets;
+ if (remoteTargetHandles.length == 1) {
+ targets = remoteTargetHandles[0].getTransformParams().getTargetSet();
+ } else {
+ TransformParams topLeftParams = remoteTargetHandles[0].getTransformParams();
+ TransformParams rightBottomParams = remoteTargetHandles[1].getTransformParams();
+ RemoteAnimationTargetCompat[] apps = Stream.concat(
+ Arrays.stream(topLeftParams.getTargetSet().apps),
+ Arrays.stream(rightBottomParams.getTargetSet().apps))
+ .toArray(RemoteAnimationTargetCompat[]::new);
+ RemoteAnimationTargetCompat[] wallpapers = Stream.concat(
+ Arrays.stream(topLeftParams.getTargetSet().wallpapers),
+ Arrays.stream(rightBottomParams.getTargetSet().wallpapers))
+ .toArray(RemoteAnimationTargetCompat[]::new);
+ targets = new RemoteAnimationTargets(apps, wallpapers,
+ topLeftParams.getTargetSet().nonApps,
+ topLeftParams.getTargetSet().targetMode);
+ }
+ if (targets == null) {
+ // If the recents animation is cancelled somehow between the parent if block and
+ // here, try to launch the task as a non live tile task.
+ launchTaskAnimated();
+ mIsClickableAsLiveTile = true;
+ return;
+ }
+
+ AnimatorSet anim = new AnimatorSet();
+ TaskViewUtils.composeRecentsLaunchAnimator(
+ anim, this, targets.apps,
+ targets.wallpapers, targets.nonApps, true /* launcherClosing */,
+ mActivity.getStateManager(), recentsView,
+ recentsView.getDepthController());
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ recentsView.runActionOnRemoteHandles(
+ (Consumer<RemoteTargetHandle>) remoteTargetHandle ->
+ remoteTargetHandle
+ .getTaskViewSimulator()
+ .setDrawsBelowRecents(false));
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ if (mTask != null && mTask.key.displayId != getRootViewDisplayId()) {
+ launchTaskAnimated();
+ }
+ mIsClickableAsLiveTile = true;
+ }
+ });
+ anim.start();
+ recentsView.onTaskLaunchedInLiveTileMode();
+ } else {
+ launchTaskAnimated();
+ }
+ }
+
+ /**
* See {@link TaskDataChanges}
* @param visible If this task view will be visible to the user in overview or hidden
*/
@@ -825,12 +854,12 @@
}
private boolean showTaskMenu(IconView iconView) {
- if (getRecentsView().mActivity.isInState(OVERVIEW_SPLIT_SELECT)) {
+ if (!getRecentsView().canLaunchFullscreenTask()) {
// Don't show menu when selecting second split screen app
return true;
}
- if (!mActivity.getDeviceProfile().overviewShowAsGrid
+ if (!mActivity.getDeviceProfile().isTablet
&& !getRecentsView().isClearAllHidden()) {
getRecentsView().snapToPage(getRecentsView().indexOfChild(this));
return false;
@@ -844,7 +873,7 @@
protected boolean showTaskMenuWithContainer(IconView iconView) {
TaskIdAttributeContainer menuContainer =
mTaskIdAttributeContainer[iconView == mIconView ? 0 : 1];
- if (mActivity.getDeviceProfile().overviewShowAsGrid) {
+ if (mActivity.getDeviceProfile().isTablet) {
boolean alignSecondRow = getRecentsView().isOnGridBottomRow(menuContainer.getTaskView())
&& mActivity.getDeviceProfile().isLandscape;
return TaskMenuViewWithArrow.Companion.showForTask(menuContainer, alignSecondRow);
@@ -860,15 +889,7 @@
if (confirmSecondSplitSelectApp()) {
return;
}
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask()) {
- RecentsView recentsView = getRecentsView();
- recentsView.switchToScreenshot(
- () -> recentsView.finishRecentsAnimation(true /* toRecents */,
- false /* shouldPip */,
- () -> showTaskMenu(iconView)));
- } else {
- showTaskMenu(iconView);
- }
+ showTaskMenu(iconView);
});
iconView.setOnLongClickListener(v -> {
requestDisallowInterceptTouchEvent(true);
@@ -884,27 +905,32 @@
public void setOrientationState(RecentsOrientedState orientationState) {
PagedOrientationHandler orientationHandler = orientationState.getOrientationHandler();
boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
- LayoutParams snapshotParams = (LayoutParams) mSnapshotView.getLayoutParams();
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
- snapshotParams.topMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
+
boolean isGridTask = isGridTask();
+ LayoutParams iconParams = (LayoutParams) mIconView.getLayoutParams();
+
+ int thumbnailTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
int taskIconHeight = deviceProfile.overviewTaskIconSizePx;
int taskMargin = isGridTask ? deviceProfile.overviewTaskMarginGridPx
: deviceProfile.overviewTaskMarginPx;
- int taskIconMargin = snapshotParams.topMargin - taskIconHeight - taskMargin;
- LayoutParams iconParams = (LayoutParams) mIconView.getLayoutParams();
- orientationHandler.setIconAndSnapshotParams(mIconView, taskIconMargin, taskIconHeight,
- snapshotParams, isRtl);
- mSnapshotView.setLayoutParams(snapshotParams);
+ int taskIconMargin = thumbnailTopMargin - taskIconHeight - taskMargin;
+ orientationHandler.setTaskIconParams(iconParams, taskIconMargin, taskIconHeight,
+ thumbnailTopMargin, isRtl);
iconParams.width = iconParams.height = taskIconHeight;
mIconView.setLayoutParams(iconParams);
+
mIconView.setRotation(orientationHandler.getDegreesRotated());
int iconDrawableSize = isGridTask ? deviceProfile.overviewTaskIconDrawableSizeGridPx
: deviceProfile.overviewTaskIconDrawableSizePx;
mIconView.setDrawableSize(iconDrawableSize, iconDrawableSize);
- snapshotParams.topMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
+
+ LayoutParams snapshotParams = (LayoutParams) mSnapshotView.getLayoutParams();
+ snapshotParams.topMargin = thumbnailTopMargin;
mSnapshotView.setLayoutParams(snapshotParams);
+
mSnapshotView.getTaskOverlay().updateOrientationState(orientationState);
+ mDigitalWellBeingToast.initialize(mTask);
}
/**
@@ -912,7 +938,7 @@
*/
public boolean isGridTask() {
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
- return deviceProfile.overviewShowAsGrid && !isFocusedTask();
+ return deviceProfile.isTablet && !isFocusedTask();
}
protected void setIconAndDimTransitionProgress(float progress, boolean invert) {
@@ -973,8 +999,11 @@
// resetViewTransforms is called during Quickswitch scrolling.
mDismissTranslationX = mTaskOffsetTranslationX =
mTaskResistanceTranslationX = mSplitSelectTranslationX = mGridEndTranslationX = 0f;
- mDismissTranslationY = mTaskOffsetTranslationY = mTaskResistanceTranslationY =
- mSplitSelectTranslationY = 0f;
+ mDismissTranslationY = mTaskOffsetTranslationY = mTaskResistanceTranslationY = 0f;
+ if (getRecentsView() == null || !getRecentsView().isSplitSelectionActive()) {
+ mSplitSelectTranslationY = 0f;
+ }
+
setSnapshotScale(1f);
applyTranslationX();
applyTranslationY();
@@ -1000,13 +1029,13 @@
}
public float getTaskCornerRadius() {
- return TaskCornerRadius.get(mActivity);
+ return mCurrentFullscreenParams.mCornerRadius;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- if (mActivity.getDeviceProfile().overviewShowAsGrid) {
+ if (mActivity.getDeviceProfile().isTablet) {
setPivotX(getLayoutDirection() == LAYOUT_DIRECTION_RTL ? 0 : right - left);
setPivotY(mSnapshotView.getTop());
} else {
@@ -1023,7 +1052,7 @@
* How much to scale down pages near the edge of the screen.
*/
public static float getEdgeScaleDownFactor(DeviceProfile deviceProfile) {
- return deviceProfile.overviewShowAsGrid ? EDGE_SCALE_DOWN_FACTOR_GRID
+ return deviceProfile.isTablet ? EDGE_SCALE_DOWN_FACTOR_GRID
: EDGE_SCALE_DOWN_FACTOR_CAROUSEL;
}
@@ -1423,7 +1452,7 @@
int expectedWidth;
int expectedHeight;
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
- if (deviceProfile.overviewShowAsGrid) {
+ if (deviceProfile.isTablet) {
final int thumbnailPadding = deviceProfile.overviewTaskThumbnailTopMarginPx;
final Rect lastComputedTaskSize = getRecentsView().getLastComputedTaskSize();
final int taskWidth = lastComputedTaskSize.width();
@@ -1523,7 +1552,8 @@
private int getRootViewDisplayId() {
- return getRootView().getDisplay().getDisplayId();
+ Display display = getRootView().getDisplay();
+ return display != null ? display.getDisplayId() : DEFAULT_DISPLAY;
}
/**
@@ -1534,7 +1564,6 @@
private final float mCornerRadius;
private final float mWindowCornerRadius;
- public float mFullscreenProgress;
public RectF mCurrentDrawnInsets = new RectF();
public float mCurrentDrawnCornerRadius;
/** The current scale we apply to the thumbnail to adjust for new left/right insets. */
@@ -1552,8 +1581,6 @@
*/
public void setProgress(float fullscreenProgress, float parentScale, float taskViewScale,
int previewWidth, DeviceProfile dp, PreviewPositionHelper pph) {
- mFullscreenProgress = fullscreenProgress;
-
RectF insets = pph.getInsetsToDrawInFullscreen(dp);
float currentInsetsLeft = insets.left * fullscreenProgress;
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/RecentsHitboxExtenderTest.java b/quickstep/tests/src/com/android/launcher3/taskbar/RecentsHitboxExtenderTest.java
new file mode 100644
index 0000000..929bff3
--- /dev/null
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/RecentsHitboxExtenderTest.java
@@ -0,0 +1,125 @@
+package com.android.launcher3.taskbar;
+
+import static android.view.MotionEvent.ACTION_DOWN;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.os.Handler;
+import android.view.MotionEvent;
+import android.view.View;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.launcher3.DeviceProfile;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.function.Supplier;
+
+@RunWith(AndroidJUnit4.class)
+public class RecentsHitboxExtenderTest {
+
+ private static final int TASKBAR_OFFSET_Y = 35;
+ private static final int BUTTON_WIDTH = 10;
+ private static final int BUTTON_HEIGHT = 10;
+
+ private final RecentsHitboxExtender mHitboxExtender = new RecentsHitboxExtender();
+ @Mock
+ View mMockRecentsButton;
+ @Mock
+ View mMockRecentsParent;
+ @Mock
+ DeviceProfile mMockDeviceProfile;
+ @Mock
+ Handler mMockHandler;
+ Context mContext;
+
+ float[] mRecentsCoords = new float[]{0,0};
+ private final Supplier<float[]> mSupplier = () -> mRecentsCoords;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ mContext = instrumentation.getContext();
+ mHitboxExtender.init(mMockRecentsButton, mMockRecentsParent, mMockDeviceProfile, mSupplier,
+ mMockHandler);
+ when(mMockDeviceProfile.getTaskbarOffsetY()).thenReturn(TASKBAR_OFFSET_Y);
+ when(mMockRecentsButton.getContext()).thenReturn(mContext);
+ when(mMockRecentsButton.getWidth()).thenReturn(BUTTON_WIDTH);
+ when(mMockRecentsButton.getHeight()).thenReturn(BUTTON_HEIGHT);
+ }
+
+ @Test
+ public void noRecentsButtonClick_notActive() {
+ mHitboxExtender.onAnimationProgressToOverview(0);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertFalse(mHitboxExtender.extendedHitboxEnabled());
+ }
+
+ @Test
+ public void recentsButtonClick_active() {
+ mHitboxExtender.onRecentsButtonClicked();
+ mHitboxExtender.onAnimationProgressToOverview(0);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertTrue(mHitboxExtender.extendedHitboxEnabled());
+ }
+
+ @Test
+ public void homeToTaskbar_notActive() {
+ mHitboxExtender.onAnimationProgressToOverview(1);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertFalse(mHitboxExtender.extendedHitboxEnabled());
+ }
+
+ @Test
+ public void animationEndReset() {
+ mHitboxExtender.onRecentsButtonClicked();
+ mHitboxExtender.onAnimationProgressToOverview(0);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertTrue(mHitboxExtender.extendedHitboxEnabled());
+ mHitboxExtender.onAnimationProgressToOverview(1);
+ verify(mMockHandler, times(1)).postDelayed(any(), anyLong());
+ }
+
+ @Test
+ public void motionWithinHitbox() {
+ mHitboxExtender.onRecentsButtonClicked();
+ mHitboxExtender.onAnimationProgressToOverview(0);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertTrue(mHitboxExtender.extendedHitboxEnabled());
+ // Center width, past height but w/in offset bounds
+ MotionEvent motionEvent = getMotionEvent(ACTION_DOWN,
+ BUTTON_WIDTH / 2, BUTTON_HEIGHT + TASKBAR_OFFSET_Y / 2);
+ assertTrue(mHitboxExtender.onControllerInterceptTouchEvent(motionEvent));
+ }
+
+ @Test
+ public void motionOutsideHitbox() {
+ mHitboxExtender.onRecentsButtonClicked();
+ mHitboxExtender.onAnimationProgressToOverview(0);
+ mHitboxExtender.onAnimationProgressToOverview(0.5f);
+ assertTrue(mHitboxExtender.extendedHitboxEnabled());
+ // Center width, past height and offset
+ MotionEvent motionEvent = getMotionEvent(ACTION_DOWN,
+ BUTTON_WIDTH / 2, BUTTON_HEIGHT + TASKBAR_OFFSET_Y * 2);
+ assertFalse(mHitboxExtender.onControllerInterceptTouchEvent(motionEvent));
+ }
+
+ private MotionEvent getMotionEvent(int action, int x, int y) {
+ return MotionEvent.obtain(0, 0, action, x, y, 0);
+ }
+}
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
index ba1a60d..d8be307 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
@@ -1,5 +1,11 @@
package com.android.launcher3.taskbar;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_BACK_BUTTON_LONGPRESS;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_BACK_BUTTON_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_HOME_BUTTON_LONGPRESS;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_HOME_BUTTON_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_OVERVIEW_BUTTON_LONGPRESS;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_OVERVIEW_BUTTON_TAP;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_HOME;
@@ -11,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.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -19,6 +26,7 @@
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;
@@ -42,6 +50,14 @@
OverviewCommandHelper mockCommandHelper;
@Mock
Handler mockHandler;
+ @Mock
+ StatsLogManager mockStatsLogManager;
+ @Mock
+ StatsLogManager.StatsLogger mockStatsLogger;
+ @Mock
+ TaskbarControllers mockTaskbarControllers;
+ @Mock
+ TaskbarActivityContext mockTaskbarActivityContext;
private TaskbarNavButtonController mNavButtonController;
@@ -50,6 +66,10 @@
MockitoAnnotations.initMocks(this);
when(mockService.getDisplayId()).thenReturn(DISPLAY_ID);
when(mockService.getOverviewCommandHelper()).thenReturn(mockCommandHelper);
+ when(mockStatsLogManager.logger()).thenReturn(mockStatsLogger);
+ when(mockTaskbarControllers.getTaskbarActivityContext())
+ .thenReturn(mockTaskbarActivityContext);
+ doReturn(mockStatsLogManager).when(mockTaskbarActivityContext).getStatsLogManager();
mNavButtonController = new TaskbarNavButtonController(mockService,
mockSystemUiProxy, mockHandler);
}
@@ -156,4 +176,49 @@
mNavButtonController.onButtonLongClick(BUTTON_HOME);
verify(mockSystemUiProxy, times(0)).startAssistant(any());
}
+
+ @Test
+ public void testNoCallsToNullLogger() {
+ mNavButtonController.onButtonClick(BUTTON_HOME);
+ verify(mockStatsLogManager, times(0)).logger();
+ verify(mockStatsLogger, times(0)).log(any());
+ }
+
+ @Test
+ public void testNoCallsAfterNullingOut() {
+ mNavButtonController.init(mockTaskbarControllers);
+ mNavButtonController.onButtonClick(BUTTON_HOME);
+ mNavButtonController.onDestroy();
+ mNavButtonController.onButtonClick(BUTTON_HOME);
+ verify(mockStatsLogger, times(1)).log(LAUNCHER_TASKBAR_HOME_BUTTON_TAP);
+ verify(mockStatsLogger, times(0)).log(LAUNCHER_TASKBAR_HOME_BUTTON_LONGPRESS);
+ }
+
+ @Test
+ public void testLogOnTap() {
+ mNavButtonController.init(mockTaskbarControllers);
+ mNavButtonController.onButtonClick(BUTTON_HOME);
+ verify(mockStatsLogger, times(1)).log(LAUNCHER_TASKBAR_HOME_BUTTON_TAP);
+ verify(mockStatsLogger, times(0)).log(LAUNCHER_TASKBAR_HOME_BUTTON_LONGPRESS);
+ }
+
+ @Test
+ public void testLogOnLongpress() {
+ mNavButtonController.init(mockTaskbarControllers);
+ mNavButtonController.onButtonLongClick(BUTTON_HOME);
+ verify(mockStatsLogger, times(1)).log(LAUNCHER_TASKBAR_HOME_BUTTON_LONGPRESS);
+ verify(mockStatsLogger, times(0)).log(LAUNCHER_TASKBAR_HOME_BUTTON_TAP);
+ }
+
+ @Test
+ public void testBackOverviewLogOnLongpress() {
+ mNavButtonController.init(mockTaskbarControllers);
+ mNavButtonController.onButtonLongClick(BUTTON_RECENTS);
+ verify(mockStatsLogger, times(1)).log(LAUNCHER_TASKBAR_OVERVIEW_BUTTON_LONGPRESS);
+ verify(mockStatsLogger, times(0)).log(LAUNCHER_TASKBAR_OVERVIEW_BUTTON_TAP);
+
+ mNavButtonController.onButtonLongClick(BUTTON_BACK);
+ verify(mockStatsLogger, times(1)).log(LAUNCHER_TASKBAR_BACK_BUTTON_LONGPRESS);
+ verify(mockStatsLogger, times(0)).log(LAUNCHER_TASKBAR_BACK_BUTTON_TAP);
+ }
}
diff --git a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
index 189dff8..09f0858 100644
--- a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
+++ b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
@@ -20,6 +20,8 @@
import static org.junit.Assert.assertTrue;
+import android.os.SystemProperties;
+
import com.android.launcher3.Launcher;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.LauncherInstrumentation.ContainerType;
@@ -33,6 +35,8 @@
* Base class for all instrumentation tests that deal with Quickstep.
*/
public abstract class AbstractQuickStepTest extends AbstractLauncherUiTest {
+ static final boolean ENABLE_SHELL_TRANSITIONS =
+ SystemProperties.getBoolean("persist.wm.debug.shell_transit", false);
@Override
protected TestRule getRulesInsideActivityMonitor() {
return RuleChain.
@@ -51,7 +55,7 @@
@Override
protected void checkLauncherState(Launcher launcher, ContainerType expectedContainerType,
boolean isResumed, boolean isStarted) {
- if (!isInLiveTileMode(launcher, expectedContainerType)) {
+ if (ENABLE_SHELL_TRANSITIONS || !isInLiveTileMode(launcher, expectedContainerType)) {
super.checkLauncherState(launcher, expectedContainerType, isResumed, isStarted);
} else {
assertTrue("[Live Tile] hasBeenResumed() == isStarted(), hasBeenResumed(): "
@@ -62,7 +66,7 @@
@Override
protected void checkLauncherStateInOverview(Launcher launcher,
ContainerType expectedContainerType, boolean isStarted, boolean isResumed) {
- if (!isInLiveTileMode(launcher, expectedContainerType)) {
+ if (ENABLE_SHELL_TRANSITIONS || !isInLiveTileMode(launcher, expectedContainerType)) {
super.checkLauncherStateInOverview(launcher, expectedContainerType, isStarted,
isResumed);
} else {
diff --git a/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java b/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java
index 3e84a76..5c2e14f 100644
--- a/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java
+++ b/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java
@@ -46,9 +46,10 @@
runWithShellPermission(() ->
usageStatsManager.registerAppUsageLimitObserver(observerId, packages,
Duration.ofSeconds(600), Duration.ofSeconds(300),
- PendingIntent.getActivity(mTargetContext, -1, new Intent(), 0)));
+ PendingIntent.getActivity(mTargetContext, -1, new Intent(),
+ PendingIntent.FLAG_MUTABLE)));
- mLauncher.pressHome();
+ mLauncher.goHome();
final DigitalWellBeingToast toast = getToast();
waitForLauncherCondition("Toast is not visible", launcher -> toast.hasLimit());
@@ -58,7 +59,7 @@
runWithShellPermission(
() -> usageStatsManager.unregisterAppUsageLimitObserver(observerId));
- mLauncher.pressHome();
+ mLauncher.goHome();
assertFalse("Toast is visible", getToast().hasLimit());
} finally {
runWithShellPermission(
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index cba4833..f7600ff 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -57,6 +57,8 @@
import com.android.launcher3.testcomponent.TestCommandReceiver;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.FailureWatcher;
+import com.android.launcher3.util.rule.SamplerRule;
+import com.android.launcher3.util.rule.ScreenRecordRule;
import com.android.quickstep.views.RecentsView;
import org.junit.After;
@@ -77,6 +79,8 @@
@RunWith(AndroidJUnit4.class)
public class FallbackRecentsTest {
+ private static final String FALLBACK_LAUNCHER_TITLE = "Test launcher";
+
private final UiDevice mDevice;
private final LauncherInstrumentation mLauncher;
private final ActivityInfo mOtherLauncherActivity;
@@ -90,6 +94,9 @@
@Rule
public final TestRule mOrderSensitiveRules;
+ @Rule
+ public ScreenRecordRule mScreenRecordRule = new ScreenRecordRule();
+
public FallbackRecentsTest() throws RemoteException {
Instrumentation instrumentation = getInstrumentation();
Context context = instrumentation.getContext();
@@ -105,7 +112,8 @@
}
mOrderSensitiveRules = RuleChain
- .outerRule(new NavigationModeSwitchRule(mLauncher))
+ .outerRule(new SamplerRule())
+ .around(new NavigationModeSwitchRule(mLauncher))
.around(new FailureWatcher(mDevice, mLauncher));
mOtherLauncherActivity = context.getPackageManager().queryIntentActivities(
@@ -163,9 +171,9 @@
public void goToOverviewFromHome() {
mDevice.pressHome();
assertTrue("Fallback Launcher not visible", mDevice.wait(Until.hasObject(By.pkg(
- mOtherLauncherActivity.packageName)), WAIT_TIME_MS));
+ mOtherLauncherActivity.packageName).text(FALLBACK_LAUNCHER_TITLE)), WAIT_TIME_MS));
- mLauncher.getBackground().switchToOverview();
+ mLauncher.getLaunchedAppState().switchToOverview();
}
// b/143488140
@@ -174,7 +182,7 @@
public void goToOverviewFromApp() {
startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
- mLauncher.getBackground().switchToOverview();
+ mLauncher.getLaunchedAppState().switchToOverview();
}
protected void executeOnRecents(Consumer<RecentsActivity> f) {
@@ -200,7 +208,7 @@
private BaseOverview pressHomeAndGoToOverview() {
mDevice.pressHome();
- return mLauncher.getBackground().switchToOverview();
+ return mLauncher.getLaunchedAppState().switchToOverview();
}
// b/143488140
@@ -213,7 +221,7 @@
Wait.atMost("Expected three apps in the task list",
() -> mLauncher.getRecentTasks().size() >= 3, DEFAULT_ACTIVITY_TIMEOUT, mLauncher);
- BaseOverview overview = mLauncher.getBackground().switchToOverview();
+ BaseOverview overview = mLauncher.getLaunchedAppState().switchToOverview();
executeOnRecents(recents -> {
assertTrue("Don't have at least 3 tasks", getTaskCount(recents) >= 3);
});
@@ -252,7 +260,7 @@
// Test dismissing all tasks.
pressHomeAndGoToOverview().dismissAllTasks();
assertTrue("Fallback Launcher not visible", TestHelpers.wait(Until.hasObject(By.pkg(
- mOtherLauncherActivity.packageName)), WAIT_TIME_MS));
+ mOtherLauncherActivity.packageName).text(FALLBACK_LAUNCHER_TITLE)), WAIT_TIME_MS));
}
private int getCurrentOverviewPage(RecentsActivity recents) {
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
index 8d489e3..e5e2cf3 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
@@ -20,9 +20,7 @@
import static com.android.quickstep.NavigationModeSwitchRule.Mode.ALL;
import static com.android.quickstep.NavigationModeSwitchRule.Mode.THREE_BUTTON;
-import static com.android.quickstep.NavigationModeSwitchRule.Mode.TWO_BUTTON;
import static com.android.quickstep.NavigationModeSwitchRule.Mode.ZERO_BUTTON;
-import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_2BUTTON_OVERLAY;
import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_3BUTTON_OVERLAY;
import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_GESTURAL_OVERLAY;
@@ -35,6 +33,7 @@
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.TestHelpers;
import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.FailureWatcher;
import com.android.systemui.shared.system.QuickStepContract;
@@ -61,7 +60,7 @@
public static final int WAIT_TIME_MS = 10000;
public enum Mode {
- THREE_BUTTON, TWO_BUTTON, ZERO_BUTTON, ALL
+ THREE_BUTTON, ZERO_BUTTON, ALL
}
// Annotation for tests that need to be run with quickstep enabled and disabled.
@@ -73,8 +72,8 @@
private final LauncherInstrumentation mLauncher;
- static final SysUINavigationMode SYS_UI_NAVIGATION_MODE =
- SysUINavigationMode.INSTANCE.get(getInstrumentation().getTargetContext());
+ static final DisplayController DISPLAY_CONTROLLER =
+ DisplayController.INSTANCE.get(getInstrumentation().getTargetContext());
public NavigationModeSwitchRule(LauncherInstrumentation launcher) {
mLauncher = launcher;
@@ -99,9 +98,6 @@
if (mode == ZERO_BUTTON || mode == ALL) {
evaluateWithZeroButtons();
}
- if (mode == TWO_BUTTON || mode == ALL) {
- evaluateWithTwoButtons();
- }
if (mode == THREE_BUTTON || mode == ALL) {
evaluateWithThreeButtons();
}
@@ -123,13 +119,6 @@
}
}
- private void evaluateWithTwoButtons() throws Throwable {
- if (setActiveOverlay(mLauncher, NAV_BAR_MODE_2BUTTON_OVERLAY,
- LauncherInstrumentation.NavigationModel.TWO_BUTTON, description)) {
- base.evaluate();
- }
- }
-
private void evaluateWithZeroButtons() throws Throwable {
if (setActiveOverlay(mLauncher, NAV_BAR_MODE_GESTURAL_OVERLAY,
LauncherInstrumentation.NavigationModel.ZERO_BUTTON, description)) {
@@ -145,14 +134,12 @@
public static String getCurrentOverlayPackage(int currentInteractionMode) {
return QuickStepContract.isGesturalMode(currentInteractionMode)
? NAV_BAR_MODE_GESTURAL_OVERLAY
- : QuickStepContract.isSwipeUpMode(currentInteractionMode)
- ? NAV_BAR_MODE_2BUTTON_OVERLAY
- : NAV_BAR_MODE_3BUTTON_OVERLAY;
+ : NAV_BAR_MODE_3BUTTON_OVERLAY;
}
private static LauncherInstrumentation.NavigationModel currentSysUiNavigationMode() {
return LauncherInstrumentation.getNavigationModel(
- SysUINavigationMode.getMode(
+ DisplayController.getNavigationMode(
getInstrumentation().
getTargetContext()).
resValue);
@@ -173,18 +160,18 @@
if (currentSysUiNavigationMode() != expectedMode) {
final CountDownLatch latch = new CountDownLatch(1);
final Context targetContext = getInstrumentation().getTargetContext();
- final SysUINavigationMode.NavigationModeChangeListener listener =
- newMode -> {
- if (LauncherInstrumentation.getNavigationModel(newMode.resValue)
+ final DisplayController.DisplayInfoChangeListener listener =
+ (context, info, flags) -> {
+ if (LauncherInstrumentation.getNavigationModel(info.navigationMode.resValue)
== expectedMode) {
latch.countDown();
}
};
targetContext.getMainExecutor().execute(() ->
- SYS_UI_NAVIGATION_MODE.addModeChangeListener(listener));
+ DISPLAY_CONTROLLER.addChangeListener(listener));
latch.await(60, TimeUnit.SECONDS);
targetContext.getMainExecutor().execute(() ->
- SYS_UI_NAVIGATION_MODE.removeModeChangeListener(listener));
+ DISPLAY_CONTROLLER.removeChangeListener(listener));
assertTrue(launcher, "Navigation mode didn't change to " + expectedMode,
currentSysUiNavigationMode() == expectedMode, description);
@@ -220,7 +207,7 @@
if (!condition) {
final AssertionError assertionError = new AssertionError(message);
if (description != null) {
- FailureWatcher.onError(launcher.getDevice(), description, assertionError);
+ FailureWatcher.onError(launcher, description, assertionError);
}
throw assertionError;
}
diff --git a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
index 159a51f..9e5d958 100644
--- a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
+++ b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
@@ -17,27 +17,24 @@
package com.android.quickstep;
-import static android.view.Display.DEFAULT_DISPLAY;
-
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
+import static com.android.launcher3.util.DisplayController.NavigationMode.NO_BUTTON;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
-import android.content.Context;
import android.content.res.Resources;
import android.graphics.Point;
-import android.hardware.display.DisplayManager;
+import android.graphics.Rect;
+import android.util.ArrayMap;
import android.util.DisplayMetrics;
+import android.util.Size;
import android.view.Display;
import android.view.MotionEvent;
import android.view.Surface;
@@ -47,6 +44,10 @@
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.RotationUtils;
+import com.android.launcher3.util.WindowBounds;
+import com.android.launcher3.util.window.CachedDisplayInfo;
+import com.android.launcher3.util.window.WindowManagerProxy;
import org.junit.Before;
import org.junit.Test;
@@ -56,18 +57,9 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class OrientationTouchTransformerTest {
- static class ScreenSize {
- int mHeight;
- int mWidth;
- ScreenSize(int height, int width) {
- mHeight = height;
- mWidth = width;
- }
- }
-
- private static final ScreenSize NORMAL_SCREEN_SIZE = new ScreenSize(2280, 1080);
- private static final ScreenSize LARGE_SCREEN_SIZE = new ScreenSize(3280, 1080);
+ private static final Size NORMAL_SCREEN_SIZE = new Size(1080, 2280);
+ private static final Size LARGE_SCREEN_SIZE = new Size(1080, 3280);
private static final float DENSITY_DISPLAY_METRICS = 3.0f;
private OrientationTouchTransformer mTouchTransformer;
@@ -75,7 +67,6 @@
Resources mResources;
private DisplayController.Info mInfo;
-
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
@@ -296,33 +287,24 @@
assertTrue(mTouchTransformer.touchInValidSwipeRegions(inRegion2.getX(), inRegion2.getY()));
}
- private DisplayController.Info createDisplayInfo(ScreenSize screenSize, int rotation) {
- Context context = getApplicationContext();
- Display display = spy(context.getSystemService(DisplayManager.class)
- .getDisplay(DEFAULT_DISPLAY));
-
- Point p = new Point(screenSize.mWidth, screenSize.mHeight);
- if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
- p.set(screenSize.mHeight, screenSize.mWidth);
- }
-
- doReturn(rotation).when(display).getRotation();
- doAnswer(i -> {
- ((Point) i.getArgument(0)).set(p.x, p.y);
- return null;
- }).when(display).getRealSize(any(Point.class));
- doAnswer(i -> {
- ((Point) i.getArgument(0)).set(p.x, p.y);
- ((Point) i.getArgument(1)).set(p.x, p.y);
- return null;
- }).when(display).getCurrentSizeRange(any(Point.class), any(Point.class));
- return new DisplayController.Info(context, display);
+ private DisplayController.Info createDisplayInfo(Size screenSize, int rotation) {
+ Point displaySize = new Point(screenSize.getWidth(), screenSize.getHeight());
+ RotationUtils.rotateSize(displaySize, rotation);
+ CachedDisplayInfo cdi = new CachedDisplayInfo(displaySize, rotation);
+ WindowBounds wm = new WindowBounds(
+ new Rect(0, 0, displaySize.x, displaySize.y),
+ new Rect());
+ WindowManagerProxy wmProxy = mock(WindowManagerProxy.class);
+ doReturn(cdi).when(wmProxy).getDisplayInfo(any(), any());
+ doReturn(wm).when(wmProxy).getRealBounds(any(), any(), any());
+ return new DisplayController.Info(
+ getApplicationContext(), mock(Display.class), wmProxy, new ArrayMap<>());
}
- private float generateTouchRegionHeight(ScreenSize screenSize, int rotation) {
- float height = screenSize.mHeight;
+ private float generateTouchRegionHeight(Size screenSize, int rotation) {
+ float height = screenSize.getHeight();
if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
- height = screenSize.mWidth;
+ height = screenSize.getWidth();
}
return height - ResourceUtils.DEFAULT_NAVBAR_VALUE * DENSITY_DISPLAY_METRICS;
}
diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
index f44a812..6ec6269 100644
--- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
+++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
@@ -16,23 +16,16 @@
package com.android.quickstep;
-import static com.android.launcher3.util.RaceConditionReproducer.enterEvt;
-import static com.android.launcher3.util.RaceConditionReproducer.exitEvt;
-
import android.content.Intent;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.launcher3.Launcher;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.util.RaceConditionReproducer;
-import com.android.quickstep.NavigationModeSwitchRule.Mode;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
-import com.android.quickstep.inputconsumers.OtherActivityInputConsumer;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -48,7 +41,7 @@
super.setUp();
TaplTestsLauncher3.initialize(this);
// b/143488140
- mLauncher.pressHome();
+ mLauncher.goHome();
// Start an activity where the gestures start.
startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
}
@@ -61,26 +54,11 @@
// The test action.
eventProcessor.startIteration();
- mLauncher.pressHome();
+ mLauncher.goHome();
eventProcessor.finishIteration();
}
@Test
- @Ignore // Ignoring until race condition repro framework is changes for multi-process case.
- @NavigationModeSwitch(mode = Mode.TWO_BUTTON)
- public void testPressHome() {
- runTest(enterEvt(Launcher.ON_CREATE_EVT),
- exitEvt(Launcher.ON_CREATE_EVT),
- enterEvt(OtherActivityInputConsumer.DOWN_EVT),
- exitEvt(OtherActivityInputConsumer.DOWN_EVT));
-
- runTest(enterEvt(OtherActivityInputConsumer.DOWN_EVT),
- exitEvt(OtherActivityInputConsumer.DOWN_EVT),
- enterEvt(Launcher.ON_CREATE_EVT),
- exitEvt(Launcher.ON_CREATE_EVT));
- }
-
- @Test
@NavigationModeSwitch
public void testStressPressHome() {
for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
@@ -88,7 +66,7 @@
closeLauncherActivity();
// The test action.
- mLauncher.pressHome();
+ mLauncher.goHome();
}
}
@@ -100,9 +78,9 @@
closeLauncherActivity();
// The test action.
- mLauncher.getBackground().switchToOverview();
+ mLauncher.getLaunchedAppState().switchToOverview();
}
closeLauncherActivity();
- mLauncher.pressHome();
+ mLauncher.goHome();
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 237e426..4bf247c 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -21,6 +21,7 @@
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 android.content.Intent;
@@ -31,13 +32,11 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.tapl.AllApps;
-import com.android.launcher3.tapl.Background;
+import com.android.launcher3.tapl.LaunchedAppState;
import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel;
import com.android.launcher3.tapl.Overview;
import com.android.launcher3.tapl.OverviewActions;
import com.android.launcher3.tapl.OverviewTask;
-import com.android.launcher3.tapl.TestHelpers;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
@@ -45,7 +44,6 @@
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -54,6 +52,8 @@
public class TaplTestsQuickstep extends AbstractQuickStepTest {
private static final String APP_NAME = "LauncherTestApp";
+ private static final String CALCULATOR_APP_PACKAGE =
+ resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
@Before
public void setUp() throws Exception {
@@ -75,7 +75,7 @@
public static void startTestApps() throws Exception {
startAppFast(getAppPackageName());
- startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
+ startAppFast(CALCULATOR_APP_PACKAGE);
startTestActivity(2);
}
@@ -84,7 +84,7 @@
executeOnLauncher(launcher -> assertTrue(
"Launcher activity is the top activity; expecting another activity to be the top "
+ "one",
- isInBackground(launcher)));
+ isInLaunchedApp(launcher)));
}
@Test
@@ -102,7 +102,7 @@
public void testOverview() throws Exception {
startTestAppsWithCheck();
// mLauncher.pressHome() also tests an important case of pressing home while in background.
- Overview overview = mLauncher.pressHome().switchToOverview();
+ Overview overview = mLauncher.goHome().switchToOverview();
assertTrue("Launcher internal state didn't switch to Overview",
isInState(() -> LauncherState.OVERVIEW));
executeOnLauncher(
@@ -127,7 +127,7 @@
getCurrentOverviewPage(launcher) < currentTaskAfterFlingForward));
// Test opening a task.
- OverviewTask task = mLauncher.pressHome().switchToOverview().getCurrentTask();
+ OverviewTask task = mLauncher.goHome().switchToOverview().getCurrentTask();
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(
@@ -136,10 +136,10 @@
executeOnLauncher(launcher -> assertTrue(
"Launcher activity is the top activity; expecting another activity to be the top "
+ "one",
- isInBackground(launcher)));
+ isInLaunchedApp(launcher)));
// Test dismissing a task.
- overview = mLauncher.pressHome().switchToOverview();
+ overview = mLauncher.goHome().switchToOverview();
assertTrue("Launcher internal state didn't switch to Overview",
isInState(() -> LauncherState.OVERVIEW));
final Integer numTasks = getFromLauncher(launcher -> getTaskCount(launcher));
@@ -151,7 +151,7 @@
numTasks - 1, getTaskCount(launcher)));
// Test dismissing all tasks.
- mLauncher.pressHome().switchToOverview().dismissAllTasks();
+ mLauncher.goHome().switchToOverview().dismissAllTasks();
assertTrue("Launcher internal state is not Home",
isInState(() -> LauncherState.NORMAL));
executeOnLauncher(
@@ -168,14 +168,14 @@
@ScreenRecord // b/195673272
public void testOverviewActions() throws Exception {
// Experimenting for b/165029151:
- final Overview overview = mLauncher.pressHome().switchToOverview();
+ final Overview overview = mLauncher.goHome().switchToOverview();
if (overview.hasTasks()) overview.dismissAllTasks();
- mLauncher.pressHome();
+ mLauncher.goHome();
//
startTestAppsWithCheck();
OverviewActions actionsView =
- mLauncher.pressHome().switchToOverview().getOverviewActions();
+ mLauncher.goHome().switchToOverview().getOverviewActions();
actionsView.clickAndDismissScreenshot();
}
@@ -200,7 +200,7 @@
@PortraitLandscape
public void testSwitchToOverview() throws Exception {
assertNotNull("Workspace.switchToOverview() returned null",
- mLauncher.pressHome().switchToOverview());
+ mLauncher.goHome().switchToOverview());
assertTrue("Launcher internal state didn't switch to Overview",
isInState(() -> LauncherState.OVERVIEW));
}
@@ -209,22 +209,23 @@
@NavigationModeSwitch
@PortraitLandscape
public void testBackground() throws Exception {
- startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
- final Background background = getAndAssertBackground();
+ startAppFast(CALCULATOR_APP_PACKAGE);
+ final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
- assertNotNull("Background.switchToOverview() returned null", background.switchToOverview());
+ assertNotNull("Background.switchToOverview() returned null",
+ launchedAppState.switchToOverview());
assertTrue("Launcher internal state didn't switch to Overview",
isInState(() -> LauncherState.OVERVIEW));
}
- private Background getAndAssertBackground() {
- final Background background = mLauncher.getBackground();
- assertNotNull("Launcher.getBackground() returned null", background);
+ 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",
- isInBackground(launcher)));
- return background;
+ isInLaunchedApp(launcher)));
+ return launchedAppState;
}
@Test
@@ -239,7 +240,7 @@
// Testing pressHome.
assertTrue("Launcher internal state is not All Apps",
isInState(() -> LauncherState.ALL_APPS));
- assertNotNull("pressHome returned null", mLauncher.pressHome());
+ assertNotNull("pressHome returned null", mLauncher.goHome());
assertTrue("Launcher internal state is not Home",
isInState(() -> LauncherState.NORMAL));
assertNotNull("getHome returned null", mLauncher.getWorkspace());
@@ -253,13 +254,13 @@
startTestActivity(3);
startTestActivity(4);
- Background background = getAndAssertBackground();
- background.quickSwitchToPreviousApp();
+ LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
+ launchedAppState.quickSwitchToPreviousApp();
assertTrue("The first app we should have quick switched to is not running",
isTestActivityRunning(3));
- background = getAndAssertBackground();
- background.quickSwitchToPreviousApp();
+ launchedAppState = getAndAssertLaunchedApp();
+ launchedAppState.quickSwitchToPreviousApp();
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.",
@@ -268,13 +269,13 @@
assertTrue("The second app we should have quick switched to is not running",
isTestActivityRunning(2));
}
- background = getAndAssertBackground();
- background.quickSwitchToPreviousAppSwipeLeft();
+ launchedAppState = getAndAssertLaunchedApp();
+ launchedAppState.quickSwitchToPreviousAppSwipeLeft();
assertTrue("The 2nd app we should have quick switched to is not running",
isTestActivityRunning(3));
- background = getAndAssertBackground();
- background.switchToOverview();
+ launchedAppState = getAndAssertLaunchedApp();
+ launchedAppState.switchToOverview();
}
private boolean isTestActivityRunning(int activityNumber) {
@@ -288,32 +289,22 @@
@PortraitLandscape
public void testQuickSwitchFromHome() throws Exception {
startTestActivity(2);
- mLauncher.pressHome().quickSwitchToPreviousApp();
+ mLauncher.goHome().quickSwitchToPreviousApp();
assertTrue("The most recent task is not running after quick switching from home",
isTestActivityRunning(2));
- getAndAssertBackground();
+ getAndAssertLaunchedApp();
}
- // TODO(b/204830798): test with all navigation modes(add @NavigationModeSwitch annotation)
- // after the bug resolved.
- @Ignore("b/205027405")
@Test
@PortraitLandscape
- @ScreenRecord
+ @NavigationModeSwitch
public void testPressBack() throws Exception {
mLauncher.getWorkspace().switchToAllApps();
mLauncher.pressBack();
mLauncher.getWorkspace();
waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
- AllApps allApps = mLauncher.getWorkspace().switchToAllApps();
- allApps.freeze();
- try {
- allApps.getAppIcon(APP_NAME).dragToWorkspace(false, false);
- } finally {
- allApps.unfreeze();
- }
- mLauncher.getWorkspace().getWorkspaceAppIcon(APP_NAME).launch(getAppPackageName());
+ startAppFast(CALCULATOR_APP_PACKAGE);
mLauncher.pressBack();
mLauncher.getWorkspace();
waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
@@ -322,15 +313,13 @@
@Test
@PortraitLandscape
public void testOverviewForTablet() throws Exception {
- // TODO(b/210158657): Re-enable for OOP
- if (!mLauncher.isTablet() || !TestHelpers.isInLauncherProcess()) {
- return;
- }
+ assumeTrue(mLauncher.isTablet());
+
for (int i = 2; i <= 14; i++) {
startTestActivity(i);
}
- Overview overview = mLauncher.pressHome().switchToOverview();
+ Overview overview = mLauncher.goHome().switchToOverview();
executeOnLauncher(
launcher -> assertTrue("Don't have at least 13 tasks",
getTaskCount(launcher) >= 13));
@@ -345,11 +334,11 @@
// Test opening the task.
overview.getCurrentTask().open();
assertTrue("Test activity didn't open from Overview",
- mDevice.wait(Until.hasObject(By.pkg(getAppPackageName()).text("TestActivity8")),
+ mDevice.wait(Until.hasObject(By.pkg(getAppPackageName()).text("TestActivity10")),
DEFAULT_UI_TIMEOUT));
// Scroll the task offscreen as it is now first
- overview = mLauncher.pressHome().switchToOverview();
+ overview = mLauncher.goHome().switchToOverview();
overview.scrollCurrentTaskOffScreen();
assertTrue("Launcher internal state is not Overview",
isInState(() -> LauncherState.OVERVIEW));
@@ -378,7 +367,7 @@
launcher)) <= 1)));
// Test dismissing all tasks.
- mLauncher.pressHome().switchToOverview().dismissAllTasks();
+ mLauncher.goHome().switchToOverview().dismissAllTasks();
assertTrue("Launcher internal state is not Home",
isInState(() -> LauncherState.NORMAL));
executeOnLauncher(
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
new file mode 100644
index 0000000..1df9c02
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+
+import static junit.framework.TestCase.assertEquals;
+
+import android.content.Intent;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.launcher3.tapl.Taskbar;
+import com.android.launcher3.ui.TaplTestsLauncher3;
+import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
+
+import org.junit.After;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class TaplTestsTaskbar extends AbstractQuickStepTest {
+
+ private static final String TEST_APP_NAME = "LauncherTestApp";
+ private static final String TEST_APP_PACKAGE =
+ getInstrumentation().getContext().getPackageName();
+ private static final String CALCULATOR_APP_PACKAGE =
+ resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
+
+ @Override
+ public void setUp() throws Exception {
+ Assume.assumeTrue(mLauncher.isTablet());
+ super.setUp();
+ mLauncher.useTestWorkspaceLayoutOnReload();
+ TaplTestsLauncher3.initialize(this);
+
+ startAppFast(CALCULATOR_APP_PACKAGE);
+ mLauncher.showTaskbarIfHidden();
+ }
+
+ @After
+ public void tearDown() {
+ mLauncher.useDefaultWorkspaceLayoutOnReload();
+ }
+
+ @Test
+ public void testHideShowTaskbar() {
+ getTaskbar().hide();
+ mLauncher.getLaunchedAppState().showTaskbar();
+ }
+
+ @Test
+ public void testLaunchApp() throws Exception {
+ getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ }
+
+ @Test
+ public void testOpenMenu() throws Exception {
+ getTaskbar().getAppIcon(TEST_APP_NAME).openMenu();
+ }
+
+ @Test
+ public void testLaunchShortcut() throws Exception {
+ getTaskbar().getAppIcon(TEST_APP_NAME)
+ .openDeepShortcutMenu()
+ .getMenuItem("Shortcut 1")
+ .launch(TEST_APP_PACKAGE);
+ }
+
+ @Test
+ @ScreenRecord // b/231615831
+ @PortraitLandscape
+ public void testLaunchAppInSplitscreen() throws Exception {
+ getTaskbar().getAppIcon(TEST_APP_NAME).dragToSplitscreen(
+ TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
+ }
+
+ @Test
+ @ScreenRecord // b/231615831
+ @PortraitLandscape
+ public void testLaunchShortcutInSplitscreen() throws Exception {
+ getTaskbar().getAppIcon(TEST_APP_NAME)
+ .openDeepShortcutMenu()
+ .getMenuItem("Shortcut 1")
+ .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
+ }
+
+ @Test
+ public void testLaunchApp_FromTaskbarAllApps() throws Exception {
+ getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ }
+
+ @Test
+ public void testOpenMenu_FromTaskbarAllApps() throws Exception {
+ getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).openMenu();
+ }
+
+ @Test
+ public void testLaunchShortcut_FromTaskbarAllApps() throws Exception {
+ getTaskbar().openAllApps()
+ .getAppIcon(TEST_APP_NAME)
+ .openDeepShortcutMenu()
+ .getMenuItem("Shortcut 1")
+ .launch(TEST_APP_PACKAGE);
+ }
+
+ @Test
+ @ScreenRecord // b/231615831
+ @PortraitLandscape
+ public void testLaunchAppInSplitscreen_FromTaskbarAllApps() throws Exception {
+ getTaskbar().openAllApps()
+ .getAppIcon(TEST_APP_NAME)
+ .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
+ }
+
+ @Test
+ @ScreenRecord // b/231615831
+ @PortraitLandscape
+ public void testLaunchShortcutInSplitscreen_FromTaskbarAllApps() throws Exception {
+ getTaskbar().openAllApps()
+ .getAppIcon(TEST_APP_NAME)
+ .openDeepShortcutMenu()
+ .getMenuItem("Shortcut 1")
+ .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
+ }
+
+ private Taskbar getTaskbar() {
+ Taskbar taskbar = mLauncher.getLaunchedAppState().getTaskbar();
+ List<String> taskbarIconNames = taskbar.getIconNames();
+ List<String> hotseatIconNames = mLauncher.getHotseatIconNames();
+
+ assertEquals("Taskbar and hotseat icon counts do not match",
+ taskbarIconNames.size(), hotseatIconNames.size());
+
+ for (int i = 0; i < taskbarIconNames.size(); i++) {
+ assertEquals("Taskbar and Hotseat icons do not match",
+ taskbarIconNames, hotseatIconNames);
+ }
+
+ return taskbar;
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java b/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java
index 0f5a1c8..7e408a8 100644
--- a/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java
+++ b/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java
@@ -51,7 +51,7 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
-import com.android.launcher3.tapl.Background;
+import com.android.launcher3.tapl.LaunchedAppState;
import com.android.launcher3.testcomponent.ListViewService;
import com.android.launcher3.testcomponent.ListViewService.SimpleViewsFactory;
import com.android.launcher3.testcomponent.TestCommandReceiver;
@@ -119,13 +119,13 @@
try {
// Go to overview once so that all views are initialized and cached
startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
- mLauncher.getBackground().switchToOverview().dismissAllTasks();
+ mLauncher.getLaunchedAppState().switchToOverview().dismissAllTasks();
// Track view creations
mInitTracker.startTracking();
startTestActivity(2);
- mLauncher.getBackground().switchToOverview();
+ mLauncher.getLaunchedAppState().switchToOverview();
assertEquals("Views inflated during swipe up", 0, mInitTracker.viewInitCount);
} finally {
@@ -197,7 +197,7 @@
addItemToScreen(item);
assertTrue("Widget is not present",
- mLauncher.pressHome().tryGetWidget(info.label, DEFAULT_UI_TIMEOUT) != null);
+ mLauncher.goHome().tryGetWidget(info.label, DEFAULT_UI_TIMEOUT) != null);
int widgetId = item.appWidgetId;
// Verify widget id
@@ -205,23 +205,23 @@
// Go to overview once so that all views are initialized and cached
startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
- mLauncher.getBackground().switchToOverview().dismissAllTasks();
+ mLauncher.getLaunchedAppState().switchToOverview().dismissAllTasks();
// Track view creations
mInitTracker.startTracking();
startTestActivity(2);
- Background background = mLauncher.getBackground();
+ LaunchedAppState launchedAppState = mLauncher.getLaunchedAppState();
// Update widget
updateBeforeSwipeUp.accept(widgetId);
- background.switchToOverview();
+ launchedAppState.switchToOverview();
assertEquals("Views inflated during swipe up", 0, mInitTracker.viewInitCount);
// Widget is updated when going home
mInitTracker.disableLog();
- mLauncher.pressHome();
+ mLauncher.goHome();
verifyWidget(finalWidgetText);
assertNotEquals(1, mInitTracker.viewInitCount);
} finally {
diff --git a/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java b/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
index 9c5cfcd..7d414f4 100644
--- a/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
+++ b/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
@@ -15,16 +15,15 @@
*/
package com.android.quickstep.util;
-import static android.view.Display.DEFAULT_DISPLAY;
-
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.util.ArrayMap;
+import android.util.Pair;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -38,8 +37,11 @@
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.LauncherModelHelper;
import com.android.launcher3.util.ReflectionHelpers;
+import com.android.launcher3.util.RotationUtils;
+import com.android.launcher3.util.WindowBounds;
+import com.android.launcher3.util.window.CachedDisplayInfo;
+import com.android.launcher3.util.window.WindowManagerProxy;
import com.android.quickstep.FallbackActivityInterface;
-import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SystemUiProxy;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
@@ -143,30 +145,34 @@
LauncherModelHelper helper = new LauncherModelHelper();
try {
helper.sandboxContext.allow(SystemUiProxy.INSTANCE);
- helper.sandboxContext.allow(SysUINavigationMode.INSTANCE);
+ int rotation = mDisplaySize.x > mDisplaySize.y
+ ? Surface.ROTATION_90 : Surface.ROTATION_0;
+ CachedDisplayInfo cdi =
+ new CachedDisplayInfo("test-display", mDisplaySize, rotation , new Rect());
+ WindowBounds wm = new WindowBounds(
+ new Rect(0, 0, mDisplaySize.x, mDisplaySize.y),
+ mDisplayInsets);
+ WindowBounds[] allBounds = new WindowBounds[4];
+ for (int i = 0; i < 4; i++) {
+ Rect boundsR = new Rect(wm.bounds);
+ Rect insetsR = new Rect(wm.insets);
- Display display = mock(Display.class);
- doReturn(DEFAULT_DISPLAY).when(display).getDisplayId();
- doReturn(mDisplaySize.x > mDisplaySize.y ? Surface.ROTATION_90 : Surface.ROTATION_0)
- .when(display).getRotation();
- doAnswer(i -> {
- ((Point) i.getArgument(0)).set(mDisplaySize.x, mDisplaySize.y);
- return null;
- }).when(display).getRealSize(any());
- doAnswer(i -> {
- Point smallestSize = i.getArgument(0);
- Point largestSize = i.getArgument(1);
- smallestSize.x = smallestSize.y = Math.min(mDisplaySize.x, mDisplaySize.y);
- largestSize.x = largestSize.y = Math.max(mDisplaySize.x, mDisplaySize.y);
+ 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);
+ }
- smallestSize.x -= mDisplayInsets.left + mDisplayInsets.right;
- largestSize.x -= mDisplayInsets.left + mDisplayInsets.right;
+ WindowManagerProxy wmProxy = mock(WindowManagerProxy.class);
+ doReturn(cdi).when(wmProxy).getDisplayInfo(any(), any());
+ doReturn(wm).when(wmProxy).getRealBounds(any(), any(), any());
- smallestSize.y -= mDisplayInsets.top + mDisplayInsets.bottom;
- largestSize.y -= mDisplayInsets.top + mDisplayInsets.bottom;
- return null;
- }).when(display).getCurrentSizeRange(any(), any());
- DisplayController.Info mockInfo = new Info(helper.sandboxContext, display);
+ ArrayMap<String, Pair<CachedDisplayInfo, WindowBounds[]>> perDisplayBoundsCache =
+ new ArrayMap<>();
+ perDisplayBoundsCache.put(cdi.id, Pair.create(cdi.normalize(), allBounds));
+
+ DisplayController.Info mockInfo = new Info(
+ helper.sandboxContext, mock(Display.class), wmProxy, perDisplayBoundsCache);
DisplayController controller =
DisplayController.INSTANCE.get(helper.sandboxContext);
@@ -174,7 +180,7 @@
ReflectionHelpers.setField(controller, "mInfo", mockInfo);
mDeviceProfile = InvariantDeviceProfile.INSTANCE.get(helper.sandboxContext)
- .getBestMatch(mAppBounds.width(), mAppBounds.height());
+ .getBestMatch(mAppBounds.width(), mAppBounds.height(), rotation);
mDeviceProfile.updateInsets(mLauncherInsets);
TaskViewSimulator tvs = new TaskViewSimulator(helper.sandboxContext,
diff --git a/res/anim-v33/shared_x_axis_activity_close_enter.xml b/res/anim-v33/shared_x_axis_activity_close_enter.xml
new file mode 100644
index 0000000..94ef06c
--- /dev/null
+++ b/res/anim-v33/shared_x_axis_activity_close_enter.xml
@@ -0,0 +1,42 @@
+<?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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:showBackdrop="true">
+
+ <alpha
+ android:fromAlpha="0.0"
+ android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/standard_decelerate"
+ android:startOffset="100"
+ android:duration="350" />
+
+ <translate
+ android:fromXDelta="-25%"
+ android:toXDelta="0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:startOffset="0"
+ android:duration="450" />
+
+</set>
\ No newline at end of file
diff --git a/res/anim-v33/shared_x_axis_activity_close_exit.xml b/res/anim-v33/shared_x_axis_activity_close_exit.xml
new file mode 100644
index 0000000..19eb09e
--- /dev/null
+++ b/res/anim-v33/shared_x_axis_activity_close_exit.xml
@@ -0,0 +1,41 @@
+<?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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false">
+
+ <alpha
+ android:fromAlpha="1.0"
+ android:toAlpha="0.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/standard_accelerate"
+ android:startOffset="0"
+ android:duration="100" />
+
+ <translate
+ android:fromXDelta="0"
+ android:toXDelta="25%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:startOffset="0"
+ android:duration="450" />
+
+</set>
\ No newline at end of file
diff --git a/res/anim-v33/shared_x_axis_activity_open_enter.xml b/res/anim-v33/shared_x_axis_activity_open_enter.xml
new file mode 100644
index 0000000..f699cec
--- /dev/null
+++ b/res/anim-v33/shared_x_axis_activity_open_enter.xml
@@ -0,0 +1,42 @@
+<?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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:showBackdrop="true">
+
+ <alpha
+ android:fromAlpha="0.0"
+ android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/standard_decelerate"
+ android:startOffset="100"
+ android:duration="350" />
+
+ <translate
+ android:fromXDelta="25%"
+ android:toXDelta="0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:startOffset="0"
+ android:duration="450" />
+
+</set>
\ No newline at end of file
diff --git a/res/anim-v33/shared_x_axis_activity_open_exit.xml b/res/anim-v33/shared_x_axis_activity_open_exit.xml
new file mode 100644
index 0000000..85988ec
--- /dev/null
+++ b/res/anim-v33/shared_x_axis_activity_open_exit.xml
@@ -0,0 +1,41 @@
+<?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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false">
+
+ <alpha
+ android:fromAlpha="1.0"
+ android:toAlpha="0.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/standard_accelerate"
+ android:startOffset="0"
+ android:duration="100" />
+
+ <translate
+ android:fromXDelta="0"
+ android:toXDelta="-25%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:startOffset="0"
+ android:duration="450" />
+
+</set>
\ No newline at end of file
diff --git a/res/color-night-v31/all_apps_button_color_2.xml b/res/color-night-v31/all_apps_button_color_2.xml
new file mode 100644
index 0000000..e400543
--- /dev/null
+++ b/res/color-night-v31/all_apps_button_color_2.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:color="@android:color/system_accent2_500"
+ android:lStar="98" />
+</selector>
diff --git a/res/color-night-v31/folder_background_dark.xml b/res/color-night-v31/folder_background_dark.xml
index d607395..696e8ea 100644
--- a/res/color-night-v31/folder_background_dark.xml
+++ b/res/color-night-v31/folder_background_dark.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_neutral2_50"
+ android:color="@android:color/system_neutral2_500"
android:lStar="35" />
</selector>
diff --git a/res/color-night-v31/folder_preview_dark.xml b/res/color-night-v31/folder_preview_dark.xml
index a5bd636..bdd48a2 100644
--- a/res/color-night-v31/folder_preview_dark.xml
+++ b/res/color-night-v31/folder_preview_dark.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_neutral2_50"
+ android:color="@android:color/system_neutral2_500"
android:lStar="30" />
</selector>
diff --git a/res/color-v31/all_apps_button_bg_color.xml b/res/color-v31/all_apps_button_bg_color.xml
new file mode 100644
index 0000000..8959020
--- /dev/null
+++ b/res/color-v31/all_apps_button_bg_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:color="@android:color/system_neutral1_500"
+ android:lStar="98" />
+</selector>
diff --git a/res/color-v31/all_apps_button_color_1.xml b/res/color-v31/all_apps_button_color_1.xml
new file mode 100644
index 0000000..71c7d8d
--- /dev/null
+++ b/res/color-v31/all_apps_button_color_1.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:color="@android:color/system_accent1_500"
+ android:lStar="40" />
+</selector>
diff --git a/res/color-v31/all_apps_button_color_2.xml b/res/color-v31/all_apps_button_color_2.xml
new file mode 100644
index 0000000..608c8a9
--- /dev/null
+++ b/res/color-v31/all_apps_button_color_2.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:color="@android:color/system_accent2_500"
+ android:lStar="48" />
+</selector>
diff --git a/res/color-v31/all_apps_button_color_3.xml b/res/color-v31/all_apps_button_color_3.xml
new file mode 100644
index 0000000..dbb97b1
--- /dev/null
+++ b/res/color-v31/all_apps_button_color_3.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:color="@android:color/system_accent1_500"
+ android:lStar="35" />
+</selector>
diff --git a/res/color-v31/all_apps_button_color_4.xml b/res/color-v31/all_apps_button_color_4.xml
new file mode 100644
index 0000000..d02528f6
--- /dev/null
+++ b/res/color-v31/all_apps_button_color_4.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item
+ android:color="@android:color/system_accent3_500"
+ android:lStar="48" />
+</selector>
diff --git a/res/color-v31/folder_background_light.xml b/res/color-v31/folder_background_light.xml
index e3c7e7d..eb2fdd7 100644
--- a/res/color-v31/folder_background_light.xml
+++ b/res/color-v31/folder_background_light.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_neutral1_50"
+ android:color="@android:color/system_neutral1_500"
android:lStar="98" />
</selector>
diff --git a/res/color-v31/folder_preview_light.xml b/res/color-v31/folder_preview_light.xml
index fe30c87..ed1205e 100644
--- a/res/color-v31/folder_preview_light.xml
+++ b/res/color-v31/folder_preview_light.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:color="@android:color/system_accent2_50"
+ android:color="@android:color/system_accent2_500"
android:lStar="80" />
</selector>
diff --git a/res/color-v31/overview_scrim.xml b/res/color-v31/overview_scrim.xml
index 8079995..212518f 100644
--- a/res/color-v31/overview_scrim.xml
+++ b/res/color-v31/overview_scrim.xml
@@ -14,5 +14,5 @@
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral2_500" android:lStar="87" />
+ <item android:color="@android:color/system_neutral2_200" />
</selector>
diff --git a/res/color-v31/taskbar_background.xml b/res/color-v31/taskbar_background.xml
new file mode 100644
index 0000000..eaf676f
--- /dev/null
+++ b/res/color-v31/taskbar_background.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="@android:color/system_neutral1_500" android:lStar="15" />
+</selector>
diff --git a/res/color/system_shortcut_text.xml b/res/color/system_shortcut_text.xml
new file mode 100644
index 0000000..f9f8239
--- /dev/null
+++ b/res/color/system_shortcut_text.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="?android:attr/textColorTertiary" android:state_enabled="false"/>
+ <item android:color="?android:attr/textColorPrimary"/>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/bg_rounded_corner_bottom_sheet.xml b/res/drawable/bg_rounded_corner_bottom_sheet.xml
index aa49bce..dfcd354 100644
--- a/res/drawable/bg_rounded_corner_bottom_sheet.xml
+++ b/res/drawable/bg_rounded_corner_bottom_sheet.xml
@@ -16,7 +16,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
- <solid android:color="@color/surface" />
+ <solid android:color="?android:attr/colorBackground" />
<corners
android:topLeftRadius="@dimen/dialogCornerRadius"
android:topRightRadius="@dimen/dialogCornerRadius" />
diff --git a/res/drawable/bg_rounded_corner_bottom_sheet_handle.xml b/res/drawable/bg_rounded_corner_bottom_sheet_handle.xml
new file mode 100644
index 0000000..c502178
--- /dev/null
+++ b/res/drawable/bg_rounded_corner_bottom_sheet_handle.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="rectangle" >
+ <solid android:color="?androidprv:attr/colorSurfaceVariant"/>
+ <corners android:radius="@dimen/bottom_sheet_handle_corner_radius" />
+</shape>
diff --git a/res/drawable/drop_target_frame.xml b/res/drawable/drop_target_frame.xml
index 666a96e..9f04103 100644
--- a/res/drawable/drop_target_frame.xml
+++ b/res/drawable/drop_target_frame.xml
@@ -17,6 +17,6 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/transparent" />
- <corners android:radius="28dp" />
+ <corners android:radius="80dp" />
<stroke android:width="2dp" android:color="?attr/workspaceAccentColor" />
</shape>
\ No newline at end of file
diff --git a/res/drawable/gm_edit_24.xml b/res/drawable/gm_edit_24.xml
index 59a0dc2..f741333 100644
--- a/res/drawable/gm_edit_24.xml
+++ b/res/drawable/gm_edit_24.xml
@@ -5,6 +5,6 @@
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/textColorPrimaryInverse"
android:pathData="M20.41,4.94l-1.35,-1.35c-0.78,-0.78 -2.05,-0.78 -2.83,0L3,16.82L3,21h4.18L20.41,7.77c0.79,-0.78 0.79,-2.05 0,-2.83zM6.41,19.06L5,19v-1.36l9.82,-9.82 1.41,1.41 -9.82,9.83z"/>
</vector>
diff --git a/res/drawable/ic_all_apps_button.xml b/res/drawable/ic_all_apps_button.xml
new file mode 100644
index 0000000..5770d3c
--- /dev/null
+++ b/res/drawable/ic_all_apps_button.xml
@@ -0,0 +1,44 @@
+<?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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="80dp"
+ android:height="80dp"
+ android:viewportWidth="80"
+ android:viewportHeight="80"
+ android:theme="@style/AllAppsTheme">
+ <path
+ android:pathData="M40,0.5L40,0.5c21.8,0 39.5,17.7 39.5,39.5l0,0c0,21.8 -17.7,39.5 -39.5,39.5l0,0C18.2,79.5 0.5,61.8 0.5,40l0,0C0.5,18.2 18.2,0.5 40,0.5z"
+ android:fillColor="?attr/allAppsButtonBgColor"/>
+ <path
+ android:pathData="M26.8,32.1m-5.3,0a5.3,5.3 0,1 1,10.6 0a5.3,5.3 0,1 1,-10.6 0"
+ android:fillColor="?attr/allAppsButtonColor1"/>
+ <path
+ android:pathData="M26.8,47.9m-5.3,0a5.3,5.3 0,1 1,10.6 0a5.3,5.3 0,1 1,-10.6 0"
+ android:fillColor="?attr/allAppsButtonColor2"/>
+ <path
+ android:pathData="M40,32.1m-5.3,0a5.3,5.3 0,1 1,10.6 0a5.3,5.3 0,1 1,-10.6 0"
+ android:fillColor="?attr/allAppsButtonColor3"/>
+ <path
+ android:pathData="M40,47.9m-5.3,0a5.3,5.3 0,1 1,10.6 0a5.3,5.3 0,1 1,-10.6 0"
+ android:fillColor="?attr/allAppsButtonColor2"/>
+ <path
+ android:pathData="M53.2,32.1m-5.3,0a5.3,5.3 0,1 1,10.6 0a5.3,5.3 0,1 1,-10.6 0"
+ android:fillColor="?attr/allAppsButtonColor4"/>
+ <path
+ android:pathData="M53.2,47.9m-5.3,0a5.3,5.3 0,1 1,10.6 0a5.3,5.3 0,1 1,-10.6 0"
+ android:fillColor="?attr/allAppsButtonColor2"/>
+</vector>
diff --git a/res/drawable/rounded_action_button.xml b/res/drawable/rounded_action_button.xml
index b9942c0..81e94f7 100644
--- a/res/drawable/rounded_action_button.xml
+++ b/res/drawable/rounded_action_button.xml
@@ -18,10 +18,11 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
+ <solid android:color="?androidprv:attr/colorSurfaceVariant" />
<corners android:radius="@dimen/rounded_button_radius" />
<stroke
android:width="1dp"
- android:color="?androidprv:attr/colorAccentPrimaryVariant" />
+ android:color="?androidprv:attr/colorSurfaceVariant" />
<padding
android:left="@dimen/rounded_button_padding"
android:right="@dimen/rounded_button_padding" />
diff --git a/res/interpolator/back_cancel.xml b/res/interpolator/back_cancel.xml
new file mode 100644
index 0000000..2165457
--- /dev/null
+++ b/res/interpolator/back_cancel.xml
@@ -0,0 +1,24 @@
+<?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
new file mode 100644
index 0000000..f296a82
--- /dev/null
+++ b/res/interpolator/fast_out_extra_slow_in.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<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/standard_accelerate.xml b/res/interpolator/standard_accelerate.xml
new file mode 100644
index 0000000..394393d
--- /dev/null
+++ b/res/interpolator/standard_accelerate.xml
@@ -0,0 +1,22 @@
+<?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/interpolator/standard_decelerate.xml b/res/interpolator/standard_decelerate.xml
new file mode 100644
index 0000000..579f4f5
--- /dev/null
+++ b/res/interpolator/standard_decelerate.xml
@@ -0,0 +1,22 @@
+<?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"
+ android:controlY1="0"
+ android:controlX2="0"
+ android:controlY2="1"/>
\ No newline at end of file
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
index 7f9f63e..d0d82d4 100644
--- a/res/layout/all_apps.xml
+++ b/res/layout/all_apps.xml
@@ -26,6 +26,14 @@
android:saveEnabled="false">
<include
+ layout="@layout/all_apps_bottom_sheet_background"
+ android:visibility="gone" />
+
+ <include
+ layout="@layout/search_results_rv_layout"
+ android:visibility="gone" />
+
+ <include
layout="@layout/all_apps_rv_layout"
android:visibility="gone" />
@@ -33,7 +41,6 @@
android:id="@+id/all_apps_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_below="@id/search_container_all_apps"
android:clipToPadding="false"
android:paddingTop="@dimen/all_apps_header_top_padding"
android:paddingBottom="@dimen/all_apps_header_bottom_padding"
diff --git a/res/layout/all_apps_bottom_sheet_background.xml b/res/layout/all_apps_bottom_sheet_background.xml
new file mode 100644
index 0000000..12b6b7b
--- /dev/null
+++ b/res/layout/all_apps_bottom_sheet_background.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/bottom_sheet_background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/bg_rounded_corner_bottom_sheet">
+
+ <View
+ android:id="@+id/bottom_sheet_handle_area"
+ android:layout_width="match_parent"
+ android:layout_height="36dp" />
+
+ <View
+ android:id="@+id/bottom_sheet_handle"
+ android:layout_width="@dimen/bottom_sheet_handle_width"
+ android:layout_height="@dimen/bottom_sheet_handle_height"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="@dimen/bottom_sheet_handle_margin"
+ android:layout_marginBottom="@dimen/bottom_sheet_handle_margin"
+ android:background="@drawable/bg_rounded_corner_bottom_sheet_handle" />
+</FrameLayout>
diff --git a/res/layout/all_apps_fast_scroller.xml b/res/layout/all_apps_fast_scroller.xml
index 5537bc6..0f1d933 100644
--- a/res/layout/all_apps_fast_scroller.xml
+++ b/res/layout/all_apps_fast_scroller.xml
@@ -21,7 +21,8 @@
android:id="@+id/fast_scroller_popup"
style="@style/FastScrollerPopup"
android:layout_alignParentEnd="true"
- android:layout_below="@+id/search_container_all_apps"
+ android:layout_alignTop="@+id/all_apps_header"
+ android:layout_marginTop="@dimen/all_apps_header_bottom_padding"
android:layout_marginEnd="@dimen/fastscroll_popup_margin" />
<com.android.launcher3.views.RecyclerViewFastScroller
@@ -30,7 +31,8 @@
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
- android:layout_below="@+id/search_container_all_apps"
+ android:layout_alignTop="@+id/all_apps_header"
+ android:layout_marginTop="@dimen/all_apps_header_bottom_padding"
android:layout_marginEnd="@dimen/fastscroll_end_margin"
launcher:canThumbDetach="true" />
diff --git a/res/layout/all_apps_rv_layout.xml b/res/layout/all_apps_rv_layout.xml
index c353b36..26d8ecc 100644
--- a/res/layout/all_apps_rv_layout.xml
+++ b/res/layout/all_apps_rv_layout.xml
@@ -19,7 +19,6 @@
android:id="@+id/apps_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_below="@id/search_container_all_apps"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
android:focusable="true" />
diff --git a/res/layout/all_apps_tabs.xml b/res/layout/all_apps_tabs.xml
index de4a69d..6dcae21 100644
--- a/res/layout/all_apps_tabs.xml
+++ b/res/layout/all_apps_tabs.xml
@@ -20,13 +20,12 @@
android:id="@+id/all_apps_tabs_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_below="@id/search_container_all_apps"
android:layout_gravity="center_horizontal|top"
android:layout_marginTop="@dimen/all_apps_header_pill_height"
android:clipChildren="true"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
- android:paddingTop="@dimen/all_apps_header_top_padding"
+ android:paddingTop="@dimen/all_apps_paged_view_top_padding"
launcher:pageIndicator="@+id/tabs" >
<include layout="@layout/all_apps_rv_layout" />
diff --git a/res/layout/floating_split_select_view.xml b/res/layout/floating_split_select_view.xml
index 8d47f4e..e4ca52e 100644
--- a/res/layout/floating_split_select_view.xml
+++ b/res/layout/floating_split_select_view.xml
@@ -4,7 +4,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <ImageView
+ <com.android.quickstep.views.FloatingTaskThumbnailView
android:id="@+id/thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -14,7 +14,6 @@
android:id="@+id/split_placeholder"
android:layout_width="match_parent"
android:layout_height="@dimen/split_placeholder_size"
- android:background="?android:colorPrimary"
android:visibility="gone" />
</com.android.quickstep.views.FloatingTaskView>
\ No newline at end of file
diff --git a/res/layout/all_apps_content_layout.xml b/res/layout/search_results_rv_layout.xml
similarity index 64%
rename from res/layout/all_apps_content_layout.xml
rename to res/layout/search_results_rv_layout.xml
index 5698977..567cb5f 100644
--- a/res/layout/all_apps_content_layout.xml
+++ b/res/layout/search_results_rv_layout.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2020 The Android Open Source Project
+ ~ 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.
@@ -14,14 +14,11 @@
~ 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/apps_list_view_override"
+<com.android.launcher3.allapps.SearchRecyclerView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/search_results_list_view"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_below="@id/search_container_all_apps"
+ android:layout_height="wrap_content"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
- android:focusable="true"
- android:layout_marginTop="@dimen/all_apps_header_top_padding"
- android:orientation="vertical">
-</LinearLayout>
+ android:focusable="true" />
diff --git a/res/layout/secondary_launcher.xml b/res/layout/secondary_launcher.xml
index b15a320..635db14 100644
--- a/res/layout/secondary_launcher.xml
+++ b/res/layout/secondary_launcher.xml
@@ -41,7 +41,8 @@
android:contentDescription="@string/all_apps_button_label"
android:onClick="onAppsButtonClicked" />
- <com.android.launcher3.allapps.AllAppsContainerView
+ <view
+ class="com.android.launcher3.allapps.SecondaryLauncherAllAppsContainerView"
android:id="@+id/apps_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -55,6 +56,14 @@
android:visibility="invisible" >
<include
+ layout="@layout/all_apps_bottom_sheet_background"
+ android:visibility="gone" />
+
+ <include
+ layout="@layout/search_results_rv_layout"
+ android:visibility="gone" />
+
+ <include
layout="@layout/all_apps_rv_layout"
android:visibility="gone" />
@@ -121,5 +130,5 @@
android:textSize="16sp" />
<include layout="@layout/all_apps_fast_scroller" />
- </com.android.launcher3.allapps.AllAppsContainerView>
+ </view>
</com.android.launcher3.secondarydisplay.SecondaryDragLayer>
\ No newline at end of file
diff --git a/res/layout/system_shortcut_content.xml b/res/layout/system_shortcut_content.xml
index e693dbd..ddcef09 100644
--- a/res/layout/system_shortcut_content.xml
+++ b/res/layout/system_shortcut_content.xml
@@ -33,7 +33,7 @@
android:maxLines="2"
android:ellipsize="end"
android:hyphenationFrequency="full"
- android:textColor="?android:attr/textColorPrimary"
+ android:textColor="@color/system_shortcut_text"
launcher:iconDisplay="shortcut_popup"
launcher:layoutHorizontal="true"
android:focusable="false" />
@@ -44,5 +44,5 @@
android:layout_height="@dimen/system_shortcut_icon_size"
android:layout_marginStart="@dimen/system_shortcut_margin_start"
android:layout_gravity="start|center_vertical"
- android:backgroundTint="?android:attr/textColorPrimary"/>
+ android:backgroundTint="@color/system_shortcut_text"/>
</merge>
diff --git a/res/layout/widget_cell_content.xml b/res/layout/widget_cell_content.xml
index 0f6fc6c..feebfe1 100644
--- a/res/layout/widget_cell_content.xml
+++ b/res/layout/widget_cell_content.xml
@@ -22,7 +22,7 @@
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"
- android:importantForAccessibility="no"
+ android:importantForAccessibility="noHideDescendants"
android:layout_marginVertical="8dp">
<!-- The image of the widget. This view does not support padding. Any placement adjustment
should be done using margins. Width & height are set at runtime after scaling the
diff --git a/res/layout/widgets_bottom_sheet_content.xml b/res/layout/widgets_bottom_sheet_content.xml
index 1a2cfc6..a5f72ef 100644
--- a/res/layout/widgets_bottom_sheet_content.xml
+++ b/res/layout/widgets_bottom_sheet_content.xml
@@ -19,16 +19,16 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_rounded_corner_bottom_sheet"
- android:paddingTop="16dp"
+ android:paddingTop="@dimen/bottom_sheet_handle_margin"
android:orientation="vertical">
<View
android:id="@+id/collapse_handle"
- android:layout_width="48dp"
- android:layout_height="2dp"
+ android:layout_width="@dimen/bottom_sheet_handle_width"
+ android:layout_height="@dimen/bottom_sheet_handle_height"
android:layout_gravity="center_horizontal"
- android:layout_marginBottom="16dp"
+ android:layout_marginBottom="@dimen/bottom_sheet_handle_margin"
android:visibility="gone"
- android:background="?android:attr/textColorSecondary"/>
+ android:background="@drawable/bg_rounded_corner_bottom_sheet_handle"/>
<TextView
style="@style/TextHeadline"
android:id="@+id/title"
diff --git a/res/layout/widgets_full_sheet.xml b/res/layout/widgets_full_sheet.xml
index 309dc42..e3f1fca 100644
--- a/res/layout/widgets_full_sheet.xml
+++ b/res/layout/widgets_full_sheet.xml
@@ -31,20 +31,20 @@
<View
android:id="@+id/collapse_handle"
- android:layout_width="48dp"
- android:layout_height="2dp"
- android:layout_marginTop="16dp"
+ android:layout_width="@dimen/bottom_sheet_handle_width"
+ android:layout_height="@dimen/bottom_sheet_handle_height"
+ android:layout_marginTop="@dimen/bottom_sheet_handle_margin"
android:layout_centerHorizontal="true"
- android:background="?android:attr/textColorSecondary"/>
+ android:background="@drawable/bg_rounded_corner_bottom_sheet_handle"/>
<TextView
+ style="@style/PrimaryHeadline"
android:id="@+id/no_widgets_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone"
- android:fontFamily="sans-serif-medium"
- android:textSize="20sp"
+ android:textSize="18sp"
android:layout_below="@id/search_and_recommendations_container"
tools:text="No widgets available" />
diff --git a/res/layout/widgets_list_row_header.xml b/res/layout/widgets_list_row_header.xml
index 8f0eae7..3cdc2e8 100644
--- a/res/layout/widgets_list_row_header.xml
+++ b/res/layout/widgets_list_row_header.xml
@@ -21,7 +21,10 @@
android:layout_height="wrap_content"
android:paddingVertical="@dimen/widget_list_header_view_vertical_padding"
android:orientation="horizontal"
- launcher:appIconSize="48dp">
+ android:importantForAccessibility="yes"
+ android:focusable="true"
+ launcher:appIconSize="48dp"
+ android:descendantFocusability="afterDescendants">
<ImageView
android:id="@+id/app_icon"
@@ -32,14 +35,11 @@
tools:src="@drawable/ic_corp"/>
<LinearLayout
- android:id="@+id/app_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
- android:orientation="vertical"
- android:focusable="true"
- android:descendantFocusability="afterDescendants">
+ android:orientation="vertical">
<TextView
android:id="@+id/app_title"
diff --git a/res/layout/work_apps_edu.xml b/res/layout/work_apps_edu.xml
index 1517087..eeb7f4f 100644
--- a/res/layout/work_apps_edu.xml
+++ b/res/layout/work_apps_edu.xml
@@ -16,40 +16,52 @@
<com.android.launcher3.allapps.WorkEduCard xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
+ android:paddingTop="@dimen/work_edu_card_margin"
+ android:paddingBottom="@dimen/work_edu_card_bottom_margin"
android:gravity="center">
-
- <LinearLayout
+ <RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingHorizontal="@dimen/work_card_padding_horizontal"
- android:paddingVertical="@dimen/work_card_padding_horizontal"
+ android:orientation="horizontal"
android:background="@drawable/work_card"
android:layout_gravity="center_horizontal"
- android:gravity="center"
+ android:paddingEnd="@dimen/work_card_margin"
+ android:paddingStart="@dimen/work_card_margin"
+ android:paddingTop="@dimen/work_card_margin"
android:id="@+id/wrapper">
-
<TextView
style="@style/PrimaryHeadline"
android:textColor="?android:attr/textColorPrimary"
android:id="@+id/work_apps_paused_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginBottom="@dimen/work_card_padding_horizontal"
+ android:layout_marginBottom="@dimen/work_card_margin"
+ android:layout_marginEnd="@dimen/work_card_margin"
android:text="@string/work_profile_edu_work_apps"
- android:textAlignment="center"
- android:textSize="20sp" />
-
- <Button
+ android:textDirection="locale"
+ android:textSize="18sp" />
+ <RelativeLayout
android:layout_width="match_parent"
- android:layout_height="@dimen/work_card_button_height"
- android:id="@+id/action_btn"
- android:textColor="?attr/workProfileOverlayTextColor"
- android:text="@string/work_profile_edu_accept"
- android:textAlignment="center"
- android:background="@drawable/rounded_action_button"
+ android:layout_height="@dimen/padded_rounded_button_height"
+ android:orientation="horizontal">
+ <FrameLayout
+ android:layout_width="@dimen/rounded_button_width"
+ android:layout_height="@dimen/rounded_button_width"
+ android:layout_alignParentEnd="true"
+ android:background="@drawable/rounded_action_button"
+ android:padding="@dimen/rounded_button_padding">
+ <ImageButton
+ android:id="@+id/action_btn"
+ android:layout_width="@dimen/x_icon_size"
+ android:layout_height="@dimen/x_icon_size"
+ android:layout_gravity="center"
+ android:padding="@dimen/x_icon_padding"
+ android:contentDescription="@string/accessibility_close"
+ android:src="@drawable/ic_remove_no_shadow" />
+ </FrameLayout>
+ </RelativeLayout>
+ </RelativeLayout>
- android:textSize="14sp" />
- </LinearLayout>
+
+
</com.android.launcher3.allapps.WorkEduCard>
\ No newline at end of file
diff --git a/res/layout/work_mode_fab.xml b/res/layout/work_mode_fab.xml
index 04faa15..d2fa5fa 100644
--- a/res/layout/work_mode_fab.xml
+++ b/res/layout/work_mode_fab.xml
@@ -21,12 +21,14 @@
android:layout_width="wrap_content"
android:gravity="center"
android:includeFontPadding="false"
+ android:textDirection="locale"
android:drawableTint="@color/all_apps_tab_text"
android:textColor="@color/all_apps_tab_text"
android:textSize="14sp"
android:background="@drawable/work_apps_toggle_background"
android:drawablePadding="8dp"
android:drawableStart="@drawable/ic_corp_off"
- android:layout_marginBottom="@dimen/work_fab_margin"
- android:layout_marginEnd="@dimen/work_fab_margin"
+ android:layout_marginBottom="@dimen/work_fab_margin_bottom"
+ android:paddingLeft="@dimen/work_mode_fab_padding"
+ android:paddingRight="@dimen/work_mode_fab_padding"
android:text="@string/work_apps_pause_btn_text" />
\ No newline at end of file
diff --git a/res/raw/downgrade_schema.json b/res/raw/downgrade_schema.json
index 14eac9f..b8d0c6f 100644
--- a/res/raw/downgrade_schema.json
+++ b/res/raw/downgrade_schema.json
@@ -2,8 +2,9 @@
// Note: Comments are not supported in JSON schema, but android parser is lenient.
// Maximum DB version supported by this schema
- "version" : 30,
+ "version" : 31,
+ "downgrade_to_30" : [],
"downgrade_to_29" : [],
"downgrade_to_28" : [
"ALTER TABLE favorites RENAME TO temp_favorites;",
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 18fa12f..89b62ee 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d breed by %2$d hoog"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-legstuk"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Raak en hou die legstuk om dit op die Tuisskerm rond te beweeg"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Voeg by Tuisskerm"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Werk"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Gesprekke"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Nuttige inligting binne jou bereik"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Jy kan legstukke by jou tuisskerm voeg om inligting te kry sonder om programme oop te maak"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Het dit"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Verander legstukinstellings"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Kennisgewings"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Raak en hou om \'n kortpad te skuif."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Dubbeltik en hou om \'n kortpad te skuif of gebruik gepasmaakte handelinge."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Geen plek op hierdie tuisskerm nie"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Geen plek op hierdie tuisskerm nie"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Geen plek meer in die Gunstelinge-laai nie"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Programmelys"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Soekresultate"</string>
@@ -75,14 +75,14 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Deïnstalleer"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Programinligting"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Installeer"</string>
- <string name="dismiss_prediction_label" msgid="3357562989568808658">"Moenie program voorstel nie"</string>
+ <string name="dismiss_prediction_label" msgid="3357562989568808658">"Moenie voorstel nie"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Vasspeldvoorspelling"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"installeer kortpaaie"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Laat \'n program toe om kortpaaie by te voeg sonder gebruikerinmenging."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"lees Tuis-instellings en -kortpaaie"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Laat die program toe om die instellings en kortpaaie in Tuis te lees."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"skryf Tuis-instellings en -kortpaaie"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Laat die program toe om die instellings en kortpaaie in Tuis te verander."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"lees tuis-instellings en -kortpaaie"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Dit is \'n stelselprogram en kan nie gedeïnstalleer word nie."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Wysig naam"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Het <xliff:g id="APP_NAME">%1$s</xliff:g> gedeaktiveer"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} het # kennisgewing}other{{app_name} het # kennisgewings}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} het # kennisgewing}other{{app_name} het # kennisgewings}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Bladsy %1$d van %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Tuisskerm %1$d van %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nuwe tuisskermbladsy"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Muurpapier en styl"</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="7728578836261442095">"Laat toe dat tuisskerm gedraai word"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Laat toe dat tuisskerm gedraai word"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Wanneer foon gedraai word"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Kennisgewingkolle"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Aan"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Skakel programkennisgewings vir <xliff:g id="NAME">%1$s</xliff:g> aan om kennisgewingkolle te sien"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Verander instellings"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Wys kennisgewingkolle"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Voeg programikone by tuisskerm"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Ontwikkelaaropsies"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Voeg programikone by tuisskerm"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Vir nuwe programme"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Onbekend"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Verwyder"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installeer tans; <xliff:g id="PROGRESS">%2$s</xliff:g> voltooi"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> laai tans af, <xliff:g id="PROGRESS">%2$s</xliff:g> voltooid"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> wag tans om te installeer"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Programopdatering word vereis"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Die program vir hierdie ikoon is nie opgedateer nie. Jy kan dit handmatig opdateer om hierdie kortpad weer te aktiveer, of die ikoon verwyder."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Dateer op"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Verwyder"</string>
<string name="widgets_list" msgid="796804551140113767">"Legstukkelys"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Legstukkelys is toegemaak"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Voeg by tuisskerm"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Voeg by tuisskerm"</string>
<string name="action_move_here" msgid="2170188780612570250">"Skuif item hierheen"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item is by tuisskerm gevoeg"</string>
<string name="item_removed" msgid="851119963877842327">"Item is verwyder"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Item by vouer gevoeg"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Skep vouer met: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Vouer geskep"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Skuif na tuisskerm"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Skuif na tuisskerm"</string>
<string name="action_resize" msgid="1802976324781771067">"Verander grootte"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Vermeerder breedte"</string>
<string name="action_increase_height" msgid="459390020612501122">"Vermeerder hoogte"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Skakel werkprogramme af"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Misluk: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index f75e7e1..ec69acb 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"በመነሻ ገጽ አካባቢ ላይ ለማንቀሳቀስ ነክተው ይያዙት"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"ወደ መነሻ ገጽ አክል"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ምግብር}one{# ምግብሮች}other{# ምግብሮች}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# አቋራጭ}one{# አቋራጭ}other{# አቋራጮች}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ስራ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"ውይይቶች"</string>
<string name="widget_education_header" msgid="4874760613775913787">"በጣቶችዎ ጫፎች ላይ ጠቃሚ መረጃ"</string>
- <string name="widget_education_content" msgid="745542879510751525">"መተግበሪያዎችን ሳይከፍቱ መረጃ ለማግኘት በመነሻ ማያ ገጽዎ ላይ ምግብሮችን ማከል ይችላሉ"</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>
@@ -65,7 +65,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="6692471482459245734">"በዚህ የመነሻ ማያ ገጽ ላይ ምንም ክፍል የለም"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"የፒን ግምት"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"አቋራጮችን ይጭናል"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"መተግበሪያው ያለተጠቃሚ ጣልቃ ገብነት አቋራጭ እንዲያክል ያስችለዋል።"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"የመነሻ ቅንብሮች እና አቋራጮችን ያነባል"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"መተግበሪያው በመነሻ ውስጥ ያሉ ቅንብሮችን እና አቋራጮችን እንዲያነብ ያስችለዋል።"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"የመነሻ ቅንብሮችን እና አቋራጮችን ይጽፋል"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"መተግብሪያው ቅንብሮችን እና አቋራጮችን በመነሻ ውስጥ እንዲቀይራቸው ያስችለዋል።"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"የመነሻ ቅንብሮች እና አቋራጮችን ያነባል"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ይህ የስርዓት መተግበሪያ ነው እና ማራገፍ አይቻልም።"</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name}፣ # ማሳወቂያ አለው}one{{app_name}፣ # ማሳወቂያ አለው}other{{app_name}፣ # ማሳወቂያዎች አሉት}}"</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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ልጣፍ እና ቅጥ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"የመነሻ ቅንብሮች"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"በእርስዎ አስተዳዳሪ የተሰናከለ"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"የመነሻ ማያ ገጽ ማሽከርከርን ይፍቀዱ"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"የማሳወቂያ ነጥቦችን ለማሳየት የመተግብሪያ ማሳወቂያዎችን ለ<xliff:g id="NAME">%1$s</xliff:g> ያብሩ"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ቅንብሮችን ቀይር"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"የማሳወቂያ ነጥቦችን አሳይ"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"የመተግበሪያ አዶዎችን ወደ መነሻ ገጹ ያክሉ"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"የገንቢ አማራጮች"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"የመተግበሪያ አዶዎችን ወደ መነሻ ገጹ ያክሉ"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ለአዲስ መተግበሪያዎች"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"የማይታወቅ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"አስወግድ"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"አዘምን"</string>
+ <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="8902165848117513641">"ወደ መነሻ ማያ ገጽ ያክሉ"</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_removed" msgid="851119963877842327">"ንጥል ነገር ተንቀሳቅሷል"</string>
@@ -141,7 +146,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="1603837886334246317">"ወደ መነሻ ማያ ገጽ አንቀሳቅስ"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"ገባኝ"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"የሥራ መተግበሪያዎችን ያጥፉ"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"የሥራ መተግበሪያዎችን ባሉበት አቁም"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"የሥራ መተግበሪያዎችን ያብሩ"</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="remote_action_failed" msgid="1383965239183576790">"አልተሳካም፦ <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 1fcce91..fe076c9 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"يمكنك النقر على الأداة مع الاستمرار لتحريكها على الشاشة الرئيسية."</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"إضافة إلى الشاشة الرئيسية"</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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"أدوات العمل"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"المحادثات"</string>
<string name="widget_education_header" msgid="4874760613775913787">"معلومات مفيدة في متناول يديك"</string>
- <string name="widget_education_content" msgid="745542879510751525">"للحصول على معلومات بدون فتح التطبيقات، يمكنك إضافة التطبيقات المصغّرة إلى الشاشة الرئيسية."</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>
@@ -65,7 +65,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="6692471482459245734">"ما مِن مساحة على هذه الشاشة الرئيسية."</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"تثبيت التطبيق المتوقّع"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"تثبيت اختصارات"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"للسماح لتطبيق ما بإضافة اختصارات بدون تدخل المستخدم."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"قراءة إعدادات واختصارات الشاشة الرئيسية"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"للسماح للتطبيق بقراءة الإعدادات والاختصارات في الشاشة الرئيسية."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"كتابة إعدادات واختصارات الشاشة الرئيسية"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"للسماح للتطبيق بتغيير الإعدادات والاختصارات في الشاشة الرئيسية."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"الاطلاع على الإعدادات والاختصارات على الشاشة الرئيسية"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"هذا تطبيق نظام وتتعذر إزالته."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{هناك إشعار واحد في تطبيق {app_name}.}zero{هناك # إشعار في تطبيق {app_name}.}two{هناك إشعاران في تطبيق {app_name}.}few{هناك # إشعارات في تطبيق {app_name}.}many{هناك # إشعارًا في تطبيق {app_name}.}other{هناك # إشعار في تطبيق {app_name}.}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{هناك إشعار واحد في التطبيق {app_name}.}zero{هناك # إشعار في التطبيق {app_name}.}two{هناك إشعارَان في التطبيق {app_name}.}few{هناك # إشعارات في التطبيق {app_name}.}many{هناك # إشعارًا في التطبيق {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>
@@ -102,10 +102,10 @@
<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="settings_button_text" msgid="8873672322605444408">"إعدادات الشاشة الرئيسية"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"أوقف المشرف هذه الميزة"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"السماح بتدوير الشاشة الرئيسية"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"لعرض نقاط الإشعارات، يجب تفعيل إشعارات التطبيق في <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"تغيير الإعدادات"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"عرض نقاط الإشعارات"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"إضافة رموز التطبيقات إلى الشاشة الرئيسية"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"خيارات المطوّرين"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"إضافة رموز التطبيقات إلى الشاشة الرئيسية"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"للتطبيقات الجديدة"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"غير معروفة"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"إزالة"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"تحديث"</string>
+ <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="8902165848117513641">"الإضافة إلى شاشة الصفحة الرئيسية"</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_removed" msgid="851119963877842327">"تمّت إزالة العنصر."</string>
@@ -141,7 +146,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="1603837886334246317">"نقل إلى الشاشة الرئيسية"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"حسنًا"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"إيقاف تطبيقات العمل"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"إيقاف تطبيقات العمل مؤقتًا"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"تفعيل تطبيقات العمل"</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="remote_action_failed" msgid="1383965239183576790">"تعذَّر <xliff:g id="WHAT">%1$s</xliff:g>."</string>
</resources>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 5dc35cb..ab9ef5d 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"ৱিজেটটো গৃহ স্ক্ৰীনৰ আশে-পাশে নিবলৈ সেইটোত স্পৰ্শ কৰি ধৰি ৰাখক"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"গৃহ স্ক্ৰীনত যোগ কৰক"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# টা ৱিজেট}one{# টা ৱিজেট}other{# টা ৱিজেট}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# টা শ্বৰ্টকাট}one{# টা শ্বৰ্টকাট}other{# টা শ্বৰ্টকাট}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"কৰ্মস্থান"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"বাৰ্তালাপ"</string>
<string name="widget_education_header" msgid="4874760613775913787">"আপোনাৰ আঙুলিৰে টিপতে উপযোগী তথ্য পাওক"</string>
- <string name="widget_education_content" msgid="745542879510751525">"এপ্ নোখোলাকৈ তথ্য পাবলৈ আপুনি নিজৰ গৃহ স্ক্ৰীনত ৱিজেট যোগ দিব পাৰে"</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>
@@ -65,7 +65,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="6692471482459245734">"এই গৃহ স্ক্ৰীনত খালী ঠাই নাই"</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>
@@ -73,16 +73,16 @@
<string name="all_apps_button_work_label" msgid="7270707118948892488">"কৰ্মস্থানৰ এপৰ তালিকা"</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="app_info_drop_target_label" msgid="692894985365717661">"এপ্ সম্পৰ্কীয় তথ্য"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ইনষ্টল কৰক"</string>
- <string name="dismiss_prediction_label" msgid="3357562989568808658">"এপৰ পৰামৰ্শ নিদিব"</string>
+ <string name="dismiss_prediction_label" msgid="3357562989568808658">"পৰামৰ্শ নিদিব"</string>
<string name="pin_prediction" msgid="4196423321649756498">"পূৰ্বানুমান কৰা এপ্টো পিন কৰক"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"শ্বৰ্টকাট ইনষ্টল কৰিব পাৰে"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ব্য়ৱহাৰকাৰীৰ হস্তক্ষেপ অবিহনেই কোনো এপক শ্বৰ্টকাটবোৰ যোগ কৰাৰ অনুমতি দিয়ে।"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"গৃহ ছেটিং আৰু শ্বৰ্টকাটবোৰ পঢ়িব পাৰে"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"এপটোক গৃহ পৃষ্ঠাত ছেটিং আৰু শ্বৰ্টকাটসমূহ পঢ়াৰ অনুমতি দিয়ে।"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"গৃহ ছেটিং আৰু শ্বৰ্টকাটবোৰ লিখিব পাৰে"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"এপটোক গৃহ পৃষ্ঠাত ছেটিং আৰু শ্বৰ্টকাটসমূহ সলনি কৰাৰ অনুমতি দিয়ে।"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"গৃহ স্ক্ৰীনত ছেটিং আৰু শ্বৰ্টকাটসমূহ পঢ়া"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"এইটো এটা ছিষ্টেম এপ আৰু ইয়াক আনইনষ্টল কৰিব নোৱৰি"</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name}ৰ # টা জাননী আছে}one{{app_name}ৰ # টা জাননী আছে}other{{app_name}ৰ # টা জাননী আছে}}"</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">"%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>
@@ -105,16 +105,17 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ৱালপেপাৰ আৰু শৈলী"</string>
<string name="settings_button_text" msgid="8873672322605444408">"গৃহ ছেটিং"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"আপোনাৰ প্ৰশাসকে অক্ষম কৰি ৰাখিছে"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"গৃহ স্ক্ৰীন ঘূৰোৱাৰ অনুমতি দিয়ক"</string>
+ <string name="allow_rotation_title" msgid="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_off" msgid="1760796511504341095">"অফ আছে"</string>
- <string name="title_missing_notification_access" msgid="7503287056163941064">"জাননী চাবলৈ অনুমতিৰ প্ৰয়োজন"</string>
+ <string name="title_missing_notification_access" msgid="7503287056163941064">"জাননীৰ এক্সেছৰ প্ৰয়োজন"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"জাননী সম্পৰ্কীয় বিন্দুবোৰ দেখুৱাবলৈ <xliff:g id="NAME">%1$s</xliff:g>ৰ বাবে এপৰ জাননীসমূহ অন কৰক"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ছেটিং সলনি কৰক"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"জাননী বিন্দু দেখুৱাওক"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"গৃহ স্ক্ৰীনত এপ্ চিহ্নসমূহ যোগ দিয়ক"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"বিকাশকৰ্তাৰ বিকল্পসমূহ"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"গৃহ স্ক্ৰীনত এপৰ চিহ্ন যোগ দিয়ক"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"নতুন এপসমূহৰ বাবে"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"অজ্ঞাত"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"আঁতৰাওক"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"আপডে’ট কৰক"</string>
+ <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="8902165848117513641">"গৃহ স্ক্ৰীনত যোগ দিয়ক"</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_removed" msgid="851119963877842327">"বস্তুটো আঁতৰোৱা হ’ল"</string>
@@ -141,7 +146,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="1603837886334246317">"গৃহ স্ক্ৰীনলৈ স্থানান্তৰ কৰক"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"বুজি পালোঁ"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"কৰ্মস্থানৰ এপ্সমূহ অফ কৰক"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"কৰ্মস্থানৰ এপ্ পজ কৰক"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"কৰ্মস্থানৰ এপ্সমূহ অন কৰক"</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="remote_action_failed" msgid="1383965239183576790">"বিফল: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index c2ca56d..ad72424 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%2$d hündürlük %1$d enində"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidceti"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Əsas ekranda hərəkət etdirmək üçün vidcetə toxunub saxlayın"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Əsas ekrana əlavə edin"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<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_education_header" msgid="4874760613775913787">"Faydalı məlumatlar barmaqlarınızın ucunda"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Tətbiqləri açmadan məlumat almaq üçün Əsas ekrana vidcet əlavə edə bilərsiniz"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Anladım"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Vidcet ayarlarını dəyişin"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Bildirişlər"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Qısayolu daşımaq üçün toxunub saxlayın."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Qısayolu daşımaq üçün iki dəfə toxunub saxlayın və ya fərdi əməliyyatlardan istifadə edin."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Bu Əsas ekranda yer qalmayıb"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Bu Əsas ekranda yer qalmayıb"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Favoritlər-də yer yoxdur"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Tətbiq siyahısı"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Axtarış nəticələri"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Proqnozlaşdırılan tətbiqi bərkidin"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"qısayolları quraşdır"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Tətbiqə istifadəçi müdaxiləsi olmadan qısayolları əlavə etməyə icazə verir."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"Əsas Səhifə ayarlarını və qısayolları oxuyun"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Tətbiqə Əsas Səhifədə parametrləri və qısayolları oxumağa icazə verir."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"Əsas Səhifə ayarlarını və qısayolları yazın"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Tətbiqə Əsas Səhifədə ayarları və qısayolları dəyişməyə icazə verir."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"Əsas səhifə ayarlarını və qısayollarını oxumaq"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Bu sistem tətbiqi olduğu üçün sistemdən silinə bilməz."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Adı redaktə edin"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> deaktiv edildi"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} tətbiqində # bildiriş var}other{{app_name} tətbiqində # bildiriş var}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} tətbiqində # bildiriş var}other{{app_name} tətbiqində # bildiriş var}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Səhifə %1$d of %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Əsas Səhifə ekranı %1$d of %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Yeni əsas ekran səhifəsi"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Divar kağızı və üslub"</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="7728578836261442095">"Əsas ekran çevrilsin"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Əsas ekran çevrilsin"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Telefon çevrilən zaman"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Bildiriş nöqtələri"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Aktiv"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Bildiriş Nöqtələrini göstərmək üçün <xliff:g id="NAME">%1$s</xliff:g> bildirişlərini aktiv edin"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Ayarları dəyişin"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Bildiriş nöqtələrini göstərin"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Əsas ekrana nişanlar əlavə edilsin"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Developer Seçimləri"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Əsas ekrana nişanlar əlavə edilsin"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Yeni tətbiqlər üçün"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Naməlum"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Yığışdır"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> quraşdırır, <xliff:g id="PROGRESS">%2$s</xliff:g> tamamlanıb"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> endirilir, <xliff:g id="PROGRESS">%2$s</xliff:g> tamamlandı"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> yüklənmək üçün gözləyir"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Tətbiqin güncəllənməsi tələb edilir"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Bu ikona üçün tətbiq güncəllənməyib. Bu qısayolu yenidən aktivləşdirmək üçün manual olaraq güncəlləyə və ya ikonanı silə bilərsiniz."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Güncəlləyin"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Silin"</string>
<string name="widgets_list" msgid="796804551140113767">"Vidcet siyahısı"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Vidcet siyahısı bağlandı"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Əsas ekrana əlavə edin"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Əsas ekrana əlavə edin"</string>
<string name="action_move_here" msgid="2170188780612570250">"Elementi bura köçürün"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Element əsas ekrana əlavə edildi"</string>
<string name="item_removed" msgid="851119963877842327">"Element silindi"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Element qovluğa əlavə edildi"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Qovluq yaradın: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Qovluq yaradıldı"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Əsas ekrana köçürün"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Əsas ekrana köçürün"</string>
<string name="action_resize" msgid="1802976324781771067">"Ölçüsünü dəyişin"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Eni artırın"</string>
<string name="action_increase_height" msgid="459390020612501122">"Hündürlüyü artırın"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"İş tətbiqlərini deaktiv edin"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Alınmadı: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index f1dcef4..d7e85d9 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"širina od %1$d i visina od %2$d"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidžet"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Dodirnite i zadržite vidžet da biste ga pomerali po početnom ekranu"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Dodaj na početni ekran"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Posao"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Konverzacije"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Korisne informacije nadohvat ruke"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Da biste pronašli informacije bez otvaranja aplikacija, možete da dodate vidžete na početni ekran"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Važi"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Promenite podešavanja vidžeta"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Obaveštenja"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Dodirnite i zadržite radi pomeranja prečice."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Dvaput dodirnite i zadržite da biste pomerali prečicu ili koristite prilagođene radnje."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Nema prostora na ovom početnom ekranu"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Nema mesta na ovom početnom ekranu"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Nema više prostora na traci Omiljeno"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Lista aplikacija"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Rezultati pretrage"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Zakači predviđanje"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instaliranje prečica"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Dozvoljava aplikaciji da dodaje prečice bez intervencije korisnika."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"čitanje podešavanja i prečica na početnom ekranu"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Dozvoljava aplikaciji da čita podešavanja i prečice na početnom ekranu."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"upisivanje podešavanja i prečica na početnom ekranu"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Dozvoljava aplikaciji da menja podešavanja i prečice na početnom ekranu."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"čitanje podešavanja i prečica na početnom ekranu"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ovo je sistemska aplikacija i ne može da se deinstalira."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Izmenite naziv"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je onemogućena"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name}, ima # obaveštenje}one{{app_name}, ima # obaveštenje}few{{app_name}, ima # obaveštenja}other{{app_name}, ima # obaveštenja}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name}, ima # obaveštenje}one{{app_name}, ima # obaveštenje}few{{app_name}, ima # obaveštenja}other{{app_name}, ima # obaveštenja}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d. stranica od %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%1$d. početni ekran od %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nova stranica početnog ekrana"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Pozadina i stil"</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="7728578836261442095">"Dozvoli rotaciju početnog ekrana"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Dozvoli rotaciju početnog ekrana"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kada se telefon rotira"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Tačke za obaveštenja"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Uključeno"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Da biste prikazali tačke za obaveštenja, uključite obaveštenja za aplikaciju <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Promenite podešavanja"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Prikazuj tačke za obaveštenja"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Dodaj ikone aplikacija na početni ekran"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Opcije za programera"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Dodaj ikone aplikacija na početni ekran"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Za nove aplikacije"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Nepoznato"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Ukloni"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> se instalira, <xliff:g id="PROGRESS">%2$s</xliff:g> gotovo"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> se preuzima, završeno je <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> čeka na instaliranje"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Treba da ažurirate aplikaciju"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Aplikacija za ovu ikonu nije ažurirana. Možete da je ručno ažurirate da biste ponovo omogućili ovu prečicu ili uklonite ikonu."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Ažuriraj"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Ukloni"</string>
<string name="widgets_list" msgid="796804551140113767">"Lista vidžeta"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Lista vidžeta je zatvorena"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Dodajte na početni ekran"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Dodajte na početni ekran"</string>
<string name="action_move_here" msgid="2170188780612570250">"Premesti stavku ovde"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Stavka je dodata na početni ekran"</string>
<string name="item_removed" msgid="851119963877842327">"Stavka je uklonjena"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Stavka je dodata u folder"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Napravite folder sa: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Folder je napravljen"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Premesti na početni ekran"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Premestite na početni ekran"</string>
<string name="action_resize" msgid="1802976324781771067">"Promeni veličinu"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Povećaj širinu"</string>
<string name="action_increase_height" msgid="459390020612501122">"Povećaj visinu"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Isključi poslovne aplikacije"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Nije uspelo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 3d6bde4..a845f9a 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Утрымліваючы віджэт націснутым, перамяшчайце яго па Галоўным экране"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Дадаць на Галоўны экран"</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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Працоўныя"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Размовы"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Карысная інфармацыя ў вас пад рукой"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Каб не адкрываць праграмы для прагляду патрэбнай інфармацыі, дадайце віджэты на галоўны экран"</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>
@@ -65,7 +65,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="6692471482459245734">"На галоўным экране няма месца"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Замацаваць прапанаваную праграму"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"Стварэнне ярлыкоў"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Дазваляе праграмам дадаваць ярлыкі без умяшання карыстальніка."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"счытваць налады і ярлыкі на Галоўнай старонцы"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Дазваляе праграме счытваць налады і ярлыкі на Галоўнай старонцы."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"запісваць налады і ярлыкі на галоўнай старонцы"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Дазваляе праграме змяняць налады і ярлыкі на Галоўнай старонцы."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"счытваць налады і ярлыкі на галоўным экране"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Гэта сістэмная праграма, яе нельга выдаліць."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{У праграмы \"{app_name}\" ёсць # апавяшчэнне}one{У праграмы \"{app_name}\" ёсць # апавяшчэнне}few{У праграмы \"{app_name}\" ёсць # апавяшчэнні}many{У праграмы \"{app_name}\" ёсць # апавяшчэнняў}other{У праграмы \"{app_name}\" ёсць # апавяшчэння}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{У праграмы \"{app_name}\" ёсць # апавяшчэнне}one{У праграмы \"{app_name}\" ёсць # апавяшчэнне}few{У праграмы \"{app_name}\" ёсць # апавяшчэнні}many{У праграмы \"{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Шпалеры і стыль"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Налады галоўнага экрана"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Адключаная адміністратарам"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Дазволіць паварот галоўнага экрана"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Каб паказваліся значкі апавяшчэнняў, уключыце апавяшчэнні праграм для <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Змяніць налады"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Паказваць значкі апавяшчэнняў"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Дадаваць значкі праграм на Галоўны экран"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Параметры распрацоўшчыка"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Дадаваць значкі праграм на галоўны экран"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Для новых праграм"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Невядома"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Выдаліць"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"Абнавіць"</string>
+ <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="8902165848117513641">"Дадаць на Галоўны экран"</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_removed" msgid="851119963877842327">"Элемент выдалены"</string>
@@ -141,7 +146,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="1603837886334246317">"Перамясціць на Галоўны экран"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"Зразумела"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Выключыць працоўныя праграмы"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Прыпыніць працоўныя праграмы"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Уключыць працоўныя праграмы"</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="remote_action_failed" msgid="1383965239183576790">"Не ўдалося: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 661c710..0c7fcd3 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Докоснете приспособлението и го задръжте, за да го местите по началния екран"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Добавяне към началния екран"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# приспособление}other{# приспособления}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# пряк път}other{# преки пътя}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Служебни"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Разговори"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Лесен достъп до полезна информация"</string>
- <string name="widget_education_content" msgid="745542879510751525">"За да получавате информация, без да отваряте приложенията, можете да добавите приспособления към началния екран"</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>
@@ -65,7 +65,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="6692471482459245734">"Няма място на този начален екран"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Фиксиране на предвиждането"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"инсталиране на преки пътища"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Разрешава на приложението да добавя преки пътища без намеса на потребителя."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"четене на настройките и преките пътища в Начало"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Разрешава на приложението да чете настройките и преките пътища в Начало."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"запис на настройките и преките пътища в Начало"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Разрешава на приложението да променя настройките и преките пътища в Начало."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"четене на настройките и преките пътища на началния екран"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Това е системно приложение и не може да се деинсталира."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} има # известие}other{{app_name} има # известия}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Тапет и стил"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Настройки за началния екран"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Деактивирано от администратора ви"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Разрешаване на завъртането на началния екран"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"За да се показват точки за известия, включете известията за приложението <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Промяна на настройките"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Показване на точките за известия"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Добавяне на икони на прил. на нач. екран"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Опции за програмисти"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Добавяне на икони на приложения на началния екран"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"За нови приложения"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Няма информация"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Премахване"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"Актуализиране"</string>
+ <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="8902165848117513641">"Добавяне към началния екран"</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_removed" msgid="851119963877842327">"Елементът е премахнат"</string>
@@ -141,7 +146,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="1603837886334246317">"Преместване към началния екран"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"Разбрах"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Изключване на служебните приложения"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Поставяне на пауза на служебните приложения"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Включване на служебните приложения"</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="remote_action_failed" msgid="1383965239183576790">"Неуспешно: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 299a014..5c8c342 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%2$d উচ্চতা অনুযায়ী %1$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="5653291305078645405">"হোম স্ক্রিনের যেকোনও জায়গায় উইজেটটি নিয়ে যেতে, টাচ করে ধরে থাকুন"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"হোম স্ক্রিনে যোগ করুন"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{#টি উইজেট}one{#টি উইজেট}other{#টি উইজেট}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{#টি শর্টকাট}one{#টি শর্টকাট}other{#টি শর্টকাট}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"অফিস"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"কথোপকথন"</string>
<string name="widget_education_header" msgid="4874760613775913787">"সহজেই দরকারি তথ্য পান"</string>
- <string name="widget_education_content" msgid="745542879510751525">"অ্যাপ না খুলে তথ্য পাওয়ার জন্য, আপনার হোম স্ক্রিনে উইজেট যোগ করতে পারেন"</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>
@@ -65,7 +65,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="6692471482459245734">"এই হোম স্ক্রিনে আর জায়গা খালি নেই"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"আপনার প্রয়োজন হতে পারে এমন অ্যাপ পিন করুন"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"শর্টকাটগুলি ইনস্টল করে"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"একটি অ্যাপ্লিকেশানকে ব্যবহারকারীর হস্তক্ষেপ ছাড়াই শর্টকাটগুলি যোগ করার অনুমতি দেয়৷"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"হোম সেটিংস এবং শর্টকাটগুলি পড়ে"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"হোমে অ্যাপ্লিকেশানটিকে সেটিংস এবং শর্টকাটগুলি পড়তে দেয়৷"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"হোম সেটিংস এবং শর্টকাটগুলি লেখে"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"হোমে অ্যাপ্লিকেশানটিকে সেটিংস এবং শর্টকাটগুলি পরিবর্তন করতে দেয়৷"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"হোম স্ক্রিনে সেটিংস ও শর্টকাট পড়ুন"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"এটি একটি সিস্টেম অ্যাপ্লিকেশান এবং আনইনস্টল করা যাবে না৷"</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name}-এর #টি বিজ্ঞপ্তি আছে}one{{app_name}-এর #টি বিজ্ঞপ্তি আছে}other{{app_name}-এর #টি বিজ্ঞপ্তি আছে}}"</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">"%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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ওয়ালপেপার এবং স্টাইল"</string>
<string name="settings_button_text" msgid="8873672322605444408">"হোম সেটিংস"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"আপনার প্রশাসক দ্বারা অক্ষম করা হয়েছে"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"হোম স্ক্রিন ঘোরানোর অনুমতি দিন"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"বিজ্ঞপ্তির ডটগুলি দেখানোর জন্য, <xliff:g id="NAME">%1$s</xliff:g> এর অ্যাপ বিজ্ঞপ্তি চালু করুন"</string>
<string name="title_change_settings" msgid="1376365968844349552">"সেটিংস পরিবর্তন করুন"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"বিজ্ঞপ্তির ডট দেখুন"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"হোম স্ক্রিনে অ্যাপ আইকন যোগ করুন"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"ডেভেলপার বিকল্প"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"হোম স্ক্রিনে অ্যাপের আইকন যোগ করুন"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"নতুন অ্যাপের জন্য"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"অজানা"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"সরান"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"আপডেট করুন"</string>
+ <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="8902165848117513641">"হোম স্ক্রিনে যোগ করুন"</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_removed" msgid="851119963877842327">"আইটেম সরানো হয়েছে"</string>
@@ -141,7 +146,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="1603837886334246317">"হোম স্ক্রীনে সরান"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"বুঝেছি"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"অফিসের অ্যাপ বন্ধ করুন"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"অফিসের অ্যাপ পজ করুন"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"অফিস অ্যাপ চালু করুন"</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="remote_action_failed" msgid="1383965239183576790">"কাজটি করা যায়নি: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 50b2b3c..173518f 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"Širina %1$d, visina %2$d"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Vidžet <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Dodirnite i držite vidžet da ga pomjerate po Početnom ekranu"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Dodaj na početni ekran"</string>
+ <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Dodirnite i držite vidžet da ga pomjerate 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">"Vidžet <xliff:g id="WIDGET_NAME">%1$s</xliff:g> je dodan na početni ekran"</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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Posao"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Razgovori"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Korisne informacije nadohvat ruke"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Da dobijete informacije bez otvaranja aplikacija, možete dodati vidžete na početni ekran"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Razumijem"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Promjena postavki vidžeta"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Obavještenja"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Dodirnite i zadržite da pomjerite prečicu."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Dvaput dodirnite i zadržite da pomjerite prečicu ili da koristite prilagođene radnje."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Nema prostora na ovom početnom ekranu"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Nema prostora na ovom početnom ekranu"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Nema više prostora u ladici Omiljeno"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Lista aplikacija"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Rezultati pretraživanja"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Zakači predviđanje"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instaliraj prečice"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Dopušta aplikaciji dodavanje prečica bez posredovanja korisnika."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"čitaj postavke na početnom ekranu i prečice"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Dopušta aplikaciji čitanje postavki i prečica na početnom ekranu."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"zapisuj postavke na početnom ekranu i prečice"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Dopušta aplikaciji promjenu postavki i prečica na početnom ekranu."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"čita postavke na početnom ekranu i prečice"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ovo je sistemska aplikacija i ne može se deinstalirati."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Uređivanje naziva"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je onemogućena"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} ima # obavještenje}one{{app_name} ima # obavještenje}few{{app_name} ima # obavještenja}other{{app_name} ima # obavještenja}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{Aplikacija {app_name} ima # obavještenje}one{Aplikacija {app_name} ima # obavještenje}few{Aplikacija {app_name} ima # obavještenja}other{Aplikacija {app_name} ima # obavještenja}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Strana %1$d od %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Početni ekran %1$d od %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nova stranica početnog ekrana"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Pozadinska slika i stil"</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="7728578836261442095">"Dozvoli rotiranje početnog ekrana"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Dozvoli rotiranje početnog ekrana"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kada se telefon zarotira"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Tačke za obavještenja"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Uključeno"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Za prikaz tačaka za obavještenja, uključite obavještenja za aplikacije za aplikaciju <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Promijeni postavke"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Prikaži tačke za obavještenja"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Dodaj ikone aplikacija na početni ekran"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Opcije za programere"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Dodaj ikone aplikacija na početni ekran"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Za nove aplikacije"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Nepoznato"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Ukloni"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Instaliranje aplikacije <xliff:g id="NAME">%1$s</xliff:g>, završeno je <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> se preuzima, završeno <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> čeka da se instalira"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Potrebno je ažurirati aplikaciju"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Aplikacija za ovu ikonu nije ažurirana. Možete je ažurirati ručno da ponovo omogućite ovu prečicu ili možete ukloniti ikonu."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Ažuriraj"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Ukloni"</string>
<string name="widgets_list" msgid="796804551140113767">"Spisak vidžeta"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Spisak vidžeta je zatvoren"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Dodavanje na početni ekran"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Dodavanje na početni ekran"</string>
<string name="action_move_here" msgid="2170188780612570250">"Premjesti stavku ovdje"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Stavka je dodana na Početni ekran."</string>
<string name="item_removed" msgid="851119963877842327">"Stavka je uklonjena"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Stavka je dodana u folder"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Kreirajte folder sa stavkom: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Folder je kreiran"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Pomjeri na početni ekran"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Pomjeranje na početni ekran"</string>
<string name="action_resize" msgid="1802976324781771067">"Promijeni veličinu"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Povećaj širinu"</string>
<string name="action_increase_height" msgid="459390020612501122">"Povećaj visinu"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Isključi poslovne aplikacije"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Nije uspjelo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index a0f03c8..e6a4af2 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d d\'amplada per %2$d d\'alçada"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Widget de <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Mantén premut el widget per moure\'l per la pantalla d\'inici"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Afegeix a la pantalla d\'inici"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Treball"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Converses"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Informació útil a l\'abast de la mà"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Per obtenir informació sense obrir les aplicacions, pots afegir widgets a la pantalla d\'inici"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Entesos"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Canvia la configuració del widget"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notificacions"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Fes doble toc i mantén premut per moure una drecera."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Fes doble toc i mantén premut per moure una drecera o per utilitzar accions personalitzades."</string>
- <string name="out_of_space" msgid="6692471482459245734">"No queda espai en aquesta pantalla d\'inici"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"No queda espai en aquesta pantalla d\'inici"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"No hi ha més espai a la safata Preferits."</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Llista d\'aplicacions"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Resultats de la cerca"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Fixa la predicció"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instal·la dreceres"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permet que una aplicació afegeixi dreceres sense la intervenció de l\'usuari."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"llegeix la configuració i les dreceres de la pantalla d\'inici"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Permet que l\'aplicació llegeixi la configuració i les dreceres de la pantalla d\'inici."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"escriu la configuració i les dreceres de la pantalla d\'inici"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Permet que l\'aplicació canviï la configuració i les dreceres de la pantalla d\'inici."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"llegir la configuració i les dreceres de la pantalla d\'inici"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Aquesta aplicació és una aplicació del sistema i no es pot desinstal·lar."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Edita el nom"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"S\'ha desactivat <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} té # notificació}other{{app_name} té # notificacions}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} té # notificació}other{{app_name} té # notificacions}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Pàgina %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Pantalla d\'inici %1$d de %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Pàgina de la pantalla d\'inici nova"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Estil i fons de pantalla"</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="7728578836261442095">"Permet la rotació de la pantalla d\'inici"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Permet la rotació de la pantalla d\'inici"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"En girar el telèfon"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Punts de notificació"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Activats"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Per veure els punts de notificació, activa les notificacions de l\'aplicació <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Canvia la configuració"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Mostra els punts de notificació"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Afegeix icones d\'aplicacions a la pantalla d\'inici"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Opcions per a desenvolupadors"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Afegeix icones d\'aplicacions a la pantalla d\'inici"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Per a les aplicacions noves"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconegut"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Suprimeix"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"S\'està instal·lant <xliff:g id="NAME">%1$s</xliff:g>; s\'ha completat un <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"S\'està baixant <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> completat"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"S\'està esperant per instal·lar <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Cal actualitzar l\'aplicació"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"L\'aplicació d\'aquesta icona no està actualitzada. Pots actualitzar-la manualment per tornar a activar aquesta drecera o pots suprimir la icona."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Actualitza"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Suprimeix"</string>
<string name="widgets_list" msgid="796804551140113767">"Llista de widgets"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"S\'ha tancat la llista de widgets"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Afegeix a la pantalla d\'inici"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Afegeix a la pantalla d\'inici"</string>
<string name="action_move_here" msgid="2170188780612570250">"Mou l\'element aquí"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"S\'ha afegit l\'element a la pantalla d\'inici"</string>
<string name="item_removed" msgid="851119963877842327">"S\'ha suprimit l\'element"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Element afegit a la carpeta"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Crea una carpeta amb: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Carpeta creada"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Desplaça a la pantalla d\'inici"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Mou a la pantalla d\'inici"</string>
<string name="action_resize" msgid="1802976324781771067">"Canvia la mida"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Augmenta l\'amplada"</string>
<string name="action_increase_height" msgid="459390020612501122">"Augmenta l\'alçada"</string>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"Entesos"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Desactiva les aplicacions de treball"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Error: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 8cf9c23..5c357f7 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"šířka %1$d, výška %2$d"</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="5653291305078645405">"Pokud chcete widgetem pohybovat po ploše, podržte ho"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Přidat na plochu"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Práce"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Konverzace"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Užitečné informace na dosah"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Pokud chcete mít informace k dispozici bez otevírání aplikací, můžete si na plochu přidat widgety"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Rozumím"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Změnit nastavení widgetu"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Oznámení"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Klepnutím a podržením přesunete zkratku."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Dvojitým klepnutím a podržením přesunete zkratku, případně použijte vlastní akce."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Na této ploše není místo"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Na této ploše není místo"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Na panelu Oblíbené položky již není místo."</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Seznam aplikací"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Výsledky vyhledávání"</string>
@@ -75,14 +75,14 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Odinstalovat"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"O aplikaci"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Nainstalovat"</string>
- <string name="dismiss_prediction_label" msgid="3357562989568808658">"Aplikaci nenavrhovat"</string>
+ <string name="dismiss_prediction_label" msgid="3357562989568808658">"Nenavrhovat aplikaci"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Připnout předpověď"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalace zástupce"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Umožňuje aplikaci přidat zástupce bez zásahu uživatele."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"čtení nastavení a odkazů plochy"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Umožňuje aplikaci číst nastavení a odkazy na ploše."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"zápis nastavení a odkazů plochy"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Umožňuje aplikaci změnit nastavení a odkazy na ploše."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"čtení nastavení a zkratek plochy"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Toto je systémová aplikace a nelze ji odinstalovat."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Upravit název"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> je zakázána"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{Aplikace {app_name} má # oznámení}few{Aplikace {app_name} má # oznámení}many{Aplikace {app_name} má # oznámení}other{Aplikace {app_name} má # oznámení}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{Aplikace {app_name} má # oznámení}few{Aplikace {app_name} má # oznámení}many{Aplikace {app_name} má # oznámení}other{Aplikace {app_name} má # oznámení}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Strana %1$d z %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Plocha %1$d z %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nová stránka plochy"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Tapeta a styl"</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="7728578836261442095">"Povolit otáčení plochy"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Povolit otáčení plochy"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Při otočení telefonu"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Puntíky s oznámením"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Zapnuto"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Chcete-li zobrazovat puntíky s oznámením, zapněte oznámení z aplikace <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Změnit nastavení"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Zobrazovat puntíky s oznámením"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Přidávat na plochu ikony aplikací"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Pro vývojáře"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Přidávat na plochu ikony aplikací"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"U nových aplikací"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Neznámé"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Odstranit"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Instalace aplikace <xliff:g id="NAME">%1$s</xliff:g>, dokončeno <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Stahování aplikace <xliff:g id="NAME">%1$s</xliff:g> (dokončeno <xliff:g id="PROGRESS">%2$s</xliff:g>)"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Instalace aplikace <xliff:g id="NAME">%1$s</xliff:g> čeká na zahájení"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Je nutná aktualizace aplikace"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Aplikace pro tuto ikonu není nainstalována. Můžete ji ručně aktualizovat, aby zkratka znovu fungovala, případně můžete ikonu odstranit."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Aktualizovat"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Odstranit"</string>
<string name="widgets_list" msgid="796804551140113767">"Seznam widgetů"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Seznam widgetů zavřen"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Přidat na plochu"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Přidat na plochu"</string>
<string name="action_move_here" msgid="2170188780612570250">"Přesunout položku sem"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Položka byla přidána na plochu"</string>
<string name="item_removed" msgid="851119963877842327">"Položka byla odstraněna"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Položka byla přidána do složky"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Vytvořit složku s položkou <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Složka byla vytvořena"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Přesunout na plochu"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Přesunout na plochu"</string>
<string name="action_resize" msgid="1802976324781771067">"Změnit velikost"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Zvýšit šířku"</string>
<string name="action_increase_height" msgid="459390020612501122">"Zvýšit výšku"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Vypnout pracovní aplikace"</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="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="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 ee339c4..8160465 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d i bredden og %2$d i højden"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Widgetten <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Hold widgetten nede for at flytte den rundt på startskærmen"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Føj til startskærm"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Arbejde"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Samtaler"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Nyttige oplysninger lige ved hånden"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Hvis du vil have oplysninger uden at åbne apps, kan du føje widgets til din startskærm"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Skift widgetindstillinger"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notifikationer"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Hold en genvej nede for at flytte den."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Tryk to gange, og hold en genvej nede for at flytte den eller bruge tilpassede handlinger."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Der er ikke ledig plads på startskærmen"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Der er ikke ledig plads på startskærmen"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Der er ikke mere plads i bakken Favoritter"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Liste med apps"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Søgeresultater"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Fastgør forslaget"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"installere genveje"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Tillader, at en app tilføjer genveje uden brugerens indgriben."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"læs indstillinger og genveje for startskærmen"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Tillader, at appen læser indstillingerne og genvejene på startskærmen."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"skrive indstillinger og genveje for startskærmen"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Tillader, at appen ændrer indstillingerne og genvejene på startskærmen."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"læs indstillinger og genveje for startskærm"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Dette er en systemapp, som ikke kan afinstalleres."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Rediger navn"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> er deaktiveret"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} har # notifikation}one{{app_name} har # notifikation}other{{app_name} har # notifikationer}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} har # notifikation}one{{app_name} har # notifikation}other{{app_name} har # notifikationer}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Side %1$d ud af %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Startskærm %1$d ud af %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Ny startskærm"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Baggrund og stil"</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="7728578836261442095">"Tillad rotation af startskærmen"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Tillad rotation af startskærmen"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Når telefonen roteres"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Notifikationsprikker"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Til"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Hvis du vil se notifikationsprikker, skal du aktivere appnotifikationer for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Skift indstillinger"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Vis notifikationsprikker"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Føj appikoner til startskærmen"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Indstillinger for udviklere"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Føj appikoner til startskærmen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For nye apps"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Ukendt"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Fjern"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installeres. <xliff:g id="PROGRESS">%2$s</xliff:g> fuldført"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloades. <xliff:g id="PROGRESS">%2$s</xliff:g> er gennemført"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> venter på at installere"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Appen skal opdateres"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Appen, der tilhører dette ikon, er ikke opdateret. Du kan opdatere appen manuelt for at genaktivere denne genvej, eller du kan fjerne ikonet."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Opdater"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Fjern"</string>
<string name="widgets_list" msgid="796804551140113767">"Liste med widgets"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Listen med widgets blev lukket"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Føj til startskærm"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Føj til startskærm"</string>
<string name="action_move_here" msgid="2170188780612570250">"Flyt elementet hertil"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Elementet er føjet til startskærmen"</string>
<string name="item_removed" msgid="851119963877842327">"Elementet er fjernet"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Elementet blev føjet til mappen"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Opret mappe med: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Mappen blev oprettet"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Flyt til startskærmen"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Flyt til startskærm"</string>
<string name="action_resize" msgid="1802976324781771067">"Tilpas størrelse"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Øg bredden"</string>
<string name="action_increase_height" msgid="459390020612501122">"Øg højden"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Deaktiver arbejdsapps"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Mislykket: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 3a1fde5..912e7fa 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d breit und %2$d hoch"</string>
<string name="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="5653291305078645405">"Wenn du das Widget auf dem Startbildschirm verschieben möchtest, halte es gedrückt"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Zum Startbildschirm hinzufügen"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Geschäftlich"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Unterhaltungen"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Praktische Informationen – immer zur Hand"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Wenn du Informationen erhalten möchtest, ohne Apps zu öffnen, kannst du deinem Startbildschirm Widgets hinzufügen"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Widget-Einstellungen ändern"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Benachrichtigungen"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Zum Verschieben einer Verknüpfung berühren und halten"</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Doppeltippen und halten, um eine Verknüpfung zu bewegen oder benutzerdefinierte Aktionen zu nutzen."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Auf diesem Startbildschirm ist kein Platz mehr vorhanden"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Auf diesem Startbildschirm ist kein Platz mehr vorhanden"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Ablage \"Favoriten\" ist voll."</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Liste der Apps"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Suchergebnisse"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Vorgeschlagene App fixieren"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"Verknüpfungen installieren"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Ermöglicht einer App das Hinzufügen von Verknüpfungen ohne Eingreifen des Nutzers"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"Einstellungen und Verknüpfungen auf dem Startbildschirm lesen"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Ermöglicht der App, die Einstellungen und Verknüpfungen auf dem Startbildschirm zu lesen"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"Einstellungen und Verknüpfungen für den Startbildschirm schreiben"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Ermöglicht der App, die Einstellungen und Verknüpfungen auf dem Startbildschirm zu ändern"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"Einstellungen und Verknüpfungen auf dem Startbildschirm lesen"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Dies ist eine Systemanwendung, die nicht deinstalliert werden kann."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Name bearbeiten"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> deaktiviert"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} hat # Benachrichtigung}other{{app_name} hat # Benachrichtigungen}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} hat # Benachrichtigung}other{{app_name} hat # Benachrichtigungen}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Seite %1$d von %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Startbildschirm %1$d von %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Neue Startbildschirmseite"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Hintergrund & Stil"</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="7728578836261442095">"Drehen des Startbildschirms zulassen"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Drehen des Startbildschirms zulassen"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Beim Drehen des Smartphones"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"App-Benachrichtigungspunkte"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"An"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Um dir Benachrichtigungspunkte anzeigen zu lassen, aktiviere die Benachrichtigungen für die App \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
<string name="title_change_settings" msgid="1376365968844349552">"Einstellungen ändern"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"App-Benachrichtigungspunkte anzeigen"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"App-Symbole auf Startbildschirm setzen"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Entwickleroptionen"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"App-Symbole zum Startbildschirm hinzufügen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Bei neuen Apps"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Unbekannt"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Entfernen"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> wird installiert, <xliff:g id="PROGRESS">%2$s</xliff:g> abgeschlossen"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> wird heruntergeladen, <xliff:g id="PROGRESS">%2$s</xliff:g> abgeschlossen"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Warten auf Installation von <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"App-Update erforderlich"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Die App für dieses Symbol wurde noch nicht aktualisiert. Du kannst sie manuell aktualisieren, um die Verknüpfung wieder zu aktivieren, oder das Symbol entfernen."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Aktualisieren"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Entfernen"</string>
<string name="widgets_list" msgid="796804551140113767">"Widgetliste"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Widgetliste geschlossen"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Zum Startbildschirm hinzufügen"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Zum Startbildschirm hinzufügen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Element hierhin verschieben"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Element zum Startbildschirm hinzugefügt"</string>
<string name="item_removed" msgid="851119963877842327">"Element entfernt"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Element zum Ordner hinzugefügt"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Anhand von <xliff:g id="NAME">%1$s</xliff:g> Ordner erstellen"</string>
<string name="folder_created" msgid="6409794597405184510">"Ordner erstellt"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Auf Startbildschirm verschieben"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Zu Startbildschirm verschieben"</string>
<string name="action_resize" msgid="1802976324781771067">"Größe anpassen"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Breite vergrößern"</string>
<string name="action_increase_height" msgid="459390020612501122">"Höhe vergrößern"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Geschäftliche Apps deaktivieren"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Fehler: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index b78db22..0f613de 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Αγγίξτε παρατεταμένα το γραφικό στοιχείο για να το μετακινήσετε στην Αρχική οθόνη"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Προσθήκη στην Αρχική οθόνη"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# γραφικό στοιχείο}other{# γραφικά στοιχεία}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# συντόμευση}other{# συντομεύσεις}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Εργασίας"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Συζητήσεις"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Χρήσιμες πληροφορίες στη διάθεσή σας"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Για να λάβετε πληροφορίες χωρίς να ανοίξετε εφαρμογές, μπορείτε να προσθέσετε γραφικά στοιχεία στην αρχική σας οθόνη."</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>
@@ -65,7 +65,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="6692471482459245734">"Δεν υπάρχει χώρος σε αυτήν την αρχική οθόνη"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Καρφίτσωμα πρόβλεψης"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"εγκατάσταση συντομεύσεων"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Επιτρέπει σε μια εφαρμογή την προσθήκη συντομεύσεων χωρίς την παρέμβαση του χρήστη."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"ανάγνωση ρυθμίσεων και συντομεύσεων αρχικής οθόνης"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Επιτρέπει στην εφαρμογή την ανάγνωση των ρυθμίσεων και των συντομεύσεων στην Αρχική οθόνη."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"εγγραφή ρυθμίσεων και συντομεύσεων αρχικής οθόνης"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Επιτρέπει στην εφαρμογή την αλλαγή των ρυθμίσεων και των συντομεύσεων στην Αρχική οθόνη."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"ανάγνωση ρυθμίσεων και συντομεύσεων αρχικής οθόνης"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Αυτή είναι μια εφαρμογή συστήματος και δεν είναι δυνατή η κατάργηση της εγκατάστασής της."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{Η εφαρμογή {app_name} έχει # ειδοποίηση}other{Η εφαρμογή {app_name} έχει # ειδοποιήσεις}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{Η εφαρμογή {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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Ταπετσαρία και στιλ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Ρυθμίσεις Αρχ. Οθ."</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Απενεργοποιήθηκε από τον διαχειριστή σας"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Να επιτρέπεται η περιστροφή της αρχικής οθόνης"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Για να εμφανιστούν οι Κουκκίδες ειδοποίησης, ενεργοποιήστε τις κουκκίδες εφαρμογής για την εφαρμογή <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Αλλαγή ρυθμίσεων"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Εμφάνιση κουκκίδων ειδοποιήσεων"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Προσθ. εικονιδίων εφαρμ. σε αρχική οθόνη"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Επιλογές για προγραμματιστές"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Προσθήκη εικονιδίων εφαρμογών στην αρχική οθόνη"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Για νέες εφαρμογές"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Άγνωστο"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Κατάργηση"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Έχει ολοκληρωθεί το <xliff:g id="PROGRESS">%2$s</xliff:g> της εγκατάστασης της εφαρμογής <xliff:g id="NAME">%1$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" msgid="2178028071796141234">"Ενημέρωση"</string>
+ <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="8902165848117513641">"Προσθήκη στην αρχική οθόνη"</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_removed" msgid="851119963877842327">"Το στοιχείο καταργήθηκε"</string>
@@ -141,7 +146,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="1603837886334246317">"Μετακίνηση Αρχικής οθόνης"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"Το κατάλαβα"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Απενεργοποίηση εφαρμογών εργασιών"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Παύση εφαρμογών εργασιών"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Ενεργοποίηση εφαρμογών εργασίας"</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>
<string name="remote_action_failed" msgid="1383965239183576790">"Αποτυχία: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index fa00100..a78c7f8 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Touch and hold the widget to move it around the home screen"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Add to 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="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# shortcut}other{# shortcuts}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Work"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Useful info at your fingertips"</string>
- <string name="widget_education_content" msgid="745542879510751525">"To get info without opening apps, you can add widgets to your home screen"</string>
+ <string name="widget_education_content" msgid="1731667670753497052">"To get info without opening apps, you can add widgets to your home screen"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tap to change widget settings"</string>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Change widget settings"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Touch & hold to move a shortcut."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Double-tap & hold to move a shortcut or use custom actions."</string>
- <string name="out_of_space" msgid="6692471482459245734">"No room on this home screen"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"No room on this home screen"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"No more room in the Favourites tray"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Apps list"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Search results"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Pin prediction"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"install shortcuts"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Allows an app to add shortcuts without user intervention."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"read Home settings and shortcuts"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Allows the app to read the settings and shortcuts in Home."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"write Home settings and shortcuts"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Allows the app to change the settings and shortcuts in Home."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"read Home settings and shortcuts"</string>
+ <string name="permdesc_read_settings" msgid="4208061150510996676">"Allows the app to read the settings and shortcuts in Home."</string>
+ <string name="permlab_write_settings" msgid="4820028712156303762">"write Home settings and shortcuts"</string>
+ <string name="permdesc_write_settings" msgid="726859348127868466">"Allows the app to change the settings and shortcuts in Home."</string>
<string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not allowed to make phone calls"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Can\'t load widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Widget settings"</string>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"This is a system app and can\'t be uninstalled."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Edit Name"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Disabled <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} has # notification}other{{app_name} has # notifications}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} has # notification}other{{app_name} has # notifications}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Page %1$d of %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Home screen %1$d of %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"New home screen page"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Wallpaper and style"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Home settings"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Allow Home screen rotation"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Allow home screen rotation"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"When phone is rotated"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Notification dots"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"On"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Show notification dots"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Add app icons to the home screen"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Developer options"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Add app icons to home screen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For new apps"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installing, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"App update required"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut or remove the icon."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Update"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Remove"</string>
<string name="widgets_list" msgid="796804551140113767">"Widgets list"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Widgets list closed"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Add to Home screen"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Add to home screen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Move item here"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item added to home screen"</string>
<string name="item_removed" msgid="851119963877842327">"Item removed"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Item added to folder"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Create folder with: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Folder created"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Move to Home screen"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Move to home screen"</string>
<string name="action_resize" msgid="1802976324781771067">"Re-size"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Increase width"</string>
<string name="action_increase_height" msgid="459390020612501122">"Increase height"</string>
@@ -163,8 +168,10 @@
<string name="work_apps_paused_content_description" msgid="5149623040804051095">"Work apps are off. Your work apps can’t send you notifications, use your battery or access your location"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Work apps are badged and visible to your IT admin"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Turn off work apps"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pause work apps"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Turn on work apps"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
+ <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>
<string name="remote_action_failed" msgid="1383965239183576790">"Failed: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index fa00100..a78c7f8 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Touch and hold the widget to move it around the home screen"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Add to 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="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# shortcut}other{# shortcuts}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Work"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Useful info at your fingertips"</string>
- <string name="widget_education_content" msgid="745542879510751525">"To get info without opening apps, you can add widgets to your home screen"</string>
+ <string name="widget_education_content" msgid="1731667670753497052">"To get info without opening apps, you can add widgets to your home screen"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tap to change widget settings"</string>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Change widget settings"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Touch & hold to move a shortcut."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Double-tap & hold to move a shortcut or use custom actions."</string>
- <string name="out_of_space" msgid="6692471482459245734">"No room on this home screen"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"No room on this home screen"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"No more room in the Favourites tray"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Apps list"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Search results"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Pin prediction"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"install shortcuts"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Allows an app to add shortcuts without user intervention."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"read Home settings and shortcuts"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Allows the app to read the settings and shortcuts in Home."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"write Home settings and shortcuts"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Allows the app to change the settings and shortcuts in Home."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"read Home settings and shortcuts"</string>
+ <string name="permdesc_read_settings" msgid="4208061150510996676">"Allows the app to read the settings and shortcuts in Home."</string>
+ <string name="permlab_write_settings" msgid="4820028712156303762">"write Home settings and shortcuts"</string>
+ <string name="permdesc_write_settings" msgid="726859348127868466">"Allows the app to change the settings and shortcuts in Home."</string>
<string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not allowed to make phone calls"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Can\'t load widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Widget settings"</string>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"This is a system app and can\'t be uninstalled."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Edit Name"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Disabled <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} has # notification}other{{app_name} has # notifications}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} has # notification}other{{app_name} has # notifications}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Page %1$d of %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Home screen %1$d of %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"New home screen page"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Wallpaper and style"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Home settings"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Allow Home screen rotation"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Allow home screen rotation"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"When phone is rotated"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Notification dots"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"On"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Show notification dots"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Add app icons to the home screen"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Developer options"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Add app icons to home screen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For new apps"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installing, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"App update required"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut or remove the icon."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Update"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Remove"</string>
<string name="widgets_list" msgid="796804551140113767">"Widgets list"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Widgets list closed"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Add to Home screen"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Add to home screen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Move item here"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item added to home screen"</string>
<string name="item_removed" msgid="851119963877842327">"Item removed"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Item added to folder"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Create folder with: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Folder created"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Move to Home screen"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Move to home screen"</string>
<string name="action_resize" msgid="1802976324781771067">"Re-size"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Increase width"</string>
<string name="action_increase_height" msgid="459390020612501122">"Increase height"</string>
@@ -163,8 +168,10 @@
<string name="work_apps_paused_content_description" msgid="5149623040804051095">"Work apps are off. Your work apps can’t send you notifications, use your battery or access your location"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Work apps are badged and visible to your IT admin"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Turn off work apps"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pause work apps"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Turn on work apps"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
+ <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>
<string name="remote_action_failed" msgid="1383965239183576790">"Failed: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index fa00100..a78c7f8 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Touch and hold the widget to move it around the home screen"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Add to 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="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# shortcut}other{# shortcuts}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Work"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Useful info at your fingertips"</string>
- <string name="widget_education_content" msgid="745542879510751525">"To get info without opening apps, you can add widgets to your home screen"</string>
+ <string name="widget_education_content" msgid="1731667670753497052">"To get info without opening apps, you can add widgets to your home screen"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tap to change widget settings"</string>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Change widget settings"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Touch & hold to move a shortcut."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Double-tap & hold to move a shortcut or use custom actions."</string>
- <string name="out_of_space" msgid="6692471482459245734">"No room on this home screen"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"No room on this home screen"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"No more room in the Favourites tray"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Apps list"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Search results"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Pin prediction"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"install shortcuts"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Allows an app to add shortcuts without user intervention."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"read Home settings and shortcuts"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Allows the app to read the settings and shortcuts in Home."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"write Home settings and shortcuts"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Allows the app to change the settings and shortcuts in Home."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"read Home settings and shortcuts"</string>
+ <string name="permdesc_read_settings" msgid="4208061150510996676">"Allows the app to read the settings and shortcuts in Home."</string>
+ <string name="permlab_write_settings" msgid="4820028712156303762">"write Home settings and shortcuts"</string>
+ <string name="permdesc_write_settings" msgid="726859348127868466">"Allows the app to change the settings and shortcuts in Home."</string>
<string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not allowed to make phone calls"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Can\'t load widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Widget settings"</string>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"This is a system app and can\'t be uninstalled."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Edit Name"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Disabled <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} has # notification}other{{app_name} has # notifications}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} has # notification}other{{app_name} has # notifications}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Page %1$d of %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Home screen %1$d of %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"New home screen page"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Wallpaper and style"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Home settings"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Allow Home screen rotation"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Allow home screen rotation"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"When phone is rotated"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Notification dots"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"On"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Show notification dots"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Add app icons to the home screen"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Developer options"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Add app icons to home screen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For new apps"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installing, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"App update required"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut or remove the icon."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Update"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Remove"</string>
<string name="widgets_list" msgid="796804551140113767">"Widgets list"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Widgets list closed"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Add to Home screen"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Add to home screen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Move item here"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item added to home screen"</string>
<string name="item_removed" msgid="851119963877842327">"Item removed"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Item added to folder"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Create folder with: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Folder created"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Move to Home screen"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Move to home screen"</string>
<string name="action_resize" msgid="1802976324781771067">"Re-size"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Increase width"</string>
<string name="action_increase_height" msgid="459390020612501122">"Increase height"</string>
@@ -163,8 +168,10 @@
<string name="work_apps_paused_content_description" msgid="5149623040804051095">"Work apps are off. Your work apps can’t send you notifications, use your battery or access your location"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Work apps are badged and visible to your IT admin"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Turn off work apps"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pause work apps"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Turn on work apps"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
+ <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>
<string name="remote_action_failed" msgid="1383965239183576790">"Failed: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index fa00100..a78c7f8 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Touch and hold the widget to move it around the home screen"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Add to 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="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# shortcut}other{# shortcuts}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Work"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Useful info at your fingertips"</string>
- <string name="widget_education_content" msgid="745542879510751525">"To get info without opening apps, you can add widgets to your home screen"</string>
+ <string name="widget_education_content" msgid="1731667670753497052">"To get info without opening apps, you can add widgets to your home screen"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tap to change widget settings"</string>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Change widget settings"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Touch & hold to move a shortcut."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Double-tap & hold to move a shortcut or use custom actions."</string>
- <string name="out_of_space" msgid="6692471482459245734">"No room on this home screen"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"No room on this home screen"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"No more room in the Favourites tray"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Apps list"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Search results"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Pin prediction"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"install shortcuts"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Allows an app to add shortcuts without user intervention."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"read Home settings and shortcuts"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Allows the app to read the settings and shortcuts in Home."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"write Home settings and shortcuts"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Allows the app to change the settings and shortcuts in Home."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"read Home settings and shortcuts"</string>
+ <string name="permdesc_read_settings" msgid="4208061150510996676">"Allows the app to read the settings and shortcuts in Home."</string>
+ <string name="permlab_write_settings" msgid="4820028712156303762">"write Home settings and shortcuts"</string>
+ <string name="permdesc_write_settings" msgid="726859348127868466">"Allows the app to change the settings and shortcuts in Home."</string>
<string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not allowed to make phone calls"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Can\'t load widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Widget settings"</string>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"This is a system app and can\'t be uninstalled."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Edit Name"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Disabled <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} has # notification}other{{app_name} has # notifications}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} has # notification}other{{app_name} has # notifications}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Page %1$d of %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Home screen %1$d of %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"New home screen page"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Wallpaper and style"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Home settings"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Allow Home screen rotation"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Allow home screen rotation"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"When phone is rotated"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Notification dots"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"On"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Show notification dots"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Add app icons to the home screen"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Developer options"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Add app icons to home screen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For new apps"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installing, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"App update required"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut or remove the icon."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Update"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Remove"</string>
<string name="widgets_list" msgid="796804551140113767">"Widgets list"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Widgets list closed"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Add to Home screen"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Add to home screen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Move item here"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item added to home screen"</string>
<string name="item_removed" msgid="851119963877842327">"Item removed"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Item added to folder"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Create folder with: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Folder created"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Move to Home screen"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Move to home screen"</string>
<string name="action_resize" msgid="1802976324781771067">"Re-size"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Increase width"</string>
<string name="action_increase_height" msgid="459390020612501122">"Increase height"</string>
@@ -163,8 +168,10 @@
<string name="work_apps_paused_content_description" msgid="5149623040804051095">"Work apps are off. Your work apps can’t send you notifications, use your battery or access your location"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Work apps are badged and visible to your IT admin"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"OK"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Turn off work apps"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pause work apps"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Turn on work apps"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
+ <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>
<string name="remote_action_failed" msgid="1383965239183576790">"Failed: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index f975d5c..d6951ad 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Touch & hold the widget to move it around the Home screen"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Add to Home screen"</string>
+ <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Touch & hold the widget to move it around the home screen"</string>
+ <string name="add_to_home_screen" msgid="9168649446635919791">"Add to home screen"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget added to home screen"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# shortcut}other{# shortcuts}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Work"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Useful info at your fingertips"</string>
- <string name="widget_education_content" msgid="745542879510751525">"To get info without opening apps, you can add widgets to your Home screen"</string>
+ <string name="widget_education_content" msgid="1731667670753497052">"To get info without opening apps, you can add widgets to your home screen"</string>
<string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tap to change widget settings"</string>
<string name="widget_education_close_button" msgid="8676165703104836580">"Got it"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Change widget settings"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Touch & hold to move a shortcut."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Double-tap & hold to move a shortcut or use custom actions."</string>
- <string name="out_of_space" msgid="6692471482459245734">"No room on this Home screen"</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>
<string name="all_apps_search_results" msgid="5889367432531296759">"Search results"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Pin Prediction"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"install shortcuts"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Allows an app to add shortcuts without user intervention."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"read Home settings and shortcuts"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Allows the app to read the settings and shortcuts in Home."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"write Home settings and shortcuts"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Allows the app to change the settings and shortcuts in Home."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"read home settings and shortcuts"</string>
+ <string name="permdesc_read_settings" msgid="4208061150510996676">"Allows the app to read the settings and shortcuts in home."</string>
+ <string name="permlab_write_settings" msgid="4820028712156303762">"write home settings and shortcuts"</string>
+ <string name="permdesc_write_settings" msgid="726859348127868466">"Allows the app to change the settings and shortcuts in home."</string>
<string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not allowed to make phone calls"</string>
<string name="gadget_error_text" msgid="740356548025791839">"Can\'t load widget"</string>
<string name="gadget_setup_text" msgid="8348374825537681407">"Widget settings"</string>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"This is a system app and can\'t be uninstalled."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Edit Name"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Disabled <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} has # notification}other{{app_name} has # notifications}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} has # notification}other{{app_name} has # notifications}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Page %1$d of %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Home screen %1$d of %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"New home screen page"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Wallpaper & style"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Home settings"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Allow Home screen rotation"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Allow home screen rotation"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"When phone is rotated"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Notification dots"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"On"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Show notification dots"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Add app icons to Home screen"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Developer Options"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Add app icons to home screen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For new apps"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Unknown"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remove"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installing, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> downloading, <xliff:g id="PROGRESS">%2$s</xliff:g> complete"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> waiting to install"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"App update required"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"The app for this icon isn\'t updated. You can update manually to re-enable this shortcut, or remove the icon."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Update"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Remove"</string>
<string name="widgets_list" msgid="796804551140113767">"Widgets list"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Widgets list closed"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Add to Home screen"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Add to home screen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Move item here"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item added to home screen"</string>
<string name="item_removed" msgid="851119963877842327">"Item removed"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Item added to folder"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Create folder with: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Folder created"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Move to Home screen"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Move to home screen"</string>
<string name="action_resize" msgid="1802976324781771067">"Resize"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Increase width"</string>
<string name="action_increase_height" msgid="459390020612501122">"Increase height"</string>
@@ -163,8 +168,10 @@
<string name="work_apps_paused_content_description" msgid="5149623040804051095">"Work apps are off. Your work apps can’t send you notifications, use your battery, or access your location"</string>
<string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Work apps are badged and visible to your IT admin"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"Got it"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Turn off work apps"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Pause work apps"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Turn on work apps"</string>
<string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
+ <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>
<string name="remote_action_failed" msgid="1383965239183576790">"Failed: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 314a3af..3897974 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de ancho por %2$d de alto"</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="5653291305078645405">"Mantén presionado el widget para moverlo por la pantalla principal"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Agregar a pantalla principal"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabajo"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversaciones"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Información útil a tu alcance"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Para recibir información de apps sin abrirlas, puedes agregar widgets a la pantalla principal"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Entendido"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Cambiar la configuración del widget"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notificaciones"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Mantén presionado para mover un acceso directo."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Presiona dos veces y mantén presionado para mover un acceso directo o usar acciones personalizadas."</string>
- <string name="out_of_space" msgid="6692471482459245734">"No hay más espacio en esta pantalla principal"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"No hay más espacio en esta pantalla principal"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"La bandeja de favoritos está llena."</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Lista de apps"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Resultados de la búsqueda"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Fijar predicción"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalar accesos directos"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite que una aplicación agregue accesos directos sin que el usuario intervenga."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"leer configuración y accesos directos de la pantalla principal"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Permite que la aplicación lea la configuración y los accesos directos de la pantalla principal."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"escribir configuración y accesos directos de la pantalla principal"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Permite que la aplicación cambie la configuración y los accesos directos de la pantalla principal."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"leer parámetros de configuración y accesos directos de la página principal"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Esta es una aplicación del sistema y no se puede desinstalar."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Editar nombre"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Se inhabilitó <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} tiene # notificación}other{{app_name} tiene # notificaciones}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} tiene # notificación}other{{app_name} tiene # notificaciones}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Página %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Pantalla principal %1$d de %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nueva página en la pantalla principal"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Fondo de pantalla y estilo"</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="7728578836261442095">"Permitir la rotación de la pantalla principal"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Permitir la rotación de la pantalla principal"</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_desc_on" msgid="1679848116452218908">"Activado"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Para mostrar los puntos de notificación, activa las notificaciones de la app para <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Cambiar la configuración"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Mostrar puntos de notificación"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Agrega íconos de apps a pantalla principal"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Opciones para desarrolladores"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Agrega íconos de las apps a la pantalla principal"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para nuevas apps"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconocido"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminar"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Se está instalando <xliff:g id="NAME">%1$s</xliff:g>; <xliff:g id="PROGRESS">%2$s</xliff:g> completado"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Se completó el <xliff:g id="PROGRESS">%2$s</xliff:g> de la descarga de <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Instalación de <xliff:g id="NAME">%1$s</xliff:g> en espera"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Es necesario actualizar la app"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"No se actualizó la app de este ícono. Puedes actualizarla manualmente para rehabilitar el acceso directo, o bien quitar el ícono."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Actualizar"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Quitar"</string>
<string name="widgets_list" msgid="796804551140113767">"Lista de widgets"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Se cerró la lista de widgets"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Agregar a la pantalla principal"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Agregar a pantalla principal"</string>
<string name="action_move_here" msgid="2170188780612570250">"Mover elemento aquí"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Se agregó el elemento a la pantalla principal."</string>
<string name="item_removed" msgid="851119963877842327">"Se eliminó el elemento."</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Elemento agregado a la carpeta"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Crear carpeta con: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Carpeta creada"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Mover a la pantalla principal"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Mover a la pantalla principal"</string>
<string name="action_resize" msgid="1802976324781771067">"Ajustar tamaño"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Aumentar el ancho"</string>
<string name="action_increase_height" msgid="459390020612501122">"Aumentar la altura"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Desactivar las apps de trabajo"</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="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="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 87eb67a..823e5a7 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de ancho por %2$d de alto"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Widget de <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Mantén pulsado el widget para moverlo por la pantalla de inicio"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Añadir a pantalla de inicio"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabajo"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversaciones"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Información útil al alcance de la mano"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Para ver información sin abrir una aplicación, puedes añadir widgets a la pantalla de inicio"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Entendido"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Cambiar ajustes del widget"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notificaciones"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Mantén pulsado un acceso directo para moverlo."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Toca dos veces y mantén pulsado un acceso directo para moverlo o usar acciones personalizadas."</string>
- <string name="out_of_space" msgid="6692471482459245734">"No queda espacio en la pantalla de inicio"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"No queda espacio en esta pantalla de inicio"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"La bandeja de favoritos está completa"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Lista de aplicaciones"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Resultados de búsqueda"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Fijar predicción"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalar accesos directos"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite que una aplicación añada accesos directos sin intervención del usuario."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"leer información de accesos directos y de ajustes de la pantalla de inicio"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Permite que la aplicación consulte los ajustes y los accesos directos de la pantalla de inicio."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"escribir información de accesos directos y de ajustes de la pantalla de inicio"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Permite que las aplicaciones cambien los ajustes y los accesos directos de la pantalla de inicio."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"leer ajustes y accesos directos de la pantalla de inicio"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Esta aplicación es del sistema y no se puede desinstalar."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Editar nombre"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Se ha inhabilitado <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} tiene # notificación}other{{app_name} tiene # notificaciones}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} tiene # notificación}other{{app_name} tiene # notificaciones}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Página %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Pantalla de inicio %1$d de %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nueva página de pantalla de inicio"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Fondo de pantalla y estilo"</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="7728578836261442095">"Permitir rotación de la pantalla de inicio"</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_desc_on" msgid="1679848116452218908">"Activado"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Para mostrar puntos de notificación, activa las notificaciones de <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Cambiar ajustes"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Mostrar puntos de notificación"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Añadir aplicaciones a la pantalla de inicio"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Opciones para desarrolladores"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Añadir iconos de aplicaciones a la pantalla de inicio"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Añade el icono de una aplicación nueva instalada a la pantalla de inicio"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconocido"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Quitar"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Instalando <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> completado"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Descargando <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="PROGRESS">%2$s</xliff:g> completado)"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Esperando para instalar <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Debes actualizar la aplicación"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"La aplicación de este icono no está actualizada. Puedes actualizarla manualmente para volver a habilitar este acceso directo o puedes eliminar el icono."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Actualizar"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Quitar"</string>
<string name="widgets_list" msgid="796804551140113767">"Lista de widgets"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Lista de widgets cerrada"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Añadir a pantalla de inicio"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Añadir a pantalla de inicio"</string>
<string name="action_move_here" msgid="2170188780612570250">"Mover elemento aquí"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Elemento añadido a la pantalla de inicio"</string>
<string name="item_removed" msgid="851119963877842327">"Elemento quitado"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Elemento añadido a carpeta"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Crear carpeta con: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Carpeta creada"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Mover a la pantalla de inicio"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Mover a la pantalla de inicio"</string>
<string name="action_resize" msgid="1802976324781771067">"Modificar tamaño"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Aumentar ancho"</string>
<string name="action_increase_height" msgid="459390020612501122">"Aumentar altura"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Desactivar aplicaciones de trabajo"</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="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="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 e483041..bd2190a 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Vidina teisaldamiseks avakuval puudutage vidinat ja hoidke seda all"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Lisa avakuvale"</string>
+ <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Vidina teisaldamiseks avakuval puudutage vidinat ja hoidke seda all"</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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Töö"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Vestlused"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Kasulik teave on teie käeulatuses"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Teabe saamiseks rakendusi avamata võite oma avakuvale lisada vidinaid"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Selge"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Vidina seadete muutmine"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Märguanded"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Otsetee teisaldamiseks puudutage ja hoidke all."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Otsetee teisaldamiseks või kohandatud toimingute kasutamiseks topeltpuudutage ja hoidke all."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Sellel avakuval pole ruumi"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Sellel avakuval pole ruumi"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Salves Lemmikud pole rohkem ruumi"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Rakenduste loend"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Otsingutulemused"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Kinnita ennustus"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"installi otseteed"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Võimaldab rakendusel lisada otseteid kasutaja sekkumiseta."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"avakuva seadete ja otseteede lugemine"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Võimaldab rakendusel lugeda avaekraanil seadeid ja otseteid."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"avakuva seadete ja otseteede kirjutamine"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Võimaldab rakendusel muuta avaekraanil seadeid ja otseteid."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"avakuva seadete ja otseteede lugemine"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"See on süsteemirakendus ja seda ei saa desinstallida."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Muuda nime"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> on keelatud"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{Rakenduses {app_name} on # märguanne}other{Rakenduses {app_name} on # märguannet}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{Rakenduses {app_name} on # märguanne}other{Rakenduses {app_name} on # märguannet}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Leht %1$d/%2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Avakuva %1$d/%2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Uus avakuva leht"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Taustapilt ja stiil"</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="7728578836261442095">"Luba avakuva pööramine"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Luba avakuva pööramine"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kui telefoni pööratakse"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Märguandetäpid"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Sees"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Märguandetäppide kuvamiseks lülitage sisse rakenduse <xliff:g id="NAME">%1$s</xliff:g> märguanded"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Seadete muutmine"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Kuva märguandetäpid"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Lisa rakenduste ikoonid avakuvale"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Arendaja valikud"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Lisa rakenduste ikoonid avakuvale"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Uute rakenduste puhul"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Teadmata"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Eemalda"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Üksust <xliff:g id="NAME">%1$s</xliff:g> installitakse, <xliff:g id="PROGRESS">%2$s</xliff:g> on valmis"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Rakenduse <xliff:g id="NAME">%1$s</xliff:g> allalaadimine, <xliff:g id="PROGRESS">%2$s</xliff:g> on valmis"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> on installimise ootel"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Rakendust tuleb värskendada"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Selle ikooni rakendust pole värskendatud. Otsetee uuesti lubamiseks võite rakendust käsitsi värskendada või ikooni eemaldada."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Värskenda"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Eemalda"</string>
<string name="widgets_list" msgid="796804551140113767">"Vidinate loend"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Vidinate loend on suletud"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Lisa avakuvasse"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Lisa avakuvale"</string>
<string name="action_move_here" msgid="2170188780612570250">"Teisalda üksus siia"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Üksus lisati avaekraanile"</string>
<string name="item_removed" msgid="851119963877842327">"Üksus eemaldati"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Üksus lisati kausta"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Kausta loomine nimega <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Kaust on loodud"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Teisalda avaekraanile"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Teisalda avakuvale"</string>
<string name="action_resize" msgid="1802976324781771067">"Muuda suurust"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Suurenda laiust"</string>
<string name="action_increase_height" msgid="459390020612501122">"Suurenda kõrgust"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Lülita töörakendused välja"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Nurjus: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 90da2b1..c1eaea8 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d zabal eta %2$d luze"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widgeta"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Widgeta hasierako pantailan zehar mugitzeko, eduki ezazu sakatuta"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Gehitu hasierako pantailan"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Lanekoak"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Elkarrizketak"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Informazio erabilgarria beti eskura"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Aplikaziorik ireki beharrik gabe informazioa zuzenean jasotzeko, gehitu widgetak hasierako pantailan"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Ados"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Aldatu widgeten ezarpenak"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Jakinarazpenak"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Eduki sakatuta lasterbide bat mugitzeko."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Sakatu birritan eta eduki sakatuta lasterbide bat mugitzeko edo ekintza pertsonalizatuak erabiltzeko."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Ez dago tokirik hasierako pantailan"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Ez dago tokirik hasierako pantailan"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Ez dago toki gehiago Gogokoak erretiluan"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Aplikazioen zerrenda"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Bilaketa-emaitzak"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Ainguratu iragarpena"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"Instalatu lasterbideak"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Erabiltzaileak ezer egin gabe lasterbideak gehitzeko baimena ematen die aplikazioei."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"Irakurri hasierako ezarpenak eta lasterbideak"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Hasierako pantailako ezarpenak eta lasterbideak irakurtzeko baimena ematen die aplikazioei."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"Idatzi hasierako ezarpenak eta lasterbideak"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Hasierako pantailako ezarpenak eta lasterbideak aldatzeko baimena ematen die aplikazioei."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"irakurri hasierako pantailako ezarpenak eta lasterbideak"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Sistema-aplikazioa da hau eta ezin da desinstalatu."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Editatu izena"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> desgaituta dago"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} aplikazioak # jakinarazpen dauka}other{{app_name} aplikazioak # jakinarazpen dauzka}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} aplikazioak # jakinarazpen dauka}other{{app_name} aplikazioak # jakinarazpen dauzka}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d/%2$d orria"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%1$d/%2$d hasierako pantaila"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Hasierako pantailaren orri berria"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Horma-papera eta estiloa"</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="7728578836261442095">"Eman hasierako pantaila biratzeko baimena"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Eman hasierako pantaila biratzeko baimena"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Telefonoa biratzean"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Jakinarazpen-biribiltxoak"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Aktibatuta"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Jakinarazpen-biribiltxoak ikusteko, aktibatu <xliff:g id="NAME">%1$s</xliff:g> aplikazioaren jakinarazpenak"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Aldatu ezarpenak"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Erakutsi jakinarazpen-biribiltxoak"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Gehitu aplikazioen ikonoak hasierako pantailan"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Garatzaileentzako aukerak"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Gehitu aplikazioen ikonoak hasierako pantailan"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Aplikazio berrien kasuan"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Ezezaguna"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Kendu"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> instalatzen, <xliff:g id="PROGRESS">%2$s</xliff:g> osatuta"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> deskargatzen, <xliff:g id="PROGRESS">%2$s</xliff:g> osatuta"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> instalatzeko zain"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Aplikazioa eguneratu behar da"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Ikonoaren aplikazioa ez dago eguneratuta. Lasterbidea berriro gaitzeko, eskuz egunera dezakezu aplikazioa. Bestela, kendu ikonoa."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Eguneratu"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Kendu"</string>
<string name="widgets_list" msgid="796804551140113767">"Widget-zerrenda"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Itxi da widget-zerrenda"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Gehitu hasierako pantailan"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Gehitu hasierako pantailan"</string>
<string name="action_move_here" msgid="2170188780612570250">"Ekarri elementua hona"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Gehitu da elementua hasierako pantailan"</string>
<string name="item_removed" msgid="851119963877842327">"Kendu da elementua"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Elementua karpetan gehitu da"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Sortu karpeta <xliff:g id="NAME">%1$s</xliff:g> elementuarekin"</string>
<string name="folder_created" msgid="6409794597405184510">"Karpeta sortu da"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Eraman hasierako pantailara"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Eraman hasierako pantailara"</string>
<string name="action_resize" msgid="1802976324781771067">"Aldatu tamaina"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Handitu zabalera"</string>
<string name="action_increase_height" msgid="459390020612501122">"Handitu altuera"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Desaktibatu laneko aplikazioak"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Huts egin du: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index a6888fd..d23eac2 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"ابزارک را لمس کنید و نگه دارید تا آن را در صفحه اصلی حرکت دهید"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"افزودن به صفحه اصلی"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ابزارک}one{# ابزارک}other{# ابزارک}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# میانبر}one{# میانبر}other{# میانبر}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"کار"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"مکالمهها"</string>
<string name="widget_education_header" msgid="4874760613775913787">"دسترسی آسان به اطلاعات سودمند"</string>
- <string name="widget_education_content" msgid="745542879510751525">"با افزودن ابزارکها به «صفحه اصلی» میتوانید اطلاعات را بدون باز کردن برنامهها دریافت کنید"</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>
@@ -65,7 +65,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="6692471482459245734">"فضای خالی در این صفحه اصلی وجود ندارد"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"سنجاق کردن پیشنهاد"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"نصب میانبرها"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"به برنامه اجازه میدهد میانبرها را بدون دخالت کاربر اضافه کند."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"خواندن تنظیمات و میانبرهای صفحه اصلی"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"به برنامه اجازه میدهد تنظیمات و میانبرها را در صفحه اصلی بخواند."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"نوشتن تنظیمات و میانبرهای صفحه اصلی"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"به برنامه اجازه میدهد تنظیمات و میانبرها را در صفحه اصلی تغییر دهد."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"خواندن تنظیمات و میانبرهای صفحه اصلی"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"این برنامه سیستمی است و حذف نصب نمیشود."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} # اعلان دارد}one{{app_name} # اعلان دارد}other{{app_name} # اعلان دارد}}"</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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"کاغذدیواری و سبک"</string>
<string name="settings_button_text" msgid="8873672322605444408">"تنظیمات صفحه اصلی"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"توسط سرپرست سیستم غیرفعال شده است"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"قابلچرخش بودن صفحه اصلی"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"برای نمایش «نقطههای اعلان»، اعلانهای برنامه را برای <xliff:g id="NAME">%1$s</xliff:g> روشن کنید"</string>
<string name="title_change_settings" msgid="1376365968844349552">"تغییر تنظیمات"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"نمایش نقطههای اعلان"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"افزودن نماد برنامهها به صفحه اصلی"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"گزینههای برنامهنویس"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"افزودن نماد برنامهها به صفحه اصلی"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"برای برنامههای جدید"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"نامشخص"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"حذف"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"بهروزرسانی"</string>
+ <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="8902165848117513641">"افزودن به صفحه اصلی"</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_removed" msgid="851119963877842327">"مورد حذف شد"</string>
@@ -141,7 +146,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="1603837886334246317">"انتقال به صفحه اصلی"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"متوجهام"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"خاموش کردن برنامههای کاری"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"توقف موقت برنامههای کاری"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"روشن کردن برنامههای کاری"</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="remote_action_failed" msgid="1383965239183576790">"ناموفق بود: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 874c85d..ccc22f0 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"Leveys: %1$d, korkeus: %2$d"</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="5653291305078645405">"Voit siirtää widgetiä aloitusnäytöllä koskettamalla sitä pitkään"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Lisää aloitusnäytölle"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Työ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Keskustelut"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Hyödyllisiä tietoja käden ulottuvilla"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Jos haluat nähdä tietoja avaamatta sovelluksia, voit lisätä aloitusnäytölle widgetejä"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Muuta widgetin asetuksia"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Ilmoitukset"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Kosketa pitkään, niin voit siirtää pikakuvaketta."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Kaksoisnapauta ja paina pitkään, niin voit siirtää pikakuvaketta tai käyttää muokattuja toimintoja."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Tällä aloitusnäytöllä ei ole tilaa"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Aloitusnäytöllä ei ole tilaa"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Suosikit-valikossa ei ole enää tilaa"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Sovellusluettelo"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Hakutulokset"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Kiinnitä sovellus"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"asenna pikakuvakkeita"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Antaa sovelluksen lisätä pikakuvakkeita itsenäisesti ilman käyttäjän valintaa."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"lue aloitusruudun asetuksia ja pikakuvakkeita"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Antaa sovelluksen lukea aloitusruudun asetukset ja pikakuvakkeet."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"kirjoita aloitusruudun asetuksia ja pikakuvakkeita"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Antaa sovelluksen muuttaa aloitusruudun asetuksia ja pikakuvakkeita."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"lukea aloitusnäytön asetuksia ja pikakuvakkeita"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Tämä on järjestelmäsovellus, eikä sitä voi poistaa."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Muokkaa nimeä"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> poistettiin käytöstä"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name}: # ilmoitus}other{{app_name}: # ilmoitusta}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name}: # ilmoitus}other{{app_name}: # ilmoitusta}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Sivu %1$d / %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Aloitusruutu %1$d/%2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Uusi aloitusnäytön sivu"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Taustakuva ja tyyli"</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="7728578836261442095">"Salli aloitusnäytön kiertäminen"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Salli aloitusnäytön kiertäminen"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kun puhelinta kierretään"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Pistemerkit"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Päällä"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"<xliff:g id="NAME">%1$s</xliff:g> tarvitsee ilmoitusten käyttöoikeuden, jotta pistemerkkejä voidaan näyttää."</string>
<string name="title_change_settings" msgid="1376365968844349552">"Muuta asetuksia"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Näytä ilmoituksista kertovat pistemerkit"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Lisää sovelluskuvakkeet aloitusnäytölle"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Kehittäjäasetukset"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Lisää sovelluskuvakkeet aloitusnäytölle"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Uusille sovelluksille"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Tuntematon"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Poista"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> asennetaan, <xliff:g id="PROGRESS">%2$s</xliff:g> valmis"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> latautuu, valmiina <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> odottaa asennusta"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Sovelluspäivitys vaaditaan"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Kuvakkeen sovellusta ei ole päivitetty. Voit ottaa pikakuvakkeen uudelleen käyttöön päivittämällä sovelluksen tai poistaa kuvakkeen."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Päivitä"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Poista"</string>
<string name="widgets_list" msgid="796804551140113767">"Widget-luettelo"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Widget-luettelo suljettu"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Lisää aloitusnäytölle"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Lisää aloitusnäytölle"</string>
<string name="action_move_here" msgid="2170188780612570250">"Siirrä kohde tänne"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Kohde lisättiin aloitusnäytölle."</string>
<string name="item_removed" msgid="851119963877842327">"Kohde poistettiin"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Kohde on lisätty kansioon."</string>
<string name="create_folder_with" msgid="4050141361160214248">"Luo kansio, jossa on <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="folder_created" msgid="6409794597405184510">"Kansio on luotu."</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Siirrä aloitusnäytölle"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Siirrä aloitusnäytölle"</string>
<string name="action_resize" msgid="1802976324781771067">"Muuta kokoa"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Lisää leveyttä"</string>
<string name="action_increase_height" msgid="459390020612501122">"Lisää korkeutta"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Laita työsovellukset pois päältä"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Epäonnistui: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 9a77c87..11bcae1 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largeur sur %2$d de hauteur"</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="5653291305078645405">"Maintenez le doigt sur le widget pour le déplacer sur l\'écran d\'accueil"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Ajouter à l\'écran d\'accueil"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Professionnels"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Renseignements utiles à portée de main"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Pour obtenir des renseignements sans ouvrir d\'application, vous pouvez ajouter des widgets à votre écran d\'accueil"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Modifier les paramètres du widget"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Maintenez le doigt sur un raccourci pour le déplacer."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Touchez deux fois un raccourci et maintenez le doigt dessus pour le déplacer ou utiliser des actions personnalisées."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Pas d\'espace libre sur cet écran d\'accueil"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Pas d\'espace libre sur cet écran d\'accueil"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Il n\'y a plus d\'espace dans la zone des favoris"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Liste des applications"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Résultats de recherche"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Épingler la prédiction"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"installer des raccourcis"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permet à une application d\'ajouter des raccourcis sans l\'intervention de l\'utilisateur."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"lire les paramètres et les raccourcis de la page d\'accueil"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Permet à l\'application de lire les paramètres et les raccourcis de l\'écran d\'accueil."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"enregistrer les paramètres de la page d\'accueil et des raccourcis"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Permet à l\'application de modifier les paramètres et les raccourcis de l\'écran d\'accueil."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"lire les paramètres et les raccourcis de la page d\'accueil"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Impossible de désinstaller cette application, car il s\'agit d\'une application système."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Modifier le nom"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"L\'application <xliff:g id="APP_NAME">%1$s</xliff:g> est désactivée"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} a # notification}one{{app_name} a # notification}other{{app_name} a # notifications}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} a # notification}one{{app_name} a # notification}other{{app_name} a # notifications}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Page %1$d sur %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Écran d\'accueil %1$d sur %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nouvelle page d\'écran d\'accueil"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Fond d\'écran et style"</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="7728578836261442095">"Autoriser la rotation de l\'écran d\'accueil"</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">"Points de notification"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Activé"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Pour afficher les points de notification, activez les notifications d\'application pour <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Modifier les paramètres"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Afficher les points de notification"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Ajouter icônes d\'applis à l\'écran d\'accueil"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Options pour les développeurs"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Ajouter les icônes des applications à l\'écran d\'accueil"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Pour les nouvelles applications"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Inconnu"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Supprimer"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Installation de l\'application <xliff:g id="NAME">%1$s</xliff:g> en cours, <xliff:g id="PROGRESS">%2$s</xliff:g> terminée"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Téléchargement de <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> en attente d\'installation"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Mise à jour de l\'application requise"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"L\'application pour cette icône n\'est pas à jour. Vous pouvez soit la mettre à jour manuellement pour réactiver ce raccourci, soit retirer l\'icône."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Mettre à jour"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Retirer"</string>
<string name="widgets_list" msgid="796804551140113767">"Liste des widgets"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Liste des widgets fermée"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Ajouter à l\'écran d\'accueil"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Ajouter à l\'écran d\'accueil"</string>
<string name="action_move_here" msgid="2170188780612570250">"Déplacer l\'élément ici"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Élément ajouté à l\'écran d\'accueil"</string>
<string name="item_removed" msgid="851119963877842327">"Élément retiré"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Élément ajouté au dossier"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Créer un dossier avec : <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Dossier créé"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Déplacer sur l\'écran d\'accueil"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Déplacer sur l\'écran d\'accueil"</string>
<string name="action_resize" msgid="1802976324781771067">"Redimensionner"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Augmenter la largeur"</string>
<string name="action_increase_height" msgid="459390020612501122">"Augmenter la hauteur"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Désactiver les applications professionnelles"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Échec : <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index af81a13..dc1129f 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largeur et %2$d de hauteur"</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="5653291305078645405">"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="8631549138215492708">"Ajouter à l\'écran d\'accueil"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Professionnels"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Infos utiles à portée de main"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Pour obtenir des infos sans ouvrir d\'applis, vous pouvez ajouter des widgets à votre écran d\'accueil"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Modifier les paramètres du widget"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Appuyez de manière prolongée pour déplacer un raccourci."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Appuyez deux fois et maintenez la pression pour déplacer un raccourci ou utiliser les actions personnalisées."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Espace insuffisant sur cet écran d\'accueil"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Espace insuffisant sur cet écran d\'accueil"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Plus d\'espace disponible dans la zone de favoris."</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Liste d\'applications"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Résultats de recherche"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Épingler la prédiction"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"installer des raccourcis"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permettre à une application d\'ajouter des raccourcis sans l\'intervention de l\'utilisateur"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"lire les paramètres et les raccourcis de l\'écran d\'accueil"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Permettre à l\'application de lire les paramètres et les raccourcis de l\'écran d\'accueil"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"modifier les paramètres et les raccourcis de l\'écran d\'accueil"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Permettre à l\'application de modifier les paramètres et les raccourcis de l\'écran d\'accueil"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"Lire les paramètres et les raccourcis de la page d\'accueil"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Impossible de désinstaller cette application, car il s\'agit d\'une application système."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Modifier le nom"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> est désactivé."</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} a # notification}one{{app_name} a # notification}other{{app_name} a # notifications}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} a # notification}one{{app_name} a # notification}other{{app_name} a # notifications}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Page %1$d sur %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Écran d\'accueil %1$d sur %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nouvelle page d\'écran d\'accueil"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Fond d\'écran et style"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Paramètres de l\'accueil"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Désactivé par votre administrateur"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Autoriser la rotation de l\'écran d\'accueil"</string>
+ <string name="allow_rotation_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>
@@ -114,7 +114,8 @@
<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>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Afficher les pastilles de notification"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Ajouter les icônes des applis à l\'écran d\'accueil"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Options pour les développeurs"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Ajouter les icônes des applications à l\'écran d\'accueil"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Pour les nouvelles applications"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Inconnu"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Supprimer"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Installation de <xliff:g id="NAME">%1$s</xliff:g>… (<xliff:g id="PROGRESS">%2$s</xliff:g> terminés)"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> en cours de téléchargement, <xliff:g id="PROGRESS">%2$s</xliff:g> effectué(s)"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> en attente d\'installation"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Mise à jour de l\'appli requise"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"L\'appli correspondant à cette icône n\'est pas mise à jour. Vous pouvez la mettre à jour manuellement pour réactiver le raccourci ou supprimer l\'icône."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Modifier"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Supprimer"</string>
<string name="widgets_list" msgid="796804551140113767">"Liste des widgets"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"La liste des widgets est fermée"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Ajouter à l\'écran d\'accueil"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Ajouter à l\'écran d\'accueil"</string>
<string name="action_move_here" msgid="2170188780612570250">"Déplacer l\'élément ici"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"L\'élément a bien été ajouté à l\'écran d\'accueil."</string>
<string name="item_removed" msgid="851119963877842327">"Élément supprimé"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Élément ajouté au dossier"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Créer un dossier avec \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
<string name="folder_created" msgid="6409794597405184510">"Dossier créé"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Déplacer vers l\'écran d\'accueil"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Déplacer sur l\'écran d\'accueil"</string>
<string name="action_resize" msgid="1802976324781771067">"Redimensionner"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Augmenter la largeur"</string>
<string name="action_increase_height" msgid="459390020612501122">"Augmenter la hauteur"</string>
@@ -153,8 +158,8 @@
<string name="action_dismiss_notification" msgid="5909461085055959187">"Ignorer"</string>
<string name="accessibility_close" msgid="2277148124685870734">"Fermer"</string>
<string name="notification_dismissed" msgid="6002233469409822874">"Notification ignorée"</string>
- <string name="all_apps_personal_tab" msgid="4190252696685155002">"Personnelles"</string>
- <string name="all_apps_work_tab" msgid="4884822796154055118">"Professionnelles"</string>
+ <string name="all_apps_personal_tab" msgid="4190252696685155002">"Personnel"</string>
+ <string name="all_apps_work_tab" msgid="4884822796154055118">"Professionnel"</string>
<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>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Désactiver les applis professionnelles"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Échec : <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index d669ef0..013011a 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largo por %2$d de alto"</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="5653291305078645405">"Mantén premido o widget para movelo pola pantalla de inicio"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Engadir á pantalla de inicio"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<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_education_header" msgid="4874760613775913787">"Información útil ao teu alcance"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Se queres obter información sen abrir as aplicacións, podes engadir widgets á pantalla de inicio"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Entendido"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Cambiar configuración do widget"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notificacións"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Mantén premido un atallo para movelo."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Toca dúas veces un atallo e manteno premido para movelo ou utiliza accións personalizadas."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Non queda espazo nesta pantalla de inicio"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Non queda espazo nesta pantalla de inicio"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Non hai máis espazo na bandexa de favoritos"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Lista de aplicacións"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Resultados da busca"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Fixar predición"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalar atallos"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite a unha aplicación engadir atallos sen intervención do usuario."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"ler a configuración e os atallos da pantalla de inicio"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Permite a unha aplicación ler a configuración e os atallos da páxina de inicio."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"modificar a configuración e os atallos da pantalla de inicio"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Permite a unha aplicación cambiar a configuración e os atallos da pantalla de inicio."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"ler a configuración e os atallos da pantalla de inicio"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Esta aplicación é do sistema e non se pode desinstalar."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Edita o nome"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Desactivouse <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} ten # notificación}other{{app_name} ten # notificacións}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} ten # notificación}other{{app_name} ten # notificacións}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Páxina %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Pantalla de inicio %1$d de %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nova páxina da pantalla de inicio"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Estilo e fondo de pantalla"</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="7728578836261442095">"Permitir xirar a pantalla de inicio"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Permitir xirar a pantalla de inicio"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Ao xirar o teléfono"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Puntos de notificacións"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Activados"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Para que se mostren os puntos de notificacións, activa as notificacións da aplicación <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Cambiar configuración"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Mostra puntos de notificacións"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Engadir iconas de aplicacións á pantalla de inicio"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Opcións de programador"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Engadir iconas de aplicacións á pantalla de inicio"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para novas aplicacións"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Descoñecido"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Quitar"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Instalando <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> completado"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Descargando <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="PROGRESS">%2$s</xliff:g> completado)"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Esperando para instalar <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"É necesario actualizar a aplicación"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"A aplicación á que corresponde esta icona non está actualizada. Podes actualizala manualmente para activar de novo este atallo, ou ben quitar a icona."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Actualizar"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Quitar"</string>
<string name="widgets_list" msgid="796804551140113767">"Lista de widgets"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Pechouse a lista de widgets"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Engadir á pantalla de inicio"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Engadir á pantalla de inicio"</string>
<string name="action_move_here" msgid="2170188780612570250">"Mover elemento aquí"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Engadiuse o elemento á pantalla de inicio"</string>
<string name="item_removed" msgid="851119963877842327">"Quitouse o elemento"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Engadiuse o elemento ao cartafol"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Crear cartafol con: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Creouse o cartafol"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Mover á pantalla de inicio"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Mover á pantalla de inicio"</string>
<string name="action_resize" msgid="1802976324781771067">"Cambiar tamaño"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Aumentar ancho"</string>
<string name="action_increase_height" msgid="459390020612501122">"Aumentar altura"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Desactivar aplicacións do traballo"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Erro: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index 09e58b0..2d504e3 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"વિજેટને હોમ સ્ક્રીનની આજુબાજુ ખસેડવા માટે, તેને ટચ કરીને થોડીવાર દબાવી રાખો"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"હોમ સ્ક્રીન પર ઉમેરો"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# વિજેટ}one{# વિજેટ}other{# વિજેટ}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# શૉર્ટકટ}one{# શૉર્ટકટ}other{# શૉર્ટકટ}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ઑફિસ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"વાતચીતો"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ઉપયોગી માહિતી તમારી આંગળીના ટેરવે"</string>
- <string name="widget_education_content" msgid="745542879510751525">"ઍપને ખોલ્યા વિના માહિતી મેળવવા માટે, તમે તમારી હોમ સ્ક્રીન પર વિજેટ ઉમેરી શકો છો"</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>
@@ -65,7 +65,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="6692471482459245734">"આ હોમ સ્ક્રીન પર વધુ જગ્યા નથી"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"પૂર્વાનુમાનને પિન કરો"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"શૉર્ટકટ ઇન્સ્ટૉલ કરો"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"એપ્લિકેશનને વપરાશકર્તા હસ્તક્ષેપ વગર શોર્ટકટ્સ ઉમેરવાની મંજૂરી આપે છે."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"હોમ સેટિંગ અને શૉર્ટકટ વાંચો"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"ઍપને હોમમાં સેટિંગ અને શૉર્ટકટ વાંચવાની મંજૂરી આપે છે."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"હોમ સેટિંગ અને શૉર્ટકટ લખો"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"ઍપને હોમમાં સેટિંગ અને શૉર્ટકટ બદલવાની મંજૂરી આપે છે."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"હોમ સેટિંગ અને શૉર્ટકટ વાંચો"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"આ એક સિસ્ટમ ઍપ્લિકેશન છે અને અનઇન્સ્ટોલ કરી શકાતી નથી."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name}ના # નોટિફિકેશન છે}one{{app_name}ના # નોટિફિકેશન છે}other{{app_name}ના # નોટિફિકેશન છે}}"</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">"%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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"વૉલપેપર અને સ્ટાઇલ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"હોમ સેટિંગ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"તમારા વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"હોમ સ્ક્રીનને ફેરવવાની મંજૂરી આપો"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"નોટિફિકેશન માટેનું ચિહ્ન બતાવવા હેતુ, <xliff:g id="NAME">%1$s</xliff:g> માટેની ઍપ્લિકેશન નોટિફિકેશન ચાલુ કરો"</string>
<string name="title_change_settings" msgid="1376365968844349552">"સેટિંગ બદલો"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"નોટિફિકેશન માટેના ચિહ્ન બતાવો"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"ઍપના આઇકન હોમ સ્ક્રીન પર ઉમેરો"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"ડેવલપરના વિકલ્પો"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"ઍપના આઇકન હોમ સ્ક્રીનમાં ઉમેરો"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"નવી ઍપ માટે"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"અજાણ્યો"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"કાઢી નાખો"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"અપડેટ કરો"</string>
+ <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="8902165848117513641">"હોમ સ્ક્રીન પર ઉમેરો"</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_removed" msgid="851119963877842327">"આઇટમ કાઢી નાખી"</string>
@@ -141,7 +146,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="1603837886334246317">"હોમ સ્ક્રીન પર ખસેડો"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"સમજાઈ ગયું"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"ઑફિસ માટેની ઍપ બંધ કરો"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ઑફિસની ઍપ થોભાવો"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ઑફિસ માટેની ઍપ ચાલુ કરો"</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="remote_action_failed" msgid="1383965239183576790">"નિષ્ફળ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index c7f2d9c..26c0983 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"होम स्क्रीन पर यहां-वहां ले जाने के लिए विजेट को दबाकर रखें"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"होम स्क्रीन पर जोड़ें"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# विजेट}one{# विजेट}other{# विजेट}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# शॉर्टकट}one{# शॉर्टकट}other{# शॉर्टकट}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ऑफ़िस"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"बातचीत"</string>
<string name="widget_education_header" msgid="4874760613775913787">"काम की जानकारी आसानी से पाएं"</string>
- <string name="widget_education_content" msgid="745542879510751525">"ऐप्लिकेशन को खोले बिना उनकी जानकारी पाने के लिए, होम स्क्रीन पर विजेट जोड़े जा सकते हैं"</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>
@@ -65,7 +65,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="6692471482459245734">"इस होम स्क्रीन पर जगह खाली नहीं है"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"सुझाए गए ऐप्लिकेशन को पिन करें"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"शॉर्टकट इंस्टॉल करें"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ऐप को उपयोगकर्ता के हस्तक्षेप के बिना शॉर्टकट जोड़ने देती है."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"होम पेज की सेटिंग और शॉर्टकट पढ़ें"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"ऐप्लिकेशन को होम पेज में सेटिंग और शॉर्टकट पढ़ने देती है."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"होम पेज की सेटिंग और शॉर्टकट लिखें"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"ऐप्लिकेशन को होम पेज में सेटिंग और शॉर्टकट बदलने देती है."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"होम स्क्रीन की सेटिंग और शॉर्टकट पढ़ने की अनुमति"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"यह एक सिस्टम ऐप्लिकेशन है और इसे अनइंस्टॉल नहीं किया जा सकता."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} से जुड़ी # सूचना है}one{{app_name} से जुड़ी # सूचना है}other{{app_name} से जुड़ी # सूचनाएं हैं}}"</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">"पेज %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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"वॉलपेपर और स्टाइल"</string>
<string name="settings_button_text" msgid="8873672322605444408">"होम पेज की सेटिंग"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"आपके एडमिन ने बंद किया हुआ है"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"होमस्क्रीन घुमाने की अनुमति दें"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"सूचना बिंदु दिखाने के लिए, <xliff:g id="NAME">%1$s</xliff:g> के ऐप्लिकेशन सूचना चालू करें"</string>
<string name="title_change_settings" msgid="1376365968844349552">"सेटिंग बदलें"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"नई सूचनाएं बताने वाला गोल निशान दिखाएं"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"होम स्क्रीन पर ऐप्लिकेशन के आइकॉन जोड़ें"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"डेवलपर के लिए सेटिंग और टूल"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"होम स्क्रीन पर ऐप्लिकेशन के आइकॉन जोड़ें"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नए ऐप्लिकेशन के लिए"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"निकालें"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"अपडेट करें"</string>
+ <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="8902165848117513641">"होम स्क्रीन में जोड़ें"</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_removed" msgid="851119963877842327">"आइटम हटाया गया"</string>
@@ -141,7 +146,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="1603837886334246317">"होम स्क्रीन पर ले जाएं"</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>
@@ -154,17 +159,19 @@
<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">"ऑफ़िस के काम से जुड़े ऐप्लिकेशन बैज किए गए हैं और आईटी एडमिन को दिख रहे हैं"</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_body" msgid="261634750995824906">"ऑफ़िस के काम से जुड़े आपके ऐप्लिकेशन, आपको सूचनाएं नहीं भेज सकते. साथ ही, आपकी बैटरी का इस्तेमाल या आपकी जगह की जानकारी को ऐक्सेस भी नहीं कर सकते"</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">"ऑफ़िस के काम से जुड़े ऐप्लिकेशन बैज किए गए हैं और आईटी एडमिन को दिख रहे हैं"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"ठीक है"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"ऑफ़िस के काम से जुड़े ऐप्लिकेशन बंद करें"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"वर्क ऐप्लिकेशन रोकें"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ऑफ़िस के काम से जुड़े ऐप्लिकेशन चालू करें"</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="remote_action_failed" msgid="1383965239183576790">"पूरा नहीं हुआ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 75e47a1..0e58e53 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d širine i %2$d visine"</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="5653291305078645405">"Dodirnite i zadržite widget da biste ga pomicali po početnom zaslonu"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Dodaj na početni zaslon"</string>
+ <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Dodirnite i zadržite widget da biste ga pomicali po početnom zaslonu"</string>
+ <string name="add_to_home_screen" msgid="9168649446635919791">"Dodaj na početni zaslon"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> dodan je na početni zaslon"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}few{# widgeta}other{# widgeta}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# prečac}one{# prečac}few{# prečaca}other{# prečaca}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Posao"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Razgovori"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Korisne informacije nadohvat ruke"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Da biste dobili informacije bez otvaranja aplikacija, možete dodati widgete na početni zaslon"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Shvaćam"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Promijenite postavke widgeta"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Obavijesti"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Dodirnite i zadržite da biste premjestili prečac."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Dvaput dodirnite i zadržite pritisak da biste premjestili prečac ili upotrijebite prilagođene radnje."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Na ovom početnom zaslonu više nema mjesta"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Na ovom početnom zaslonu više nema mjesta."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Nema više prostora na traci Favoriti"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Popis aplikacija"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Rezultati pretraživanja"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Prikvači predviđenu apl."</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instaliranje prečaca"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Aplikaciji omogućuje dodavanje prečaca bez intervencije korisnika."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"čitanje postavki početnog zaslona i prečaca"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Aplikaciji omogućuje čitanje postavki i prečaca na početnom zaslonu."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"pisanje postavki početnog zaslona i prečaca"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Aplikaciji omogućuje promjenu postavki i prečaca na početnom zaslonu."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"čitati postavke i prečace početnog zaslona"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ovo je aplikacija sustava i ne može se ukloniti."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Uređivanje naziva"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> onemogućena"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{Aplikacija {app_name} ima # obavijest}one{Aplikacija {app_name} ima # obavijest}few{Aplikacija {app_name} ima # obavijesti}other{Aplikacija {app_name} ima # obavijesti}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{Aplikacija {app_name} ima # obavijest}one{Aplikacija {app_name} ima # obavijest}few{Aplikacija {app_name} ima # obavijesti}other{Aplikacija {app_name} ima # obavijesti}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Stranica %1$d od %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Početni zaslon %1$d od %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nova stranica početnog zaslona"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Pozadina i stil"</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="7728578836261442095">"Dopusti zakretanje početnog zaslona"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Dopusti zakretanje početnog zaslona"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kada se telefon zakrene"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Točke obavijesti"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Uključeno"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Za prikaz točaka obavijesti uključite obavijesti aplikacije <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Promjena postavki"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Prikaži točke obavijesti"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Dodaj ikone aplikacija na početni zaslon"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Opcije za razvojne programere"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Dodaj ikone aplikacija na početni zaslon"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Za nove aplikacije"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Nepoznato"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Ukloni"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Instaliranje aplikacije <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> dovršeno"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Preuzimanje aplikacije <xliff:g id="NAME">%1$s</xliff:g>, dovršeno <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Čekanje na instaliranje aplikacije <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Aplikacija se treba ažurirati"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Aplikacija ove ikone nije ažurirana. Možete ručno ažurirati da biste ponovo omogućili ovaj prečac ili uklonite ikonu."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Ažuriraj"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Ukloni"</string>
<string name="widgets_list" msgid="796804551140113767">"Popis widgeta"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Popis widgeta zatvoren"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Dodavanje na početni zaslon"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Dodajte na početni zaslon"</string>
<string name="action_move_here" msgid="2170188780612570250">"Premjesti stavku ovdje"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Stavka je dodana na početni zaslon"</string>
<string name="item_removed" msgid="851119963877842327">"Stavka je uklonjena"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Stavka dodana u mapu"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Izrada mape pomoću stavke: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Mapa izrađena"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Premještanje na početni zaslon"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Premjestite na početni zaslon"</string>
<string name="action_resize" msgid="1802976324781771067">"Promjena veličine"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Povećanje širine"</string>
<string name="action_increase_height" msgid="459390020612501122">"Povećanje visine"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Isključite poslovne aplikacije"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Nije uspjelo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 71a8d69..30095d7 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d széles és %2$d magas"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> modul"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Tartsa lenyomva a modult a kezdőképernyőn való mozgatáshoz"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Hozzáadás a kezdőképernyőhöz"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<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_education_header" msgid="4874760613775913787">"Hasznos információk egy koppintásnyira"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Ha az alkalmazások megnyitása nélkül szeretne információhoz jutni, felvehet modulokat a kezdőképernyőre."</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Értem"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"A modulbeállítások módosítása"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Értesítések"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Tartsa lenyomva a parancsikont az áthelyezéshez."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Parancsikon áthelyezéséhez koppintson duplán, és tartsa nyomva az ujját, vagy használjon egyéni műveleteket."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Nincs több hely ezen a kezdőképernyőn"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Nincs több hely ezen a kezdőképernyőn"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Nincs több hely a Kedvencek tálcán"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Alkalmazások listája"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Keresési találatok"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Várható kitűzése"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"parancsikonok telepítése"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Lehetővé teszi egy alkalmazás számára, hogy felhasználói beavatkozás nélkül adjon hozzá parancsikonokat."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"Főoldal beállításainak és parancsikonjainak beolvasása"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Lehetővé teszi az alkalmazás számára, hogy beolvassa a kezdőképernyő beállításait és parancsikonjait."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"Főoldal beállításainak és parancsikonjainak írása"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Lehetővé teszi az alkalmazás számára, hogy módosítsa a kezdőképernyő beállításait és parancsikonjait."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"kezdőképernyő beállításainak és parancsikonjainak olvasása"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ez egy rendszeralkalmazás, és nem lehet eltávolítani."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Név módosítása"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> letiltva"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{A(z) {app_name} # értesítéssel rendelkezik}other{A(z) {app_name} # értesítéssel rendelkezik}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{A(z) {app_name} alkalmazásnak # értesítése van}other{A(z) {app_name} alkalmazásnak # értesítése van}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$d/%1$d. oldal"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%2$d/%1$d. kezdőképernyő"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Új kezdőképernyő oldal"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Háttérkép és stílus"</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="7728578836261442095">"A kezdőképernyő elforgatásának engedélyezése"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"A kezdőképernyő elforgatásának engedélyezése"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"A telefon elforgatásakor"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Értesítési pöttyök"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Be"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Az értesítési pöttyök megjelenítéséhez kapcsolja be a(z) <xliff:g id="NAME">%1$s</xliff:g> alkalmazás értesítéseit"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Beállítások módosítása"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Értesítési pöttyök megjelenítése"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Appikonok hozzáadása a kezdőképernyőhöz"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Fejlesztői beállítások"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Alkalmazásikonok hozzáadása a kezdőképernyőhöz"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Új alkalmazásoknál"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Ismeretlen"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Törlés"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Folyamatban van a(z) <xliff:g id="NAME">%1$s</xliff:g> telepítése, <xliff:g id="PROGRESS">%2$s</xliff:g> kész"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"A(z) <xliff:g id="NAME">%1$s</xliff:g> letöltése, <xliff:g id="PROGRESS">%2$s</xliff:g> kész"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"A(z) <xliff:g id="NAME">%1$s</xliff:g> telepítésre vár"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Alkalmazásfrissítés szükséges"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Az ikonhoz tartozó alkalmazás nincs frissítve. A parancsikon újbóli engedélyezéséhez frissítse az alkalmazást, vagy távolítsa ez az ikont."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Frissítés"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Eltávolítás"</string>
<string name="widgets_list" msgid="796804551140113767">"Widgetlista"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Widgetlista bezárva"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Hozzáadás a kezdőképernyőhöz"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Hozzáadás a kezdőképernyőhöz"</string>
<string name="action_move_here" msgid="2170188780612570250">"Elem áthelyezése ide"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Elem hozzáadva a kezdőképernyőhöz"</string>
<string name="item_removed" msgid="851119963877842327">"Elem eltávolítva"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Elem hozzáadva a mappához"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Mappa létrehozása a következővel: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Mappa létrehozva"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Áthelyezés a kezdőképernyőre"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Áthelyezés a kezdőképernyőre"</string>
<string name="action_resize" msgid="1802976324781771067">"Átméretezés"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Szélesség növelése"</string>
<string name="action_increase_height" msgid="459390020612501122">"Magasság növelése"</string>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"Értem"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Kapcsolja ki a munkahelyi alkalmazásokat"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Sikertelen: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 3a84b87..af0e168 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Հպեք վիջեթին և պահեք տեղափոխելու համար"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Ավելացնել հիմնական էկրանին"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# վիջեթ}one{# վիջեթ}other{# վիջեթ}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# դյուրանցում}one{# դյուրանցում}other{# դյուրանցում}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Աշխատանքային"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Զրույցներ"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Բոլոր կարևոր տեղեկությունները՝ ձեռքի տակ"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Առանց հավելվածները բացելու տեղեկություններ ստանալու համար ձեր հիմնական էկրանին ավելացրեք վիջեթներ։"</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>
@@ -65,7 +65,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="6692471482459245734">"Հիմնական էկրանին ազատ տեղ չկա"</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>
@@ -75,14 +75,14 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Ապատեղադրել"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Հավելվածի մասին"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Տեղադրել"</string>
- <string name="dismiss_prediction_label" msgid="3357562989568808658">"Թաքցնել առաջարկը"</string>
+ <string name="dismiss_prediction_label" msgid="3357562989568808658">"Չառաջարկել"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Ամրացնել առաջարկվող հավելվածը"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"Դյուրանցումների տեղադրում"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Հավելվածին թույլ է տալիս ավելացնել դյուրանցումներ՝ առանց օգտագործողի միջամտության:"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"կարդալ հիմնաէջի կարգավորումներն ու դյուրանցումները"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Հավելվածին թույլ է տալիս կարդալ հիմնաէջի կարգավորումներն ու դյուրանցումները:"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"ստեղծել հիմնաէջի կարգավորումներ ու դյուրանցումներ"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Հավելվածին թույլ է տալիս փոփոխել հիմնաէջի կարգավորումներն ու դյուրանցումները:"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"կարդալ հիմնական էկրանի կարգավորումներն ու դյուրանցումները"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Սա համակարգային ծրագիր է և չի կարող ապատեղադրվել:"</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{«{app_name}» հավելվածն ունի # ծանուցում}one{«{app_name}» հավելվածն ունի # ծանուցում}other{«{app_name}» հավելվածն ունի # ծանուցում}}"</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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Պաստառ և ոճ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Գլխավոր էկրանի կարգավորումներ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Անջատվել է ձեր ադմինիստրատորի կողմից"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Թույլ տալ հիմնական էկրանի պտտումը"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Ծանուցումների կետիկները ցուցադրելու համար միացրեք ծանուցումները <xliff:g id="NAME">%1$s</xliff:g>-ի համար"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Փոխել կարգավորումները"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Ցուցադրել ծանուցումների կետիկները"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Ավելացնել պատկերակները հիմնական էկրանին"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Մշակողի ընտրանքներ"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Ավելացնել պատկերակները հիմնական էկրանին"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Նոր հավելվածների համար"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Անհայտ է"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Հեռացնել"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"Թարմացնել"</string>
+ <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="8902165848117513641">"Ավելացնել Հիմնական էկրանին"</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_removed" msgid="851119963877842327">"Տարրը հեռացվեց"</string>
@@ -141,7 +146,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="1603837886334246317">"Տեղափոխել Հիմնական էկրան"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"Եղավ"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Անջատել աշխատանքային հավելվածները"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Դադարեցնել աշխատանքային հավելվածները"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Միացնել աշխատանքային հավելվածները"</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="remote_action_failed" msgid="1383965239183576790">"Չհաջողվեց կատարել գործողությունը (<xliff:g id="WHAT">%1$s</xliff:g>)"</string>
</resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index f106774..02f4860 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Sentuh lama widget untuk memindahkannya di sekitar Layar utama"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Tambahkan ke Layar utama"</string>
+ <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Sentuh lama widget untuk memindahkannya di sekitar 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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Kerja"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Percakapan"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Info bermanfaat mudah dilihat"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Untuk mendapatkan info tanpa membuka aplikasi, Anda dapat menambahkan widget ke Layar utama"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Oke"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Ubah setelan widget"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notifikasi"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Sentuh lama untuk memindahkan pintasan."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Ketuk dua kali & tahan untuk memindahkan pintasan atau gunakan tindakan khusus."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Tidak ada ruang di Layar utama ini"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Tidak ada ruang di layar utama ini"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Tidak ada ruang tersisa di baki Favorit"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Daftar aplikasi"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Hasil penelusuran"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Pin Prediksi"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"memasang pintasan"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Mengizinkan aplikasi menambahkan pintasan tanpa campur tangan pengguna."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"membaca setelan dan pintasan layar Utama"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Mengizinkan aplikasi membaca setelan dan pintasan di layar Utama."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"menulis setelan dan pintasan layar Utama"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Mengizinkan aplikasi mengubah setelan dan pintasan di layar Utama."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"membaca setelan dan pintasan layar utama"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ini adalah aplikasi sistem dan tidak dapat dicopot pemasangannya."</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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} memiliki # notifikasi}other{{app_name} memiliki # notifikasi}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} memiliki # notifikasi}other{{app_name} memiliki # notifikasi}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Halaman %1$d dari %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Layar utama %1$d dari %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Halaman layar utama baru"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Wallpaper & gaya"</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="7728578836261442095">"Izinkan Layar utama diputar"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Izinkan layar utama diputar"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Saat ponsel diputar"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Titik notifikasi"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Aktif"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Guna menampilkan Titik Notifikasi, aktifkan notifikasi aplikasi untuk <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Ubah setelan"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Tampilkan titik notifikasi"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Tambahkan ikon aplikasi ke Layar utama"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Opsi Developer"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Tambahkan ikon aplikasi ke layar utama"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Untuk aplikasi baru"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Tidak dikenal"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Buang"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> sedang diinstal, <xliff:g id="PROGRESS">%2$s</xliff:g> selesai"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> sedang didownload, <xliff:g id="PROGRESS">%2$s</xliff:g> selesai"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> menunggu dipasang"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Aplikasi perlu diupdate"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Aplikasi untuk ikon ini belum diupdate. Anda dapat mengupdate secara manual untuk mengaktifkan kembali pintasan ini, atau hapus ikon."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Update"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Hapus"</string>
<string name="widgets_list" msgid="796804551140113767">"Daftar widget"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Daftar widget ditutup"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Tambahkan ke Layar Utama"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Tambahkan ke layar utama"</string>
<string name="action_move_here" msgid="2170188780612570250">"Pindahkan item ke sini"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item ditambahkan ke layar utama"</string>
<string name="item_removed" msgid="851119963877842327">"Item dihapus"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Item ditambahkan ke folder"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Buat folder dengan: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Folder dibuat"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Pindahkan ke layar Utama"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Pindahkan ke layar utama"</string>
<string name="action_resize" msgid="1802976324781771067">"Ubah ukuran"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Tambahi lebar"</string>
<string name="action_increase_height" msgid="459390020612501122">"Tambahi tinggi"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Nonaktifkan aplikasi kerja"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Gagal: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 1397b88..17cf2e4 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d á breidd og %2$d á hæð"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Græjan <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Haltu fingri á græjunni til að hreyfa hana um heimaskjáinn"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Bæta á heimaskjá"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Vinna"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Samtöl"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Gagnlegar upplýsingar innan seilingar"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Þú getur bætt við græjum á heimaskjáinn til að fá upplýsingar án þess að opna forrit"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Ég skil"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Breyta græjustillingum"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Tilkynningar"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Haltu fingri á flýtileið til að færa hana."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Ýttu tvisvar og haltu fingri á flýtileið til að færa hana eða notaðu sérsniðnar aðgerðir."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Ekkert pláss á þessum heimaskjá"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Ekkert pláss á þessum heimaskjá"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Ekki meira pláss í bakka fyrir uppáhald"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Forritalisti"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Leitarniðurstöður"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Festa tillögu"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"setja upp flýtileiðir"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Leyfir forriti að bæta við flýtileiðum án íhlutunar notanda."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"lesa stillingar og flýtileiðir heimaskjás"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Leyfir forriti að lesa stillingar og flýtileiðir heimaskjás."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"skrifa stillingar og flýtileiðir heimaskjás"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Leyfir forriti að breyta stillingum og flýtileiðum heimaskjás."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"lesa stillingar og flýtileiðir heimaskjás"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Þetta er kerfisforrit sem ekki er hægt að fjarlægja."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Breyta nafni"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Óvirkt <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} er með # tilkynningu}one{{app_name} er með # tilkynningu}other{{app_name} er með # tilkynningar}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} er með # tilkynningu}one{{app_name} er með # tilkynningu}other{{app_name} er með # tilkynningar}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Síða %1$d af %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Heimaskjár %1$d af %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Ný síða á heimaskjá"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Veggfóður og stíll"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Heimastillingar"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Gert óvirkt af kerfisstjóra"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Leyfa snúning á heimaskjá"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Leyfa snúning á heimaskjá"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Þegar símanum er snúið"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Tilkynningapunktar"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Kveikt"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Til að sýna tilkynningarpunkta skaltu kveikja á forritstilkynningum fyrir <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Breyta stillingum"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Sýna tilkynningapunkta"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Bæta forritatáknum við heimaskjáinn"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Forritunarkostir"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Bæta forritatáknum við heimaskjáinn"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Fyrir ný forrit"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Óþekkt"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Taka niður"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Setur upp <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> lokið"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> í niðurhali, <xliff:g id="PROGRESS">%2$s</xliff:g> lokið"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> bíður uppsetningar"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Uppfæra þarf forritið"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Forritið fyrir þetta tákn er ekki uppfært. Þú getur uppfært það handvirkt til að kveikja aftur á þessari flýtileið eða fjarlægt táknið."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Uppfæra"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Fjarlægja"</string>
<string name="widgets_list" msgid="796804551140113767">"Græjulisti"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Græjulista lokað"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Bæta á heimaskjá"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Bæta á heimaskjá"</string>
<string name="action_move_here" msgid="2170188780612570250">"Færa atriði hingað"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Atriði bætt á heimaskjáinn"</string>
<string name="item_removed" msgid="851119963877842327">"Atriði fjarlægt"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Atriði sett í möppu"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Búa til möppu með: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Mappa búin til"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Færa á heimaskjá"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Færa á heimaskjá"</string>
<string name="action_resize" msgid="1802976324781771067">"Breyta stærð"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Auka breidd"</string>
<string name="action_increase_height" msgid="459390020612501122">"Auka hæð"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Slökkva á vinnuforritum"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Mistókst: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index db6a22a..edff814 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d di larghezza per %2$d di altezza"</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="5653291305078645405">"Tocca e tieni premuto il widget per spostarlo nella schermata Home"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Aggiungi a schermata Home"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Lavoro"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversazioni"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Informazioni utili a portata di mano"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Per ricevere informazioni senza aprire le app, puoi aggiungere dei widget alla schermata Home"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Modifica le impostazioni del widget"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notifiche"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Tocca e tieni premuto per spostare una scorciatoia."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Tocca due volte e tieni premuto per spostare una scorciatoia o per usare le azioni personalizzate."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Non c\'è più spazio nella schermata Home"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Non c\'è più spazio nella schermata Home"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Spazio esaurito nella barra dei Preferiti"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Elenco di app"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Risultati di ricerca"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Blocca previsione"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"Aggiunta di scorciatoie"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Consente a un\'app di aggiungere scorciatoie automaticamente."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"lettura di impostazioni e scorciatoie in Home"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Consente all\'app di leggere le impostazioni e le scorciatoie in Home."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"creazione di impostazioni e scorciatoie in Home"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Consente all\'app di modificare le impostazioni e le scorciatoie in Home."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"leggere le impostazioni e le scorciatoie nella schermata Home"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Questa è un\'app di sistema e non può essere disinstallata."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Modifica nome"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"App <xliff:g id="APP_NAME">%1$s</xliff:g> disattivata"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} ha # notifica}other{{app_name} ha # notifiche}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} ha # notifica}other{{app_name} ha # notifiche}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Pagina %1$d di %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Schermata Home %1$d di %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nuova pagina Schermata Home"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Sfondo e stile"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Impostazioni schermata Home"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disattivata dall\'amministratore"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Consenti rotazione della schermata Home"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Consenti rotazione della schermata Home"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Con il telefono ruotato"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Indicatori di notifica"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"On"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Per mostrare gli indicatori di notifica, attiva le notifiche per l\'app <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Modifica impostazioni"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Mostra indicatori di notifica"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Aggiungi icone delle app alla schermata Home"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Opzioni sviluppatore"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Aggiungi icone delle app alla schermata Home"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Per le nuove app"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Sconosciuto"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Rimuovi"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Installazione di <xliff:g id="NAME">%1$s</xliff:g>, completamento: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Download di <xliff:g id="NAME">%1$s</xliff:g> in corso, <xliff:g id="PROGRESS">%2$s</xliff:g> completato"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> in attesa di installazione"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"È necessario aggiornare l\'app"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"L\'app relativa a questa icona non è aggiornata. Puoi eseguire manualmente l\'aggiornamento per riattivare questa scorciatoia oppure rimuovere l\'icona."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Aggiorna"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Rimuovi"</string>
<string name="widgets_list" msgid="796804551140113767">"Elenco di widget"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Elenco di widget chiuso"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Aggiungi a schermata Home"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Aggiungi alla schermata Home"</string>
<string name="action_move_here" msgid="2170188780612570250">"Sposta elemento qui"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Elemento aggiunto alla schermata Home"</string>
<string name="item_removed" msgid="851119963877842327">"Elemento rimosso"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Elemento aggiunto alla cartella"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Crea cartella con: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Cartella creata"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Sposta nella schermata Home"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Sposta nella schermata Home"</string>
<string name="action_resize" msgid="1802976324781771067">"Ridimensiona"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Aumenta larghezza"</string>
<string name="action_increase_height" msgid="459390020612501122">"Aumenta altezza"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Disattiva app di lavoro"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Operazione non riuscita: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index a852587..7de8f08 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"יש ללחוץ לחיצה ארוכה על הווידג\'ט כדי להזיז אותו ברחבי מסך הבית"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"הוספה למסך הבית"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ווידג\'ט אחד}two{# ווידג\'טים}many{# ווידג\'טים}other{# ווידג\'טים}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{קיצור דרך אחד}two{# קיצורי דרך}many{# קיצורי דרך}other{# קיצורי דרך}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"עבודה"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"שיחות"</string>
<string name="widget_education_header" msgid="4874760613775913787">"קבלת מידע שימושי בהקשה"</string>
- <string name="widget_education_content" msgid="745542879510751525">"רוצה לקבל מידע בלי לפתוח אפליקציות? אפשר להוסיף ווידג\'טים למסך הבית"</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>
@@ -65,7 +65,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="6692471482459245734">"אין מקום במסך הבית הזה"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"הצמדת החיזוי"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"התקנת קיצורי דרך"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"מאפשר לאפליקציה להוסיף קיצורי דרך ללא התערבות המשתמש."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"קריאת הגדרות וקיצורי דרך של דף הבית"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"מאפשר לאפליקציה לקרוא את ההגדרות וקיצורי הדרך בדף הבית."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"כתיבת הגדרות וקיצורי דרך של דף הבית"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"מאפשר לאפליקציה לשנות את ההגדרות וקיצורי הדרך בדף הבית."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"קריאת ההגדרות וקיצורי הדרך בדף הבית"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"זוהי אפליקציית מערכת ולא ניתן להסיר את התקנתה."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{לאפליקציה {app_name} יש התראה אחת}two{לאפליקציה {app_name} יש # התראות}many{לאפליקציה {app_name} יש # התראות}other{לאפליקציה {app_name} יש # התראות}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{לאפליקציה {app_name} יש התראה אחת}two{לאפליקציה {app_name} יש # התראות}many{לאפליקציה {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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"טפט וסגנון"</string>
<string name="settings_button_text" msgid="8873672322605444408">"הגדרות של מסך הבית"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"הושבת על ידי מנהל המערכת שלך"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"סיבוב של מסך הבית"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"כדי להציג את סימני ההתראות,יש להפעיל התראות מהאפליקציה <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"שינוי ההגדרות"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"הצגת סימני ההתראות"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"הוספת סמלי אפליקציות למסך הבית"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"אפשרויות למפתחים"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"הוספת סמלי אפליקציות למסך הבית"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"לאפליקציות חדשות"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"לא ידוע"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"הסרה"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"עדכון"</string>
+ <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="8902165848117513641">"הוספה למסך דף הבית"</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_removed" msgid="851119963877842327">"הפריט הוסר"</string>
@@ -141,7 +146,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="1603837886334246317">"העבר אל מסך הבית"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"הבנתי"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"השבתה של אפליקציות לעבודה"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"השהיית האפליקציות לעבודה"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"הפעלה של אפליקציות לעבודה"</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="remote_action_failed" msgid="1383965239183576790">"הפעולה נכשלה: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index a497eab..272183d 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$dx%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="5653291305078645405">"ウィジェットを押し続けると、ホーム画面上に移動できます。"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"ホーム画面に追加"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 件のウィジェット}other{# 件のウィジェット}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# 件のショートカット}other{# 件のショートカット}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"仕事用"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"会話"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ウィジェットで情報を得る"</string>
- <string name="widget_education_content" msgid="745542879510751525">"ホーム画面にウィジェットを追加すると、アプリを開かずに情報を入手できます"</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">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"ウィジェットの設定を変更します"</string>
@@ -65,7 +65,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="6692471482459245734">"このホーム画面には空きスペースがありません"</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>
@@ -75,14 +75,14 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"アンインストール"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"アプリ情報"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"インストール"</string>
- <string name="dismiss_prediction_label" msgid="3357562989568808658">"アプリの候補を表示しない"</string>
+ <string name="dismiss_prediction_label" msgid="3357562989568808658">"アプリを表示しない"</string>
<string name="pin_prediction" msgid="4196423321649756498">"アプリの候補を固定"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"ショートカットのインストール"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ユーザー操作なしでショートカットを追加することをアプリに許可します。"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"ホームの設定とショートカットの読み取り"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"ホームの設定とショートカットの読み取りをアプリに許可します。"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"ホームの設定とショートカットの書き込み"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"ホームの設定とショートカットの変更をアプリに許可します。"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"ホームの設定とショートカットの読み取り"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"このシステムアプリはアンインストールできません。"</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} の通知が # 件あります}other{{app_name} の通知が # 件あります}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"壁紙とスタイル"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ホームの設定"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"管理者により無効にされています"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"ホーム画面の回転を許可"</string>
+ <string name="allow_rotation_title" msgid="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">"ON"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"通知ドットを表示するには、「<xliff:g id="NAME">%1$s</xliff:g>」のアプリ通知を ON にしてください"</string>
<string name="title_change_settings" msgid="1376365968844349552">"設定を変更"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"通知ドットの表示"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"ホーム画面にアプリのアイコンを追加"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"開発者向けオプション"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"ホーム画面にアプリのアイコンを追加"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"新しいアプリをダウンロードしたときに自動で追加します"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"削除"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"更新"</string>
+ <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="8902165848117513641">"ホーム画面に追加"</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_removed" msgid="851119963877842327">"アイテムを削除しました"</string>
@@ -141,7 +146,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="1603837886334246317">"ホーム画面に移動"</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>
@@ -163,8 +168,10 @@
<string name="work_apps_paused_content_description" msgid="5149623040804051095">"仕事用アプリは OFF になっています。仕事用アプリでは、通知の送信、バッテリーの使用、位置情報の取得が無効になっています"</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="1921059713673767460">"仕事用アプリを OFF にする"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"仕事用アプリを一時停止"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"仕事用アプリを ON にする"</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="remote_action_failed" msgid="1383965239183576790">"失敗: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index a0cbbc7..ba5be87 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"ხანგრძლივად შეეხეთ ვიჯეტს მთავარ ეკრანზე მის გადასაადგილებლად"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"მთავარ ეკრანზე დამატება"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ვიჯეტი}other{# ვიჯეტი}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# მალსახმობი}other{# მალსახმობი}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"სამსახური"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"მიმოწერები"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ადვილად მისაწვდომი სასარგებლო ინფორმაცია"</string>
- <string name="widget_education_content" msgid="745542879510751525">"იმისთვის, რომ ინფორმაცია აპების გაუხსნელად მიიღოთ, შეგიძლიათ, მთავარ ეკრანზე ვიჯეტები დაამატოთ"</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>
@@ -65,7 +65,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="6692471482459245734">"ამ მთავარ ეკრანზე ადგილი არ არის"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"ჩამაგრების პროგნოზირება"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"მალსახმობების დაყენება"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"აპისთვის მალსახმობების დამოუკიდებლად დამატების უფლების მიცემა."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"მთავარი ეკრანის პარამეტრებისა და მალსახმობების წაკითხვა"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"აპისთვის მთავარი ეკრანის პარამეტრებისა და მალსახმობების წაკითხვის უფლების მიცემა."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"მთავარი ეკრანის პარამეტრებისა და მალსახმობების ჩაწერა"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"აპისთვის მთავარი ეკრანის პარამეტრებისა და მალსახმობების შეცვლის უფლების მიცემა."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"მთავარი ეკრანის პარამეტრებისა და მალსახმობების წაკითხვა"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ეს სისტემური აპია და მისი წაშლა შეუძლებელია."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name}-ში # შეტყობინებაა}other{{app_name}-ში # შეტყობინებაა}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ფონი და სტილი"</string>
<string name="settings_button_text" msgid="8873672322605444408">"მთავარი გვერდის პარამეტრები"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"გათიშულია თქვენი ადმინისტრატორის მიერ"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"მთავარი ეკრანის შეტრიალების დაშვება"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"შეტყობინებათა ნიშნულების საჩვენებლად, ჩართეთ აპის შეტყობინებები <xliff:g id="NAME">%1$s</xliff:g>-ისთვის"</string>
<string name="title_change_settings" msgid="1376365968844349552">"პარამეტრების შეცვლა"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"შეტყობინების ნიშნულების ჩვენება"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"აპის ხატულების მთავარ ეკრანზე დამატება"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"დეველოპერთა პარამეტრები"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"აპის ხატულების მთავარ ეკრანზე დამატება"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ახალი აპებისთვის"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"უცნობი"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ამოშლა"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"განახლება"</string>
+ <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="8902165848117513641">"მთავარ ეკრანზე დამატება"</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_removed" msgid="851119963877842327">"ერთეული წაიშალა"</string>
@@ -141,7 +146,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="1603837886334246317">"მთავარ ეკრანზე გადატანა"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"გასაგებია"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"სამსახურის აპების გამორთვა"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"სამსახურის აპების დაპაუზება"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"სამსახურის აპების ჩართვა"</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="remote_action_failed" msgid="1383965239183576790">"ვერ მოხერხდა: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index 48bb2eb..83b5a66 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Негізгі экранда қозғалту үшін виджетті басып тұрыңыз."</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Негізгі экранға қосу"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}other{# виджет}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# таңбаша}other{# таңбаша}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Жұмыс виджеттері"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Әңгімелер"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Саусақпен түртсеңіз болғаны – пайдалы ақпарат көз алдыңызда"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Қолданбаларды ашпай-ақ ақпарат алу үшін негізгі экранға тиісті виджеттерді қосыңыз."</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>
@@ -65,7 +65,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="6692471482459245734">"Негізгі экранда бос орын қалмады."</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Болжанған қолданбаны бекіту"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"таңбаша орнату"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Қолданбаға пайдаланушының қатысуынсыз төте пернелерді қосу мүмкіндігін береді."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"Негізгі экрандағы параметрлер мен төте пернелерді оқу"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Қолданбаға Негізгі экрандағы параметрлер мен төте пернелерді оқу мүмкіндігін береді."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"Негізгі экран параметрлері мен төте пернелерін жазу"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Қолданбаға Негізгі экрандағы параметрлер мен төте пернелерді өзгерту мүмкіндігін береді."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"негізгі экран параметрлері мен таңбашаларын оқу"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Бұл жүйе қолданбасы, сондықтан оны алу мүмкін емес."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} қолданбасында # хабарландыру бар}other{{app_name} қолданбасында # хабарландыру бар}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Тұсқағаз және стиль"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Негізгі экран параметрлері"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Әкімші өшірді"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Негізгі экранның бұрылуына рұқсат ету"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Хабарландыру белгілерін көрсету үшін <xliff:g id="NAME">%1$s</xliff:g> қолданбасының қолданба хабарландыруларын қосыңыз"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Параметрлерді өзгерту"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Хабарландыру белгілерін көрсету"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Қолданба белгішесін негізгі экранға қосу"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Әзірлеуші опциялары"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Қолданба белгішелерін негізгі экранға қосу"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Жаңа қолданбаларға арналған"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Белгісіз"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Алып тастау"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"Жаңарту"</string>
+ <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="8902165848117513641">"Негізгі экранға қосу"</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_removed" msgid="851119963877842327">"Элемент жойылды"</string>
@@ -141,7 +146,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="1603837886334246317">"Негізгі экранға жылжыту"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"Түсінікті"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Жұмыс қолданбаларын өшіру"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Жұмыс қолданбаларын тоқтата тұру"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Жұмыс қолданбаларын қосу"</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="remote_action_failed" msgid="1383965239183576790">"Қате шықты: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index a98151e..73ec4df 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"ចុចធាតុក្រាហ្វិកឱ្យជាប់ ដើម្បីផ្លាស់ទីវាជុំវិញអេក្រង់ដើម"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"បញ្ចូលទៅអេក្រង់ដើម"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ធាតុក្រាហ្វិក #}other{ធាតុក្រាហ្វិក #}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{ផ្លូវកាត់ #}other{ផ្លូវកាត់ #}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ការងារ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"ការសន្ទនា"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ទទួលបានព័ត៌មានដែលមានប្រយោជន៍យ៉ាងងាយស្រួល"</string>
- <string name="widget_education_content" msgid="745542879510751525">"ដើម្បីទទួលបានព័ត៌មានដោយមិនចាំបាច់បើកកម្មវិធី អ្នកអាចបញ្ចូលធាតុក្រាហ្វិកទៅក្នុងអេក្រង់ដើមរបស់អ្នក"</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>
@@ -65,7 +65,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="6692471482459245734">"គ្មានកន្លែងនៅលើអេក្រង់ដើមនេះទេ"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"ខ្ទាស់ការព្យាករ"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"ដំឡើងផ្លូវកាត់"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"អនុញ្ញាតឲ្យកម្មវិធីបន្ថែមផ្លូវកាត់ ដោយមិនចាំបាច់អំពើពីអ្នកប្រើ។"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"អានការកំណត់ និងផ្លូវកាត់អេក្រង់ដើម"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"អនុញ្ញាតឲ្យកម្មវិធីអានការកំណត់ និងផ្លូវកាត់ក្នុងអេក្រង់ដើម។"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"សរសេរការកំណត់ និងផ្លូវកាត់លើអេក្រង់ដើម"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"អនុញ្ញាតឲ្យកម្មវិធីប្ដូរការកំណត់ និងផ្លូវកាត់ក្នុងអេក្រង់ដើម។"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"អានការកំណត់ និងផ្លូវកាត់របស់អេក្រង់ដើម"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"នេះជាកម្មវិធីប្រព័ន្ធ មិនអាចលុបបានទេ។"</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} មានការជូនដំណឹង #}other{{app_name} មានការជូនដំណឹង #}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ផ្ទាំងរូបភាព និងរចនាប័ទ្ម"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ការកំណត់ទំព័រដើម"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"បានបិទដំណើរការដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"អនុញ្ញាតការបងិ្វលអេក្រង់ដើម"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"ដើម្បីបង្ហាញស្លាកជូនដំណឹង សូមបើកការជូនដំណឹងកម្មវិធីសម្រាប់ <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ប្ដូរការកំណត់"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"បង្ហាញស្លាកជូនដំណឹង"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"បញ្ចូលរូបកម្មវិធីទៅក្នុងអេក្រង់ដើម"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"ជម្រើសសម្រាប់អ្នកអភិវឌ្ឍន៍"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"បញ្ចូលរូបកម្មវិធីទៅក្នុងអេក្រង់ដើម"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"សម្រាប់កម្មវិធីថ្មី"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"មិនស្គាល់"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"លុបចេញ"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"ដំឡើងកំណែ"</string>
+ <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="8902165848117513641">"បញ្ចូលទៅអេក្រង់ដើម"</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_removed" msgid="851119963877842327">"បានដកធាតុចេញ"</string>
@@ -141,7 +146,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="1603837886334246317">"ផ្លាស់ទៅអេក្រង់ដើម"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"យល់ហើយ"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"បិទកម្មវិធីការងារ"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ផ្អាកកម្មវិធីការងារ"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"បើកកម្មវិធីការងារ"</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="remote_action_failed" msgid="1383965239183576790">"បានបរាជ័យ៖ <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 4eedd5b..1e6f39e 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"ಮುಖಪುಟದ ಪರದೆ ಸುತ್ತ ವಿಜೆಟ್ ಅನ್ನು ಸರಿಸಲು, ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಒತ್ತಿ ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"ಮುಖಪುಟಕ್ಕೆ ಸೇರಿಸಿ"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ವಿಜೆಟ್}one{# ವಿಜೆಟ್ಗಳು}other{# ವಿಜೆಟ್ಗಳು}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ಶಾರ್ಟ್ಕಟ್}one{# ಶಾರ್ಟ್ಕಟ್ಗಳು}other{# ಶಾರ್ಟ್ಕಟ್ಗಳು}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ಕೆಲಸ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"ಸಂಭಾಷಣೆಗಳು"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ನಿಮ್ಮ ಬೆರಳ ತುದಿಯಲ್ಲಿ ಉಪಯುಕ್ತ ಮಾಹಿತಿ"</string>
- <string name="widget_education_content" msgid="745542879510751525">"ಆ್ಯಪ್ಗಳನ್ನು ತೆರೆಯದೆಯೇ ಮಾಹಿತಿಯನ್ನು ಪಡೆಯಲು, ನಿಮ್ಮ ಹೋಮ್ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ನೀವು ವಿಜೆಟ್ಗಳನ್ನು ಸೇರಿಸಬಹುದು"</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>
@@ -65,7 +65,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="6692471482459245734">"ಈ ಹೋಮ್ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ಸ್ಥಳಾವಕಾಶವಿಲ್ಲ"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"ಮುನ್ನೋಟ ಪಿನ್ ಮಾಡಿ"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಸ್ಥಾಪಿಸಿ"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ಬಳಕೆದಾರರ ಹಸ್ತಕ್ಷೇಪವಿಲ್ಲದೆ ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಸೇರಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"ಮುಖಪುಟದ ಸೆಟ್ಟಿಂಗ್ಗಳು ಮತ್ತು ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಓದಿ"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"ಮುಖಪುಟದಲ್ಲಿ ಸೆಟ್ಟಿಂಗ್ಗಳು ಮತ್ತು ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿ ನೀಡುತ್ತದೆ."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"ಮುಖಪುಟದ ಸೆಟ್ಟಿಂಗ್ಗಳು ಮತ್ತು ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಬರೆಯಿರಿ"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"ಮುಖಪುಟದಲ್ಲಿ ಸೆಟ್ಟಿಂಗ್ಗಳು ಮತ್ತು ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿ ನೀಡುತ್ತದೆ."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ ಸೆಟ್ಟಿಂಗ್ಗಳು ಮತ್ತು ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಓದಿ"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ಇದೊಂದು ಅಪ್ಲಿಕೇಶನ್ ಆಗಿದೆ ಮತ್ತು ಅಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} ಆ್ಯಪ್ # ಅಧಿಸೂಚನೆಯನ್ನು ಹೊಂದಿದೆ}one{{app_name} ಆ್ಯಪ್ # ಅಧಿಸೂಚನೆಗಳನ್ನು ಹೊಂದಿದೆ}other{{app_name} ಆ್ಯಪ್ # ಅಧಿಸೂಚನೆಗಳನ್ನು ಹೊಂದಿದೆ}}"</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">"%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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ವಾಲ್ಪೇಪರ್ ಮತ್ತು ಶೈಲಿ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ಮುಖಪುಟ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದ್ದಾರೆ"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"ಮುಖಪುಟ ತಿರುಗುವಿಕೆಯನ್ನು ಅನುಮತಿಸಿ"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"ಅಧಿಸೂಚನೆ ಚುಕ್ಕೆಗಳನ್ನು ತೋರಿಸಲು, <xliff:g id="NAME">%1$s</xliff:g> ಗೆ ಅಪ್ಲಿಕೇಶನ್ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆನ್ ಮಾಡಿ"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಬದಲಾಯಿಸಿ"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"ಅಧಿಸೂಚನೆ ಡಾಟ್ಗಳನ್ನು ತೋರಿಸಿ"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ಗೆ ಆ್ಯಪ್ ಐಕಾನ್ಗಳು ಸೇರಿಸಿ"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"ಡೆವಲಪರ್ ಆಯ್ಕೆಗಳು"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ಗೆ ಆ್ಯಪ್ ಐಕಾನ್ಗಳನ್ನು ಸೇರಿಸಿ"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ಹೊಸ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗೆ"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ಅಪರಿಚಿತ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ತೆಗೆದುಹಾಕಿ"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"ಅಪ್ಡೇಟ್ ಮಾಡಿ"</string>
+ <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="8902165848117513641">"ಮುಖಪುಟಕ್ಕೆ ಸೇರಿಸಿ"</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_removed" msgid="851119963877842327">"ಐಟಂ ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
@@ -141,7 +146,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="1603837886334246317">"ಮುಖಪುಟಕ್ಕೆ ಸರಿಸಿ"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"ಅರ್ಥವಾಯಿತು"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳನ್ನು ಆಫ್ ಮಾಡಿ"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳನ್ನು ವಿರಾಮಗೊಳಿಸಿ"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳನ್ನು ಆನ್ ಮಾಡಿ"</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="remote_action_failed" msgid="1383965239183576790">"ವಿಫಲವಾಗಿದೆ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 9859752..d5ec664 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"홈 화면에서 위젯을 이동하려면 길게 터치하세요."</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"홈 화면에 추가"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{위젯 #개}other{위젯 #개}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{바로가기 #개}other{바로가기 #개}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"직장 위젯"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"대화"</string>
<string name="widget_education_header" msgid="4874760613775913787">"빠르게 유용한 정보 확인"</string>
- <string name="widget_education_content" msgid="745542879510751525">"앱을 열지 않고 정보를 확인하려면 홈 화면에 위젯을 추가하세요."</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>
@@ -65,7 +65,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="6692471482459245734">"홈 화면에 더 이상 공간이 없습니다."</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"예상 앱 고정"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"바로가기 설치"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"앱이 사용자의 작업 없이 바로가기를 추가할 수 있도록 합니다."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"홈 설정 및 바로가기 읽기"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"앱이 홈에 있는 설정 및 바로가기를 읽을 수 있도록 합니다."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"홈 설정 및 바로가기 쓰기"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"앱이 홈에 있는 설정 및 바로가기를 변경할 수 있도록 합니다."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"홈 설정 및 바로가기 읽기"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"시스템 앱은 제거할 수 없습니다."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} 알림 #개}other{{app_name}알림 #개}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"배경화면 및 스타일"</string>
<string name="settings_button_text" msgid="8873672322605444408">"홈 설정"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"관리자가 사용 중지함"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"홈 화면 회전 허용"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"알림 표시점을 표시하려면 <xliff:g id="NAME">%1$s</xliff:g>의 앱 알림을 사용 설정하세요."</string>
<string name="title_change_settings" msgid="1376365968844349552">"설정 변경"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"알림 표시 점 보기"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"홈 화면에 앱 아이콘 추가"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"개발자 옵션"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"홈 화면에 앱 아이콘 추가"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"새로 설치한 앱에 적용"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"알 수 없음"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"삭제"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"업데이트"</string>
+ <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="8902165848117513641">"홈 화면에 추가"</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_removed" msgid="851119963877842327">"항목 삭제됨"</string>
@@ -141,7 +146,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="1603837886334246317">"홈 화면으로 이동"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"확인"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"직장 앱 사용 중지"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"직장 앱 일시중지"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"직장 앱 사용 설정"</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="remote_action_failed" msgid="1383965239183576790">"실패: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 1d4df09..5d401bc 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Башкы экранга жылдыруу үчүн виджетти коё бербей басып туруңуз"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Башкы экранга кошуу"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}other{# виджет}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ыкчам баскыч}other{# ыкчам баскыч}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Жумуш"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Сүйлөшүүлөр"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Керектүү маалымат манжаңыздын учунда"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Бир нерсе билүү үчүн колдонмолорду улам ачып убара болбостон, башкы экранга виджеттерди кошуп коюңуз."</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>
@@ -65,7 +65,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="6692471482459245734">"Башкы экранда бош орун жок"</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>
@@ -75,22 +75,22 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Чыгарып салуу"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Колдонмо тууралуу"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Орнотуу"</string>
- <string name="dismiss_prediction_label" msgid="3357562989568808658">"Колдонмо сунушталбасын"</string>
+ <string name="dismiss_prediction_label" msgid="3357562989568808658">"Cунушталбасын"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Божомолдонгон колдонмону кадап коюу"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"тез чакырмаларды орнотуу"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Колдонмого колдонуучуга кайрылбастан тез чакырма кошууга уруксат берет."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"Үйдүн тууралоолорун жана тез чакырмаларын окуу"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Колдонмого Үйдүн тууралоолорун жана тез чакырмаларын окууга уруксат берет."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"Үйдүн тууралоолорун жана тез чакырмаларын жазуу"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Колдонмого Үйдүн тууралоолорун жана тез чакырмаларын өзгөртүүгө уруксат берет."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"үйдүн жөндөөлөрүн жана ыкчам баскычтарын окуу"</string>
+ <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>
+ <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>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> өчүрүлгөн"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name}, # билдирмеси бар}other{{app_name}, # билдирмеси бар}}"</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="workspace_scroll_format" msgid="8458889198184077399">"Үй экраны %2$d ичинен %1$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Жаңы башкы экран барагы"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Тушкагаз жана стиль"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Башкы бет жөндөөлөрү"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Администраторуңуз өчүрүп койгон"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Башкы экранды бурууга уруксат берүү"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Эскертме белгилерин көрсөтүү максатында, <xliff:g id="NAME">%1$s</xliff:g> үчүн колдонмонун билдирмелерин күйгүзүү керек"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Параметрлерди өзгөртүү"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Билдирмелер белгилерин көрсөтүү"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Колдонмонун сүрөтчөсүн Башкы экранга кошуу"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Иштеп чыгуучунун параметрлери"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Колдонмонун сүрөтчөсүн башкы экранга кошуу"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Жаңы колдонмолор үчүн"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Белгисиз"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Өчүрүү"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"Жаңыртуу"</string>
+ <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="8902165848117513641">"Башкы экранга кошуу"</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_removed" msgid="851119963877842327">"Жоюлду"</string>
@@ -141,7 +146,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="1603837886334246317">"Башкы экранга жылдыруу"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"Түшүндүм"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Жумуш колдонмолорун өчүрүү"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Жумуш колдонмолорун тындыруу"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Жумуш колдонмолорун күйгүзүү"</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="remote_action_failed" msgid="1383965239183576790">"Аткарылган жок: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 662b86e..422240c 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -22,8 +22,22 @@
<dimen name="fastscroll_popup_text_size">24dp</dimen>
<!-- Dynamic grid -->
+ <dimen name="dynamic_grid_edge_margin">15.28dp</dimen>
<dimen name="dynamic_grid_icon_drawable_padding">4dp</dimen>
+ <dimen name="dynamic_grid_drop_target_size">36dp</dimen>
+ <dimen name="cell_layout_padding">20dp</dimen>
<!-- Hotseat -->
<dimen name="dynamic_grid_hotseat_side_padding">16dp</dimen>
+ <dimen name="spring_loaded_hotseat_top_margin">45dp</dimen>
+
+ <!-- Dragging -->
+ <dimen name="drop_target_button_gap">28dp</dimen>
+ <dimen name="drop_target_button_drawable_horizontal_padding">16dp</dimen>
+ <dimen name="drop_target_button_drawable_vertical_padding">2dp</dimen>
+ <dimen name="drop_target_top_margin">6dp</dimen>
+ <dimen name="drop_target_bottom_margin">6dp</dimen>
+
+ <!-- Workspace grid visualization parameters -->
+ <dimen name="grid_visualization_horizontal_cell_spacing">24dp</dimen>
</resources>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index e47fefd..7291cf2 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"ແຕະວິດເຈັດຄ້າງໄວ້ເພື່ອຍ້າຍມັນໄປມາຢູ່ໂຮມສະກຣີນ"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"ເພີ່ມໄປໃສ່ໂຮມສະກຣີນ"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ວິດເຈັດ}other{# ວິດເຈັດ}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ທາງລັດ}other{# ທາງລັດ}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ວຽກ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"ການສົນທະນາ"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ຂໍ້ມູນທີ່ເປັນປະໂຫຍດຢູ່ປາຍນິ້ວຂອງທ່ານ"</string>
- <string name="widget_education_content" msgid="745542879510751525">"ເພື່ອຮັບຂໍ້ມູນໂດຍບໍ່ຕ້ອງເປີດແອັບ, ທ່ານສາມາດເພີ່ມວິດເຈັດໃສ່ໂຮມສະກຣີນຂອງທ່ານໄດ້"</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>
@@ -65,7 +65,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="6692471482459245734">"ບໍ່ມີບ່ອນຫວ່າງໃນໜ້າໂຮມສະກຣີນນີ້"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"ປັກໝຸດການຄາດເດົາ"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"ຕິດຕັ້ງທາງລັດ"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ອະນຸຍາດໃຫ້ແອັບຯ ເພີ່ມທາງລັດໂດຍບໍ່ຕ້ອງຮັບການຢືນຢັນຈາກຜູ່ໃຊ້."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"ອ່ານການຕັ້ງຄ່າໜ້າຫຼັກ ແລະທາງລັດ"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"ອະນຸຍາດໃຫ້ແອັບຯດັ່ງກ່າວອ່ານການຕັ້ງຄ່າ ແລະທາງລັດໃນໜ້າຫຼັກ."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"ຂຽນການຕັ້ງຄ່າໜ້າຫຼັກ ແລະທາງລັດ"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"ອະນຸຍາດໃຫ້ແອັບຯດັ່ງກ່າວ ປ່ຽນການຕັ້ງຄ່າ ແລະທາງລັດໃນໜ້າຫຼັກ."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"ອ່ານການຕັ້ງຄ່າໜ້າຫຼັກ ແລະ ທາງລັດ"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ນີ້ແມ່ນແອັບຯຂອງລະບົບ ແລະບໍ່ສາມາດຖອນການຕິດຕັ້ງອອກໄດ້."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} ມີ # ການແຈ້ງເຕືອນ}other{{app_name} ມີ # ການແຈ້ງເຕືອນ}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ຮູບພື້ນຫຼັງ ແລະ ຮູບແບບ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ການຕັ້ງຄ່າໜ້າຫຼັກ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ຖືກປິດການນຳໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"ອະນຸຍາດໃຫ້ໝຸນໜ້າຈໍຢູ່ໜ້າຫຼັກໄດ້"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"ເພື່ອສະແດງຈຸດການແຈ້ງເຕືອນ, ໃຫ້ເປີດການແຈ້ງເຕືອນສຳລັບ <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ບັນທຶກການຕັ້ງຄ່າ"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"ສະແດງຈຸດການແຈ້ງເຕືອນ"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"ເພີ່ມໄອຄອນແອັບໄປໃສ່ໜ້າຈໍຫຼັກ"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"ຕົວເລືອກນັກພັດທະນາ"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"ເພີ່ມໄອຄອນແອັບໄປໃສ່ໂຮມສະກຣີນ"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ສຳລັບແອັບໃໝ່"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ບໍ່ຮູ້ຈັກ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ລຶບ"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"ອັບເດດ"</string>
+ <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="8902165848117513641">"ເພີ່ມໃສ່ໜ້າຈໍຫຼັກ"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"ເພີ່ມໃສ່ໂຮມສະກຣີນ"</string>
<string name="action_move_here" msgid="2170188780612570250">"Move item here"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"ເພີ່ມລາຍການໃສ່ໜ້າຈໍຫຼັກແລ້ວ"</string>
<string name="item_removed" msgid="851119963877842327">"ເອົາລາຍການອອກໄປແລ້ວ"</string>
@@ -141,7 +146,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="1603837886334246317">"ຍ້າຍໄປໃສ່ໜ້າຈໍຫຼັກ"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"ເຂົ້າໃຈແລ້ວ"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"ປິດການໃຊ້ແອັບບ່ອນເຮັດວຽກ"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ຢຸດແອັບບ່ອນເຮັດວຽກຊົ່ວຄາວ"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ເປີດໃຊ້ແອັບບ່ອນເຮັດວຽກ"</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="remote_action_failed" msgid="1383965239183576790">"ບໍ່ສຳເລັດ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index e4fdfc6..ddff9d4 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d plotis ir %2$d aukštis"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> valdiklis"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Paliesdami ir palaikydami valdiklį galite judėti pagrindiniame ekrane"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Pridėti prie pagrindinio ekrano"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Darbas"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Pokalbiai"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Lengvai pasiekiama naudinga informacija"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Jei norite gauti informacijos neatidarę programų, galite pridėti valdiklių pagrindiniame ekrane"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Supratau"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Pakeisti valdiklio nustatymus"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Pranešimai"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Dukart pal. ir palaik., kad perk. spart. klavišą."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Dukart palieskite ir palaikykite, kad perkeltumėte spartųjį klavišą ar naudotumėte tinkintus veiksmus."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Šiame pagrindiniame ekrane nebėra vietos"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Šiame pagrindiniame ekrane nebėra vietos"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Mėgstamiausių dėkle nebėra vietos"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Programų sąrašas"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Paieškos rezultatai"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Prisegti numatymą"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"įdiegti sparčiuosius klavišus"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Programai leidžiama pridėti sparčiuosius klavišus be naudotojo įsikišimo."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"skaityti pagrindinio puslapio nustatymus ir sparčiuosius klavišus"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Programai leidžiama skaityti pagrindinio puslapio nustatymus ir sparčiuosius klavišus."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"rašyti pagrindinio puslapio nustatymus ir sparčiuosius klavišus"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Programai leidžiama keisti pagrindinio puslapio nustatymus ir sparčiuosius klavišus."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"skaityti pagrindinio ekrano nustatymus ir sparčiuosius klavišus"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Tai sistemos programa ir jos negalima pašalinti."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Pavadinimo redagavimas"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ išjungta"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{Programoje „{app_name}“ yra # pranešimas}one{Programoje „{app_name}“ yra # pranešimas}few{Programoje „{app_name}“ yra # pranešimai}many{Programoje „{app_name}“ yra # pranešimo}other{Programoje „{app_name}“ yra # pranešimų}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{Programoje „{app_name}“ yra # pranešimas}one{Programoje „{app_name}“ yra # pranešimas}few{Programoje „{app_name}“ yra # pranešimai}many{Programoje „{app_name}“ yra # pranešimo}other{Programoje „{app_name}“ yra # pranešimų}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d psl. iš %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"%1$d pagrindinis ekranas iš %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Naujas pagrindinio ekrano puslapis"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Ekrano fonas ir stilius"</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="7728578836261442095">"Leisti pasukti pagrindinį ekraną"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Leisti pasukti pagrindinį ekraną"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kai telefonas pasukamas"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Pranešimų taškai"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Įjungta"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Kad būtų rodomi pranešimų taškai, įjunkite programos „<xliff:g id="NAME">%1$s</xliff:g>“ pranešimus."</string>
<string name="title_change_settings" msgid="1376365968844349552">"Keisti nustatymus"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Rodyti pranešimų taškus"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Pridėti progr. piktogr. pagrind. ekrane"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Kūrėjo parinktys"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Pridėti programų piktogramas pagrindiniame ekrane"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Skirta naujoms programoms"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Nežinoma"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Panaikinti"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Įdiegiama: „<xliff:g id="NAME">%1$s</xliff:g>“; baigta: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Atsisiunčiama programa „<xliff:g id="NAME">%1$s</xliff:g>“, <xliff:g id="PROGRESS">%2$s</xliff:g> baigta"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Laukiama, kol bus įdiegta programa „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Būtina atnaujinti programą"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Šios piktogramos programa neatnaujinta. Galite patys atnaujinti, kad iš naujo įgalintumėte šį spartųjį klavišą, arba pašalinkite piktogramą."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Atnaujinti"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Pašalinti"</string>
<string name="widgets_list" msgid="796804551140113767">"Valdiklių sąrašas"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Valdiklių sąrašas uždarytas"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Pridėti prie pagrind. ekrano"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Pridėti prie pagrind. ekrano"</string>
<string name="action_move_here" msgid="2170188780612570250">"Perkelti elementą čia"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Elementas pridėtas prie pagrindinio ekrano"</string>
<string name="item_removed" msgid="851119963877842327">"Elementas perkeltas"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Elementas pridėtas prie aplanko"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Kurti aplanką naudojant: „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
<string name="folder_created" msgid="6409794597405184510">"Aplankas sukurtas"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Perkelti į pagrindinį ekraną"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Perkelti į pagrindinį ekraną"</string>
<string name="action_resize" msgid="1802976324781771067">"Pakeisti dydį"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Padidinti plotį"</string>
<string name="action_increase_height" msgid="459390020612501122">"Padidinti aukštį"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Išjungti darbo programas"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Nepavyko: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index f02d4fb..a5b7c66 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d plats un %2$d augsts"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Logrīks <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Pieskarieties logrīkam un turiet to, lai to pārvietotu pa sākuma ekrānu."</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Pievienot sākuma ekrānam"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Darba"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Sarunas"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Ērta piekļuve noderīgai informācijai"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Lai iegūtu informāciju, neatverot lietotnes, varat pievienot logrīkus sākuma ekrānā."</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Labi"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Mainīt logrīka iestatījumus"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Paziņojumi"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Lai pārvietotu saīsni, pieskarieties un turiet."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Lai pārvietotu saīsni, uz tās veiciet dubultskārienu un turiet. Varat arī veikt pielāgotas darbības."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Šajā sākuma ekrānā nav vietas"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Šajā sākuma ekrānā nav vietas"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Izlases joslā vairs nav vietas."</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Lietotņu saraksts"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Meklēšanas rezultāti"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Piespraust prognozēto lietotni"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalēt saīsnes"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Ļauj lietotnei pievienot saīsnes, nejautājot lietotājam."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"lasīt sākuma ekrāna iestatījumus un saīsnes"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Ļauj lietotnei lasīt iestatījumus un saīsnes sākuma ekrānā."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"rakstīt sākuma ekrāna iestatījumus un saīsnes"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Ļauj lietotnei mainīt iestatījumus un saīsnes sākuma ekrānā."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"sākuma ekrāna iestatījumu un saīšņu lasīšana"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Šī ir sistēmas lietotne, un to nevar atinstalēt."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Nosaukuma rediģēšana"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> ir atspējota"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{Lietotnē {app_name} ir # paziņojums}zero{Lietotnē {app_name} ir # paziņojumi}one{Lietotnē {app_name} ir # paziņojums}other{Lietotnē {app_name} ir # paziņojumi}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{Lietotnē {app_name} ir # paziņojums}zero{Lietotnē {app_name} ir # paziņojumi}one{Lietotnē {app_name} ir # paziņojums}other{Lietotnē {app_name} ir # paziņojumi}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%1$d. lapa no %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Sākuma ekrāns: %1$d no %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Jauna sākuma ekrāna lapa"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Fona tapete un stils"</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="7728578836261442095">"Atļaut sākuma ekrāna pagriešanu"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Atļaut sākuma ekrāna pagriešanu"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Pagriežot tālruni"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Paziņojumu punkti"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Ieslēgts"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Lai tiktu rādīti paziņojumu punkti, ieslēdziet paziņojumus lietotnei <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="title_change_settings" msgid="1376365968844349552">"Mainīt iestatījumus"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Rādīt paziņojumu punktus"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Pievienot lietotņu ikonas sākuma ekrānam"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Izstrādātāju opcijas"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Pievienot lietotņu ikonas sākuma ekrānam"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Jaunām lietotnēm"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Nezināma"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Noņemt"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Notiek lietotnes “<xliff:g id="NAME">%1$s</xliff:g>” instalēšana. Norise: <xliff:g id="PROGRESS">%2$s</xliff:g>."</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Lietotnes <xliff:g id="NAME">%1$s</xliff:g> lejupielāde (<xliff:g id="PROGRESS">%2$s</xliff:g> pabeigti)"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Notiek <xliff:g id="NAME">%1$s</xliff:g> instalēšana"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Lietotne ir jāatjaunina"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Šai ikonai paredzētā lietotne nav atjaunināta. Varat to atjaunināt manuāli, lai atkārtoti iespējotu šo saīsni, vai noņemt ikonu."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Atjaunināt"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Noņemt"</string>
<string name="widgets_list" msgid="796804551140113767">"Logrīku saraksts"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Logrīku saraksts aizvērts"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Pievienot sākuma ekrānam"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Pievienot sākuma ekrānam"</string>
<string name="action_move_here" msgid="2170188780612570250">"Pārvietot vienumu šeit"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Vienums pievienots sākuma ekrānam"</string>
<string name="item_removed" msgid="851119963877842327">"Vienums noņemts"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Vienums pievienots mapei"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Izveidot mapi ar: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Mape izveidota"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Pārvietot uz sākuma ekrānu"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Pārvietot uz sākuma ekrānu"</string>
<string name="action_resize" msgid="1802976324781771067">"Mainīt lielumu"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Palielināt platumu"</string>
<string name="action_increase_height" msgid="459390020612501122">"Palielināt augstumu"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Izslēgt darba lietotnes"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Neizdevās: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 2f69e30..32c3fc0 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Допрете го и задржете го виџетот за да го движите наоколу на почетниот екран"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Додај на почетниот екран"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виџет}one{# виџет}other{# виџети}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# кратенка}one{# кратенка}other{# кратенки}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Работни"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Разговори"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Корисни информации на дофат на прстите"</string>
- <string name="widget_education_content" msgid="745542879510751525">"За да добивате информации без да ги отворате апликациите, може да додадете виџети на почетниот екран"</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>
@@ -65,7 +65,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="6692471482459245734">"Нема простор на почетниов екран"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Закачи го предвидувањето"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"инсталирање кратенки"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Овозможува апликацијата да додава кратенки без интервенција на корисникот."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"чита поставки и кратенки на почетна страница"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Овозможува апликацијата да ги менува подесувањата и кратенките на почетната страница."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"пишува поставки и кратенки на почетна страница"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Овозможува апликацијата да ги менува подесувањата и кратенките на почетната страница."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"да чита поставки и кратенки на почетна страница"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ова е системска апликација и не може да се деинсталира."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} има # известување}one{{app_name} има # известување}other{{app_name} има # известувања}}"</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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Тапет и стил"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Поставки за почетен екран"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Оневозможено од администраторот"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Дозволи ротација на почетниот екран"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"За да се прикажуваат „Точки за известување“, вклучете ги известувањата за апликацијата <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Промени ги поставките"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Прикажувај точки за известување"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Додавај икони за апликации на почетниот екран"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Опции за програмери"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Додавај икони за апликации на почетниот екран"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"За нови апликации"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Непознато"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Отстрани"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"Ажурирај"</string>
+ <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="8902165848117513641">"Додај на почетниот екран"</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_removed" msgid="851119963877842327">"Ставката е отстранета"</string>
@@ -141,7 +146,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="1603837886334246317">"Премести на Почетен екран"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"Сфатив"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Исклучете ги работните апликации"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Паузирај ги работните апликации"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Вклучете ги работните апликации"</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="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 e0e7d4a..d25f9dd 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"ഹോം സ്ക്രീനിന് ചുറ്റും വിജറ്റ് നീക്കാൻ അതിൽ സ്പർശിച്ച് പിടിക്കുക"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"ഹോം സ്ക്രീനിലേക്ക് ചേർക്കുക"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# വിജറ്റ്}other{# വിജറ്റുകൾ}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# കുറുക്കുവഴി}other{# കുറുക്കുവഴികൾ}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ജോലി"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"സംഭാഷണങ്ങൾ"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ഉപകാരപ്രദമായ വിവരങ്ങൾ നിങ്ങളുടെ വിരൽത്തുമ്പിൽ"</string>
- <string name="widget_education_content" msgid="745542879510751525">"ആപ്പുകൾ തുറക്കാതെ വിവരങ്ങൾ ലഭിക്കാൻ, നിങ്ങൾക്ക് ഹോം സ്ക്രീനിലേക്ക് വിജറ്റുകൾ ചേർക്കാം"</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>
@@ -65,7 +65,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="6692471482459245734">"ഈ ഹോം സ്ക്രീനിലിൽ ഇടമില്ല"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"പ്രവചനം പിൻ ചെയ്യുക"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"കുറുക്കുവഴികൾ ഇൻസ്റ്റാളുചെയ്യുക"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ഉപയോക്തൃ ഇടപെടൽ ഇല്ലാതെ കുറുക്കുവഴികൾ ചേർക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"ഹോം ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും റീഡുചെയ്യുക"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"ഹോമിലെ ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"ഹോം ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും റൈറ്റുചെയ്യുക"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"ഹോമിലെ ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും മാറ്റാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"ഹോം ക്രമീകരണവും കുറുക്കുവഴികളും വായിക്കുക"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ഇതൊരു സിസ്റ്റം അപ്ലിക്കേഷനായതിനാൽ അൺഇൻസ്റ്റാളുചെയ്യാനാവില്ല."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} ആപ്പിന് # അറിയിപ്പുണ്ട്}other{{app_name} ആപ്പിന് # അറിയിപ്പുകളുണ്ട്}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"വാൾപേപ്പറും സ്റ്റൈലും"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ഹോം ക്രമീകരണം"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"അഡ്മിൻ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"ഹോം സ്ക്രീൻ തിരിക്കൽ അനുവദിക്കുക"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"അറിയിപ്പ് ഡോട്ടുകൾ കാണിക്കുന്നതിന്, <xliff:g id="NAME">%1$s</xliff:g> എന്നയാളിനായുള്ള ആപ്പ് അറിയിപ്പുകൾ ഓണാക്കുക"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ക്രമീകരണം മാറ്റുക"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"അറിയിപ്പ് ഡോട്ടുകൾ കാണിക്കുക"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"ഹോം സ്ക്രീനിൽ ആപ്പ് ഐക്കണുകൾ ചേർക്കുക"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"ഡെവലപ്പർ ഓപ്ഷനുകൾ"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"ഹോം സ്ക്രീനിലേക്ക് ആപ്പ് ഐക്കണുകൾ ചേർക്കുക"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"പുതിയ ആപ്പുകൾക്ക്"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"അജ്ഞാതം"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"നീക്കംചെയ്യുക"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"അപ്ഡേറ്റ് ചെയ്യുക"</string>
+ <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="8902165848117513641">"ഹോം സ്ക്രീനിൽ ചേർക്കുക"</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_removed" msgid="851119963877842327">"ഇനം നീക്കംചെയ്തു"</string>
@@ -141,7 +146,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="1603837886334246317">"ഹോം സ്ക്രീനിലേക്ക് നീക്കുക"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"മനസ്സിലായി"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"ഔദ്യോഗിക ആപ്പുകൾ ഓഫാക്കുക"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ഔദ്യോഗിക ആപ്പുകൾ താൽക്കാലികമായി നിർത്തുക"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ഔദ്യോഗിക ആപ്പുകൾ ഓണാക്കുക"</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="remote_action_failed" msgid="1383965239183576790">"പരാജയപ്പെട്ടു: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index e6fcefa..0723c25 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Жижиг хэрэгслийг Үндсэн нүүрний эргэн тойронд зөөхийн тулд түүнд хүрээд, удаан дарна уу"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Үндсэн нүүрэнд нэмэх"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}other{# виджет}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# товчлол}other{# товчлол}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Ажил"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Харилцан яриа"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Хэрэгтэй мэдээллээ хурууныхаа үзүүрээр аваарай"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Аппуудыг нээлгүйгээр мэдээлэл авахын тулд та Үндсэн нүүрэндээ виджет нэмэх боломжтой"</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>
@@ -65,7 +65,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="6692471482459245734">"Энэ үндсэн нүүрэнд зай байхгүй байна"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Таамаглалыг бэхлэх"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"товчлол суулгах"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Апп нь хэрэглэгчийн оролцоогүйгээр товчлолыг нэмэж чадна"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"Нүүрний тохиргоо болон товчлолыг унших"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Апп нь Нүүрэндэх товчлол болон тохиргоог уншиж чадна."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"Нүүрний тохиргоо болон товчлолыг бичих"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Апп нь Нүүрэндэх товчлол болон тохиргоог өөрчилж чадна."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"нүүрний тохиргоо болон товчлолыг унших"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Энэ апп нь системийн апп ба устгах боломжгүй."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} дээр # мэдэгдэл байна}other{{app_name} дээр # мэдэгдэл байна}}"</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="workspace_scroll_format" msgid="8458889198184077399">"%2$d-н Нүүр дэлгэц %1$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Шинэ үндсэн нүүр хуудас"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Дэлгэцийн зураг, загвар"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Нүүр хуудасны тохиргоо"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Таны админ идэвхгүй болгосон"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Нүүр дэлгэцийг эргүүлэхийг зөвшөөрөх"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Мэдэгдлийн цэгийг харуулахын тулд <xliff:g id="NAME">%1$s</xliff:g>-д аппын мэдэгдлийг асаана уу"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Тохиргоог өөрчлөх"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Мэдэгдлийн цэгийг харуулах"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Аппын дүрс тэмдгийг Үндсэн нүүрэнд нэмэх"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Хөгжүүлэгчийн тохиргоо"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Үндсэн нүүрэнд аппын дүрс тэмдгүүдийг нэмэх"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Шинэ аппад зориулсан"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Тодорхойгүй"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Хасах"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"Шинэчлэх"</string>
+ <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="8902165848117513641">"Нүүр дэлгэцэд нэмэх"</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_removed" msgid="851119963877842327">"Зүйлийг устгалаа"</string>
@@ -141,7 +146,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="1603837886334246317">"Нүүр дэлгэц рүү зөөх"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"Ойлголоо"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Ажлын аппуудыг унтраах"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Ажлын аппуудыг түр зогсоох"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Ажлын аппуудыг асаах"</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="remote_action_failed" msgid="1383965239183576790">"Амжилтгүй болсон: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index e798a3d..8625ae5 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"होम स्क्रीनवर ते हलवण्यासाठी विजेटला स्पर्श करा आणि धरून ठेवा"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"होम स्क्रीनवर जोडा"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# विजेट}other{# विजेट}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# शॉर्टकट}other{# शॉर्टकट}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ऑफिस"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"संभाषणे"</string>
<string name="widget_education_header" msgid="4874760613775913787">"तुमच्यासाठी सहज उपलब्ध असलेली माहिती"</string>
- <string name="widget_education_content" msgid="745542879510751525">"ॲप्स न उघडता माहिती मिळवण्यासाठी, तुम्ही तुमच्या होम स्क्रीनवर विजेट जोडू शकता"</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>
@@ -65,7 +65,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="6692471482459245734">"या होम स्क्रीनवर कोणतीही रूम नाही"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"पूर्वानुमान पिन करा"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"शॉर्टकट इंस्टॉल करा"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"वापरकर्ता हस्तक्षेपाशिवाय शॉर्टकट जोडण्यास अॅप ला अनुमती देते."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"होम सेटिंग्ज आणि शॉर्टकट वाचा"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट वाचण्यास अॅप ला अनुमती देते."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"होम सेटिंग्ज आणि शॉर्टकट लिहा"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट बदलण्यास अॅप ला अनुमती देते."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"होम सेटिंग्ज आणि शॉर्टकट वाचा"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"हा सिस्टम अॅप आहे आणि अनइंस्टॉल केला जाऊ शकत नाही."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} साठी # सूचना आहे}other{{app_name} साठी # सूचना आहेत}}"</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="workspace_scroll_format" msgid="8458889198184077399">"%2$d पैकी %1$d मुख्य स्क्रीन"</string>
<string name="workspace_new_page" msgid="257366611030256142">"नवीन मुख्य स्क्रीन पृष्ठ"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"वॉलपेपर आणि शैली"</string>
<string name="settings_button_text" msgid="8873672322605444408">"होम सेटिंग्ज"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"आपल्या प्रशासकाने अक्षम केले"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"मुख्य स्क्रीन फिरविण्यास अनुमती द्या"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,19 +114,24 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"सूचना बिंदू दाखवण्यासाठी, <xliff:g id="NAME">%1$s</xliff:g> साठी अॅप सूचना सुरू करा"</string>
<string name="title_change_settings" msgid="1376365968844349552">"सेटिंग्ज बदला"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"सूचना बिंदू दाखवा"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"होम स्क्रीनवर ॲप आयकन जोडा"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"डेव्हलपर पर्याय"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"होम स्क्रीनवर ॲप आयकन जोडा"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नवीन अॅप्ससाठी"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"काढा"</string>
<string name="abandoned_search" msgid="891119232568284442">"शोधा"</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" msgid="2178028071796141234">"अपडेट करा"</string>
+ <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="8902165848117513641">"होम स्क्रीनवर जोडा"</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_removed" msgid="851119963877842327">"आयटम काढला"</string>
@@ -141,7 +146,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="1603837886334246317">"मुख्य स्क्रीनवर हलवा"</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>
@@ -156,15 +161,17 @@
<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_body" msgid="261634750995824906">"तुमची कार्य ॲप्स तुम्हाला सूचना पाठवू शकत नाहीत, तुमची बॅटरी वापरू शकत नाहीत किंवा तुमचे स्थान अॅक्सेस करू शकत नाहीत"</string>
<string name="work_apps_paused_content_description" msgid="5149623040804051095">"कामाशी संबंधित ॲप्स बंद आहेत. तुमचे कामाशी संबंधित ॲप्स तुम्हाला सूचना पाठवू शकत नाहीत, तुमची बॅटरी वापरू शकत नाहीत किंवा तुमचे स्थान अॅक्सेस करू शकत नाहीत"</string>
- <string name="work_apps_paused_edu_banner" msgid="8872412121608402058">"Work apps ही बॅज केलेली असून तुमच्या IT ॲडमिनला दृश्यमान आहेत"</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="1921059713673767460">"कामाशी संबंधित ॲप्स बंद करा"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"कार्य ॲप्स थांबवा"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"कार्य ॲप्स सुरू करा"</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="remote_action_failed" msgid="1383965239183576790">"हे करता आले नाही: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index bde420b..d123d14 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"Lebar %1$d kali 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="5653291305078645405">"Sentuh & tahan widget untuk menggerakkan widget di sekitar Skrin utama"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Tambahkan pada Skrin utama"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Tempat kerja"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Perbualan"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Maklumat berguna di hujung jari anda"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Untuk mendapatkan maklumat tanpa membuka apl, anda boleh menambahkan widget pada skrin Utama 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>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Tukar tetapan widget"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Pemberitahuan"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Sentuh & tahan untuk menggerakkan pintasan."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Ketik dua kali & tahan untuk menggerakkan pintasan atau menggunakan tindakan tersuai."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Tiada ruang di skrin Utama ini"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Tiada ruang di skrin utama ini"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Tiada ruang dalam dulang Kegemaran lagi"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Senarai apl"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Hasil carian"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Sematkan Ramalan"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"pasang pintasan"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Membenarkan apl menambah pintasan tanpa campur tangan pengguna."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"baca tetapan dan pintasan Laman Utama"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Membenarkan apl membaca tetapan dan pintasan di Laman Utama."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"tulis tetapan dan pintasan Laman Utama"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Membenarkan apl menukar tetapan dan pintasan di Laman Utama."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"membaca tetapan dan pintasan skrin utama"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ini ialah apl sistem dan tidak boleh dinyahpasang."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Edit Nama"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> dilumpuhkan"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} mempunyai # pemberitahuan}other{{app_name} mempunyai # pemberitahuan}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} mempunyai # pemberitahuan}other{{app_name} mempunyai # pemberitahuan}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Halaman %1$d daripada %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Skrin Laman Utama %1$d daripada %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Halaman skrin utama baharu"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Kertas dinding & gaya"</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="7728578836261442095">"Benarkan putaran Skrin Utama"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Benarkan putaran skrin utama"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Apabila telefon diputar"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Titik pemberitahuan"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Hidup"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Untuk menunjukkan Titik Pemberitahuan, hidupkan pemberitahuan apl untuk <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Tukar tetapan"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Tunjukkan titik pemberitahuan"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Tambahkan ikon apl pada Skrin utama"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Pilihan Pembangun"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Tambahkan ikon apl pada skrin utama"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Untuk apl baharu"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Tidak diketahui"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Alih keluar"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> dipasang, <xliff:g id="PROGRESS">%2$s</xliff:g> selesai"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> memuat turun, <xliff:g id="PROGRESS">%2$s</xliff:g> selesai"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> menunggu untuk dipasang"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Kemas kini apl diperlukan"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Apl untuk ikon ini tidak dikemas kini. Anda boleh mengemas kini secara manual untuk mendayakan semula pintasan atau mengalih keluar ikon."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Kemas kini"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Alih keluar"</string>
<string name="widgets_list" msgid="796804551140113767">"Senarai widget"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Senarai widget ditutup"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Tambahkan pada Skrin Utama"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Tambahkan pada skrin utama"</string>
<string name="action_move_here" msgid="2170188780612570250">"Alihkan item ke sini"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item ditambahkan pada skrin utama"</string>
<string name="item_removed" msgid="851119963877842327">"Item dialih keluar"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Item ditambahkan pada folder"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Buat folder dengan: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Folder dibuat"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Alihkan ke Skrin Utama"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Alihkan ke skrin utama"</string>
<string name="action_resize" msgid="1802976324781771067">"Ubah saiz"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Tambahkan kelebaran"</string>
<string name="action_increase_height" msgid="459390020612501122">"Tambahkan ketinggian"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Matikan apl kerja"</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="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="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 e6434b6..d264c31 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"ပင်မစာမျက်နှာအနီးတွင် ဝိဂျက်ကိုရွှေ့ရန် ၎င်းကို တို့ထိ၍ဖိထားပါ"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"ပင်မစာမျက်နှာသို့ ထည့်ရန်"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ဝိဂျက် # ခု}other{ဝိဂျက် # ခု}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{ဖြတ်လမ်းလင့်ခ် # ခု}other{ဖြတ်လမ်းလင့်ခ် # ခု}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"အလုပ်"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"စကားဝိုင်းများ"</string>
<string name="widget_education_header" msgid="4874760613775913787">"အသုံးဝင်သော အချက်အလက်များကို အလွယ်တကူ ရယူလိုက်ပါ"</string>
- <string name="widget_education_content" msgid="745542879510751525">"အက်ပ်များကိုမဖွင့်ဘဲ အချက်အလက်များရယူရန် သင်၏ ပင်မစာမျက်နှာသို့ ဝိဂျက်များ ထည့်နိုင်သည်"</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>
@@ -65,7 +65,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="6692471482459245734">"ဤပင်မစာမျက်နှာတွင် နေရာလွတ် မရှိတော့ပါ"</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>
@@ -75,14 +75,14 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"ဖယ်ရှားရန်"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"အက်ပ်အချက်အလက်"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ထည့်သွင်းရန်"</string>
- <string name="dismiss_prediction_label" msgid="3357562989568808658">"အက်ပ်ကို အကြံမပြုပါနှင့်"</string>
+ <string name="dismiss_prediction_label" msgid="3357562989568808658">"အက်ပ်အကြံမပြုပါနှင့်"</string>
<string name="pin_prediction" msgid="4196423321649756498">"ခန့်မှန်းချက်ကို ပင်ထိုးရန်"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"ဖြတ်လမ်းလင့်ခ်များ ထည့်သွင်းခြင်း"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"အသုံးပြုသူ လုပ်ဆောင်မှုမရှိပဲ အပ်ပလီကေးရှင်းကို အတိုကောက်မှတ်သားမှုများ ပြုလုပ်ခွင့် ပေးခြင်း"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"ပင်မမျက်နှာစာ အပြင်အဆင် နှင့် အတိုကောက်မှတ်သားမှုများအား ဖတ်ခြင်း"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"ပင်မမျက်နှာစာတွင်ရှိသော အပြင်အဆင်နှင့် အတိုကောက်မှတ်သားမှုများကို အပ်ပလီကေးရှင်းအား ဖတ်ခွင့်ပြုခြင်း"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"ပင်မမျက်နှာစာ အပြင်အဆင် နှင့် အတိုကောက်မှတ်သားမှုများအား ရေးသားခြင်း"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"ပင်မမျက်နှာစာတွင် ရှိသော အပြင်အဆင် နှင့် အတိုကောက်မှတ်သားမှုများ ကို အပ်ပလီကေးရှင်းအား ပြောင်းခွင့်ပြုခြင်း"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"ပင်မဆက်တင်နှင့် ဖြတ်လမ်းလင့်ခ်များ ဖတ်ခြင်း"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ဤအပ်ပလီကေးရှင်းမှာ စစ်စတန်ပိုင်းဆိုင်ရာ အပ်ပလီကေးရှင်းဖြစ်ပါသည်။ ထုတ်ပစ်၍ မရပါ"</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} တွင် အကြောင်းကြားချက် # ခု ရှိသည်}other{{app_name} တွင် အကြောင်းကြားချက် # ခု ရှိသည်}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"နောက်ခံနှင့် ပုံစံ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ပင်မဆက်တင်များ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"သင့်စီမံခန့်ခွဲသူက ပိတ်လိုက်ပါသည်"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"ပင်မစာမျက်နှာလှည့်ခြင်းကို ခွင့်ပြုပါ"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"အကြောင်းကြားချက် အစက်များကို ပြသရန် <xliff:g id="NAME">%1$s</xliff:g> အတွက် အက်ပ်အကြောင်းကြားချက်များကို ဖွင့်ပါ"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ဆက်တင်များ ပြောင်းရန်"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"အကြောင်းကြားချက် အစက်များ ပြရန်"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"ပင်မစာမျက်နှာတွင် အက်ပ်သင်္ကေတထည့်ရန်"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"တီထွင်သူ ရွေးစရာများ"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"ပင်မစာမျက်နှာတွင် အက်ပ်သင်္ကေတထည့်ခြင်း"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"အက်ပ်အသစ်များအတွက်"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"မသိ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ဖယ်ရှားရန်"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"အပ်ဒိတ်လုပ်ရန်"</string>
+ <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="8902165848117513641">"ပင်မမျက်နှာစာသို့ ထည့်ပါ"</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_removed" msgid="851119963877842327">"ဖယ်ရှားပြီးပြီ"</string>
@@ -141,7 +146,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="1603837886334246317">"ပင်မမျက်နှာပြင်သို့ ရွှေ့ပါ"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"ရပြီ"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"အလုပ်သုံးအက်ပ်များ ပိတ်ရန်"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"အလုပ်သုံးအက်ပ်များကို ခဏရပ်ရန်"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"အလုပ်သုံးအက်ပ်များ ဖွင့်ရန်"</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="remote_action_failed" msgid="1383965239183576790">"မအောင်မြင်ပါ− <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 8093939..eba195c 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d bredde x %2$d høyde"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-modul"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Trykk og hold på modulen for å bevege den rundt på startskjermen"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Legg til på startskjermen"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Jobb"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Samtaler"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Lett tilgjengelig nyttig informasjon"</string>
- <string name="widget_education_content" msgid="745542879510751525">"For å se informasjon uten å åpne apper kan du legge til moduler på startskjermen"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Greit"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Endre modulinnstillinger"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Varsler"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Trykk og hold for å flytte en snarvei."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Dobbelttrykk og hold for å flytte en snarvei eller bruke tilpassede handlinger."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Ingen ledig plass på denne startskjermen"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Ingen ledig plass på denne startskjermen"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Favoritter-skuffen er full"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"App-liste"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Søkeresultater"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Fest forslaget"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"installere snarveier"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Gir apper tillatelse til å legge til snarveier uten innblanding fra brukeren."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"lese startsideinnstillinger og -snarveier"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Lar appen lese innstillingene og snarveiene på startsiden."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"angi startsideinnstillinger og -snarveier"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Lar appen endre innstillingene og snarveiene på startsiden."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"lese startsideinnstillinger og -snarveier"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Dette er en systemapp som ikke kan avinstalleres."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Rediger navn"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Slo av <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} har # varsel}other{{app_name} har # varsler}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} har # varsel}other{{app_name} har # varsler}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Side %1$d av %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Startside %1$d av %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Ny side på startskjermen"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Bakgrunn og stil"</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="7728578836261442095">"Tillat at startskjermen roterer"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Tillat at startskjermen roterer"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Når telefonen roteres"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Varselsprikker"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"På"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Slå på appvarsler for <xliff:g id="NAME">%1$s</xliff:g> for å vise varselsprikker"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Endre innstillingene"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Vis varselsprikker"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Legg til appikoner på startskjermen"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Utvikleralternativer"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Legg til appikoner på startskjermen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For nye apper"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Ukjent"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Fjern"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installerer, <xliff:g id="PROGRESS">%2$s</xliff:g> er fullført"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Laster ned <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> er fullført"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Venter på å installere <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Appen må oppdateres"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Appen for dette ikonet er ikke oppdatert. Du kan oppdatere manuelt for å aktivere denne snarveien igjen, eller du kan fjerne ikonet."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Oppdater"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Fjern"</string>
<string name="widgets_list" msgid="796804551140113767">"Modulliste"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Modullisten er lukket"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Legg til på startskjermen"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Legg til på startskjermen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Flytt elementet hit"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Elementet er lagt til på startskjermen"</string>
<string name="item_removed" msgid="851119963877842327">"Elementet er fjernet"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Elementet er lagt til i mappen"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Opprett mappe med: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Mappen er opprettet"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Flytt til startskjermen"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Flytt til startskjermen"</string>
<string name="action_resize" msgid="1802976324781771067">"Endre størrelse"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Øk bredden"</string>
<string name="action_increase_height" msgid="459390020612501122">"Øk høyden"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Slå av jobbapper"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Mislyktes: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index ded1efd..0d149a0 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"यो विजेट होम स्क्रिनमा यताउता सार्न त्यसमा टच एन्ड होल्ड गर्नुहोस्"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"होम स्क्रिनमा हाल्नुहोस्"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# विजेट}other{# वटा विजेट}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# सर्टकट}other{# वटा सर्टकट}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"कामसम्बन्धी"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"वार्तालापहरू"</string>
<string name="widget_education_header" msgid="4874760613775913787">"उपयोगी जानकारी सजिलै प्राप्त गर्नुहोस्"</string>
- <string name="widget_education_content" msgid="745542879510751525">"एपहरू नखोलिकनै जानकारी प्राप्त गर्न तपाईं आफ्नो होम स्क्रिनमा विजेटहरू हाल्न सक्नुहुन्छ"</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>
@@ -65,7 +65,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="6692471482459245734">"यो होम स्क्रिनमा ठाउँ छैन"</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>
@@ -75,14 +75,14 @@
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"अनइन्स्टल गर्नुहोस्"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"एपसम्बन्धी जानकारी"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"स्थापना गर्नुहोस्"</string>
- <string name="dismiss_prediction_label" msgid="3357562989568808658">"यो एप सिफारिस नगरियोस्"</string>
+ <string name="dismiss_prediction_label" msgid="3357562989568808658">"एप सिफारिस नगरियोस्"</string>
<string name="pin_prediction" msgid="4196423321649756498">"सिफारिस गरिएको एप पिन गर्नुहोस्"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"सर्टकट स्थापना गर्नेहोस्"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"प्रयोगकर्ताको हस्तक्षेप बिना एउटा एपलाई सर्टकटमा थप्नको लागि अनुमति दिनुहोस्।"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"गृह सेटिङहरू र सर्टकटहरू पढ्नुहोस्"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"गृहमा एउटा एपलाई सेटिङहरू र सर्टकटहरू पढ्न अनुमति दिनुहोस्।"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"गृह सेटिङहरू र सर्टकटहरू लेख्नुहोस्"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"गृहमा एउटा एपलाई सेटिङ र सर्टकट बदल्न अनुमति दिनुहोस्।"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"होम स्क्रिनका सेटिङ र सर्टकटहरू रिड गरियोस्"</string>
+ <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>
@@ -90,10 +90,10 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"यो प्रणाली एप हो र यसलाई स्थापना रद्द गर्न सकिँदैन।"</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} सँग सम्बन्धित # सूचना छ}other{{app_name} सँग सम्बन्धित # वटा सूचना छन्}}"</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="workspace_scroll_format" msgid="8458889198184077399">"गृह स्क्रिन %1$d को %2$d"</string>
- <string name="workspace_new_page" msgid="257366611030256142">"नयाँ गृह स्क्रिन पृष्ठ"</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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"वालपेपर तथा शैली"</string>
<string name="settings_button_text" msgid="8873672322605444408">"होम पेजका सेटिङहरू"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"तपाईँको प्रशासकद्वारा असक्षम गरिएको"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"होम स्क्रिन रोटेट हुन दिइयोस्"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"सूचनाको प्रतीक जनाउने थोप्लाहरू देखाउन <xliff:g id="NAME">%1$s</xliff:g> को एपसम्बन्धी सूचनाहरूलाई अन गर्नुहोस्"</string>
<string name="title_change_settings" msgid="1376365968844349552">"सेटिङहरू बदल्नुहोस्"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"सूचनाको प्रतीक जनाउने थोप्लाहरू देखाउनुहोस्"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"होम स्क्रिनमा एपका आइकन थपियोस्"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"विकासकर्ताका लागि उपलब्ध विकल्पहरू"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"एपका आइकनहरू होम स्क्रिनमा राखियोस्"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"नयाँ एपका लागि"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"अज्ञात"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"हटाउनुहोस्"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"अपडेट गर्नुहोस्"</string>
+ <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="8902165848117513641">"होम स्क्रिनमा हाल्नुहोस्"</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_removed" msgid="851119963877842327">"वस्तु हटाइयो"</string>
@@ -141,7 +146,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="1603837886334246317">"गृह स्क्रिनमा सार्नुहोस्"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"बुझेँ"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"कामसम्बन्धी एपहरू अफ गर्नुहोस्"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"कामसम्बन्धी एपहरू अस्थायी रूपमा रोक्का गर्नुहोस्"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"कामसम्बन्धी एपहरू अन गर्नुहोस्"</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="remote_action_failed" msgid="1383965239183576790">"कार्य पूरा गर्न सकिएन: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-night-v31/colors.xml b/res/values-night-v31/colors.xml
index 2c1bc90..eefe8c5 100644
--- a/res/values-night-v31/colors.xml
+++ b/res/values-night-v31/colors.xml
@@ -24,4 +24,9 @@
<color name="home_settings_thumb_off_color">@android:color/system_neutral2_300</color>
<color name="home_settings_track_on_color">@android:color/system_accent2_700</color>
<color name="home_settings_track_off_color">@android:color/system_neutral1_700</color>
+
+ <color name="all_apps_button_bg_color">@android:color/system_neutral1_800</color>
+ <color name="all_apps_button_color_1">@android:color/system_accent1_300</color>
+ <color name="all_apps_button_color_3">@android:color/system_accent1_100</color>
+ <color name="all_apps_button_color_4">@android:color/system_accent2_100</color>
</resources>
\ No newline at end of file
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
new file mode 100644
index 0000000..ce272ce
--- /dev/null
+++ b/res/values-night/colors.xml
@@ -0,0 +1,25 @@
+<?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.
+*/
+-->
+
+<resources>
+ <color name="all_apps_button_bg_color">#2E3132</color>
+ <color name="all_apps_button_color_1">#33B9DB</color>
+ <color name="all_apps_button_color_2">#EFFBFF</color>
+ <color name="all_apps_button_color_3">#B1EBFF</color>
+ <color name="all_apps_button_color_4">#DEE0FF</color>
+</resources>
\ No newline at end of file
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index f9ec65c..e19b361 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d breed en %2$d hoog"</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="5653291305078645405">"Houd de widget ingedrukt om deze te verplaatsen op het startscherm"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Toevoegen aan startscherm"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Werk"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Gesprekken"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Nuttige informatie binnen handbereik"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Als je informatie wilt krijgen zonder apps te openen, kun je widgets toevoegen aan je startscherm"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Widgetinstellingen wijzigen"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Meldingen"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Tik en houd vast om een snelkoppeling te verplaatsen."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Dubbeltik en houd vast om een snelkoppeling te verplaatsen of aangepaste acties te gebruiken."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Er is geen ruimte op dit startscherm"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Er is geen ruimte op dit startscherm"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Geen ruimte meer in het vak \'Favorieten\'"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Lijst met apps"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Zoekresultaten"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Vastzetvoorspelling"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"Snelle links instellen"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Een app toestaan snelkoppelingen toe te voegen zonder tussenkomst van de gebruiker."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"instellingen en snelkoppelingen op startscherm lezen"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"De app toestaan de instellingen en snelkoppelingen op de homepage te lezen."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"instellingen en snelkoppelingen op startscherm zetten"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"De app toestaan de instellingen en snelkoppelingen op de homepage te wijzigen."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"instellingen en snelkoppelingen op startscherm lezen"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Dit is een systeemapp die niet kan worden verwijderd."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Naam bewerken"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> staat uit"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} heeft # melding}other{{app_name} heeft # meldingen}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} heeft # melding}other{{app_name} heeft # meldingen}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Pagina %1$d van %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Startscherm %1$d van %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nieuwe startschermpagina"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Achtergrond en stijl"</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="7728578836261442095">"Draaien van startscherm toestaan"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Draaien van startscherm toestaan"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Als de telefoon gedraaid is"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Meldingsstipjes"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Aan"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Als je meldingsstipjes wilt tonen, zet je app-meldingen aan voor <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Instellingen wijzigen"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Toon meldingsstipjes"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"App-iconen toevoegen aan startscherm"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Ontwikkelaarsopties"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"App-iconen toevoegen aan startscherm"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Voor nieuwe apps"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Onbekend"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Verwijderen"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installeren, <xliff:g id="PROGRESS">%2$s</xliff:g> voltooid"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> wordt gedownload, <xliff:g id="PROGRESS">%2$s</xliff:g> voltooid"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> wacht op installatie"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"App-update vereist"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"De app voor dit icoon is niet geüpdatet. Je kunt handmatig updaten om deze snelkoppeling weer aan te zetten of het icoon verwijderen."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Updaten"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Verwijderen"</string>
<string name="widgets_list" msgid="796804551140113767">"Lijst met widgets"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Lijst met widgets gesloten"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Toevoegen aan startscherm"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Toevoegen aan startscherm"</string>
<string name="action_move_here" msgid="2170188780612570250">"Item hier naartoe verplaatsen"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item toegevoegd aan startscherm"</string>
<string name="item_removed" msgid="851119963877842327">"Item verwijderd"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Item toegevoegd aan map"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Map maken met: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Map gemaakt"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Verplaatsen naar startscherm"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Verplaatsen naar startscherm"</string>
<string name="action_resize" msgid="1802976324781771067">"Formaat aanpassen"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Breedte vergroten"</string>
<string name="action_increase_height" msgid="459390020612501122">"Hoogte vergroten"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Werk-apps uitzetten"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Mislukt: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 4139285..9067076 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -26,7 +26,7 @@
<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="home_screen" msgid="5629429142036709174">"ହୋମ"</string>
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"ସ୍କ୍ରିନକୁ ସ୍ପ୍ଲିଟ୍ କରନ୍ତୁ"</string>
<string name="split_screen_position_top" msgid="1504965011158689649">"ଶୀର୍ଷକୁ ସ୍ପ୍ଲିଟ କରନ୍ତୁ"</string>
<string name="split_screen_position_left" msgid="7537793098851830883">"ବାମପତକୁ ସ୍ପ୍ଲିଟ କରନ୍ତୁ"</string>
@@ -37,9 +37,9 @@
<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="5653291305078645405">"ମୂଳସ୍କ୍ରିନର ଆଖପାଖରେ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ଏହାକୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"ମୂଳସ୍କ୍ରିନରେ ଯୋଗ କରନ୍ତୁ"</string>
- <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ୱାର୍କ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ଉପଯୋଗୀ ସୂଚନା ଆପଣଙ୍କ ପାଖରେ ସହଜରେ ଉପଲବ୍ଧ"</string>
- <string name="widget_education_content" msgid="745542879510751525">"ଆପଗୁଡ଼ିକୁ ନଖୋଲି ସୂଚନା ପାଇବା ପାଇଁ, ଆପଣ ଆପଣଙ୍କ ମୂଳସ୍କ୍ରିନରେ ୱିଜେଟଗୁଡ଼ିକୁ ଯୋଗ କରିପାରିବେ"</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>
@@ -65,35 +65,35 @@
<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="6692471482459245734">"ଏହି ମୂଳସ୍କ୍ରିନରେ ଆଉ ଜାଗା ନାହିଁ"</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>
<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="uninstall_drop_target_label" msgid="4722034217958379417">"ଅନଇନଷ୍ଟଲ୍ କରନ୍ତୁ"</string>
+ <string name="uninstall_drop_target_label" msgid="4722034217958379417">"ଅନଇନଷ୍ଟଲ କରନ୍ତୁ"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"ଆପ୍ ସୂଚନା"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ଇନଷ୍ଟଲ୍ କରନ୍ତୁ"</string>
- <string name="dismiss_prediction_label" msgid="3357562989568808658">"ଆପ୍ ପରାମର୍ଶ ଦିଅନ୍ତୁ ନାହିଁ"</string>
+ <string name="dismiss_prediction_label" msgid="3357562989568808658">"ଆପ ପରାମର୍ଶ ଦିଅନ୍ତୁ ନାହିଁ"</string>
<string name="pin_prediction" msgid="4196423321649756498">"ପୂର୍ବାନୁମାନକୁ ପିନ୍ କରନ୍ତୁ"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"ସର୍ଟକଟ୍ ଇନଷ୍ଟଲ୍ କରନ୍ତୁ"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ୟୁଜରଙ୍କ ବିନା ହସ୍ତକ୍ଷେପରେ ଶର୍ଟକଟ୍ ଯୋଡ଼ିବାକୁ ଆପକୁ ଅନୁମତି ଦିଏ।"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"ହୋମ ସେଟିଂସ ଏବଂ ସର୍ଟକଟ ପଢ଼ନ୍ତୁ"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"ହୋମରେ ସେଟିଂସ ଏବଂ ସର୍ଟକଟକୁ ପଢ଼ିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ।"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"ହୋମ ସେଟିଂସ ଏବଂ ସର୍ଟକଟ ଲେଖନ୍ତୁ"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"ହୋମରେ ସେଟିଂସ ଏବଂ ସର୍ଟକଟକୁ ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ।"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"ହୋମ ସେଟିଂସ ଏବଂ ସର୍ଟକଟଗୁଡ଼ିକୁ ପଢ଼ନ୍ତୁ"</string>
+ <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>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ଏହା ଏକ ସିଷ୍ଟମ୍ ଆପ୍ ଅଟେ ଏବଂ ଏହା ଅନଇନଷ୍ଟଲ୍ କରାଯାଇ ପାରିବ ନାହିଁ।"</string>
- <string name="folder_hint_text" msgid="5174843001373488816">"ନାମ ସମ୍ପାଦନ କରନ୍ତୁ"</string>
+ <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="1704091277755818896">"{count,plural,offset:1 =1{{app_name}ର #ଟି ବିଜ୍ଞପ୍ତି ରହିଛି}other{{app_name}ର #ଟି ବିଜ୍ଞପ୍ତି ରହିଛି}}"</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="workspace_scroll_format" msgid="8458889198184077399">"%2$dରୁ %1$d ହୋମ୍ ସ୍କ୍ରୀନ୍"</string>
- <string name="workspace_new_page" msgid="257366611030256142">"ନୂଆ ହୋମ୍ ସ୍କ୍ରୀନ୍ ପୃଷ୍ଠା"</string>
+ <string name="workspace_scroll_format" msgid="8458889198184077399">"%2$dରୁ %1$d ହୋମ ସ୍କ୍ରିନ"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"ନୂଆ ହୋମ ସ୍କ୍ରିନ ପେଜ"</string>
<string name="folder_opened" msgid="94695026776264709">"<xliff:g id="HEIGHT">%2$d</xliff:g> / <xliff:g id="WIDTH">%1$d</xliff:g>ର ଫୋଲ୍ଡର ଖୋଲାଗଲା"</string>
<string name="folder_tap_to_close" msgid="4625795376335528256">"ଫୋଲ୍ଡର୍ ବନ୍ଦ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string>
<string name="folder_tap_to_rename" msgid="4017685068016979677">"ନାମ ବଦଳାଇବା ସେଭ୍ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ୱାଲପେପର ଏବଂ ଷ୍ଟାଇଲ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ହୋମ ସେଟିଂସ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ଆପଣଙ୍କ ଆଡମିନଙ୍କ ଦ୍ୱାରା ଅକ୍ଷମ କରାଯାଇଛି"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"ହୋମ୍ ସ୍କ୍ରିନ୍ ବୁଲାଇବାକୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"ବିଜ୍ଞପ୍ତି ବିନ୍ଦୁ ଦେଖାଇବାକୁ, <xliff:g id="NAME">%1$s</xliff:g> ପାଇଁ ଆପ୍ ବିଜ୍ଞପ୍ତି ଅନ୍ କରନ୍ତୁ"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ସେଟିଂସ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"ବିଜ୍ଞପ୍ତି ଡଟ୍ଗୁଡ଼ିକୁ ଦେଖାନ୍ତୁ"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"ହୋମ୍ ସ୍କ୍ରିନରେ ଆପ୍ ଆଇକନଗୁଡ଼ିକୁ ଯୋଗ କରନ୍ତୁ"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"ଡେଭେଲପର ବିକଳ୍ପଗୁଡ଼ିକ"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"ହୋମ ସ୍କ୍ରିନରେ ଆପ ଆଇକନଗୁଡ଼ିକୁ ଯୋଗ କରନ୍ତୁ"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ନୂଆ ଆପ୍ ପାଇଁ"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ଅଜଣା"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"କାଢ଼ି ଦିଅନ୍ତୁ"</string>
@@ -124,11 +125,15 @@
<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" msgid="2178028071796141234">"ଅପଡେଟ କରନ୍ତୁ"</string>
+ <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="8902165848117513641">"ହୋମ୍ ସ୍କ୍ରୀନରେ ଯୋଡ଼ନ୍ତୁ"</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>
@@ -141,7 +146,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="1603837886334246317">"ହାମ୍ ସ୍କ୍ରୀନକୁ ଘୁଞ୍ଚାନ୍ତୁ"</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>
@@ -156,15 +161,17 @@
<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_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_edu_banner" msgid="8872412121608402058">"ୱାର୍କ ଆପ୍ସ ବ୍ୟାଜ୍ କରାଯାଇଛି ଏବଂ ଆପଣଙ୍କ IT ଆଡମିନଙ୍କୁ ଦେଖାଯାଉଛି"</string>
<string name="work_apps_paused_edu_accept" msgid="6377476824357318532">"ବୁଝିଗଲି"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"ୱାର୍କ ଆପଗୁଡ଼ିକୁ ବନ୍ଦ କରନ୍ତୁ"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ୱାର୍କ ଆପ୍ସ ବିରତ କରନ୍ତୁ"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ୱାର୍କ ଆପଗୁଡ଼ିକୁ ଚାଲୁ କରନ୍ତୁ"</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="remote_action_failed" msgid="1383965239183576790">"ବିଫଳ ହୋଇଛି: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 35a279b..e0f2138 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"ਵਿਜੇਟ ਨੂੰ ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਇੱਧਰ-ਉੱਧਰ ਲਿਜਾਉਣ ਲਈ ਸਪਰਸ਼ ਕਰਕੇ ਦਬਾਈ ਰੱਖੋ"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਸ਼ਾਮਲ ਕਰੋ"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ਵਿਜੇਟ}one{# ਵਿਜੇਟ}other{# ਵਿਜੇਟ}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ਸ਼ਾਰਟਕੱਟ}one{# ਸ਼ਾਰਟਕੱਟ}other{# ਸ਼ਾਰਟਕੱਟ}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ਕਾਰਜ-ਸਥਾਨ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"ਗੱਲਾਂਬਾਤਾਂ"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ਮਹੱਤਵਪੂਰਨ ਜਾਣਕਾਰੀ ਤੁਰੰਤ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
- <string name="widget_education_content" msgid="745542879510751525">"ਐਪਾਂ ਨੂੰ ਖੋਲ੍ਹੇ ਬਿਨਾਂ ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ, ਤੁਸੀਂ ਆਪਣੀ ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਵਿਜੇਟ ਸ਼ਾਮਲ ਕਰ ਸਕਦੇ ਹੋ"</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>
@@ -65,7 +65,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="6692471482459245734">"ਇਸ ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਜਗ੍ਹਾ ਨਹੀਂ ਬਚੀ"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"ਪੂਰਵ-ਅਨੁਮਾਨ ਪਿੰਨ ਕਰੋ"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"ਸ਼ਾਰਟਕੱਟ ਸਥਾਪਤ ਕਰੋ"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"ਇੱਕ ਐਪ ਨੂੰ ਵਰਤੋਂਕਾਰ ਦੇ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਸ਼ਾਰਟਕੱਟ ਸ਼ਾਮਲ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"ਹੋਮ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਪੜ੍ਹੋ"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"ਐਪ ਨੂੰ ਹੋਮ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"ਹੋਮ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਲਿਖੋ"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"ਐਪ ਨੂੰ ਹੋਮ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਬਦਲਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"ਹੋਮ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਪੜ੍ਹੋ"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ਇਹ ਇੱਕ ਸਿਸਟਮ ਐਪ ਹੈ ਅਤੇ ਇਸਨੂੰ ਅਣਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} \'ਤੇ # ਸੂਚਨਾ ਹੈ}one{{app_name} \'ਤੇ # ਸੂਚਨਾ ਹੈ}other{{app_name} \'ਤੇ # ਸੂਚਨਾਵਾਂ ਹਨ}}"</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">"ਸਫ਼ਾ %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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"ਵਾਲਪੇਪਰ ਅਤੇ ਸਟਾਈਲ"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ਹੋਮ ਸੈਟਿੰਗਾਂ"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਅਯੋਗ ਬਣਾਈ ਗਈ"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"ਹੋਮ ਸਕ੍ਰੀਨ ਨੂੰ ਘੁਮਾਉਣ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"ਸੂਚਨਾ ਬਿੰਦੂਆਂ ਦਿਖਾਉਣ ਲਈ, <xliff:g id="NAME">%1$s</xliff:g> ਲਈ ਐਪ ਸੂਚਨਾਵਾਂ ਚਾਲੂ ਕਰੋ"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ਸੈਟਿੰਗਾਂ ਬਦਲੋ"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"ਸੂਚਨਾ ਬਿੰਦੂ ਦਿਖਾਓ"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਐਪ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰੋ"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"ਵਿਕਾਸਕਾਰ ਚੋਣਾਂ"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਐਪ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ਨਵੀਆਂ ਐਪਾਂ ਲਈ"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ਅਗਿਆਤ"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ਹਟਾਓ"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"ਅੱਪਡੇਟ ਕਰੋ"</string>
+ <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="8902165848117513641">"ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਸ਼ਾਮਲ ਕਰੋ"</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_removed" msgid="851119963877842327">"ਆਈਟਮ ਹਟਾਈ ਗਈ"</string>
@@ -141,7 +146,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="1603837886334246317">"ਹੋਮ ਸਕ੍ਰੀਨ ਵਿੱਚ ਮੂਵ ਕਰੋ"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"ਸਮਝ ਲਿਆ"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਬੰਦ ਕਰੋ"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਰੋਕੋ"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਚਾਲੂ ਕਰੋ"</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="remote_action_failed" msgid="1383965239183576790">"ਇਹ ਕਾਰਵਾਈ ਅਸਫਲ ਹੋਈ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index f9bfb77..b6ddbbf 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Kliknij i przytrzymaj widżet, by poruszać nim po ekranie głównym"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Dodaj do ekranu głównego"</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_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>
<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>
@@ -52,7 +52,7 @@
<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_education_header" msgid="4874760613775913787">"Użyteczne informacje w zasięgu ręki"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Aby uzyskać informacje bez otwierania aplikacji, możesz dodać widżety do ekranu głównego"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Zmień ustawienia widżetu"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Powiadomienia"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Naciśnij i przytrzymaj, aby przenieść skrót."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Naciśnij dwukrotnie i przytrzymaj, aby przenieść skrót lub użyć działań niestandardowych."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Brak miejsca na tym ekranie głównym"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Brak miejsca na tym ekranie głównym"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Brak miejsca w Ulubionych"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Lista aplikacji"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Wyniki wyszukiwania"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Przypnij podpowiedź"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"Instalowanie skrótów"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Pozwala aplikacji dodawać skróty bez interwencji użytkownika."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"odczytywanie ustawień i skrótów na ekranie głównym"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Pozwala aplikacji na odczytywanie ustawień i skrótów na ekranie głównym."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"zapisywanie ustawień i skrótów na ekranie głównym"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Umożliwia aplikacji zmianę ustawień i skrótów na ekranie głównym."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"Odczytuje ustawienia i skróty na ekranie głównym"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"To aplikacja systemowa i nie można jej odinstalować."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Edytuj nazwę"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> jest wyłączona"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} – # powiadomienie}few{{app_name} – # powiadomienia}many{{app_name} – # powiadomień}other{{app_name} – # powiadomienia}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} – # powiadomienie}few{{app_name} – # powiadomienia}many{{app_name} – # powiadomień}other{{app_name} – # powiadomienia}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Strona %1$d z %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Ekran główny %1$d z %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nowa strona ekranu głównego"</string>
@@ -105,16 +105,17 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Tapeta i styl"</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="7728578836261442095">"Zezwalaj na obrót ekranu głównego"</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">"Plakietki z powiadomieniami"</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="title_missing_notification_access" msgid="7503287056163941064">"Wymagany jest dostęp do powiadomień"</string>
- <string name="msg_missing_notification_access" msgid="281113995110910548">"Aby pokazać plakietki z powiadomieniami, włącz powiadomienia aplikacji <xliff:g id="NAME">%1$s</xliff:g>"</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>
- <string name="notification_dots_service_title" msgid="4284221181793592871">"Pokaż plakietki z powiadomieniami"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Dodawaj ikony aplikacji do ekranu głównego"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Pokaż kropki powiadomień"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Opcje programisty"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Dodawaj ikony aplikacji do ekranu głównego"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"W przypadku nowych aplikacji"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Brak informacji"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Usuń"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Instaluję aplikację <xliff:g id="NAME">%1$s</xliff:g>, postęp: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Pobieranie elementu <xliff:g id="NAME">%1$s</xliff:g>, ukończono: <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> oczekuje na instalację"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Wymagana aktualizacja aplikacji"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Aplikacja z tą ikoną nie jest aktualizowana. Możesz zaktualizować ją ręcznie, aby ponownie uruchomić ten skrót, lub usunąć ikonę."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Aktualizuj"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Usuń"</string>
<string name="widgets_list" msgid="796804551140113767">"Lista widgetów"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Lista widgetów zamknięta"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Dodaj do ekranu głównego"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Dodaj do ekranu głównego"</string>
<string name="action_move_here" msgid="2170188780612570250">"Przenieś element tutaj"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Element został dodany do ekranu głównego"</string>
<string name="item_removed" msgid="851119963877842327">"Element został usunięty"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Element został dodany do folderu"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Utwórz folder z: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Folder został utworzony"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Przenieś na ekran główny"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Przenieś na ekran główny"</string>
<string name="action_resize" msgid="1802976324781771067">"Zmień rozmiar"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Zwiększ szerokość"</string>
<string name="action_increase_height" msgid="459390020612501122">"Zwiększ wysokość"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Wyłącz aplikacje służbowe"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Niepowodzenie: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 61e6a67..3587f7c 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largura por %2$d de altura"</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="5653291305078645405">"Toque sem soltar no widget para o mover no ecrã principal"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Adicionar ao ecrã principal"</string>
+ <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Toque sem soltar no widget para o mover no ecrã principal"</string>
+ <string name="add_to_home_screen" msgid="9168649446635919791">"Adicionar ao ecrã principal"</string>
<string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> adicionado ao ecrã principal"</string>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# atalho}other{# atalhos}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabalho"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversas"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Informações úteis à sua disposição"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Para obter informações sem abrir apps, pode adicionar widgets ao seu ecrã principal"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Alterar definições do widget"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notificações"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Toque sem soltar para mover um atalho."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Toque duas vezes sem soltar para mover um atalho ou utilizar ações personalizadas."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Sem espaço neste ecrã principal."</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Sem espaço neste ecrã principal"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Não existe mais espaço no tabuleiro de Favoritos"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Lista de aplicações"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Resultados da pesquisa"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Fixar previsão"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalar atalhos"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite a uma app adicionar atalhos sem a intervenção do utilizador."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"ler definições e atalhos do Ecrã Principal"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Permite à app ler as definições e os atalhos no Ecrã Principal."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"escrever definições e atalhos do Ecrã principal"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Permite à app alterar as definições e os atalhos no Ecrã Principal."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"ler definições e atalhos do ecrã Principal"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"É uma app de sistema e não pode ser desinstalada."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Edite o nome"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> desativado"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{A app {app_name} tem # notificação}other{A app {app_name} tem # notificações}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{A app {app_name} tem # notificação}other{A app {app_name} tem # notificações}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Página %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Ecrã principal %1$d de %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nova página do ecrã principal"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Imagem fundo/estilo"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Definições de início"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Desativada pelo gestor"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Permitir rotação do ecrã principal"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Permitir rotação do ecrã principal"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Quando o telemóvel é rodado"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Pontos de notificação"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Ativados"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Para mostrar os Pontos de notificação, ative as notificações de aplicações para o <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Alterar definições"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Mostrar pontos de notificação"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Adic. ícones de apps ao ecrã principal"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Opções de programador"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Adicionar ícones de apps ao ecrã principal"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para novas apps"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconhecido"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remover"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"A instalar <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> concluído"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"A transferir o <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> concluído"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"A aguardar a instalação do <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Atualização da app necessária"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"A app deste ícone não está atualizada. Pode atualizar manualmente para reativar este atalho ou remover o ícone."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Atualizar"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Remover"</string>
<string name="widgets_list" msgid="796804551140113767">"Lista de widgets"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Lista de widgets fechada."</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Adicionar ao ecrã principal"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Adicionar ao ecrã principal"</string>
<string name="action_move_here" msgid="2170188780612570250">"Mover o item para aqui"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item adicionado ao ecrã principal"</string>
<string name="item_removed" msgid="851119963877842327">"Item removido"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Item adicionado à pasta"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Criar pasta com: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Pasta criada"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Mover para o Ecrã principal"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Mover para o ecrã principal"</string>
<string name="action_resize" msgid="1802976324781771067">"Redimensionar"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Aumentar largura"</string>
<string name="action_increase_height" msgid="459390020612501122">"Aumentar altura"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Desativar apps de trabalho"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Falhou: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 7beedcb..2dcb98f 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largura por %2$d de altura"</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="5653291305078645405">"Toque no widget e mantenha-o pressionado para movê-lo pela tela inicial"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Adicionar à tela inicial"</string>
+ <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Toque no widget e o mantenha pressionado 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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabalho"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Conversas"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Informações úteis ao seu alcance"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Para receber informações sem precisar abrir apps, adicione widgets à sua tela inicial"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Ok"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Mudar as configurações do widget"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Notificações"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Toque e mantenha a tela pressionada para mover um atalho."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Toque duas vezes e mantenha a tela pressionada para mover um atalho ou usar ações personalizadas."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Não há espaço nesta tela inicial"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Não há espaço nesta tela inicial"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Sem espaço na bandeja de favoritos"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Lista de apps"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Resultados da pesquisa"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Fixar previsão"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalar atalhos"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite que um app adicione atalhos sem intervenção do usuário."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"ler configurações e atalhos da tela inicial"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Permite que o app leia as configurações e os atalhos na tela inicial."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"gravar configurações e atalhos da tela inicial"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Permite que o app altere as configurações e os atalhos na tela inicial."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"ler configurações e atalhos da tela inicial"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Este é um app do sistema e não pode ser desinstalado."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Editar nome"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> desativado"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{O app {app_name} tem # notificação}one{O app {app_name} tem # notificação}other{O app {app_name} tem # notificações}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{O app {app_name} tem # notificação}one{O app {app_name} tem # notificação}other{O app {app_name} tem # notificações}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Página %1$d de %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Tela inicial %1$d de %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nova página na tela inicial"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Plano de fundo e estilo"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Configurações da tela inicial"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Desativado pelo administrador"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Permitir rotação da tela inicial"</string>
+ <string name="allow_rotation_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>
@@ -114,7 +114,8 @@
<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>
<string name="title_change_settings" msgid="1376365968844349552">"Alterar configurações"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Mostrar pontos de notificação"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Adicionar ícones de apps à tela inicial"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Opções do desenvolvedor"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Adicionar ícones de apps à tela inicial"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para novos apps"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Desconhecido"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Remover"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Instalando <xliff:g id="NAME">%1$s</xliff:g>. <xliff:g id="PROGRESS">%2$s</xliff:g> concluído"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Fazendo download de <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> concluído"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Aguardando instalação de <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Atualização obrigatória do app"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"O app desse ícone não está atualizado. Você pode remover o ícone ou atualizar o app manualmente para reativar esse atalho."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Atualizar"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Remover"</string>
<string name="widgets_list" msgid="796804551140113767">"Lista de widgets"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Lista de widgets fechada"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Adicionar à tela inicial"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Adicionar à tela inicial"</string>
<string name="action_move_here" msgid="2170188780612570250">"Mover item para cá"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Item adicionado à tela inicial"</string>
<string name="item_removed" msgid="851119963877842327">"Item removido"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Item adicionado à pasta"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Criar pasta com: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Pasta criada"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Mover para a tela inicial"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Mover para a tela inicial"</string>
<string name="action_resize" msgid="1802976324781771067">"Redimensionar"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Aumentar largura"</string>
<string name="action_increase_height" msgid="459390020612501122">"Aumentar altura"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Desativar apps de trabalho"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Falha: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 14db745..9d9fb76 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -28,75 +28,75 @@
<string name="shortcut_not_available" msgid="2536503539825726397">"Comanda rapidă nu este disponibilă"</string>
<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_screen_position_top" msgid="1504965011158689649">"Împărțiți în sus"</string>
- <string name="split_screen_position_left" msgid="7537793098851830883">"Împărțiți în stânga"</string>
- <string name="split_screen_position_right" msgid="1569377524925193369">"Împărțiți în dreapta"</string>
+ <string name="split_screen_position_top" msgid="1504965011158689649">"Împarte în sus"</string>
+ <string name="split_screen_position_left" msgid="7537793098851830883">"Împarte în stânga"</string>
+ <string name="split_screen_position_right" msgid="1569377524925193369">"Împarte în dreapta"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informații despre aplicație pentru %1$s"</string>
- <string name="long_press_widget_to_add" msgid="3587712543577675817">"Atingeți și țineți apăsat pentru a muta un widget."</string>
- <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Atingeți de două ori și țineți apăsat pentru a muta un widget sau folosiți acțiuni personalizate."</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>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d lățime și %2$d înălțime"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Widgetul <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Atingeți lung widgetul pentru a-l muta pe ecranul de pornire"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Adăugați pe ecranul de pornire"</string>
+ <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>
<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>
<string name="widget_button_text" msgid="2880537293434387943">"Widgeturi"</string>
<string name="widgets_full_sheet_search_bar_hint" msgid="8484659090860596457">"Căutare"</string>
- <string name="widgets_full_sheet_cancel_button_description" msgid="5766167035728653605">"Ștergeți textul din caseta de căutare"</string>
+ <string name="widgets_full_sheet_cancel_button_description" msgid="5766167035728653605">"Șterge textul din caseta de căutare"</string>
<string name="no_widgets_available" msgid="4337693382501046170">"Widgeturile și comenzile rapide nu sunt disponibile"</string>
<string name="no_search_results" msgid="3787956167293097509">"Nu au fost găsite widgeturi sau comenzi rapide"</string>
<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_education_header" msgid="4874760613775913787">"Informații utile la îndemâna dvs."</string>
- <string name="widget_education_content" msgid="745542879510751525">"Pentru a primi informații fără să deschideți aplicațiile, puteți adăuga widgeturi pe ecranul de pornire"</string>
- <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Atingeți ca să schimbați setările pentru widgeturi"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
- <string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Modificați setările pentru widgeturi"</string>
- <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"Căutați aplicații"</string>
+ <string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Modifică setările pentru widgeturi"</string>
+ <string name="all_apps_search_bar_hint" msgid="1390553134053255246">"Caută aplicații"</string>
<string name="all_apps_loading_message" msgid="5813968043155271636">"Se încarcă aplicații…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Nu s-a găsit nicio aplicație pentru „<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
- <string name="all_apps_search_market_message" msgid="1366263386197059176">"Căutați mai multe aplicații"</string>
+ <string name="all_apps_search_market_message" msgid="1366263386197059176">"Caută mai multe aplicații"</string>
<string name="label_application" msgid="8531721983832654978">"Aplicație"</string>
<string name="all_apps_label" msgid="5015784846527570951">"Toate aplicațiile"</string>
<string name="notifications_header" msgid="1404149926117359025">"Notificări"</string>
- <string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Atingeți și țineți apăsat pentru a muta comanda rapidă."</string>
- <string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Atingeți de două ori și țineți apăsat pentru a muta o comandă rapidă sau folosiți acțiuni personalizate."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Nu există spațiu liber pe acest ecran de pornire"</string>
+ <string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Atinge și ține apăsat ca să muți comanda rapidă."</string>
+ <string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Atinge de două ori și ține apăsat pentru a muta o comandă rapidă sau folosește acțiuni personalizate."</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Nu există spațiu liber pe acest ecran de pornire"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Spațiu epuizat în bara Preferate"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Lista de aplicații"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Rezultatele căutării"</string>
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Lista de aplicații personale"</string>
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Lista de aplicații de serviciu"</string>
- <string name="remove_drop_target_label" msgid="7812859488053230776">"Eliminați"</string>
- <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Dezinstalați"</string>
+ <string name="remove_drop_target_label" msgid="7812859488053230776">"Elimină"</string>
+ <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Dezinstalează"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Informații despre aplicații"</string>
- <string name="install_drop_target_label" msgid="2539096853673231757">"Instalați"</string>
+ <string name="install_drop_target_label" msgid="2539096853673231757">"Instalează"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Nu sugera aplicația"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Fixează predicția"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalează comenzi rapide"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Permite unei aplicații să adauge comenzi rapide fără intervenția utilizatorului."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"citește setări și comenzi rapide pentru ecranul de pornire"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Permite aplicației să citească setările și comenzile rapide din ecranul de pornire."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"scrie setări și comenzi rapide pentru ecranul de pornire"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Permite aplicației să modifice setările și comenzile rapide din ecranul de pornire."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"citește setările și comenzile rapide de pe ecranul de pornire"</string>
+ <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ți pentru a finaliza configurarea"</string>
+ <string name="gadget_complete_setup_text" msgid="309040266978007925">"Atinge pentru a finaliza configurarea"</string>
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Aceasta este o aplicație de sistem și nu poate fi dezinstalată."</string>
- <string name="folder_hint_text" msgid="5174843001373488816">"Modificați numele"</string>
+ <string name="folder_hint_text" msgid="5174843001373488816">"Modifică numele"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"S-a dezactivat <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} are # notificare}few{{app_name} are # notificări}other{{app_name} are # de notificări}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} are # notificare}few{{app_name} are # notificări}other{{app_name} are # de notificări}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Pagina %1$d din %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Ecranul de pornire %1$d din %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Pagină nouă pe ecranul de pornire"</string>
<string name="folder_opened" msgid="94695026776264709">"Dosar deschis, <xliff:g id="WIDTH">%1$d</xliff:g> pe <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
- <string name="folder_tap_to_close" msgid="4625795376335528256">"Atingeți pentru a închide dosarul"</string>
- <string name="folder_tap_to_rename" msgid="4017685068016979677">"Atingeți pentru a salva noul nume"</string>
+ <string name="folder_tap_to_close" msgid="4625795376335528256">"Atinge pentru a închide dosarul"</string>
+ <string name="folder_tap_to_rename" msgid="4017685068016979677">"Atinge pentru a salva noul nume"</string>
<string name="folder_closed" msgid="4100806530910930934">"Dosar închis"</string>
<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>
@@ -105,53 +105,58 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Imagine de fundal și stil"</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="7728578836261442095">"Permite rotirea ecranului de pornire"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Permite rotirea ecranului de pornire"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Când telefonul este rotit"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Puncte de notificare"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Activate"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"Dezactivate"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"Este necesar accesul la notificări"</string>
- <string name="msg_missing_notification_access" msgid="281113995110910548">"Pentru a afișa punctele de notificare, activați notificările din aplicație pentru <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="title_change_settings" msgid="1376365968844349552">"Modificați setările"</string>
- <string name="notification_dots_service_title" msgid="4284221181793592871">"Afișați punctele de notificare"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Adaugă pictograme de aplicații pe ecran"</string>
+ <string name="msg_missing_notification_access" msgid="281113995110910548">"Pentru a afișa punctele de notificare, activează notificările din aplicație pentru <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="title_change_settings" msgid="1376365968844349552">"Modifică setările"</string>
+ <string name="notification_dots_service_title" msgid="4284221181793592871">"Afișează punctele de notificare"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Opțiuni dezvoltator"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Adaugă pictograme de aplicații pe ecranul de pornire"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Pentru aplicații noi"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Necunoscut"</string>
- <string name="abandoned_clean_this" msgid="7610119707847920412">"Eliminați"</string>
- <string name="abandoned_search" msgid="891119232568284442">"Căutați"</string>
+ <string name="abandoned_clean_this" msgid="7610119707847920412">"Elimină"</string>
+ <string name="abandoned_search" msgid="891119232568284442">"Caută"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"Aplicația nu este instalată"</string>
- <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplicația pentru această pictogramă nu este instalată. Puteți să ștergeți pictograma sau să căutați aplicația și s-o instalați manual."</string>
+ <string name="abandoned_promise_explanation" msgid="3990027586878167529">"Aplicația pentru această pictogramă nu este instalată. Poți să ștergi pictograma sau să cauți aplicația și s-o instalezi manual."</string>
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> se instalează, <xliff:g id="PROGRESS">%2$s</xliff:g> finalizat"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> se descarcă (finalizat <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> așteaptă instalarea"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Este necesară actualizarea aplicației"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Aplicația pentru această pictogramă nu este actualizată. Poți să actualizezi manual ca să reactivezi comanda rapidă sau să elimini pictograma."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Actualizează"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Elimină"</string>
<string name="widgets_list" msgid="796804551140113767">"Listă de widgeturi"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Lista de widgeturi este închisă"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Adăugați pe ecranul de pornire"</string>
- <string name="action_move_here" msgid="2170188780612570250">"Mutați elementul aici"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Adaugă pe ecranul de pornire"</string>
+ <string name="action_move_here" msgid="2170188780612570250">"Mută elementul aici"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Element adăugat pe ecranul de pornire"</string>
<string name="item_removed" msgid="851119963877842327">"Element eliminat"</string>
- <string name="undo" msgid="4151576204245173321">"Anulați"</string>
- <string name="action_move" msgid="4339390619886385032">"Mutați elementul"</string>
- <string name="move_to_empty_cell" msgid="2833711483015685619">"Mutați pe rândul <xliff:g id="NUMBER_0">%1$s</xliff:g>, coloana <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
- <string name="move_to_position" msgid="6750008980455459790">"Mutați pe poziția <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
- <string name="move_to_hotseat_position" msgid="6295412897075147808">"Mutați în preferate, pe poziția <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="undo" msgid="4151576204245173321">"Anulează"</string>
+ <string name="action_move" msgid="4339390619886385032">"Mută elementul"</string>
+ <string name="move_to_empty_cell" msgid="2833711483015685619">"Mută pe rândul <xliff:g id="NUMBER_0">%1$s</xliff:g>, coloana <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
+ <string name="move_to_position" msgid="6750008980455459790">"Mută pe poziția <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+ <string name="move_to_hotseat_position" msgid="6295412897075147808">"Mută în preferate, pe poziția <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
<string name="item_moved" msgid="4606538322571412879">"Element mutat"</string>
- <string name="add_to_folder" msgid="9040534766770853243">"Adăugați în dosar: <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="add_to_folder_with_app" msgid="4534929978967147231">"Adăugați în dosarul cu <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder" msgid="9040534766770853243">"Adaugă în dosar: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="add_to_folder_with_app" msgid="4534929978967147231">"Adaugă în dosarul cu <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="added_to_folder" msgid="4793259502305558003">"Element adăugat în dosar"</string>
- <string name="create_folder_with" msgid="4050141361160214248">"Creați dosar cu: <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="create_folder_with" msgid="4050141361160214248">"Creează dosar cu: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Dosar creat"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Mutați pe ecranul de pornire"</string>
- <string name="action_resize" msgid="1802976324781771067">"Redimensionați"</string>
- <string name="action_increase_width" msgid="8773715375078513326">"Creșteți lățimea"</string>
- <string name="action_increase_height" msgid="459390020612501122">"Creșteți înălțimea"</string>
- <string name="action_decrease_width" msgid="1374549771083094654">"Reduceți lățimea"</string>
- <string name="action_decrease_height" msgid="282377193880900022">"Reduceți înălțimea"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Mută pe ecranul de pornire"</string>
+ <string name="action_resize" msgid="1802976324781771067">"Redimensionează"</string>
+ <string name="action_increase_width" msgid="8773715375078513326">"Crește lățimea"</string>
+ <string name="action_increase_height" msgid="459390020612501122">"Crește înălțimea"</string>
+ <string name="action_decrease_width" msgid="1374549771083094654">"Redu lățimea"</string>
+ <string name="action_decrease_height" msgid="282377193880900022">"Redu înălțimea"</string>
<string name="widget_resized" msgid="9130327887929620">"Widgetul a fost redimensionat la lățimea <xliff:g id="NUMBER_0">%1$s</xliff:g> și înălțimea <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
<string name="action_deep_shortcut" msgid="2864038805849372848">"Comenzi rapide"</string>
<string name="shortcuts_menu_with_notifications_description" msgid="2676582286544232849">"Comenzi rapide și notificări"</string>
- <string name="action_dismiss_notification" msgid="5909461085055959187">"Închideți"</string>
- <string name="accessibility_close" msgid="2277148124685870734">"Închideți"</string>
+ <string name="action_dismiss_notification" msgid="5909461085055959187">"Închide"</string>
+ <string name="accessibility_close" msgid="2277148124685870734">"Închide"</string>
<string name="notification_dismissed" msgid="6002233469409822874">"Notificare închisă"</string>
<string name="all_apps_personal_tab" msgid="4190252696685155002">"Personale"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"Profesionale"</string>
@@ -159,12 +164,14 @@
<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_body" msgid="261634750995824906">"Aplicațiile pentru lucru nu pot să vă trimită notificări, să folosească bateria sau să vă acceseze locația"</string>
- <string name="work_apps_paused_content_description" msgid="5149623040804051095">"Aplicațiile pentru lucru sunt dezactivate. Acestea nu pot să vă trimită notificări, să folosească bateria sau să vă acceseze locația."</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_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="1921059713673767460">"Dezactivați aplicațiile pentru lucru"</string>
- <string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Activați aplicațiile pentru lucru"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Eșuare: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index bf6970b..9733ac6 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %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="5653291305078645405">"Чтобы переместить виджет, нажмите на него и удерживайте."</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Добавить на главный экран"</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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Рабочие виджеты"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Разговоры"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Вся нужная информация перед глазами"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Чтобы не открывать приложения каждый раз, когда нужна информация, добавьте виджеты на главный экран."</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>
@@ -65,7 +65,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="6692471482459245734">"На главном экране нет свободного места."</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Закрепить рекомендацию"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"Создание ярлыков"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Приложение сможет самостоятельно добавлять ярлыки."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"Доступ к настройкам и ярлыкам главного экрана"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Приложение получит доступ к данным о настройках и ярлыках на главном экране."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"Изменение настроек и ярлыков главного экрана"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Приложение сможет изменять настройки и ярлыки на главном экране."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"Доступ к данным о настройках и ярлыках на главном экране"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Это системное приложение, его нельзя удалить."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{В приложении \"{app_name}\" # уведомление}one{В приложении \"{app_name}\" # уведомление}few{В приложении \"{app_name}\" # уведомления}many{В приложении \"{app_name}\" # уведомлений}other{В приложении \"{app_name}\" # уведомления}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{В приложении \"{app_name}\" # уведомление}one{В приложении \"{app_name}\" # уведомление}few{В приложении \"{app_name}\" # уведомления}many{В приложении \"{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Обои и стиль"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Главный экран"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Функция отключена администратором"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Разрешить поворачивать главный экран"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Чтобы показывать значки уведомлений, включите уведомления в приложении \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
<string name="title_change_settings" msgid="1376365968844349552">"Изменить настройки"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Показывать значки уведомлений"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Добавлять значки на главный экран"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Для разработчиков"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Добавлять значки приложений на главный экран"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Добавлять значки установленных приложений на главный экран"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Неизвестно"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Убрать"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"Обновить"</string>
+ <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="8902165848117513641">"Добавить на главный экран"</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_removed" msgid="851119963877842327">"Объект убран."</string>
@@ -141,7 +146,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="1603837886334246317">"Переместить на главный экран"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"ОК"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Отключить рабочие приложения"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Приостановить рабочие приложения"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Включить рабочие приложения"</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="remote_action_failed" msgid="1383965239183576790">"Не удалось выполнить действие (<xliff:g id="WHAT">%1$s</xliff:g>)."</string>
</resources>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index 17531bd..e160e81 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"එය මුල් පිටු තිරය වටා ගෙන යාමට විජට් එක ස්පර්ශ කර අල්ලා ගන්න"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"මුල් පිටු තිරය වෙත එක් කරන්න"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{විජට් #}one{විජට් #}other{විජට් #}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{කෙටි මං #}one{කෙටි මං #}other{කෙටි මං #}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"කාර්යාලය"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"සංවාද"</string>
<string name="widget_education_header" msgid="4874760613775913787">"ප්රයෝජනවත් තොරතුරු ඔබගේ ඇඟිලි තුඩු අග"</string>
- <string name="widget_education_content" msgid="745542879510751525">"යෙදුම් විවෘත නොකර තොරතුරු ලබා ගැනීම සඳහා, ඔබට ඔබගේ මුල් තිරයට විජට් එක් කළ හැකිය"</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>
@@ -65,7 +65,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="6692471482459245734">"මෙම මුල් තිරයේ ඉඩ නැත"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"පුරෝකථනය අමුණන්න"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"කෙටිමං ස්ථාපනය කරන්න"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"පරිශීලක මැදිහත්වීමෙන් තොරව කෙටිමං එක් කිරීමට යෙදුමකට අවසර දෙයි."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"මුල් පිටු සැකසීම් සහ කෙටිමං කියවන්න"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"මුල් පිටුවේ ඇති සැකසීම් සහ කෙටිමං කියවීමට යෙදුමකට අවසර දෙයි."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"මුල් පිටු සැකසීම් සහ කෙටිමං ලියන්න"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"මුල් පිටුවේ සැකසීම් සහ කෙටිමං ඉවත් කිරීමට යෙදුමට අවසර දෙයි."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"මුල් පිටු සැකසීම් සහ කෙටි මං කියවන්න"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"මෙය පද්ධති යෙදුමක් වන අතර අස්ථාපනය කළ නොහැක."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} හට දැනුම්දීම් #ක් ඇත}one{{app_name} හට දැනුම්දීම් #ක් ඇත}other{{app_name} හට දැනුම්දීම් #ක් ඇත}}"</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">"%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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"වෝල්පේපරය සහ මෝස්තරය"</string>
<string name="settings_button_text" msgid="8873672322605444408">"නිවසේ සැකසීම්"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ඔබගේ පරිපාලක විසින් අබල කරන ලදී"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"මුල් පිටු තිරය කරකැවීමට ඉඩ දෙන්න"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"දැනුම්දීම් තිත් පෙන්වීමට, <xliff:g id="NAME">%1$s</xliff:g> සඳහා යෙදුම් දැනුම්දීම් සබල කරන්න"</string>
<string name="title_change_settings" msgid="1376365968844349552">"සැකසීම් වෙනස් කරන්න"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"දැනුම්දීම් තිත් පෙන්වන්න"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"මුල් තිරයට යෙදුම් අයිකන එක් කරන්න"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"සංවර්ධක විකල්ප"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"මුල් තිරයට යෙදුම් නිරූපක එක් කරන්න"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"නව යෙදුම් සඳහා"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"නොදනී"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ඉවත් කරන්න"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"යාවත්කාලීන කරන්න"</string>
+ <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="8902165848117513641">"මුල් තිරය වෙත එක් කරන්න"</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_removed" msgid="851119963877842327">"අයිතමය ඉවත් කරන ලදි"</string>
@@ -141,7 +146,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="1603837886334246317">"මුල් තිරය වෙත ගෙන යන්න"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"තේරුණා"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"කාර්යාල යෙදුම් ක්රියාවිරහිත කරන්න"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"කාර්යාල යෙදුම් විරාම කරන්න"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"කාර්යාල යෙදුම් ක්රියාත්මක කරන්න"</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="remote_action_failed" msgid="1383965239183576790">"අසාර්ථකයි: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index a5c27a3..a6608f3 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"šírka %1$d, výška %2$d"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Miniaplikácia <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Pridržaním môžete miniaplikáciu posúvať po ploche"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Pridať na plochu"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<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_education_header" msgid="4874760613775913787">"Užitočné informácie poruke"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Ak chcete získavať informácie bez otvárania aplikácií, môžete si pridať miniaplikácie na plochu"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Dobre"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Zmena nastavení miniaplikácie"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Upozornenia"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Pridržaním presuňte skratku."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Dvojitým klepnutím a pridržaním presuňte odkaz alebo použite vlastné akcie."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Na tejto ploche nie je miesto"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Na tejto ploche nie je miesto"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Na paneli Obľúbené položky už nie je miesto"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Zoznam aplikácií"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Výsledky vyhľadávania"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Pripnúť predpoveď"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"inštalácia odkazov"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Povoľuje aplikácii pridať odkazy bez zásahu používateľa."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"čítanie nastavení a odkazov plochy"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Povoľuje aplikácii čítať nastavenia a odkazy na ploche."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"zápis nastavení a odkazov plochy"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Povoľuje aplikácii zmeniť nastavenia a odkazy na ploche."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"čítanie nastavení a odkazov plochy"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Toto je systémová aplikácia a nedá sa odinštalovať."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Úprava názvu"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> je deaktivovaná"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{Aplikácia {app_name} má # upozornenie}few{Aplikácia {app_name} má # upozornenia}many{{app_name} has # notifications}other{Aplikácia {app_name} má # upozornení}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{Aplikácia {app_name} má # upozornenie}few{Aplikácia {app_name} má # upozornenia}many{{app_name} has # notifications}other{Aplikácia {app_name} má # upozornení}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Stránka %1$d z %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Plocha %1$d z %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nová stránka plochy"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Tapeta a štýl"</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="7728578836261442095">"Povoliť otáčanie plochy"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Povoliť otáčanie plochy"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Pri otočení telefónu"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Bodky upozornení"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Zapnuté"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Ak chcete, aby sa zobrazovali bodky upozornení, zapnite upozornenia aplikácie <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Zmeniť nastavenia"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Zobrazovať bodky upozornení"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Pridať ikony aplikácií na plochu"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Pre vývojárov"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Pridávať ikony aplikácií na plochu"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Pri inštalácii novej aplikácie"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Neznáme"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Odstrániť"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Inštaluje sa <xliff:g id="NAME">%1$s</xliff:g>. Dokončené: <xliff:g id="PROGRESS">%2$s</xliff:g>."</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Sťahuje sa aplikácia <xliff:g id="NAME">%1$s</xliff:g>. Stiahnuté: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Aplikácia <xliff:g id="NAME">%1$s</xliff:g> čaká na inštaláciu"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Vyžaduje sa aktualizácia aplikácie"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Aplikácia, ktorú zastupuje táto ikona, nie je aktualizovaná. Môžete ju ručne aktualizovať, aby odkaz znova fungoval, prípadne môžete ikonu odstrániť."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Aktualizovať"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Odstrániť"</string>
<string name="widgets_list" msgid="796804551140113767">"Zoznam miniaplikácií"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Zoznam miniaplikácií je zavretý"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Pridať na plochu"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Pridať na plochu"</string>
<string name="action_move_here" msgid="2170188780612570250">"Presunúť položku sem"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Položka bola pridaná na plochu"</string>
<string name="item_removed" msgid="851119963877842327">"Položka bola odstránená"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Položka bola pridaná do priečinka"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Vytvoriť priečinok pomocou: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Priečinok bol vytvorený"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Presunúť na plochu"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Presunúť na plochu"</string>
<string name="action_resize" msgid="1802976324781771067">"Zmeniť veľkosť"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Zvýšiť šírku"</string>
<string name="action_increase_height" msgid="459390020612501122">"Zväčšiť výšku"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Vypnúť pracovné aplikácie"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Zlyhalo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index f235606..0762cf7 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"Širina %1$d, višina %2$d"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Pripomoček <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Pridržite pripomoček, če ga želite premikati po začetnem zaslonu."</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Dodaj na začetni zaslon"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Služba"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Pogovori"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Koristne informacije na dosegu prstov"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Če si želite podatke ogledati brez odpiranja aplikacij, lahko na začetni zaslon dodate pripomočke."</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Razumem"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Spreminjanje nastavitev pripomočka"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Obvestila"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Pridržite bližnjico, da jo premaknete."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Dvakrat se dotaknite bližnjice in jo pridržite, da jo premaknete, ali pa uporabite dejanja po meri."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Na tem začetnem zaslonu ni prostora."</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Na tem začetnem zaslonu ni prostora."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"V vrstici za priljubljene ni več prostora"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Seznam aplikacij"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Rezultati iskanja"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Predvidevanje pripenjanja"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"namestitev bližnjic"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Aplikaciji dovoli dodajanje bližnjic brez posredovanja uporabnika."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"branje nastavitev in bližnjic na začetnem zaslonu"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Aplikaciji dovoli branje nastavitev in bližnjic na začetnem zaslonu."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"zapis nastavitev in bližnjic na začetnem zaslonu"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Aplikaciji dovoli spreminjanje nastavitev in bližnjic na začetnem zaslonu."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"branje nastavitev in bližnjic na začetnem zaslonu"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"To je sistemska aplikacija in je ni mogoče odstraniti."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Urejanje imena"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je onemogočena"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} ima # obvestilo}one{{app_name} ima # obvestilo}two{{app_name} ima # obvestili}few{{app_name} ima # obvestila}other{{app_name} ima # obvestil}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} ima # obvestilo.}one{{app_name} ima # obvestilo.}two{{app_name} ima # obvestili.}few{{app_name} ima # obvestila.}other{{app_name} ima # obvestil.}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Stran %1$d od %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Začetni zaslon %1$d od %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Nova stran na začetnem zaslonu"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Zaslonsko ozadje in slog"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Domače nastavitve"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogočil skrbnik."</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Omogoči sukanje začetnega zaslona"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Dovoli sukanje začetnega zaslona"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Ko se telefon zasuka"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Obvestilne pike"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Vklopljeno"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Za prikaz obvestilnih pik vklopite obvestila aplikacije <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Spremeni nastavitve"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Pokaži obvestilne pike"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Dodaj ikone aplikacij na začetni zaslon"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Možnosti za razvijalce"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Dodaj ikone aplikacij na začetni zaslon"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Za nove aplikacije"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Neznano"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Odstrani"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> se namešča, dokončano: <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Prenašanje aplikacije <xliff:g id="NAME">%1$s</xliff:g>; preneseno <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Aplikacija <xliff:g id="NAME">%1$s</xliff:g> čaka na namestitev"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Zahtevana je posodobitev aplikacije"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Aplikacija za to ikono ni posodobljena. Lahko jo ročno posodobite, da znova omogočite to bližnjico, ali pa odstranite ikono."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Posodobi"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Odstrani"</string>
<string name="widgets_list" msgid="796804551140113767">"Seznam pripomočkov"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Seznam pripomočkov se je zaprl"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Dodajanje na začetni zaslon"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Dodajanje na začetni zaslon"</string>
<string name="action_move_here" msgid="2170188780612570250">"Premik elementa sem"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Element je bil dodan na začetni zaslon"</string>
<string name="item_removed" msgid="851119963877842327">"Element je bil odstranjen."</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Element je dodan v mapo"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Ustvarjanje mape s tem: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Mapa je ustvarjena"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Premik na začetni zaslon"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Premik na začetni zaslon"</string>
<string name="action_resize" msgid="1802976324781771067">"Spreminjanje velikosti"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Povečanje širine"</string>
<string name="action_increase_height" msgid="459390020612501122">"Povečanje višine"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Izklopi delovne aplikacije"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Ni uspelo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 88ed4fa..821bd50 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d i gjerë me %2$d i lartë"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> miniaplikacion"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Prek dhe mbaj të shtypur miniaplikacionin për ta lëvizur nëpër \"Ekranin bazë\""</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Shto në \"Ekranin bazë\""</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Puna"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Bisedat"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Informacione të dobishme në majë të gishtave të tu"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Për të marrë informacione pa i hapur aplikacionet, mund të shtosh miniaplikacione në ekranin bazë"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"E kuptova"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Ndrysho cilësimet e miniaplikacionit"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Njoftimet"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Prek dhe mbaj shtypur një shkurtore për ta zhvendosur."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Trokit dy herë dhe mbaje shtypur një shkurtore për ta zhvendosur atë ose për të përdorur veprimet e personalizuara."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Nuk ka vend në këtë ekran bazë"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Nuk ka më hapësirë në këtë ekran bazë"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Nuk ka më hapësirë në tabakanë \"Të preferuarat\""</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Lista e aplikacioneve"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Rezultatet e kërkimit"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Gozhdo parashikimin"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"instalimi i shkurtoreve"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Lejon një aplikacion të shtojë shkurtore pa ndërhyrjen e përdoruesit."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"lexo cilësimet dhe shkurtoret e ekranit bazë"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Lejon aplikacionin të lexojë cilësimet dhe shkurtoret në ekranin bazë."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"shkruaj cilësimet dhe shkurtoret e ekranit bazë"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Lejon aplikacionin të ndryshojë cilësimet dhe shkurtoret në ekranin bazë."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"lexo cilësimet dhe shkurtoret e ekranit bazë"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ky është aplikacion sistemi dhe nuk mund të çinstalohet."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Redakto emrin"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> u çaktivizua"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} ka # njoftim}other{{app_name} ka # njoftime}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} ka # njoftim}other{{app_name} ka # njoftime}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Faqja: %1$d nga gjithsej %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Ekrani bazë: %1$d nga gjithsej %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Faqja e ekranit të ri kryesor"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Imazhi i sfondit dhe stili"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Cilësimet e ekranit bazë"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Çaktivizuar nga administratori"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Lejo rrotullimin e ekranit bazë"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Lejo rrotullimin e ekranit bazë"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kur telefoni rrotullohet"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Pikat e njoftimeve"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Aktiv"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Për të shfaqur \"Pikat e njoftimeve\", aktivizo njoftimet e aplikacionit për <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Ndrysho cilësimet"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Shfaq pikat e njoftimeve"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Shto ikona aplikacionesh në ekranin bazë"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Opsionet e zhvilluesit"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Shto ikona aplikacionesh në ekranin bazë"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Për aplikacionet e reja"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"I panjohur"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Hiq"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> po instalohet, <xliff:g id="PROGRESS">%2$s</xliff:g> i përfunduar"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> po shkarkohet, <xliff:g id="PROGRESS">%2$s</xliff:g> të përfunduara"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> po pret të instalohet"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Kërkohet përditësimi i aplikacionit"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Aplikacioni për këtë ikonë nuk është përditësuar. Mund ta përditësosh manualisht për të riaktivizuar këtë shkurtore ose hiq ikonën."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Përditëso"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Hiq"</string>
<string name="widgets_list" msgid="796804551140113767">"Lista e miniaplikacioneve"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Lista e miniaplikacioneve u mbyll"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Shto në Ekranin bazë"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Shto në ekranin bazë"</string>
<string name="action_move_here" msgid="2170188780612570250">"Zhvendose artikullin këtu"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Artikulli u shtua tek ekrani bazë"</string>
<string name="item_removed" msgid="851119963877842327">"Artikulli u hoq"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Artikulli u shtua te dosja"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Krijo një dosje me: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Dosja u krijua"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Zhvendose në Ekranin bazë"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Kaloje në ekranin bazë"</string>
<string name="action_resize" msgid="1802976324781771067">"Ndrysho madhësinë"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Rrit gjerësinë"</string>
<string name="action_increase_height" msgid="459390020612501122">"Rrit lartësinë"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Çaktivizo aplikacionet e punës"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Dështoi: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 99769c2..85cc281 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Додирните и задржите виџет да бисте га померали по почетном екрану"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Додај на почетни екран"</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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Посао"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Конверзације"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Корисне информације надохват руке"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Да бисте пронашли информације без отварања апликација, можете да додате виџете на почетни екран"</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>
@@ -65,7 +65,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="6692471482459245734">"Нема простора на овом почетном екрану"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Закачи предвиђање"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"инсталирање пречица"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Дозвољава апликацији да додаје пречице без интервенције корисника."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"читање подешавања и пречица на почетном екрану"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Дозвољава апликацији да чита подешавања и пречице на почетном екрану."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"уписивање подешавања и пречица на почетном екрану"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Дозвољава апликацији да мења подешавања и пречице на почетном екрану."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"читање подешавања и пречица на почетном екрану"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Ово је системска апликација и не може да се деинсталира."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name}, има # обавештење}one{{app_name}, има # обавештење}few{{app_name}, има # обавештења}other{{app_name}, има # обавештења}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name}, има # обавештење}one{{app_name}, има # обавештење}few{{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Позадина и стил"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Подешавања почетног екрана"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Администратор је онемогућио"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Дозволи ротацију почетног екрана"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Да бисте приказали тачке за обавештења, укључите обавештења за апликацију <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Промените подешавања"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Приказуј тачке за обавештења"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Додај иконе апликација на почетни екран"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Опције за програмера"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Додај иконе апликација на почетни екран"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"За нове апликације"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Непознато"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Уклони"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"Ажурирај"</string>
+ <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="8902165848117513641">"Додајте на почетни екран"</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_removed" msgid="851119963877842327">"Ставка је уклоњена"</string>
@@ -141,7 +146,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="1603837886334246317">"Премести на почетни екран"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"Важи"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Искључи пословне апликације"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Паузирај пословне апликације"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Укључи пословне апликације"</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="remote_action_failed" msgid="1383965239183576790">"Није успело: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index e590ec9..7525eec 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d bred gånger %2$d hög"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Widget för <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Tryck länge på widgeten om du vill flytta den på startskärmen"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Lägg till på startskärmen"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Arbete"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Konversationer"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Användbar information nära till hands"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Om du vill ha information utan att öppna appar kan du lägga till widgetar på startskärmen"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Ändra inställningarna för widgeten"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Aviseringar"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Tryck länge för att flytta en genväg."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Tryck snabbt två gånger och håll kvar för att flytta en genväg eller använda anpassade åtgärder."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Det finns inte plats på den här startskärmen."</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Det finns inte plats på den här startskärmen"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Favoritfältet är fullt"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Applista"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Sökresultat"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Fäst förslag"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"installera genvägar"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Tillåter att en app lägger till genvägar utan åtgärd från användaren."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"läsa inställningar och genvägar för startsidan"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Tillåter att appen läser inställningar och genvägar på startsidan."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"skriva inställningar och genvägar för startsidan"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Tillåter att appen ändrar inställningar och genvägar på startsidan."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"läsa inställningar och genvägar på startskärmen"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Det här är en systemapp som inte kan avinstalleras."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Redigera namn"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> har inaktiverats"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} har # avisering}other{{app_name} har # aviseringar}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} har # avisering}other{{app_name} har # aviseringar}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Sidan %1$d av %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Startskärmen %1$d av %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Ny sida på startskärmen"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Bakgrund och utseende"</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="7728578836261442095">"Tillåt rotering av startskärmen"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Tillåt rotering av startskärmen"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"När mobilen vrids"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Aviseringsprickar"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"På"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Aktivera appaviseringar för <xliff:g id="NAME">%1$s</xliff:g> om du vill att aviseringsprickar ska visas"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Ändra inställningar"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Visa aviseringsprickar"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Lägg till appikoner på startskärmen"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Utvecklaralternativ"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Lägg till appikoner på startskärmen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"För nya appar"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Okänt"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Ta bort"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> installeras. <xliff:g id="PROGRESS">%2$s</xliff:g> har slutförts"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> laddas ned, <xliff:g id="PROGRESS">%2$s</xliff:g> klart"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> väntar på installation"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Du måste uppdatera appen"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Appen för den här ikonen har inte uppdaterats. Du kan uppdatera den manuellt för att återaktivera genvägen eller ta bort ikonen."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Uppdatera"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Ta bort"</string>
<string name="widgets_list" msgid="796804551140113767">"Widgetlista"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Widgetslistan har stängts"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Lägg till på startskärmen"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Lägg till på startskärmen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Flytta objekt hit"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Objektet har lagts till på startskärmen"</string>
<string name="item_removed" msgid="851119963877842327">"Objektet har tagits bort"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Objektet har lagts till i mappen"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Skapa mapp med: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Mappen har skapats"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Flytta till startskärmen"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Flytta till startskärmen"</string>
<string name="action_resize" msgid="1802976324781771067">"Ändra storlek"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Öka bredden"</string>
<string name="action_increase_height" msgid="459390020612501122">"Öka höjden"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Inaktivera jobbappar"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Misslyckades: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 0f5810b..3ae5dcf 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"Upana wa %1$d na kimo cha %2$d"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Wijeti ya <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Gusa na ushikilie wijeti ili uisogeze kwenye Skrini ya kwanza"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Weka kwenye Skrini ya kwanza"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Kazini"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Mazungumzo"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Maelezo muhimu, popote ulipo"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Ili upate maelezo bila kufungua programu, unaweza kuweka wijeti kwenye Skrini yako ya kwanza"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Nimeelewa"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Badilisha mipangilio ya wijeti"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Arifa"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Gusa na ushikilie ili usogeze njia ya mkato."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Gusa mara mbili na ushikilie ili usogeze njia ya mkato au utumie vitendo maalum."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Hakuna nafasi kwenye Skrini hii ya kwanza"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Hakuna nafasi kwenye skrini hii ya kwanza"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Hakuna nafasi zaidi katika treya ya Vipendeleo"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Orodha ya programu"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Matokeo ya utafutaji"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Bandika Utabiri"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"kuweka njia za mkato"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Huruhusu programu kuongeza njia za mkato bila mtumiaji kuingilia kati."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"soma mipangilio ya Mwanzo na njia za mkato"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Huruhusu programu kusoma mipangilio na njia za mikato zilizo katika skirini ya Mwanzo."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"andika mipangilio ya skrini ya Mwanzo na njia za mkato"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Huruhusu programu kubadilisha mipangilio na njia za mkato katika skrini ya Mwanzo."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"kusoma mipangilio ya skrini ya kwanza na njia za mkato"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Hii ni programu ya mfumo na haiwezi kuondolewa."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Badilisha Jina"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> imezimwa"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} ina arifa #}other{{app_name} ina arifa #}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} ina arifa #}other{{app_name} ina arifa #}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Ukurasa%1$d wa %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Skrini ya mwanzo %1$d ya %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Ukurasa mpya wa skrini ya kwanza"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Mandhari na mtindo"</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="7728578836261442095">"Ruhusu kuzungusha skrini ya Kwanza"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Ruhusu kipengele cha kuzungusha skrini ya kwanza"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Simu inapozungushwa"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Vitone vya arifa"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Imewashwa"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Ili kuonyesha Vitone vya Arifa, washa kipengele cha arifa za programu katika <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Badilisha mipangilio"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Onyesha vitone vya arifa"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Weka aikoni za programu kwenye Skrini ya kwanza"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Chaguo za Wasanidi Programu"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Weka aikoni za programu kwenye skrini ya kwanza"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Kwa ajili ya programu mpya"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Yasiyojulikana"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Ondoa"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Inasakinisha <xliff:g id="NAME">%1$s</xliff:g>, imekamilika <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> inapakuliwa, <xliff:g id="PROGRESS">%2$s</xliff:g> imekamilika"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> inasubiri kusakinisha"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Unahitaji kusasisha programu"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Programu ya aikoni hii haijasasishwa. Unaweza kusasisha mwenyewe ili uruhusu upya njia hii ya mkato au uondoe aikoni."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Sasisha"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Ondoa"</string>
<string name="widgets_list" msgid="796804551140113767">"Orodha ya wijeti"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Orodha ya wijeti imefungwa"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Weka kwenye Skrini ya Kwanza"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Weka kwenye skrini ya kwanza"</string>
<string name="action_move_here" msgid="2170188780612570250">"Hamishia kipengee hapa"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Kipengee kimeongezwa kwenye skrini ya kwanza"</string>
<string name="item_removed" msgid="851119963877842327">"Kipengee kimeondolewa"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Kipengee kimeongezwa kwenye folda"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Unda folda ukitumia: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Folda imeundwa"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Hamishia Skrini ya kwanza"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Hamishia kwenye skrini ya kwanza"</string>
<string name="action_resize" msgid="1802976324781771067">"Badilisha ukubwa"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Ongeza upana"</string>
<string name="action_increase_height" msgid="459390020612501122">"Ongeza urefu"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Zima programu za kazini"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Hitilafu: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sw600dp-land/dimens.xml b/res/values-sw600dp-land/dimens.xml
new file mode 100644
index 0000000..63970cd
--- /dev/null
+++ b/res/values-sw600dp-land/dimens.xml
@@ -0,0 +1,35 @@
+<?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.
+ -->
+
+<resources>
+<!-- PagedView -->
+ <dimen name="min_page_snap_velocity">3600dp</dimen>
+
+<!-- Hotseat -->
+ <dimen name="spring_loaded_hotseat_top_margin">44dp</dimen>
+
+<!-- Dragging -->
+ <dimen name="drop_target_top_margin">0dp</dimen>
+ <dimen name="drop_target_bottom_margin">16dp</dimen>
+
+<!-- Dynamic grid -->
+ <dimen name="dynamic_grid_edge_margin">11.33dp</dimen>
+ <dimen name="cell_layout_padding">11.33dp</dimen>
+
+<!-- AllApps -->
+ <dimen name="all_apps_bottom_sheet_horizontal_padding">52dp</dimen>
+</resources>
diff --git a/res/values-sw600dp/config.xml b/res/values-sw600dp/config.xml
new file mode 100644
index 0000000..072b92d
--- /dev/null
+++ b/res/values-sw600dp/config.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<resources>
+
+ <!-- The duration of the PagedView page snap animation -->
+ <integer name="config_pageSnapAnimationDuration">550</integer>
+
+</resources>
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 3727932..d69e777 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -15,9 +15,41 @@
-->
<resources>
+<!-- PagedView-->
+ <dimen name="min_page_snap_velocity">3000dp</dimen>
+
<!-- DragController -->
<dimen name="drag_flingToDeleteMinVelocity">-1000dp</dimen>
<!-- Widgets pickers -->
<dimen name="widget_list_horizontal_margin">32dp</dimen>
+
+<!-- AllApps -->
+ <dimen name="all_apps_search_bar_content_overlap">0dp</dimen>
+ <dimen name="all_apps_bottom_sheet_horizontal_padding">48dp</dimen>
+
+<!-- Fast scroll -->
+ <dimen name="fastscroll_popup_width">75dp</dimen>
+ <dimen name="fastscroll_popup_height">62dp</dimen>
+ <dimen name="fastscroll_popup_padding">13dp</dimen>
+ <dimen name="fastscroll_popup_text_size">32dp</dimen>
+
+<!-- Dynamic grid -->
+ <dimen name="dynamic_grid_edge_margin">9dp</dimen>
+ <dimen name="dynamic_grid_icon_drawable_padding">7dp</dimen>
+ <dimen name="cell_layout_padding">9dp</dimen>
+
+<!-- Hotseat -->
+ <dimen name="dynamic_grid_hotseat_side_padding">0dp</dimen>
+ <dimen name="spring_loaded_hotseat_top_margin">65dp</dimen>
+
+<!-- Dragging -->
+ <dimen name="drop_target_top_margin">64dp</dimen>
+ <dimen name="drop_target_bottom_margin">16dp</dimen>
+ <dimen name="drop_target_button_drawable_horizontal_padding">16dp</dimen>
+ <dimen name="drop_target_button_drawable_vertical_padding">16dp</dimen>
+ <dimen name="dynamic_grid_drop_target_size">56dp</dimen>
+
+<!-- Workspace grid visualization parameters -->
+ <dimen name="grid_visualization_horizontal_cell_spacing">6dp</dimen>
</resources>
diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml
new file mode 100644
index 0000000..235631d
--- /dev/null
+++ b/res/values-sw720dp-land/dimens.xml
@@ -0,0 +1,40 @@
+<?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.
+-->
+
+<resources>
+<!-- PagedView -->
+ <dimen name="min_page_snap_velocity">5300dp</dimen>
+
+<!-- Dynamic grid -->
+ <dimen name="dynamic_grid_edge_margin">21.93dp</dimen>
+ <dimen name="cell_layout_padding">29.33dp</dimen>
+
+<!-- AllApps -->
+ <dimen name="all_apps_bottom_sheet_horizontal_padding">32dp</dimen>
+
+<!-- Dragging-->
+ <dimen name="drop_target_top_margin">0dp</dimen>
+ <dimen name="drop_target_bottom_margin">32dp</dimen>
+
+<!-- Hotseat -->
+ <dimen name="spring_loaded_hotseat_top_margin">64dp</dimen>
+
+<!-- Widget picker-->
+ <dimen name="widget_list_horizontal_margin">49dp</dimen>
+
+<!-- Bottom sheet-->
+ <dimen name="bottom_sheet_extra_top_padding">0dp</dimen>
+</resources>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
new file mode 100644
index 0000000..7b2ed8b
--- /dev/null
+++ b/res/values-sw720dp/dimens.xml
@@ -0,0 +1,46 @@
+<?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.
+-->
+
+<resources>
+<!-- PagedView -->
+ <dimen name="min_page_snap_velocity">3400dp</dimen>
+
+<!-- AllApps -->
+ <dimen name="all_apps_bottom_sheet_horizontal_padding">28dp</dimen>
+
+<!-- Dynamic grid -->
+ <dimen name="dynamic_grid_edge_margin">27.59dp</dimen>
+ <dimen name="cell_layout_padding">36dp</dimen>
+
+<!-- Dragging -->
+ <dimen name="drop_target_text_size">20sp</dimen>
+ <dimen name="dynamic_grid_drop_target_size">72dp</dimen>
+ <dimen name="drop_target_button_drawable_horizontal_padding">24dp</dimen>
+ <dimen name="drop_target_button_drawable_vertical_padding">20dp</dimen>
+ <dimen name="drop_target_button_gap">32dp</dimen>
+ <dimen name="drop_target_button_workspace_edge_gap">32dp</dimen>
+ <dimen name="drop_target_top_margin">110dp</dimen>
+ <dimen name="drop_target_bottom_margin">48dp</dimen>
+
+<!-- Hotseat -->
+ <dimen name="spring_loaded_hotseat_top_margin">108dp</dimen>
+
+<!-- Widget picker-->
+ <dimen name="widget_list_horizontal_margin">30dp</dimen>
+
+<!-- Bottom sheet-->
+ <dimen name="bottom_sheet_extra_top_padding">300dp</dimen>
+</resources>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index a4a0152..0547fc2 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"முகப்புத் திரைக்கு விட்ஜெட்டை நகர்த்த அதைத் தொட்டுப் பிடிக்கவும்"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"முகப்புத் திரையில் சேர்"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# விட்ஜெட்}other{# விட்ஜெட்டுகள்}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ஷார்ட்கட்}other{# ஷார்ட்கட்கள்}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"பணி"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"உரையாடல்கள்"</string>
<string name="widget_education_header" msgid="4874760613775913787">"விரல்நுனியில் பயனுள்ள தகவல்களைப் பெறுங்கள்"</string>
- <string name="widget_education_content" msgid="745542879510751525">"ஆப்ஸைத் திறக்காமல் தகவல்களைப் பெற, முகப்புத் திரையில் விட்ஜெட்டுகளைச் சேர்க்கலாம்"</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>
@@ -65,7 +65,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="6692471482459245734">"இந்த முகப்புத் திரையில் இடமில்லை"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"கணிக்கப்பட்ட ஆப்ஸைப் பின் செய்தல்"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"குறுக்குவழிகளை நிறுவுதல்"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"பயனரின் அனுமதி இல்லாமல் குறுக்குவழிகளைச் சேர்க்கப் ஆப்ஸை அனுமதிக்கிறது."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"முகப்பின் அமைப்பு மற்றும் குறுக்குவழிகளைப் படித்தல்"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"முகப்பில் உள்ள அமைப்பு மற்றும் குறுக்குவழிகளைப் படிக்க ஆப்ஸை அனுமதிக்கிறது."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"முகப்பின் அமைப்பு மற்றும் குறுக்குவழிகளை எழுதுதல்"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"முகப்பில் உள்ள அமைப்பு மற்றும் குறுக்குவழிகளை மாற்ற ஆப்ஸை அனுமதிக்கிறது."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"முகப்புத் திரையின் அமைப்புகளையும் ஷார்ட்கட்களையும் படித்தல்"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"இது அமைப்பு ஆப்ஸ் என்பதால் நிறுவல் நீக்கம் செய்ய முடியாது."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} ஆப்ஸில் # அறிவிப்பு வந்துள்ளது}other{{app_name} ஆப்ஸில் # அறிவிப்புகள் வந்துள்ளன}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{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 of %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"புதிய முகப்புத் திரை பக்கம்"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"வால்பேப்பர் & ஸ்டைல்"</string>
<string name="settings_button_text" msgid="8873672322605444408">"முகப்பு அமைப்புகள்"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"உங்கள் நிர்வாகி முடக்கியுள்ளார்"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"முகப்புத் திரை சுழற்சியை அனுமதி"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"அறிவிப்புப் புள்ளிகளைக் காட்ட, <xliff:g id="NAME">%1$s</xliff:g> இன் ஆப்ஸ் அறிவிப்புகளை இயக்கவும்"</string>
<string name="title_change_settings" msgid="1376365968844349552">"அமைப்புகளை மாற்று"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"அறிவிப்புப் புள்ளிகளைக் காட்டு"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"முகப்புத் திரையில் ஆப்ஸ் ஐகான்களைச் சேர்"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"டெவெலப்பர் விருப்பங்கள்"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"முகப்புத் திரையில் ஆப்ஸ் ஐகான்களைச் சேர்"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"புதிய ஆப்ஸை நிறுவும்போது"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"தெரியாதது"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"அகற்று"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"புதுப்பி"</string>
+ <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="8902165848117513641">"முகப்புத் திரையில் சேருங்கள்"</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_removed" msgid="851119963877842327">"அகற்றப்பட்டது"</string>
@@ -141,7 +146,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="1603837886334246317">"முகப்புத் திரைக்கு நகர்த்து"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"சரி"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"பணி ஆப்ஸை முடக்கு"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"பணி ஆப்ஸை இடைநிறுத்து"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"பணி ஆப்ஸை இயக்கு"</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="remote_action_failed" msgid="1383965239183576790">"தோல்வி: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index a343ec0..c264371 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"ఈ విడ్జెట్ను మొదటి స్క్రీన్లో కావాల్సిన చోట ఉంచడానికి, దాన్ని తాకి అలాగే నొక్కి పట్టుకోండి"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"మొదటి స్క్రీన్కు జోడించు"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# విడ్జెట్}other{# విడ్జెట్లు}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# షార్ట్కట్}other{# షార్ట్కట్లు}}"</string>
@@ -52,37 +52,37 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ఆఫీస్"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"సంభాషణలు"</string>
<string name="widget_education_header" msgid="4874760613775913787">"మీ చేతివేళ్ల మీద ఉపయోగకరమైన సమాచారం"</string>
- <string name="widget_education_content" msgid="745542879510751525">"యాప్లను తెరవకుండా సమాచారం పొందడానికి, మీరు మీ మొదటి స్క్రీన్కు విడ్జెట్లను జోడించవచ్చు"</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_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\"కి సరిపోలే అప్లికేషన్లేవీ కనుగొనబడలేదు"</string>
+ <string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\"కి మ్యాచ్ అయ్యే అప్లికేషన్లేవీ కనుగొనబడలేదు"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"మరిన్ని యాప్ల కోసం సెర్చ్ చేయండి"</string>
<string name="label_application" msgid="8531721983832654978">"యాప్"</string>
<string name="all_apps_label" msgid="5015784846527570951">"అన్ని యాప్లు"</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="6692471482459245734">"ఈ మొదటి స్క్రీన్లో స్థలం లేదు"</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>
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"వ్యక్తిగత యాప్ల లిస్ట్"</string>
<string name="all_apps_button_work_label" msgid="7270707118948892488">"కార్యాలయ యాప్ల లిస్ట్"</string>
- <string name="remove_drop_target_label" msgid="7812859488053230776">"తీసివేయి"</string>
+ <string name="remove_drop_target_label" msgid="7812859488053230776">"తీసివేయండి"</string>
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"అన్ఇన్స్టాల్ చేయండి"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"యాప్ సమాచారం"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"ఇన్స్టాల్ చేయండి"</string>
- <string name="dismiss_prediction_label" msgid="3357562989568808658">"యాప్ను సూచించవద్దు"</string>
+ <string name="dismiss_prediction_label" msgid="3357562989568808658">"యాప్ సూచించకు"</string>
<string name="pin_prediction" msgid="4196423321649756498">"సూచనను పిన్ చేయండి"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"షార్ట్కట్లను ఇన్స్టాల్ చేయడం"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"వినియోగదారు ప్రమేయం లేకుండా షార్ట్కట్లను జోడించడానికి యాప్ను అనుమతిస్తుంది."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"హోమ్ సెట్టింగ్లు మరియు షార్ట్కట్లను చదవడం"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"హోమ్లో సెట్టింగ్లు మరియు షార్ట్కట్లను చదవడానికి యాప్ను అనుమతిస్తుంది."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"హోమ్ సెట్టింగ్లు మరియు షార్ట్కట్లను రాయడం"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"హోమ్లో సెట్టింగ్లు మరియు షార్ట్కట్లను మార్చడానికి యాప్ను అనుమతిస్తుంది."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"హోమ్ సెట్టింగ్లు, షార్ట్కట్లను చదవండి"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"ఇది సిస్టమ్ యాప్ మరియు దీన్ని అన్ఇన్స్టాల్ చేయడం సాధ్యపడదు."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name}లో # నోటిఫికేషన్ ఉంది}other{{app_name}లో # నోటిఫికేషన్లు ఉన్నాయి}}"</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="workspace_scroll_format" msgid="8458889198184077399">"%2$dలో %1$dవ హోమ్ స్క్రీన్"</string>
<string name="workspace_new_page" msgid="257366611030256142">"కొత్త హోమ్ స్క్రీన్ పేజీ"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"వాల్పేపర్ & స్టయిల్"</string>
<string name="settings_button_text" msgid="8873672322605444408">"మొదటి స్క్రీన్ సెట్టింగ్లు"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"మీ నిర్వాహకులు నిలిపివేసారు"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"మొదటి స్క్రీన్ రొటేషన్ను అనుమతించండి"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,19 +114,24 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"నోటిఫికేషన్ డాట్లను చూపించడానికి <xliff:g id="NAME">%1$s</xliff:g>కు యాప్ నోటిఫికేషన్లను ఆన్ చేయండి"</string>
<string name="title_change_settings" msgid="1376365968844349552">"సెట్టింగ్లను మార్చు"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"నోటిఫికేషన్ డాట్లను చూపు"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"యాప్ చిహ్నాలను మొదటి స్క్రీన్కు జోడించు"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"డెవలపర్ ఆప్షన్లు"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"యాప్ చిహ్నాలను మొదటి స్క్రీన్కు జోడించండి"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"కొత్త యాప్ల కోసం"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"తెలియదు"</string>
- <string name="abandoned_clean_this" msgid="7610119707847920412">"తీసివేయి"</string>
+ <string name="abandoned_clean_this" msgid="7610119707847920412">"తీసివేయండి"</string>
<string name="abandoned_search" msgid="891119232568284442">"సెర్చ్"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"ఈ యాప్ ఇన్స్టాల్ చేయబడలేదు"</string>
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"ఈ ఐకాన్కు చెందిన యాప్ ఇన్స్టాల్ చేయలేదు. మీరు దీన్ని తీసివేయవచ్చు లేదా ఆ యాప్ కోసం సెర్చ్ చేసి, దాన్ని మాన్యువల్గా ఇన్స్టాల్ చేయవచ్చు."</string>
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g>ను ఇన్స్టాల్ చేయడం, <xliff:g id="PROGRESS">%2$s</xliff:g> పూర్తయింది"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> డౌన్లోడ్ అవుతోంది, <xliff:g id="PROGRESS">%2$s</xliff:g> పూర్తయింది"</string>
<string name="app_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" msgid="2178028071796141234">"అప్డేట్ చేయండి"</string>
+ <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="8902165848117513641">"హోమ్ స్క్రీన్కు జోడించండి"</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_removed" msgid="851119963877842327">"ఐటెమ్ తీసివేయబడింది"</string>
@@ -141,16 +146,16 @@
<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="1603837886334246317">"హోమ్స్క్రీన్కు తరలించు"</string>
- <string name="action_resize" msgid="1802976324781771067">"పరిమాణం మార్చు"</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>
<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="widget_resized" msgid="9130327887929620">"విడ్జెట్ సైజ్ వెడల్పు <xliff:g id="NUMBER_0">%1$s</xliff:g>కి, ఎత్తు <xliff:g id="NUMBER_1">%2$s</xliff:g>కి మార్చబడింది"</string>
<string name="action_deep_shortcut" msgid="2864038805849372848">"షార్ట్కట్స్"</string>
<string name="shortcuts_menu_with_notifications_description" msgid="2676582286544232849">"షార్ట్కట్లు మరియు నోటిఫికేషన్లు"</string>
- <string name="action_dismiss_notification" msgid="5909461085055959187">"తీసివేయి"</string>
+ <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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"అర్థమైంది"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"వర్క్ యాప్లను ఆఫ్ చేయండి"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"వర్క్ యాప్లను పాజ్ చేయి"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"వర్క్ యాప్లను ఆన్ చేయి"</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="remote_action_failed" msgid="1383965239183576790">"విఫలమైంది: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 7ca3bbc..9e8a75e 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"แตะวิดเจ็ตค้างไว้เพื่อย้ายไปรอบๆ หน้าจอหลัก"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"เพิ่มลงในหน้าจอหลัก"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{วิดเจ็ต # รายการ}other{วิดเจ็ต # รายการ}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{ทางลัด # รายการ}other{ทางลัด # รายการ}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"งาน"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"การสนทนา"</string>
<string name="widget_education_header" msgid="4874760613775913787">"เข้าถึงข้อมูลที่เป็นประโยชน์ได้จากปลายนิ้ว"</string>
- <string name="widget_education_content" msgid="745542879510751525">"หากต้องการรับข้อมูลโดยไม่เปิดแอป ให้เพิ่มวิดเจ็ตลงในหน้าจอหลัก"</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>
@@ -65,7 +65,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="6692471482459245734">"ไม่มีที่ว่างในหน้าจอหลักนี้"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"ปักหมุดแอปที่คาดการณ์ไว้"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"ติดตั้งทางลัด"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"อนุญาตให้แอปเพิ่มทางลัดโดยไม่ต้องให้ผู้ใช้จัดการ"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"อ่านการตั้งค่าและทางลัดหน้าแรกแล้ว"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"อนุญาตให้แอปอ่านการตั้งค่าและทางลัดในหน้าแรก"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"เขียนการตั้งค่าและทางลัดหน้าแรกแล้ว"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"อนุญาตให้แอปเปลี่ยนการตั้งค่าและทางลัดในหน้าแรก"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"อ่านการตั้งค่าและทางลัดในหน้าแรก"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"นี่เป็นแอประบบและไม่สามารถถอนการติดตั้งได้"</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} มีการแจ้งเตือน # รายการ}other{{app_name} มีการแจ้งเตือน # รายการ}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{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>
@@ -103,9 +103,9 @@
<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="settings_button_text" msgid="8873672322605444408">"การตั้งค่าหน้าจอหลัก"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ปิดใช้โดยผู้ดูแลระบบ"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"อนุญาตให้หมุนหน้าจอหลัก"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"เปิดการแจ้งเตือนแอปของ <xliff:g id="NAME">%1$s</xliff:g> เพื่อแสดงเครื่องหมายจุดแสดงการแจ้งเตือน"</string>
<string name="title_change_settings" msgid="1376365968844349552">"เปลี่ยนการตั้งค่า"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"แสดงเครื่องหมายจุดแสดงการแจ้งเตือน"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"เพิ่มไอคอนแอปในหน้าจอหลัก"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"ตัวเลือกสำหรับนักพัฒนาแอป"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"เพิ่มไอคอนแอปในหน้าจอหลัก"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"สำหรับแอปใหม่"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"ไม่รู้จัก"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ลบ"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"อัปเดต"</string>
+ <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="8902165848117513641">"เพิ่มลงในหน้าจอหลัก"</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_removed" msgid="851119963877842327">"นำรายการออกแล้ว"</string>
@@ -141,7 +146,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="1603837886334246317">"ย้ายไปที่หน้าจอหลัก"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"รับทราบ"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"ปิดแอปงาน"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"หยุดแอปงานชั่วคราว"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"เปิดแอปงาน"</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="remote_action_failed" msgid="1383965239183576790">"ไม่สำเร็จ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 49465c5..f7158b4 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ang lapad at %2$d ang taas"</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="5653291305078645405">"Pindutin nang matagal ang widget para ilipat-lipat ito sa Home screen"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Idagdag sa Home screen"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<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_education_header" msgid="4874760613775913787">"Abot-kamay na mahalagang impormasyon"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Para makakuha ng impormasyon nang hindi nagbubukas ng mga app, puwede kang magdagdag ng mga widget sa iyong Home screen"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Baguhin ang mga setting ng widget"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Mga Notification"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Pindutin nang matagal para ilipat ang shortcut."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"I-double tap at pindutin nang matagal para ilipat ang shortcut o gumamit ng mga custom na pagkilos."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Walang espasyo sa Home screen na ito"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Walang espasyo sa home screen na ito"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Wala nang lugar sa tray ng Mga Paborito"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Listahan ng mga app"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Mga resulta ng paghahanap"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"I-pin ang Hula"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"i-install ang mga shortcut"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Pinapayagan ang isang app na magdagdag ng mga shortcut nang walang panghihimasok ng user."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"basahin ang mga setting at shortcut ng Home"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Pinapayagan ang app na basahin ang mga setting at shortcut sa Home."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"magsulat ng mga setting at shortcut ng Home"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Pinapayagan ang app na baguhin ang mga setting at shortcut sa Home."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"basahin ang mga setting at shortcut ng home"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Isa itong app ng system at hindi maaaring i-uninstall."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"I-edit ang Pangalan"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Naka-disable ang <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{May # notification ang {app_name}}one{May # notification ang {app_name}}other{May # na notification ang {app_name}}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{May # notification ang {app_name}}one{May # notification ang {app_name}}other{May # na notification ang {app_name}}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Pahina %1$d ng %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Home screen %1$d ng %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Bagong page ng home screen"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Wallpaper & istilo"</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="7728578836261442095">"Payagan ang pag-rotate ng Home screen"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Payagan ang pag-rotate ng home screen"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kailan maro-rotate ang telepono"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Mga notification dot"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Naka-on"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Upang ipakita ang Mga Notification Dot, i-on ang mga notification ng app para sa <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Baguhin ang mga setting"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Ipakita ang mga notification dot"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Magdagdag ng mga app icon sa Home screen"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Mga Opsyon ng Developer"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Magdagdag ng mga icon ng app sa home screen"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para sa mga bagong app"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Hindi kilala"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Alisin"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Ini-install ang <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> kumpleto"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Dina-download na ang <xliff:g id="NAME">%1$s</xliff:g>, tapos na ang <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Hinihintay nang mag-install ang <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Kinakailangang i-update ang app"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Hindi updated ang app para sa icon na ito. Puwede kang manual na mag-update para ma-enable ulit ang shortcut na ito, o alisin ang icon."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"I-update"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Alisin"</string>
<string name="widgets_list" msgid="796804551140113767">"Listahan ng mga widget"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Nakasara ang listahan ng mga widget"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Idagdag sa Home screen"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Idagdag sa home screen"</string>
<string name="action_move_here" msgid="2170188780612570250">"Ilipat ang item dito"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Naidagdag sa home screen ang item"</string>
<string name="item_removed" msgid="851119963877842327">"Naalis na ang item"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Idinagdag ang item sa folder"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Gumawa ng folder na may: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Nagawa ang folder"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Ilipat sa Home screen"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Ilipat sa home screen"</string>
<string name="action_resize" msgid="1802976324781771067">"I-resize"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Dagdagan ang lapad"</string>
<string name="action_increase_height" msgid="459390020612501122">"Dagdagan ang taas"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"I-off ang mga app para sa trabaho"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Hindi nagawa: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index d71961d..b12b9b1 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"genişlik: %1$d, yükseklik: %2$d"</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="5653291305078645405">"Ana ekranda taşımak için widget\'a dokunup basılı tutun"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Ana ekrana ekle"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"İş"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Görüşmeler"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Faydalı bilgiler parmaklarınızın ucunda"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Uygulama açmadan bilgi almak için Ana ekranınıza widget ekleyebilirsiniz"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Anladım"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Widget ayarlarını değiştir"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Bildirimler"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Kısayolu taşımak için dokunup basılı tutun."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Kısayolu taşımak veya özel işlemleri kullanmak için iki kez dokunup basılı tutun."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Bu Ana ekranda yer yok"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Bu ana ekranda yer yok"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Favoriler tepsisinde başka yer kalmadı"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Uygulamalar listesi"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Arama sonuçları"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Tahmini Sabitle"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"kısayolları yükle"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Uygulamaya, kullanıcı müdahalesi olmadan kısayol ekleme izni verir."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"Ana ekran ayarlarını ve kısayollarını oku"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Uygulamaya, Ana ekrandaki ayarları ve kısayolları okuma izni verir."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"Ana ekran ayarlarını ve kısayollarını yaz"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Uygulamaya, Ana ekrandaki ayarları ve kısayolları değiştirme izni verir."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"ana ekran ayarlarını ve kısayollarını oku"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Bu bir sistem uygulamasıdır ve yüklemesi kaldırılamaz."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Adı Düzenle"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> devre dışı"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} uygulamasının # bildirimi var}other{{app_name} uygulamasının # bildirimi var}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} uygulamasının # bildirimi var}other{{app_name} uygulamasının # bildirimi var}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Sayfa %1$d / %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Ana ekran %1$d / %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Yeni ana ekran sayfası"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Duvar kağıdı ve stil"</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="7728578836261442095">"Ana ekranı döndürmeye izin ver"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Ana ekranı döndürmeye izin ver"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Telefon döndürüldüğünde"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Bildirim noktaları"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Açık"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Bildirim Noktaları\'nı göstermek için <xliff:g id="NAME">%1$s</xliff:g> uygulamasının bildirimlerini açın"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Ayarları değiştir"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Bildirim noktalarını göster"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Uygulama simgelerini Ana ekrana ekle"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Geliştirici Seçenekleri"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Uygulama simgelerini ana ekrana ekle"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Yeni uygulamalar için"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Bilinmiyor"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Kaldır"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> yükleniyor, <xliff:g id="PROGRESS">%2$s</xliff:g> tamamlandı"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> indiriliyor, <xliff:g id="PROGRESS">%2$s</xliff:g> tamamlandı"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> uygulaması yüklenmek için bekliyor"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Uygulama güncellemesi gerekli"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Bu simgenin uygulaması güncellenmemiş. Simgeyi kaldırabilir ya da uygulamayı manuel olarak güncelleyerek bu kısayolu yeniden etkinleştirebilirsiniz."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Güncelle"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Kaldır"</string>
<string name="widgets_list" msgid="796804551140113767">"Widget listesi"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Widget listesi kapalı"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Ana ekrana ekle"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Ana ekrana ekle"</string>
<string name="action_move_here" msgid="2170188780612570250">"Öğeyi buraya taşı"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Öğe ana ekrana eklendi"</string>
<string name="item_removed" msgid="851119963877842327">"Öğe silindi"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Öğe, klasöre eklendi"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Şu öğeyle klasör oluştur: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Klasör oluşturuldu"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Ana ekrana taşı"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Ana ekrana taşı"</string>
<string name="action_resize" msgid="1802976324781771067">"Yeniden boyutlandır"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Genişliği artır"</string>
<string name="action_increase_height" msgid="459390020612501122">"Yüksekliği artır"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"İş uygulamalarını kapat"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Başarısız: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 998ad84..f1eaeaf 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"Натисніть і втримуйте віджет, щоб перемістити його в потрібне місце на головному екрані"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Додати на головний екран"</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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Робочі"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Розмови"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Корисна інформація завжди під рукою"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Щоб отримувати інформацію, не відкриваючи додатки, ви можете додати на головний екран віджети"</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">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Змінити налаштування віджета"</string>
@@ -65,7 +65,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="6692471482459245734">"На головному екрані немає місця"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Закріпити передбачений додаток"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"створення ярликів"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Дозволяє програмі самостійно додавати ярлики."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"читати налаштування та ярлики головного екрана"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Дозволяє програмі читати налаштування та ярлики на головному екрані."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"записувати налаштування та ярлики головного екрана"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Дозволяє програмі змінювати налаштування та ярлики на головному екрані."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"читати налаштування та ярлики головного екрана"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Це системна програма, її неможливо видалити."</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{Додаток {app_name} має # сповіщення}one{Додаток {app_name} має # сповіщення}few{Додаток {app_name} має # сповіщення}many{Додаток {app_name} має # сповіщень}other{Додаток {app_name} має # сповіщення}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{Додаток {app_name} має # сповіщення}one{Додаток {app_name} має # сповіщення}few{Додаток {app_name} має # сповіщення}many{Додаток {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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Оформлення та стиль"</string>
<string name="settings_button_text" msgid="8873672322605444408">"Налаштування головного екрана"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Вимкнув адміністратор"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"Дозволити обертання головного екрана"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Щоб показувати значки сповіщень, увімкніть сповіщення в додатку <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Змінити налаштування"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Показувати значки сповіщень"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Додавати значки додатків на головний екран"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Параметри розробника"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Розміщати значки додатків на головному екрані"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Для нових додатків"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Невідомо"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Прибрати"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"Оновити"</string>
+ <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="8902165848117513641">"Додати на головний екран"</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_removed" msgid="851119963877842327">"Елемент вилучено"</string>
@@ -141,7 +146,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="1603837886334246317">"Перемістити на головний екран"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"Зрозуміло"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"Вимкнути робочі додатки"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"Призупинити робочі додатки"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"Увімкнути робочі додатки"</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="remote_action_failed" msgid="1383965239183576790">"Не вдалося <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index 1b4a3d1..70a853f 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"ویجیٹ کو ہوم اسکرین کے چاروں طرف منتقل کرنے کیلئے اسے ٹچ کریں اور دبائے رکھیں"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"ہوم اسکرین میں شامل کریں"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ویجیٹ}other{# ویجیٹس}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# شارٹ کٹ}other{# شارٹ کٹس}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"دفتری ویجیٹس"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"گفتگوئیں"</string>
<string name="widget_education_header" msgid="4874760613775913787">"مفید معلومات کو آسانی سے حاصل کریں"</string>
- <string name="widget_education_content" msgid="745542879510751525">"ایپس کو کھولے بغیر معلومات حاصل کرنے کے لیے آپ اپنی ہوم اسکرین پر ویجیٹس شامل کر سکتے ہیں"</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>
@@ -65,7 +65,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="6692471482459245734">"اس ہوم اسکرین پر کوئی گنجائش نہیں ہے"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"پیشگوئی پن کریں"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"شارٹ کٹس انسٹال کریں"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"کسی ایپ کو صارف کی مداخلت کے بغیر شارٹ کٹس شامل کرنے کی اجازت دیتا ہے۔"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"ہوم ترتیبات اور شارٹ کٹس کو پڑھیں"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"ایپ کو ہوم میں ترتیبات اور شارٹ کٹس کو پڑھنے کی اجازت دیتا ہے۔"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"ہوم ترتیبات اور شارٹ کٹس کو لکھیں"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"ایپ کو ہوم میں ترتیبات اور شارٹ کٹس کو تبدیل کرنے کی اجازت دیتا ہے۔"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"ہوم ترتیبات اور شارٹ کٹس کو پڑھیں"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"یہ ایک سسٹم ایپ ہے اور اسے اَن انسٹال نہیں کیا جا سکتا ہے۔"</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{{app_name} میں # اطلاع ہے}other{{app_name} میں # اطلاعات ہیں}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"وال پیپر اور طرز"</string>
<string name="settings_button_text" msgid="8873672322605444408">"ہوم ترتیبات"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"آپ کے منتظم کی طرف سے غیر فعال کر دیا گیا"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"ہوم اسکرین گھمانے کی اجازت دیں"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"اطلاعاتی ڈاٹس دکھانے کی خاطر <xliff:g id="NAME">%1$s</xliff:g> کیلئے ایپ کی اطلاعات آن کریں"</string>
<string name="title_change_settings" msgid="1376365968844349552">"ترتیبات تبدیل کریں"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"اطلاعاتی ڈاٹس دکھائیں"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"ہوم اسکرین میں ایپ آئیکنز شامل کریں"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"ڈویلپر کے اختیارات"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"ہوم اسکرین میں ایپ آئیکنز شامل کریں"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"نئی ایپس کیلئے"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"نامعلوم"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"ہٹائیں"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"اپ ڈیٹ کریں"</string>
+ <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="8902165848117513641">"ہوم اسکرین میں شامل کریں"</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_removed" msgid="851119963877842327">"آئٹم ہٹا دیا گیا"</string>
@@ -141,7 +146,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="1603837886334246317">"ہوم اسکرین میں منتقل کریں"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"سمجھ آ گئی"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"ورک ایپس آف کریں"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"ورک ایپس موقوف کریں"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"ورک ایپس آن کریں"</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="remote_action_failed" msgid="1383965239183576790">"ناکام ہو گيا: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 8984af8..57a446b 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"Eni %1$d, bo‘yi %2$d"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ta vidjet"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Vidjetni ushlagan holda kerakli joyga siljiting"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Bosh ekranga chiqarish"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Ish"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Suhbatlar"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Barcha kerakli axborot doim yoningizda"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Kerakli ilovalarni ochmasdan turib ulardan axborot olish uchun vidjetlarni bosh ekranga chiqaring"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Vidjet sozlamalarini oʻzgartirish"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Bildirishnomalar"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Yorliqni bosib turgan holatda suring."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Ikki marta bosing va yorliqni bosib turgan holatda suring yoki maxsus amaldan foydalaning."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Bosh ekranda joy qolmadi."</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Bosh ekranda joy qolmadi"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Ajratilganlarda birorta ham xona yo‘q"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Ilovalar ro‘yxati"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Qidiruv natijalari"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Tavsiyani mahkamlash"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"yorliqlar yaratish"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Ilovalarga foydalanuvchidan so‘ramasdan yorliqlar qo‘shishga ruxsat beradi."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"Uy sozlamalari va yorliqlarini o‘qish"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Ilovaga \"Uy\" ekranidagi yorliqlar va sozlamalarni o‘qish uchun ruxsat beradi."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"Uy sozlamalari va yorliqlarini yozish"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Ilovaga \"Uy\" ekranidagi yorliqlar va sozlamalrni o‘zgartirish uchun ruxsat beradi."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"Bosh ekrandagi sozlamalar va yorliqlarni koʻrish"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Bu tizim ilovasi, shuning uchun o‘chirib bo‘lmaydi."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Nomini tahrirlash"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi o‘chirib qo‘yildi"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} ilovasida # ta bildirishnoma bor}other{{app_name} ilovasida # ta bildirishnoma bor}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} ilovasida # ta bildirishnoma bor}other{{app_name} ilovasida # ta bildirishnoma bor}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"%2$ddan %1$d ta sahifa"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Uy ekrani %2$ddan %1$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Yangi bosh ekran sahifasi"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Fon rasmi va uslubi"</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="7728578836261442095">"Bosh ekranni burishga ruxsat"</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>
@@ -114,7 +114,8 @@
<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>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Bildirishnoma belgilarini chiqarish"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Ilova ikonkalarini bosh ekranga chiqarish"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Dasturchi sozlamalari"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Ilova ikonkalarini bosh ekranga chiqarish"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Yangi o‘rnatilgan ilovalar ikonkasini bosh ekranga chiqarish"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Noma’lum"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Olib tashlash"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> oʻrnatlmoqda, <xliff:g id="PROGRESS">%2$s</xliff:g> yakunlandi"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> yuklab olinmoqda, <xliff:g id="PROGRESS">%2$s</xliff:g> bajarildi"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ilovasi o‘rnatilishi kutilmoqda"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Ilovani yangilash zarur"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Bu belgi uchun ilova yangilanmagan. Ushbu yorliqni qayta yoqish uchun oddiy usulda yangilashingiz yoki belgini olib tashlashingiz mumkin."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Yangilash"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Olib tashlash"</string>
<string name="widgets_list" msgid="796804551140113767">"Vidjetlar ro‘yxati"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Vidjetlar ro‘yxati yopildi"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Bosh ekranga chiqarish"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Bosh ekranga chiqarish"</string>
<string name="action_move_here" msgid="2170188780612570250">"Obyektni bu yerga ko‘chirish"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Obyekt bosh ekranga qo‘shildi"</string>
<string name="item_removed" msgid="851119963877842327">"Element olib tashlandi"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Element jildga qo‘shildi"</string>
<string name="create_folder_with" msgid="4050141361160214248">"<xliff:g id="NAME">%1$s</xliff:g> bilan jild yaratish"</string>
<string name="folder_created" msgid="6409794597405184510">"Jild yaratildi"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Bosh ekranga ko‘chirish"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Bosh ekranga koʻchirish"</string>
<string name="action_resize" msgid="1802976324781771067">"O‘lchamini o‘zgartirish"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Enini uzaytirish"</string>
<string name="action_increase_height" msgid="459390020612501122">"Bo‘yini uzaytirish"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Ishga oid ilovalarni faolsizlantirish"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Xato: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-v31/styles.xml b/res/values-v31/styles.xml
index 0d2fce0..008a77c 100644
--- a/res/values-v31/styles.xml
+++ b/res/values-v31/styles.xml
@@ -38,6 +38,7 @@
<item name="preferenceScreenStyle">@style/HomeSettings.PreferenceScreenStyle</item>
<item name="preferenceStyle">@style/HomeSettings.PreferenceStyle</item>
<item name="switchPreferenceStyle">@style/HomeSettings.SwitchPreferenceStyle</item>
+ <item name="android:fontFamily">google-sans-text</item>
</style>
<style name="HomeSettings.CategoryStyle" parent="@style/Preference.Category.Material">
@@ -87,6 +88,7 @@
<style name="HomeSettings.CollapsedToolbarTitle"
parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
<item name="android:fontFamily">google-sans</item>
+ <item name="android:textSize">20sp</item>
</style>
<style name="HomeSettings.ExpandedToolbarTitle" parent="HomeSettings.CollapsedToolbarTitle">
diff --git a/res/values-v33/style.xml b/res/values-v33/style.xml
new file mode 100644
index 0000000..bd48468
--- /dev/null
+++ b/res/values-v33/style.xml
@@ -0,0 +1,40 @@
+<?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.
+*/
+-->
+
+<resources>
+ <style name="HomeSettings.Theme" parent="@android:style/Theme.DeviceDefault.Settings">
+ <item name="android:listPreferredItemPaddingEnd">16dp</item>
+ <item name="android:listPreferredItemPaddingStart">24dp</item>
+ <item name="android:navigationBarColor">@android:color/transparent</item>
+ <item name="android:statusBarColor">@android:color/transparent</item>
+ <item name="android:switchStyle">@style/HomeSettings.SwitchStyle</item>
+ <item name="android:textAppearanceListItem">@style/HomeSettings.PreferenceTitle</item>
+ <item name="android:windowActionBar">false</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="preferenceTheme">@style/HomeSettings.PreferenceTheme</item>
+ <item name="android:windowAnimationStyle">@style/Animation.SharedBackground</item>
+ </style>
+
+ <style name="Animation.SharedBackground" parent="@android:style/Animation.Activity">
+ <item name="android:activityOpenEnterAnimation">@anim/shared_x_axis_activity_open_enter</item>
+ <item name="android:activityOpenExitAnimation">@anim/shared_x_axis_activity_open_exit</item>
+ <item name="android:activityCloseEnterAnimation">@anim/shared_x_axis_activity_close_enter</item>
+ <item name="android:activityCloseExitAnimation">@anim/shared_x_axis_activity_close_exit</item>
+ </style>
+</resources>
\ No newline at end of file
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 6972ee3..2c81ae7 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"Rộng %1$d x cao %2$d"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Tiện ích <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Chạm và giữ để di chuyển tiện ích xung quanh Màn hình chính"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Thêm vào Màn hình chính"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<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_education_header" msgid="4874760613775913787">"Thông tin hữu ích ngay trong tầm tay bạn"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Để 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="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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Tôi hiểu"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Thay đổi chế độ cài đặt tiện ích"</string>
@@ -65,7 +65,7 @@
<string name="notifications_header" msgid="1404149926117359025">"Thông báo"</string>
<string name="long_press_shortcut_to_add" msgid="5405328730817637737">"Chạm và giữ để di chuyển một lối tắt."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="2199537273817090740">"Nhấn đúp và giữ để di chuyển một lối tắt hoặc sử dụng các thao tác tùy chỉnh."</string>
- <string name="out_of_space" msgid="6692471482459245734">"Không còn khoảng trống trên Màn hình chính này"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Không còn khoảng trống trên màn hình chính này"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Không còn chỗ trong khay Mục yêu thích"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Danh sách ứng dụng"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Kết quả tìm kiếm"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Ghim ứng dụng dự đoán"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"cài đặt lối tắt"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Cho phép ứng dụng thêm lối tắt mà không cần sự can thiệp của người dùng."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"đọc cài đặt và lối tắt trên Màn hình chính"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Cho phép ứng dụng đọc cài đặt và lối tắt trên Màn hình chính."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"ghi cài đặt và lối tắt trên Màn hình chính"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Cho phép ứng dụng thay đổi cài đặt và lối tắt trên Màn hình chính."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"đọc lối tắt và các chế độ cài đặt trên màn hình chính"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Đây là ứng dụng hệ thống và không thể gỡ cài đặt."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Chỉnh sửa tên"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Đã vô hiệu hóa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{{app_name} có # thông báo}other{{app_name} có # thông báo}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{{app_name} có # thông báo}other{{app_name} có # thông báo}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Trang %1$d / %2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Màn hình chính %1$d / %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Trang màn hình chính mới"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Hình nền và phong cách"</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="7728578836261442095">"Cho phép xoay Màn hình chính"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Cho phép xoay màn hình chính"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Khi xoay điện thoại"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Dấu chấm thông báo"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Đang bật"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Để hiển thị Dấu chấm thông báo, hãy bật thông báo ứng dụng cho <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Thay đổi cài đặt"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Hiện dấu chấm thông báo"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Thêm biểu tượng ứng dụng vào Màn hình chính"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Tùy chọn cho nhà phát triển"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Thêm biểu tượng ứng dụng vào màn hình chính"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Cho ứng dụng mới"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Không xác định"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Xóa"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"Đang cài đặt <xliff:g id="NAME">%1$s</xliff:g>, hoàn tất <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"Đang tải xuống <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="PROGRESS">%2$s</xliff:g> hoàn tất"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"Đang chờ cài đặt <xliff:g id="NAME">%1$s</xliff:g>"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Cần cập nhật ứng dụng"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"Ứng dụng cho biểu tượng này chưa được cập nhật. Bạn có thể cập nhật theo cách thủ công để bật lại phím tắt này hoặc xóa biểu tượng."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Cập nhật"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Xóa"</string>
<string name="widgets_list" msgid="796804551140113767">"Danh sách tiện ích"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Đã đóng danh sách tiện ích"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Thêm vào màn hình chính"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Thêm vào màn hình chính"</string>
<string name="action_move_here" msgid="2170188780612570250">"Di chuyển mục vào đây"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Đã thêm mục vào màn hình chính"</string>
<string name="item_removed" msgid="851119963877842327">"Đã xóa mục"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Đã thêm mục vào thư mục"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Tạo thư mục bằng: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Đã tạo thư mục"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Di chuyển đến màn hình chính"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Di chuyển đến màn hình chính"</string>
<string name="action_resize" msgid="1802976324781771067">"Đổi kích thước"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Tăng chiều rộng"</string>
<string name="action_increase_height" msgid="459390020612501122">"Tăng chiều cao"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Tắt ứng dụng công việc"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Không thực hiện được thao tác: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index f11f020..7c104e2 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"轻触并按住该微件即可将其在主屏幕上四处移动"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"添加到主屏幕"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 个微件}other{# 个微件}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# 个快捷方式}other{# 个快捷方式}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"工作"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"对话"</string>
<string name="widget_education_header" msgid="4874760613775913787">"实用信息触手可及"</string>
- <string name="widget_education_content" msgid="745542879510751525">"要想不打开应用就能获取信息,您可以将相应微件添加到主屏幕"</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>
@@ -65,7 +65,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="6692471482459245734">"此主屏幕上已没有空间"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"固定预测的应用"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"安装快捷方式"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"允许应用自行添加快捷方式。"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"读取主屏幕设置和快捷方式"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"允许应用读取主屏幕中的设置和快捷方式。"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"写入主屏幕设置和快捷方式"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"允许应用更改主屏幕中的设置和快捷方式。"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"读取主屏幕设置和快捷方式"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"这是系统应用,无法卸载。"</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{“{app_name}”有 # 条通知}other{“{app_name}”有 # 条通知}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{“{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"壁纸和样式"</string>
<string name="settings_button_text" msgid="8873672322605444408">"主屏幕设置"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"已被您的管理员停用"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"允许旋转主屏幕"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"要显示通知圆点,请开启<xliff:g id="NAME">%1$s</xliff:g>的应用通知功能"</string>
<string name="title_change_settings" msgid="1376365968844349552">"更改设置"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"显示通知圆点"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"将应用图标添加到主屏幕"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"开发者选项"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"将应用图标添加到主屏幕"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"适用于新应用"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"未知"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"更新"</string>
+ <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="8902165848117513641">"添加到主屏幕"</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_removed" msgid="851119963877842327">"项目已移除"</string>
@@ -141,7 +146,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="1603837886334246317">"移至主屏幕"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"知道了"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"关闭工作应用"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"暂停工作应用"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"开启工作应用"</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="remote_action_failed" msgid="1383965239183576790">"失败:<xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index a278327..ed288d6 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"按住小工具即可隨意在主畫面上移動"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"新增至主畫面"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 個小工具}other{# 個小工具}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# 個捷徑}other{# 個捷徑}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"工作"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"對話"</string>
<string name="widget_education_header" msgid="4874760613775913787">"實用資訊,唾手可得"</string>
- <string name="widget_education_content" msgid="745542879510751525">"將小工具新增到主畫面,不用開啟應用程式就可直接查看資訊"</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>
@@ -65,7 +65,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="6692471482459245734">"這個主畫面沒有空間了"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"固定預測"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"安裝捷徑"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"允許應用程式無需使用者許可也可新增捷徑。"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"讀取主畫面的設定和捷徑"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"允許應用程式讀取主畫面中的設定和捷徑。"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"寫入主畫面的設定和捷徑"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"允許應用程式更改主畫面中的設定和捷徑。"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"讀取主畫面設定和捷徑"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"這是系統應用程式,無法將其解除安裝。"</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{「{app_name}」有 # 項通知}other{「{app_name}」有 # 項通知}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{「{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"桌布和樣式"</string>
<string name="settings_button_text" msgid="8873672322605444408">"主畫面設定"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"已由您的管理員停用"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"允許主畫面旋轉"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"如要顯示「通知圓點」,請開啟「<xliff:g id="NAME">%1$s</xliff:g>」的應用程式通知功能"</string>
<string name="title_change_settings" msgid="1376365968844349552">"變更設定"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"顯示通知圓點"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"將應用程式圖示新增至主畫面"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"開發人員選項"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"將應用程式圖示新增至主畫面"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"新安裝的應用程式"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"更新"</string>
+ <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="8902165848117513641">"新增至主畫面"</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_removed" msgid="851119963877842327">"項目已移除"</string>
@@ -141,7 +146,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="1603837886334246317">"移動至主畫面"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"知道了"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"關閉工作應用程式"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"暫停工作應用程式"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"開啟工作應用程式"</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="remote_action_failed" msgid="1383965239183576790">"操作失敗:<xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index a2cfcc7..3690c3a 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -37,8 +37,8 @@
<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="5653291305078645405">"按住小工具即可將它拖放到主畫面上的任何位置"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"新增到主畫面"</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>
<string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 項小工具}other{# 項小工具}}"</string>
<string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# 個捷徑}other{# 個捷徑}}"</string>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"工作"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"對話"</string>
<string name="widget_education_header" msgid="4874760613775913787">"實用資訊隨手可得"</string>
- <string name="widget_education_content" msgid="745542879510751525">"只要將小工具新增到主畫面,就可以直接查看資訊,不必開啟應用程式"</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>
@@ -65,7 +65,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="6692471482459245734">"這個主畫面已無空間"</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>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"固定預測的應用程式"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"安裝捷徑"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"允許應用程式自動新增捷徑。"</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"讀取主畫面的設定和捷徑"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"允許應用程式讀取主畫面中的設定和捷徑。"</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"寫入主畫面設定和捷徑"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"允許應用程式變更主畫面中的設定和捷徑。"</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"讀取主畫面設定和捷徑"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"這是系統應用程式,不可解除安裝。"</string>
<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="1704091277755818896">"{count,plural,offset:1 =1{「{app_name}」有 # 則通知}other{「{app_name}」有 # 則通知}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{「{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>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"桌布和樣式"</string>
<string name="settings_button_text" msgid="8873672322605444408">"主畫面設定"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"已由你的管理員停用"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"允許旋轉主畫面"</string>
+ <string name="allow_rotation_title" msgid="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>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"如要顯示通知圓點,請開啟「<xliff:g id="NAME">%1$s</xliff:g>」的應用程式通知功能"</string>
<string name="title_change_settings" msgid="1376365968844349552">"變更設定"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"顯示通知圓點"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"將應用程式圖示加到主畫面"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"開發人員選項"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"將應用程式圖示加到主畫面"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"適用於新安裝的應用程式"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"不明"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"移除"</string>
@@ -124,9 +125,13 @@
<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" msgid="2178028071796141234">"更新"</string>
+ <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="8902165848117513641">"新增至主畫面"</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_removed" msgid="851119963877842327">"已移除項目"</string>
@@ -141,7 +146,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="1603837886334246317">"移至主畫面"</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>
@@ -163,8 +168,10 @@
<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_edu_accept" msgid="6377476824357318532">"我知道了"</string>
- <string name="work_apps_pause_btn_text" msgid="1921059713673767460">"關閉工作應用程式"</string>
+ <string name="work_apps_pause_btn_text" msgid="4669288269140620646">"暫停工作應用程式"</string>
<string name="work_apps_enable_btn_text" msgid="1156432622148413741">"開啟工作應用程式"</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="remote_action_failed" msgid="1383965239183576790">"失敗:<xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 1208eb2..26e7dcf 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -37,8 +37,8 @@
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ububanzi ngokungu-%2$d ukuya phezulu"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"Iwijethi elingu-<xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
- <string name="add_item_request_drag_hint" msgid="5653291305078645405">"Thinta uphinde ubambe iwijethi ukuyihambisa Kusikrini sasekhaya"</string>
- <string name="add_to_home_screen" msgid="8631549138215492708">"Engeza kusikrini sasekhaya"</string>
+ <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>
<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>
@@ -52,7 +52,7 @@
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Umsebenzi"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"Izingxoxo"</string>
<string name="widget_education_header" msgid="4874760613775913787">"Ulwazi oluwusizo phambi nje kwakho"</string>
- <string name="widget_education_content" msgid="745542879510751525">"Ukuze utholeulwazi ngaphandle kokuvula ama-app, ungakwazi ukwengeza amawijethi kusikrini sakho sasekhaya"</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>
<string name="widget_education_close_button" msgid="8676165703104836580">"Ngiyezwa"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Shintsha amasethingi ewijethi"</string>
@@ -65,7 +65,7 @@
<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>
- <string name="out_of_space" msgid="6692471482459245734">"Asikho isikhala kulesi sikrini sasekhaya"</string>
+ <string name="out_of_space" msgid="6455557115204099579">"Asikho isikhala kulesi sikrini sasekhaya"</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Asisekho isikhala kwitreyi lezintandokazi"</string>
<string name="all_apps_button_label" msgid="8130441508702294465">"Uhlu lwezinhlelo zokusebenza"</string>
<string name="all_apps_search_results" msgid="5889367432531296759">"Imiphumela yosesho"</string>
@@ -79,10 +79,10 @@
<string name="pin_prediction" msgid="4196423321649756498">"Ukubikezela Iphinikhodi"</string>
<string name="permlab_install_shortcut" msgid="5632423390354674437">"faka izinqamuleli"</string>
<string name="permdesc_install_shortcut" msgid="923466509822011139">"Ivumela uhlelo lokusebenza ukufaka izinqamuleli ngaphandle kokungenelela komsebenzisi."</string>
- <string name="permlab_read_settings" msgid="1941457408239617576">"funda izilungiselelo zokuthi Ikhaya nezinqamuleli"</string>
- <string name="permdesc_read_settings" msgid="5833423719057558387">"Ivumela uhlelo lokusebenza ukuthi lifunde izilungiselelo nezinqamuleli ekhaya."</string>
- <string name="permlab_write_settings" msgid="3574213698004620587">"bhala izilungiselelo zokuthi Ikhaya nezinqamuleli"</string>
- <string name="permdesc_write_settings" msgid="5440712911516509985">"Ivumela uhlelo lokusebenza ukuthi lushintshe izilungiselelo nezinqamuleli Ekhaya."</string>
+ <string name="permlab_read_settings" msgid="5136500343007704955">"funda amasethingi wasekhaya nezinqamuleli"</string>
+ <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>
@@ -90,7 +90,7 @@
<string name="uninstall_system_app_text" msgid="4172046090762920660">"Lolu uhlelo lokusebenza lwesistimu futhi alikwazi ukukhishwa."</string>
<string name="folder_hint_text" msgid="5174843001373488816">"Hlela igama"</string>
<string name="disabled_app_label" msgid="6673129024321402780">"Kukhutshaziwe <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="dotted_app_label" msgid="1704091277755818896">"{count,plural,offset:1 =1{I-{app_name}, inesaziso esingu-#}one{I-{app_name}, inezaziso ezingu-#}other{I-{app_name}, inezaziso ezingu-#}}"</string>
+ <string name="dotted_app_label" msgid="1865617679843363410">"{count,plural, =1{I-{app_name} inesaziso esi-#}one{I-{app_name} inezaziso ezingu-#}other{I-{app_name} inezaziso ezingu-#}}"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"Ikhasi elingu-%1$d kwangu-%2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"Isikrini sasekhaya esingu-%1$d se-%2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Ikhasi elisha lesikrini sasekhaya"</string>
@@ -105,7 +105,7 @@
<string name="styles_wallpaper_button_text" msgid="8216961355289236794">"Isithombe sangemuva nesitayela"</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="7728578836261442095">"Vumela ukuphendukiswa kwesikrini sasekhaya"</string>
+ <string name="allow_rotation_title" msgid="7222049633713050106">"Vumela ukuzungezisa kwesikrini sasekhaya"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"Uma ifoni iphendukiswa"</string>
<string name="notification_dots_title" msgid="9062440428204120317">"Amacashazi esaziso"</string>
<string name="notification_dots_desc_on" msgid="1679848116452218908">"Vuliwe"</string>
@@ -114,7 +114,8 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"Ukuze ubonisa amcashazi esaziso, vula izaziso zohlelo lokusebenza ze-<xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Shintsha izilungiselelo"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Bonisa amacashazi esaziso"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Engeza izithonjana zohlelo lokusebenza kusikrini sasekhaya"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"Izinketho zonjiniyela"</string>
+ <string name="auto_add_shortcuts_label" msgid="4926805029653694105">"Engeza izithonjana ze-app kusikrini sasekhaya"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Kwezinhlelo zokusebenza ezintsha"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"Akwaziwa"</string>
<string name="abandoned_clean_this" msgid="7610119707847920412">"Susa"</string>
@@ -124,9 +125,13 @@
<string name="app_installing_title" msgid="5864044122733792085">"I-<xliff:g id="NAME">%1$s</xliff:g> iyafakwa, seyiqede <xliff:g id="PROGRESS">%2$s</xliff:g>"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"I-<xliff:g id="NAME">%1$s</xliff:g> iyalandwa, <xliff:g id="PROGRESS">%2$s</xliff:g> kuqediwe"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ilinde ukufakwa"</string>
+ <string name="dialog_update_title" msgid="114234265740994042">"Kudingeka isibuyekezo se-app"</string>
+ <string name="dialog_update_message" msgid="4176784553982226114">"I-app yalesi sithonjana ibuyekeziwe. Ungabuyekeza mathupha ukuze uphinde unike amandla lesi sinqamuleli, noma ususe isithonjana."</string>
+ <string name="dialog_update" msgid="2178028071796141234">"Vuselela"</string>
+ <string name="dialog_remove" msgid="6510806469849709407">"Susa"</string>
<string name="widgets_list" msgid="796804551140113767">"Uhlu lwamawijethi"</string>
<string name="widgets_list_closed" msgid="6141506579418771922">"Uhlu lwamawijethi luvaliwe"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"Faka kusikrini sasekhaya"</string>
+ <string name="action_add_to_workspace" msgid="215894119683164916">"Faka kusikrini sasekhaya"</string>
<string name="action_move_here" msgid="2170188780612570250">"Hambisa into lapha"</string>
<string name="item_added_to_workspace" msgid="4211073925752213539">"Into ingezwe kusikrini sasekhaya"</string>
<string name="item_removed" msgid="851119963877842327">"Into isusiwe"</string>
@@ -141,7 +146,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"Into ingeziwe kufolda"</string>
<string name="create_folder_with" msgid="4050141361160214248">"Dala ifolda nge-: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"Ifolda idaliwe"</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"Hambisa kusikrini sasekhaya"</string>
+ <string name="action_move_to_workspace" msgid="39528912300293768">"Hambisa kusikrini sasekhaya"</string>
<string name="action_resize" msgid="1802976324781771067">"Shintsha usayizi"</string>
<string name="action_increase_width" msgid="8773715375078513326">"Khuphula ububanzi"</string>
<string name="action_increase_height" msgid="459390020612501122">"Khuphula ubude"</string>
@@ -163,8 +168,10 @@
<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_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="1921059713673767460">"Vala ama-app omsebenzi"</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="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>
<string name="remote_action_failed" msgid="1383965239183576790">"Yehlulekile: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 08570eb..13f20c2 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -54,6 +54,12 @@
<attr name="workspaceAccentColor" format="color" />
<attr name="dropTargetHoverTextColor" format="color" />
+ <attr name="allAppsButtonBgColor" format="color" />
+ <attr name="allAppsButtonColor1" format="color" />
+ <attr name="allAppsButtonColor2" format="color" />
+ <attr name="allAppsButtonColor3" format="color" />
+ <attr name="allAppsButtonColor4" format="color" />
+
<!-- BubbleTextView specific attributes. -->
<declare-styleable name="BubbleTextView">
<attr name="layoutHorizontal" format="boolean" />
@@ -133,6 +139,8 @@
<attr name="numRows" format="integer" />
<attr name="numColumns" format="integer" />
+ <!-- numSearchContainerColumns defaults to numColumns, if not specified -->
+ <attr name="numSearchContainerColumns" format="integer" />
<!-- numFolderRows & numFolderColumns defaults to numRows & numColumns, if not specified -->
<attr name="numFolderRows" format="integer" />
<attr name="numFolderColumns" format="integer" />
@@ -144,10 +152,24 @@
<!-- numHotseatIcons defaults to numColumns, if not specified -->
<attr name="numHotseatIcons" format="integer" />
+ <!-- Number of icons to use when shrinking the hotseat size,
+ defaults to numHotseatIcons / 2 -->
+ <attr name="numShrunkenHotseatIcons" format="integer" />
<!-- Number of icons to use when extending the hotseat size,
defaults to 2 * numHotseatIcons -->
<attr name="numExtendedHotseatIcons" format="integer" />
+ <!-- alignment of hotseat to the grid.
+ Not applicable for 3 button mode when taskbar is enabled -->
+ <!-- defaults to numColumns, if not specified -->
+ <attr name="hotseatColumnSpan" format="integer" />
+ <!-- defaults to numColumns, if not specified -->
+ <attr name="hotseatColumnSpanLandscape" format="integer" />
+ <!-- defaults to numColumns, if not specified -->
+ <attr name="hotseatColumnSpanTwoPanelLandscape" format="integer" />
+ <!-- defaults to numColumns, if not specified -->
+ <attr name="hotseatColumnSpanTwoPanelPortrait" format="integer" />
+
<attr name="dbFile" format="string" />
<attr name="defaultLayoutId" format="reference" />
<attr name="defaultSplitDisplayLayoutId" format="reference" />
@@ -182,76 +204,167 @@
<attr name="minHeightDps" format="float" />
<!-- These min cell values are only used if GridDisplayOption#isScalable is true -->
- <attr name="minCellHeightDps" format="float" />
- <attr name="minCellWidthDps" format="float" />
- <!-- twoPanelPortraitMinCellWidthDps defaults to minCellHeightDps, if not specified -->
- <attr name="twoPanelPortraitMinCellHeightDps" format="float" />
- <!-- twoPanelPortraitMinCellHeightDps defaults to minCellWidthDps, if not specified -->
- <attr name="twoPanelPortraitMinCellWidthDps" format="float" />
- <!-- twoPanelLandscapeMinCellHeightDps defaults to minCellHeightDps, if not specified -->
- <attr name="twoPanelLandscapeMinCellHeightDps" format="float" />
- <!-- twoPanelLandscapeMinCellWidthDps defaults to minCellWidthDps, if not specified -->
- <attr name="twoPanelLandscapeMinCellWidthDps" format="float" />
+ <attr name="minCellHeight" format="float" />
+ <attr name="minCellWidth" format="float" />
+ <!-- defaults to minCellHeight, if not specified -->
+ <attr name="minCellHeightLandscape" format="float" />
+ <!-- defaults to minCellWidth, if not specified -->
+ <attr name="minCellWidthLandscape" format="float" />
+ <!-- defaults to minCellHeight, if not specified -->
+ <attr name="minCellHeightTwoPanelPortrait" format="float" />
+ <!-- defaults to minCellWidth, if not specified -->
+ <attr name="minCellWidthTwoPanelPortrait" format="float" />
+ <!-- defaults to minCellHeight, if not specified -->
+ <attr name="minCellHeightTwoPanelLandscape" format="float" />
+ <!-- defaults to minCellWidth, if not specified -->
+ <attr name="minCellWidthTwoPanelLandscape" format="float" />
<!-- These border spaces are only used if GridDisplayOption#isScalable is true -->
<!-- space to be used horizontally and vertically -->
- <attr name="borderSpaceDps" format="float" />
- <!-- space to the right of the cell, defaults to borderSpaceDps if not specified -->
- <attr name="borderSpaceHorizontalDps" format="float" />
- <!-- space below the cell, defaults to borderSpaceDps if not specified -->
- <attr name="borderSpaceVerticalDps" format="float" />
+ <attr name="borderSpace" format="float" />
+ <!-- space to the right of the cell, defaults to borderSpace if not specified -->
+ <attr name="borderSpaceHorizontal" format="float" />
+ <!-- space below the cell, defaults to borderSpace if not specified -->
+ <attr name="borderSpaceVertical" format="float" />
+ <!-- space to be used horizontally and vertically,
+ defaults to borderSpace if not specified -->
+ <attr name="borderSpaceLandscape" format="float" />
+ <!-- space to the right of the cell, defaults to borderSpaceLandscape if not specified -->
+ <attr name="borderSpaceLandscapeHorizontal" format="float" />
+ <!-- space below the cell, defaults to borderSpaceLandscape if not specified -->
+ <attr name="borderSpaceLandscapeVertical" format="float" />
<!-- space to be used horizontally and vertically in two panels,
- defaults to borderSpaceDps if not specified -->
- <attr name="twoPanelPortraitBorderSpaceDps" format="float" />
+ defaults to borderSpace if not specified -->
+ <attr name="borderSpaceTwoPanelPortrait" format="float" />
<!-- space to the right of the cell in two panels, defaults to
- twoPanelPortraitBorderSpaceDps if not specified -->
- <attr name="twoPanelPortraitBorderSpaceHorizontalDps" format="float" />
- <!-- space below the cell in two panels, defaults to twoPanelPortraitBorderSpaceDps
+ borderSpaceTwoPanelPortrait if not specified -->
+ <attr name="borderSpaceTwoPanelPortraitHorizontal" format="float" />
+ <!-- space below the cell in two panels, defaults to borderSpaceTwoPanelPortrait
if not specified -->
- <attr name="twoPanelPortraitBorderSpaceVerticalDps" format="float" />
+ <attr name="borderSpaceTwoPanelPortraitVertical" format="float" />
<!-- space to be used horizontally and vertically in two panels,
- defaults to borderSpaceDps if not specified -->
- <attr name="twoPanelLandscapeBorderSpaceDps" format="float" />
+ defaults to borderSpace if not specified -->
+ <attr name="borderSpaceTwoPanelLandscape" format="float" />
<!-- space to the right of the cell in two panels, defaults to
- twoPanelLandscapeBorderSpaceDps if not specified -->
- <attr name="twoPanelLandscapeBorderSpaceHorizontalDps" format="float" />
- <!-- space below the cell in two panels, defaults to twoPanelLandscapeBorderSpaceDps
+ borderSpaceTwoPanelLandscape if not specified -->
+ <attr name="borderSpaceTwoPanelLandscapeHorizontal" format="float" />
+ <!-- space below the cell in two panels, defaults to borderSpaceTwoPanelLandscape
if not specified -->
- <attr name="twoPanelLandscapeBorderSpaceVerticalDps" format="float" />
+ <attr name="borderSpaceTwoPanelLandscapeVertical" format="float" />
- <!-- allAppsCellSpacingDps defaults to borderSpaceDps, if not specified -->
- <attr name="allAppsCellSpacingDps" format="float" />
+ <!-- These min cell values are only used if GridDisplayOption#isScalable is true -->
+ <!-- defaults to minCellHeight, if not specified -->
+ <attr name="allAppsCellHeight" format="float" />
+ <!-- defaults to minCellWidth, if not specified -->
+ <attr name="allAppsCellWidth" format="float" />
+ <!-- defaults to allAppsCellHeight, if not specified -->
+ <attr name="allAppsCellHeightLandscape" format="float" />
+ <!-- defaults to allAppsCellWidth, if not specified -->
+ <attr name="allAppsCellWidthLandscape" format="float" />
+ <!-- defaults to allAppsCellHeight, if not specified -->
+ <attr name="allAppsCellHeightTwoPanelPortrait" format="float" />
+ <!-- defaults to allAppsCellWidth, if not specified -->
+ <attr name="allAppsCellWidthTwoPanelPortrait" format="float" />
+ <!-- defaults to allAppsCellHeight, if not specified -->
+ <attr name="allAppsCellHeightTwoPanelLandscape" format="float" />
+ <!-- defaults to allAppsCellWidth, if not specified -->
+ <attr name="allAppsCellWidthTwoPanelLandscape" format="float" />
<!-- The following values are only enabled if grid is supported. -->
- <!-- allAppsIconSize defaults to iconSize, if not specified -->
+ <!-- defaults to iconImageSize, if not specified -->
<attr name="allAppsIconSize" format="float" />
- <!-- allAppsIconTextSize defaults to iconTextSize, if not specified -->
+ <!-- defaults to allAppsIconSize, if not specified -->
+ <attr name="allAppsIconSizeTwoPanelPortrait" format="float" />
+ <!-- defaults to allAppsIconSize, if not specified -->
+ <attr name="allAppsIconSizeTwoPanelLandscape" format="float" />
+ <!-- defaults to iconTextSize, if not specified -->
<attr name="allAppsIconTextSize" format="float" />
+ <!-- defaults to allAppsIconTextSize, if not specified -->
+ <attr name="allAppsIconTextSizeTwoPanelPortrait" format="float" />
+ <!-- defaults to allAppsIconTextSize, if not specified -->
+ <attr name="allAppsIconTextSizeTwoPanelLandscape" format="float" />
+
+ <!-- defaults to borderSpace, if not specified -->
+ <!-- space to be used horizontally and vertically -->
+ <attr name="allAppsBorderSpace" format="float" />
+ <!-- space to the right of the cell, defaults to allAppsBorderSpace if not specified -->
+ <attr name="allAppsBorderSpaceHorizontal" format="float" />
+ <!-- space below the cell, defaults to allAppsBorderSpace if not specified -->
+ <attr name="allAppsBorderSpaceVertical" format="float" />
+ <!-- space to be used horizontally and vertically,
+ defaults to allAppsBorderSpace if not specified -->
+ <attr name="allAppsBorderSpaceLandscape" format="float" />
+ <!-- space to the right of the cell, defaults to allAppsBorderSpaceLandscape
+ if not specified -->
+ <attr name="allAppsBorderSpaceLandscapeHorizontal" format="float" />
+ <!-- space below the cell, defaults to allAppsBorderSpaceLandscape if not specified -->
+ <attr name="allAppsBorderSpaceLandscapeVertical" format="float" />
+ <!-- space to be used horizontally and vertically in two panels,
+ defaults to allAppsBorderSpace if not specified -->
+ <attr name="allAppsBorderSpaceTwoPanelPortrait" format="float" />
+ <!-- space to the right of the cell in two panels, defaults to
+ allAppsBorderSpaceTwoPanelPortrait if not specified -->
+ <attr name="allAppsBorderSpaceTwoPanelPortraitHorizontal" format="float" />
+ <!-- space below the cell in two panels, defaults to allAppsBorderSpaceTwoPanelPortrait
+ if not specified -->
+ <attr name="allAppsBorderSpaceTwoPanelPortraitVertical" format="float" />
+ <!-- space to be used horizontally and vertically in two panels,
+ defaults to allAppsBorderSpace if not specified -->
+ <attr name="allAppsBorderSpaceTwoPanelLandscape" format="float" />
+ <!-- space to the right of the cell in two panels, defaults to
+ allAppsBorderSpaceTwoPanelLandscape if not specified -->
+ <attr name="allAppsBorderSpaceTwoPanelLandscapeHorizontal" format="float" />
+ <!-- space below the cell in two panels, defaults to allAppsBorderSpaceTwoPanelLandscape
+ if not specified -->
+ <attr name="allAppsBorderSpaceTwoPanelLandscapeVertical" format="float" />
+
+ <!-- defaults to borderSpaceDps, if not specified -->
+ <attr name="hotseatBorderSpace" format="float" />
+ <!-- defaults to hotseatBorderSpace, if not specified -->
+ <attr name="hotseatBorderSpaceLandscape" format="float" />
+ <!-- defaults to hotseatBorderSpace, if not specified -->
+ <attr name="hotseatBorderSpaceTwoPanelLandscape" format="float" />
+ <!-- defaults to hotseatBorderSpace, if not specified -->
+ <attr name="hotseatBorderSpaceTwoPanelPortrait" format="float" />
<attr name="iconImageSize" format="float" />
- <!-- landscapeIconSize defaults to iconImageSize, if not specified -->
- <attr name="landscapeIconSize" format="float" />
- <!-- twoPanelPortraitIconSize defaults to iconImageSize, if not specified -->
- <attr name="twoPanelPortraitIconSize" format="float" />
- <!-- twoPanelLandscapeIconSize defaults to iconImageSize, if not specified -->
- <attr name="twoPanelLandscapeIconSize" format="float" />
+ <!-- defaults to iconImageSize, if not specified -->
+ <attr name="iconSizeLandscape" format="float" />
+ <!-- defaults to iconSize, if not specified -->
+ <attr name="iconSizeTwoPanelPortrait" format="float" />
+ <!-- defaults to iconSize, if not specified -->
+ <attr name="iconSizeTwoPanelLandscape" format="float" />
<attr name="iconTextSize" format="float" />
- <!-- landscapeIconTextSize defaults to iconTextSize, if not specified -->
- <attr name="landscapeIconTextSize" format="float" />
- <!-- twoPanelPortraitIconTextSize defaults to iconTextSize, if not specified -->
- <attr name="twoPanelPortraitIconTextSize" format="float" />
- <!-- twoPanelLandscapeIconTextSize defaults to iconTextSize, if not specified -->
- <attr name="twoPanelLandscapeIconTextSize" format="float" />
+ <!-- defaults to iconTextSize, if not specified -->
+ <attr name="iconTextSizeLandscape" format="float" />
+ <!-- defaults to iconTextSize, if not specified -->
+ <attr name="iconTextSizeTwoPanelPortrait" format="float" />
+ <!-- defaults to iconTextSize, if not specified -->
+ <attr name="iconTextSizeTwoPanelLandscape" format="float" />
<!-- If set, this display option is used to determine the default grid -->
<attr name="canBeDefault" format="boolean" />
<!-- Margin on left and right of the workspace when GridDisplayOption#isScalable is true -->
<attr name="horizontalMargin" format="float"/>
- <!-- twoPanelLandscapeHorizontalMargin defaults to horizontalMargin if not specified -->
- <attr name="twoPanelLandscapeHorizontalMargin" format="float"/>
- <!-- twoPanelPortraitHorizontalMargin defaults to horizontalMargin if not specified -->
- <attr name="twoPanelPortraitHorizontalMargin" format="float"/>
+ <!-- defaults to horizontalMargin if not specified -->
+ <attr name="horizontalMarginLandscape" format="float"/>
+ <!-- defaults to horizontalMargin if not specified -->
+ <attr name="horizontalMarginTwoPanelLandscape" format="float"/>
+ <!-- defaults to horizontalMargin if not specified -->
+ <attr name="horizontalMarginTwoPanelPortrait" format="float"/>
+
+ <!-- By default all are false -->
+ <attr name="inlineQsb" format="integer" >
+ <!-- Enable on landscape only -->
+ <flag name="portrait" value="1" />
+ <!-- Enable on portrait only -->
+ <flag name="landscape" value="2" />
+ <!-- Enable on two panel portrait only -->
+ <flag name="twoPanelPortrait" value="4" />
+ <!-- Enable on two panel landscape only -->
+ <flag name="twoPanelLandscape" value="8" />
+ </attr>
</declare-styleable>
<declare-styleable name="CellLayout">
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 0b1b451..2bc9239 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -79,4 +79,10 @@
<color name="workspace_accent_color_light">#ff8df5e3</color>
<color name="workspace_accent_color_dark">#ff3d665f</color>
+
+ <color name="all_apps_button_bg_color">#F7F9FA</color>
+ <color name="all_apps_button_color_1">#00677E</color>
+ <color name="all_apps_button_color_2">#00677E</color>
+ <color name="all_apps_button_color_3">#5F757E</color>
+ <color name="all_apps_button_color_4">#005A6E</color>
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 25911e6..9aa1f03 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -1,3 +1,18 @@
+<?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.
+-->
<resources>
<!-- Miscellaneous -->
<bool name="config_largeHeap">false</bool>
@@ -22,12 +37,12 @@
<item type="id" name="drag_event_parity" />
<!-- AllApps & Launcher transitions -->
- <!-- Out of 100, the percent to shrink the workspace during spring loaded mode. -->
- <integer name="config_workspaceSpringLoadShrinkPercentage">85</integer>
-
<!-- The duration of the animation from search hint to text entry -->
<integer name="config_searchHintAnimationDuration">50</integer>
+ <!-- The duration of the PagedView page snap animation -->
+ <integer name="config_pageSnapAnimationDuration">750</integer>
+
<!-- View tag key used to store SpringAnimation data. -->
<item type="id" name="spring_animation_tag" />
@@ -69,6 +84,7 @@
<string name="test_information_handler_class" translatable="false"></string>
<string name="launcher_activity_logic_class" translatable="false"></string>
<string name="model_delegate_class" translatable="false"></string>
+ <string name="window_manager_proxy_class" translatable="false"></string>
<!-- View ID to use for QSB widget -->
<item type="id" name="qsb_widget" />
@@ -87,7 +103,10 @@
<!-- 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>
<!-- Accessibility actions -->
<item type="id" name="action_remove" />
@@ -137,19 +156,9 @@
<item name="swipe_up_scale_start" type="dimen" format="float">0.88</item>
- <item name="swipe_up_trans_y_dp" type="dimen" format="float">4.5</item>
- <item name="swipe_up_trans_y_dp_per_s" type="dimen" format="float">3</item>
-
- <item name="swipe_up_trans_y_damping" type="dimen" format="float">0.45</item>
- <item name="swipe_up_trans_y_stiffness" type="dimen" format="float">200</item>
-
<item name="swipe_up_rect_xy_damping_ratio" type="dimen" format="float">0.8</item>
<item name="swipe_up_rect_xy_stiffness" type="dimen" format="float">200</item>
- <item name="swipe_up_low_swipe_duration_multiplier" type="dimen" format="float">1</item>
-
- <item name="swipe_up_launcher_alpha_max_progress" type="dimen" format="float">0.85</item>
-
<item name="staggered_damping_ratio" type="dimen" format="float">0.7</item>
<item name="staggered_stiffness" type="dimen" format="float">150</item>
<dimen name="unlock_staggered_velocity_dp_per_s">2dp</dimen>
@@ -165,12 +174,6 @@
<array name="dynamic_resources">
<item>@dimen/swipe_up_scale_start</item>
- <item>@dimen/swipe_up_trans_y_dp</item>
- <item>@dimen/swipe_up_trans_y_dp_per_s</item>
- <item>@dimen/swipe_up_trans_y_damping</item>
- <item>@dimen/swipe_up_trans_y_stiffness</item>
- <item>@dimen/swipe_up_launcher_alpha_max_progress</item>
- <item>@dimen/swipe_up_low_swipe_duration_multiplier</item>
<item>@dimen/swipe_up_max_velocity</item>
</array>
@@ -179,4 +182,8 @@
<!-- Name of the class used to generate colors from the wallpaper colors. Must be implementing the LauncherAppWidgetHostView.ColorGenerator interface. -->
<string name="color_generator_class" translatable="false"/>
+ <!-- Swipe back to home related -->
+ <dimen name="swipe_back_window_scale_x_margin">10dp</dimen>
+ <dimen name="swipe_back_window_max_delta_y">160dp</dimen>
+ <dimen name="swipe_back_window_corner_radius">40dp</dimen>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 6d223e7..8403af4 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -19,19 +19,31 @@
<dimen name="click_shadow_elevation">4dp</dimen>
<!-- Dynamic Grid -->
- <dimen name="dynamic_grid_edge_margin">8dp</dimen>
+ <dimen name="dynamic_grid_edge_margin">10.77dp</dimen>
<dimen name="dynamic_grid_left_right_margin">8dp</dimen>
<dimen name="dynamic_grid_icon_drawable_padding">7dp</dimen>
<!-- Minimum space between workspace and hotseat in spring loaded mode -->
<dimen name="dynamic_grid_min_spring_loaded_space">8dp</dimen>
+ <!-- Minimum amount of next page visible in spring loaded mode -->
+ <dimen name="dynamic_grid_spring_loaded_min_next_space_visible">24dp</dimen>
<dimen name="dynamic_grid_cell_border_spacing">16dp</dimen>
- <dimen name="dynamic_grid_cell_layout_padding">5.5dp</dimen>
+ <dimen name="cell_layout_padding">10.77dp</dimen>
<dimen name="dynamic_grid_cell_padding_x">8dp</dimen>
<!-- Hotseat -->
<dimen name="dynamic_grid_hotseat_top_padding">8dp</dimen>
<dimen name="dynamic_grid_hotseat_bottom_padding">2dp</dimen>
+ <dimen name="dynamic_grid_hotseat_bottom_tall_padding">0dp</dimen>
+ <dimen name="inline_qsb_bottom_margin">0dp</dimen>
+ <dimen name="spring_loaded_hotseat_top_margin">76dp</dimen>
+
+ <!-- Qsb -->
+ <!-- Used for adjusting the position of QSB when placed in hotseat. This is a ratio and a higher
+ number signifies that the QSB is close to the hotseat icons and a lower number signifies that
+ it is close to the bottom of the screen -->
+ <item name="qsb_center_factor" format="float" type="dimen">0.325</item>
+
<!-- Extra bottom padding for non-tall devices. -->
<dimen name="dynamic_grid_hotseat_bottom_non_tall_padding">0dp</dimen>
<dimen name="dynamic_grid_hotseat_extra_vertical_size">34dp</dimen>
@@ -45,11 +57,18 @@
<dimen name="workspace_page_indicator_line_height">1dp</dimen>
<dimen name="workspace_page_indicator_overlap_workspace">0dp</dimen>
-<!-- Drop target bar -->
- <dimen name="dynamic_grid_drop_target_size">52dp</dimen>
+ <!-- Drop target bar -->
+ <dimen name="dynamic_grid_drop_target_size">56dp</dimen>
<dimen name="drop_target_vertical_gap">20dp</dimen>
+ <dimen name="drop_target_top_margin">32dp</dimen>
+ <dimen name="drop_target_bottom_margin">16dp</dimen>
-<!-- App Widget resize frame -->
+ <!-- App Widget resize frame -->
+ <!-- Button drop target bar -->
+ <dimen name="button_drop_target_min_text_size">10sp</dimen>
+ <dimen name="button_drop_target_resize_text_increment">1sp</dimen>
+
+ <!-- App Widget resize frame -->
<dimen name="widget_handle_margin">13dp</dimen>
<dimen name="resize_frame_background_padding">24dp</dimen>
<dimen name="resize_frame_margin">22dp</dimen>
@@ -62,7 +81,7 @@
<dimen name="widget_reconfigure_button_size">36dp</dimen>
<dimen name="widget_reconfigure_tip_top_margin">16dp</dimen>
-<!-- Fast scroll -->
+ <!-- Fast scroll -->
<dimen name="fastscroll_track_min_width">6dp</dimen>
<dimen name="fastscroll_track_max_width">8dp</dimen>
<dimen name="fastscroll_thumb_padding">1dp</dimen>
@@ -83,9 +102,18 @@
<dimen name="fastscroll_width">58dp</dimen>
<dimen name="fastscroll_end_margin">-26dp</dimen>
+ <!-- PagedView -->
+ <dimen name="fling_threshold_velocity">500dp</dimen>
+ <dimen name="easy_fling_threshold_velocity">400dp</dimen>
+ <dimen name="min_fling_velocity">250dp</dimen>
+ <!-- The minimum velocity of a page snap after a fling gesture -->
+ <dimen name="min_page_snap_velocity">1500dp</dimen>
+
<!-- All Apps -->
- <dimen name="all_apps_open_vertical_translate">320dp</dimen>
+ <dimen name="all_apps_starting_vertical_translate">300dp</dimen>
<dimen name="all_apps_search_bar_field_height">48dp</dimen>
+ <!-- all_apps_search_bar_field_height / 2 -->
+ <dimen name="all_apps_search_bar_content_overlap">24dp</dimen>
<dimen name="all_apps_search_bar_bottom_padding">30dp</dimen>
<dimen name="all_apps_empty_search_message_top_offset">40dp</dimen>
<dimen name="all_apps_empty_search_bg_top_offset">144dp</dimen>
@@ -95,8 +123,11 @@
<dimen name="all_apps_header_pill_corner_radius">12dp</dimen>
<dimen name="all_apps_header_tab_height">48dp</dimen>
<dimen name="all_apps_tabs_indicator_height">2dp</dimen>
+ <dimen name="all_apps_header_top_margin">33dp</dimen>
<dimen name="all_apps_header_top_padding">36dp</dimen>
- <dimen name="all_apps_header_bottom_padding">6dp</dimen>
+ <dimen name="all_apps_header_bottom_padding">14dp</dimen>
+ <dimen name="all_apps_header_top_adjustment">6dp</dimen>
+ <dimen name="all_apps_header_bottom_adjustment">4dp</dimen>
<dimen name="all_apps_work_profile_tab_footer_top_padding">16dp</dimen>
<dimen name="all_apps_work_profile_tab_footer_bottom_padding">20dp</dimen>
<dimen name="all_apps_tabs_button_horizontal_padding">4dp</dimen>
@@ -106,33 +137,46 @@
<dimen name="all_apps_content_fade_in_offset">150dp</dimen>
<dimen name="all_apps_tip_bottom_margin">8dp</dimen>
<dimen name="all_apps_height_extra">6dp</dimen>
+ <dimen name="all_apps_bottom_sheet_horizontal_padding">0dp</dimen>
+ <dimen name="all_apps_paged_view_top_padding">40dp</dimen>
+ <dimen name="all_apps_personal_work_tabs_vertical_margin">16dp</dimen>
+ <dimen name="all_apps_icon_drawable_padding">8dp</dimen>
<!-- The size of corner radius of the arrow in the arrow toast. -->
<dimen name="arrow_toast_corner_radius">2dp</dimen>
<dimen name="arrow_toast_elevation">2dp</dimen>
<dimen name="arrow_toast_arrow_width">10dp</dimen>
-<!-- Search bar in All Apps -->
+ <!-- Search bar in All Apps -->
<dimen name="all_apps_header_max_elevation">3dp</dimen>
<dimen name="all_apps_header_scroll_to_elevation">16dp</dimen>
<dimen name="all_apps_header_shadow_height">6dp</dimen>
<dimen name="all_apps_divider_margin_vertical">8dp</dimen>
-<!-- Floating action button inside work tab to toggle work profile -->
+ <!-- Floating action button inside work tab to toggle work profile -->
<dimen name="work_fab_height">56dp</dimen>
- <dimen name="work_fab_radius">28dp</dimen>
- <dimen name="work_card_padding_horizontal">24dp</dimen>
+ <dimen name="work_fab_radius">16dp</dimen>
+ <dimen name="work_card_padding_horizontal">10dp</dimen>
<dimen name="work_card_button_height">52dp</dimen>
<dimen name="work_fab_margin">16dp</dimen>
+ <dimen name="work_fab_margin_bottom">20dp</dimen>
+ <dimen name="work_mode_fab_padding">16dp</dimen>
<dimen name="work_profile_footer_padding">20dp</dimen>
<dimen name="work_edu_card_margin">16dp</dimen>
- <dimen name="work_edu_card_radius">28dp</dimen>
+ <dimen name="work_edu_card_radius">16dp</dimen>
+ <dimen name="work_edu_card_bottom_margin">26dp</dimen>
+
+ <dimen name="work_card_margin">24dp</dimen>
+ <!-- (x) icon button inside work edu card -->
+ <dimen name="rounded_button_width">24dp</dimen>
+ <dimen name="x_icon_size">16dp</dimen>
+ <dimen name="x_icon_padding">4dp</dimen>
<!-- rounded button shown inside card views, and snack bars -->
<dimen name="padded_rounded_button_height">48dp</dimen>
- <dimen name="rounded_button_height">32dp</dimen>
- <dimen name="rounded_button_radius">16dp</dimen>
+ <dimen name="rounded_button_height">48dp</dimen>
+ <dimen name="rounded_button_radius">200dp</dimen>
<dimen name="rounded_button_padding">8dp</dimen>
@@ -181,19 +225,23 @@
<dimen name="shortcut_preview_padding_right">0dp</dimen>
<dimen name="shortcut_preview_padding_top">0dp</dimen>
-<!-- Pin widget dialog -->
+ <!-- Pin widget dialog -->
<dimen name="pin_widget_button_padding_horizontal">8dp</dimen>
<dimen name="pin_widget_button_padding_vertical">4dp</dimen>
<dimen name="pin_widget_button_inset_horizontal">4dp</dimen>
<dimen name="pin_widget_button_inset_vertical">6dp</dimen>
-<!-- Dragging -->
+ <!-- Dragging -->
<!-- Drag padding to add to the bottom of drop targets -->
<dimen name="drop_target_drag_padding">14dp</dimen>
<dimen name="drop_target_text_size">16sp</dimen>
<dimen name="drop_target_shadow_elevation">2dp</dimen>
<dimen name="drop_target_bar_margin_horizontal">4dp</dimen>
<dimen name="drop_target_button_drawable_padding">8dp</dimen>
+ <dimen name="drop_target_button_drawable_horizontal_padding">16dp</dimen>
+ <dimen name="drop_target_button_drawable_vertical_padding">8dp</dimen>
+ <dimen name="drop_target_button_gap">28dp</dimen>
+ <dimen name="drop_target_button_workspace_edge_gap">0dp</dimen>
<!-- the distance an icon must be dragged before button drop targets accept it -->
<dimen name="drag_distanceThreshold">30dp</dimen>
@@ -207,7 +255,7 @@
<dimen name="spring_loaded_panel_border">2dp</dimen>
<dimen name="keyboard_drag_stroke_width">4dp</dimen>
-<!-- Folders -->
+ <!-- Folders -->
<dimen name="page_indicator_dot_size">8dp</dimen>
<dimen name="folder_cell_x_padding">9dp</dimen>
@@ -219,22 +267,22 @@
<dimen name="folder_content_padding_left_right">8dp</dimen>
<dimen name="folder_content_padding_top">16dp</dimen>
-<!-- Sizes for managed profile badges -->
+ <!-- Sizes for managed profile badges -->
<dimen name="profile_badge_size">24dp</dimen>
<dimen name="profile_badge_margin">5dp</dimen>
<dimen name="profile_badge_minimum_top">2dp</dimen>
-<!-- Shadows and outlines -->
+ <!-- Shadows and outlines -->
<dimen name="blur_size_thin_outline">1dp</dimen>
<dimen name="blur_size_medium_outline">2dp</dimen>
<dimen name="blur_size_click_shadow">4dp</dimen>
<dimen name="click_shadow_high_shift">2dp</dimen>
-<!-- Pending widget -->
+ <!-- Pending widget -->
<dimen name="pending_widget_min_padding">8dp</dimen>
<dimen name="pending_widget_elevation">2dp</dimen>
-<!-- Deep shortcuts -->
+ <!-- Deep shortcuts -->
<dimen name="deep_shortcuts_elevation">2dp</dimen>
<dimen name="bg_popup_padding">2dp</dimen>
<dimen name="bg_popup_item_width">216dp</dimen>
@@ -258,17 +306,17 @@
<!-- popup_padding_start + deep_shortcut_icon_size / 2 -->
<dimen name="popup_arrow_horizontal_center_offset">26dp</dimen>
<dimen name="popup_arrow_corner_radius">2dp</dimen>
- <!-- popup_padding_start + icon_size + 10dp -->
+ <!-- popup_padding_start + deep_shortcut_icon_size + 10dp -->
<dimen name="deep_shortcuts_text_padding_start">52dp</dimen>
- <dimen name="system_shortcut_icon_size">24dp</dimen>
+ <dimen name="system_shortcut_icon_size">20dp</dimen>
<!-- popup_arrow_horizontal_center_offset - system_shortcut_icon_size / 2 -->
<dimen name="system_shortcut_margin_start">16dp</dimen>
<dimen name="system_shortcut_header_height">56dp</dimen>
<dimen name="system_shortcut_header_icon_touch_size">48dp</dimen>
- <!-- (touch_size - icon_size) / 2 -->
- <dimen name="system_shortcut_header_icon_padding">12dp</dimen>
+ <!-- (system_shortcut_header_icon_touch_size - system_shortcut_icon_size) / 2 -->
+ <dimen name="system_shortcut_header_icon_padding">14dp</dimen>
-<!-- Notifications -->
+ <!-- Notifications -->
<dimen name="bg_round_rect_radius">8dp</dimen>
<dimen name="notification_max_trans">8dp</dimen>
<dimen name="notification_space">8dp</dimen>
@@ -286,11 +334,11 @@
<dimen name="notification_main_text_padding_start">56dp</dimen>
<dimen name="horizontal_ellipsis_size">18dp</dimen>
-<!-- Overview -->
+ <!-- Overview -->
<dimen name="options_menu_icon_size">24dp</dimen>
<dimen name="options_menu_thumb_size">32dp</dimen>
-<!-- Snackbar -->
+ <!-- Snackbar -->
<dimen name="snackbar_height">48dp</dimen>
<dimen name="snackbar_content_height">32dp</dimen>
<dimen name="snackbar_padding">8dp</dimen>
@@ -302,18 +350,19 @@
<dimen name="snackbar_max_text_size">14sp</dimen>
<dimen name="snackbar_max_width">504dp</dimen>
-<!-- Developer Options -->
+ <!-- Developer Options -->
<dimen name="developer_options_filter_margins">10dp</dimen>
-<!-- Theming related -->
+ <!-- Theming related -->
<dimen name="default_dialog_corner_radius">8dp</dimen>
<dimen name="dialogCornerRadius">@dimen/default_dialog_corner_radius</dimen>
<!-- Onboarding bottomsheet related -->
<dimen name="bottom_sheet_edu_padding">24dp</dimen>
-<!-- Taskbar related (placeholders to compile in Launcher3 without Quickstep) -->
+ <!-- Taskbar related (placeholders to compile in Launcher3 without Quickstep) -->
<dimen name="taskbar_size">0dp</dimen>
+ <dimen name="taskbar_stashed_size">0dp</dimen>
<dimen name="qsb_widget_height">0dp</dimen>
<dimen name="taskbar_icon_size">44dp</dimen>
<!-- Note that this applies to both sides of all icons, so visible space is double this. -->
@@ -322,41 +371,42 @@
<!-- Size of the maximum radius for the enforced rounded rectangles. -->
<dimen name="enforced_rounded_corner_max_radius">16dp</dimen>
-<!-- Base Swipe Detector, speed in dp/s -->
+ <!-- Base Swipe Detector, speed in dp/s -->
<dimen name="base_swift_detector_fling_release_velocity">1dp</dimen>
-<!-- Overview placeholder to compile in Launcher3 without Quickstep -->
+ <!-- Overview placeholder to compile in Launcher3 without Quickstep -->
<dimen name="task_thumbnail_icon_size">0dp</dimen>
<dimen name="task_thumbnail_icon_drawable_size">0dp</dimen>
<dimen name="task_thumbnail_icon_drawable_size_grid">0dp</dimen>
<dimen name="overview_task_margin">0dp</dimen>
- <dimen name="overview_task_margin_focused">0dp</dimen>
<dimen name="overview_task_margin_grid">0dp</dimen>
+ <dimen name="overview_actions_height">0dp</dimen>
<dimen name="overview_actions_button_spacing">0dp</dimen>
- <dimen name="overview_actions_button_spacing_grid">0dp</dimen>
<dimen name="overview_actions_margin_gesture">0dp</dimen>
- <dimen name="overview_actions_top_margin_gesture_grid_portrait">0dp</dimen>
- <dimen name="overview_actions_bottom_margin_gesture_grid_portrait">0dp</dimen>
- <dimen name="overview_actions_top_margin_gesture_grid_landscape">0dp</dimen>
- <dimen name="overview_actions_bottom_margin_gesture_grid_landscape">0dp</dimen>
- <dimen name="overview_actions_margin_three_button">0dp</dimen>
- <dimen name="overview_grid_side_margin_portrait">0dp</dimen>
- <dimen name="overview_grid_side_margin_landscape">0dp</dimen>
+ <dimen name="overview_actions_top_margin">0dp</dimen>
+ <dimen name="overview_grid_side_margin">0dp</dimen>
<dimen name="overview_grid_row_spacing">0dp</dimen>
<dimen name="overview_page_spacing">0dp</dimen>
- <dimen name="overview_page_spacing_grid_portrait">0dp</dimen>
- <dimen name="overview_page_spacing_grid_landscape">0dp</dimen>
- <dimen name="split_placeholder_size">110dp</dimen>
- <dimen name="task_menu_width_grid">200dp</dimen>
+ <dimen name="split_placeholder_size">72dp</dimen>
+ <dimen name="split_placeholder_inset">16dp</dimen>
+ <dimen name="split_placeholder_icon_size">44dp</dimen>
+ <dimen name="task_menu_width_grid">216dp</dimen>
-<!-- Workspace grid visualization parameters -->
- <dimen name="grid_visualization_rounding_radius">22dp</dimen>
- <dimen name="grid_visualization_cell_spacing">6dp</dimen>
+ <!-- Workspace grid visualization parameters -->
+ <dimen name="grid_visualization_rounding_radius">28dp</dimen>
+ <dimen name="grid_visualization_horizontal_cell_spacing">6dp</dimen>
+ <dimen name="grid_visualization_vertical_cell_spacing">6dp</dimen>
-<!-- Search results related parameters -->
+ <!-- Search results related parameters -->
<dimen name="search_row_icon_size">48dp</dimen>
<dimen name="search_row_small_icon_size">32dp</dimen>
<dimen name="padded_rounded_button_padding">8dp</dimen>
+ <!-- Bottom sheet related parameters -->
+ <dimen name="bottom_sheet_extra_top_padding">0dp</dimen>
+ <dimen name="bottom_sheet_handle_width">32dp</dimen>
+ <dimen name="bottom_sheet_handle_height">4dp</dimen>
+ <dimen name="bottom_sheet_handle_margin">16dp</dimen>
+ <dimen name="bottom_sheet_handle_corner_radius">2dp</dimen>
</resources>
diff --git a/res/values/id.xml b/res/values/id.xml
index 508caff..af21b27 100644
--- a/res/values/id.xml
+++ b/res/values/id.xml
@@ -34,4 +34,8 @@
<item type="id" name="accessibility_button" />
<item type="id" name="rotate_suggestion" />
<!-- /Do not change, must be kept in sync with sysui navbar button IDs for tests! -->
+
+ <item type="id" name="quick_settings_button" />
+ <item type="id" name="notifications_button" />
+ <item type="id" name="cache_entry_tag_id" />
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 868b5f3..847e4a8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -60,9 +60,9 @@
<string name="widget_preview_context_description"><xliff:g id="widget_name" example="Calendar month view">%1$s</xliff:g> widget</string>
<!-- Message to tell the user to press and hold a widget/icon to add it to the home screen.
[CHAR LIMIT=NONE] -->
- <string name="add_item_request_drag_hint">Touch & hold the widget to move it around the Home screen</string>
+ <string name="add_item_request_drag_hint">Touch & hold the widget to move it around the home screen</string>
<!-- Button label to automatically add a widget to home screen [CHAR_LIMIT=50] -->
- <string name="add_to_home_screen">Add to Home screen</string>
+ <string name="add_to_home_screen">Add to home screen</string>
<!-- Accessibility spoken message announced when a widget gets added to the home screen using a
button in a dialog. [CHAR_LIMIT=none] -->
<string name="added_to_home_screen_accessibility_text"><xliff:g id="widget_name" example="Calendar month view">%1$s</xliff:g> widget added to home screen</string>
@@ -108,7 +108,7 @@
<string name="widget_education_header">Useful info at your fingertips</string>
<!-- Dialog text. This dialog lets a user know how they can use widgets on their phone.
[CHAR_LIMIT=NONE] -->
- <string name="widget_education_content">To get info without opening apps, you can add widgets to your Home screen</string>
+ <string name="widget_education_content">To get info without opening apps, you can add widgets to your home screen</string>
<!-- Text on an educational tip on widget informing users that they can change widget settings.
[CHAR_LIMIT=NONE] -->
@@ -147,7 +147,7 @@
<skip />
<!-- Error message when a user can't add more apps, widgets, or shortcuts to a Home screen. -->
- <string name="out_of_space">No room on this Home screen</string>
+ <string name="out_of_space">No room on this home screen</string>
<!-- Error message when user has filled the hotseat -->
<string name="hotseat_out_of_space">No more room in the Favorites tray</string>
@@ -181,15 +181,15 @@
<string name="permdesc_install_shortcut">Allows an app to add
shortcuts without user intervention.</string>
<!-- Permission short label -->
- <string name="permlab_read_settings">read Home settings and shortcuts</string>
+ <string name="permlab_read_settings">read home settings and shortcuts</string>
<!-- Permission description -->
<string name="permdesc_read_settings">Allows the app to read the settings and
- shortcuts in Home.</string>
+ shortcuts in home.</string>
<!-- Permission short label -->
- <string name="permlab_write_settings">write Home settings and shortcuts</string>
+ <string name="permlab_write_settings">write home settings and shortcuts</string>
<!-- Permission description -->
<string name="permdesc_write_settings">Allows the app to change the settings and
- shortcuts in Home.</string>
+ shortcuts in home.</string>
<!-- Toast shown on clicking a direct call shortcut. [CHAR_LIMIT=80] -->
<string name="msg_no_phone_permission"><xliff:g id="app_name" example="Launcher3">%1$s</xliff:g> is not allowed to make phone calls</string>
@@ -217,7 +217,7 @@
<string name="disabled_app_label">Disabled <xliff:g id="app_name" example="Messenger">%1$s</xliff:g></string>
<!-- The format string for when an app has a notification dot (meaning it has associated notifications). [ICU_FORMAT]-->
<string name="dotted_app_label">
- {count, plural, offset:1
+ {count, plural,
=1 {{app_name} has # notification}
other {{app_name} has # notifications}
}
@@ -259,7 +259,7 @@
<!-- Strings for settings -->
<!-- Title for Allow Rotation setting. [CHAR LIMIT=50] -->
- <string name="allow_rotation_title">Allow Home screen rotation</string>
+ <string name="allow_rotation_title">Allow home screen rotation</string>
<!-- Text explaining when the home screen will get rotated. [CHAR LIMIT=100] -->
<string name="allow_rotation_desc">When phone is rotated</string>
<!-- Title for Notification dots setting. Tapping this will link to the system Notifications settings screen where the user can turn off notification dots globally. [CHAR LIMIT=50] -->
@@ -277,8 +277,11 @@
<!-- Summary for Notification dots setting. Tapping this will link enable/disable notification dots feature on the home screen. [CHAR LIMIT=50] -->
<string name="notification_dots_service_title">Show notification dots</string>
+ <!-- Title for Developer Options setting. [CHAR LIMIT=50] -->
+ <string name="developer_options_title">Developer Options</string>
+
<!-- Label for the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=60] -->
- <string name="auto_add_shortcuts_label">Add app icons to Home screen</string>
+ <string name="auto_add_shortcuts_label">Add app icons to home screen</string>
<!-- Text description of the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=NONE] -->
<string name="auto_add_shortcuts_description">For new apps</string>
@@ -303,6 +306,17 @@
<!-- Title for an app whose download has been started. -->
<string name="app_waiting_download_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> waiting to install</string>
+
+ <!-- Title shown on the alert dialog prompting the user to update the application in market
+ in order to re-enable the disabled shortcuts -->
+ <string name="dialog_update_title">App update required</string>
+ <!-- Message shown on the alert dialog prompting the user to update the application -->
+ <string name="dialog_update_message">The app for this icon isn\'t updated. You can update manually to re-enable this shortcut, or remove the icon.</string>
+ <!-- Message for the update button in the alert dialog, will bring the user to market -->
+ <string name="dialog_update">Update</string>
+ <!-- Message for the remove button in the alert dialog -->
+ <string name="dialog_remove">Remove</string>
+
<!-- Strings for widgets & more in the popup container/bottom sheet -->
<!-- Accessibility title for the popup containing a list of widgets. [CHAR_LIMIT=50] -->
@@ -312,7 +326,7 @@
<!-- Strings for accessibility actions -->
<!-- Accessibility action to add an app to workspace. [CHAR_LIMIT=30] -->
- <string name="action_add_to_workspace">Add to Home screen</string>
+ <string name="action_add_to_workspace">Add to home screen</string>
<!-- Accessibility action to move item to the current location. [CHAR_LIMIT=30] -->
<string name="action_move_here">Move item here</string>
@@ -357,7 +371,7 @@
<string name="folder_created">Folder created</string>
<!-- Accessibility action to move an item from folder to workspace. [CHAR_LIMIT=30] -->
- <string name="action_move_to_workspace">Move to Home screen</string>
+ <string name="action_move_to_workspace">Move to home screen</string>
<!-- Accessibility action to resize a widget. [CHAR_LIMIT=30] -->
<string name="action_resize">Resize</string>
@@ -417,13 +431,17 @@
<string name="work_apps_paused_edu_accept">Got it</string>
<!-- button string shown pause work profile -->
- <string name="work_apps_pause_btn_text">Turn off work apps</string>
+ <string name="work_apps_pause_btn_text">Pause work apps</string>
<!-- button string shown enable work profile -->
<string name="work_apps_enable_btn_text">Turn on work apps</string>
<!-- A hint shown in launcher settings develop options filter box -->
<string name="developer_options_filter_hint">Filter</string>
+ <!-- Title for preference screen show in Home Settings related to smart search preferences. [CHAR LIMIT=50]-->
+ <string name="search_pref_screen_title">Search your phone</string>
+ <!-- Title for preference screen show in Home Settings related to smart search preferences. [CHAR LIMIT=50]-->
+ <string name="search_pref_screen_title_tablet">Search your tablet</string>
<!-- Failed action error message: e.g. Failed: Pause -->
<string name="remote_action_failed">Failed: <xliff:g id="what" example="Pause">%1$s</xliff:g></string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 818a032..2109510 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -76,7 +76,7 @@
</style>
<style name="LauncherTheme.DarkMainColor" parent="@style/LauncherTheme">
- <item name="disabledIconAlpha">.254</item>
+ <item name="disabledIconAlpha">.54</item>
</style>
@@ -203,6 +203,14 @@
<item name="android:importantForAccessibility">no</item>
</style>
+ <style name="AllAppsButtonTheme">
+ <item name="allAppsButtonBgColor">@color/all_apps_button_bg_color</item>
+ <item name="allAppsButtonColor1">@color/all_apps_button_color_1</item>
+ <item name="allAppsButtonColor2">@color/all_apps_button_color_2</item>
+ <item name="allAppsButtonColor3">@color/all_apps_button_color_3</item>
+ <item name="allAppsButtonColor4">@color/all_apps_button_color_4</item>
+ </style>
+
<style name="AllAppsTheme">
<item name="disabledIconAlpha">.54</item>
</style>
diff --git a/res/xml/backupscheme.xml b/res/xml/backupscheme.xml
index 299e92e..0f0dde2 100644
--- a/res/xml/backupscheme.xml
+++ b/res/xml/backupscheme.xml
@@ -2,6 +2,11 @@
<full-backup-content xmlns:android="http://schemas.android.com/apk/res/android">
<include domain="database" path="launcher.db" />
+ <include domain="database" path="launcher_6_by_5.db" />
+ <include domain="database" path="launcher_4_by_5.db" />
+ <include domain="database" path="launcher_4_by_4.db" />
+ <include domain="database" path="launcher_3_by_3.db" />
+ <include domain="database" path="launcher_2_by_2.db" />
<include domain="sharedpref" path="com.android.launcher3.prefs.xml" />
<include domain="file" path="downgrade_schema.json" />
diff --git a/res/xml/default_test_workspace.xml b/res/xml/default_test_workspace.xml
new file mode 100644
index 0000000..bd718b3
--- /dev/null
+++ b/res/xml/default_test_workspace.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+
+<!-- Split display specific version of Launcher3/res/xml/default_workspace_4x4.xml -->
+<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" >
+
+ <!-- Launcher Test Activity -->
+ <resolve
+ launcher:container="-101"
+ launcher:screen="0"
+ launcher:x="0"
+ launcher:y="0" >
+ <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.CATEGORY_TEST;component=com.google.android.apps.nexuslauncher.tests/com.android.launcher3.testcomponent.BaseTestingActivity;end" />
+ </resolve>
+
+</favorites>
diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml
index 08698e7..0802552 100644
--- a/res/xml/device_profiles.xml
+++ b/res/xml/device_profiles.xml
@@ -34,6 +34,8 @@
launcher:minHeightDps="300"
launcher:iconImageSize="48"
launcher:iconTextSize="13.0"
+ launcher:allAppsBorderSpace="16"
+ launcher:allAppsCellHeight="104"
launcher:canBeDefault="true" />
<display-option
@@ -42,6 +44,8 @@
launcher:minHeightDps="400"
launcher:iconImageSize="48"
launcher:iconTextSize="13.0"
+ launcher:allAppsBorderSpace="16"
+ launcher:allAppsCellHeight="104"
launcher:canBeDefault="true" />
</grid-option>
@@ -63,6 +67,8 @@
launcher:minHeightDps="420"
launcher:iconImageSize="48"
launcher:iconTextSize="13.0"
+ launcher:allAppsBorderSpace="16"
+ launcher:allAppsCellHeight="104"
launcher:canBeDefault="true" />
<display-option
@@ -71,6 +77,8 @@
launcher:minHeightDps="450"
launcher:iconImageSize="48"
launcher:iconTextSize="13.0"
+ launcher:allAppsBorderSpace="16"
+ launcher:allAppsCellHeight="104"
launcher:canBeDefault="true" />
<display-option
@@ -79,6 +87,8 @@
launcher:minHeightDps="491.33"
launcher:iconImageSize="48"
launcher:iconTextSize="13.0"
+ launcher:allAppsBorderSpace="16"
+ launcher:allAppsCellHeight="104"
launcher:canBeDefault="true" />
<display-option
@@ -87,6 +97,8 @@
launcher:minHeightDps="567"
launcher:iconImageSize="54"
launcher:iconTextSize="13.0"
+ launcher:allAppsBorderSpace="16"
+ launcher:allAppsCellHeight="104"
launcher:canBeDefault="true" />
<display-option
@@ -95,6 +107,8 @@
launcher:minHeightDps="567"
launcher:iconImageSize="54"
launcher:iconTextSize="13.0"
+ launcher:allAppsBorderSpace="16"
+ launcher:allAppsCellHeight="104"
launcher:canBeDefault="true" />
</grid-option>
@@ -116,6 +130,8 @@
launcher:minHeightDps="694"
launcher:iconImageSize="56"
launcher:iconTextSize="14.4"
+ launcher:allAppsBorderSpace="16"
+ launcher:allAppsCellHeight="104"
launcher:canBeDefault="true" />
<display-option
@@ -124,6 +140,8 @@
launcher:minHeightDps="694"
launcher:iconImageSize="56"
launcher:iconTextSize="14.4"
+ launcher:allAppsBorderSpace="16"
+ launcher:allAppsCellHeight="104"
launcher:canBeDefault="true" />
<display-option
@@ -132,6 +150,8 @@
launcher:minHeightDps="400"
launcher:iconImageSize="48"
launcher:iconTextSize="13.0"
+ launcher:allAppsBorderSpace="16"
+ launcher:allAppsCellHeight="104"
launcher:canBeDefault="true" />
</grid-option>
@@ -140,10 +160,14 @@
launcher:name="6_by_5"
launcher:numRows="5"
launcher:numColumns="6"
+ launcher:numSearchContainerColumns="3"
launcher:numFolderRows="3"
launcher:numFolderColumns="3"
launcher:numHotseatIcons="6"
+ launcher:hotseatColumnSpanLandscape="4"
launcher:numAllAppsColumns="6"
+ launcher:isScalable="true"
+ launcher:devicePaddingId="@xml/paddings_6x5"
launcher:dbFile="launcher_6_by_5.db"
launcher:defaultLayoutId="@xml/default_workspace_6x5"
launcher:deviceCategory="tablet" >
@@ -152,14 +176,29 @@
launcher:name="Tablet"
launcher:minWidthDps="900"
launcher:minHeightDps="820"
- launcher:minCellHeightDps="104"
- launcher:minCellWidthDps="80"
+ launcher:minCellHeight="120"
+ launcher:minCellWidth="102"
+ launcher:minCellHeightLandscape="104"
+ launcher:minCellWidthLandscape="120"
launcher:iconImageSize="60"
launcher:iconTextSize="14"
- launcher:borderSpaceDps="16"
+ launcher:borderSpaceHorizontal="16"
+ launcher:borderSpaceVertical="64"
+ launcher:borderSpaceLandscapeHorizontal="64"
+ launcher:borderSpaceLandscapeVertical="16"
+ launcher:horizontalMargin="54"
+ launcher:horizontalMarginLandscape="120"
+ launcher:allAppsCellWidth="96"
+ launcher:allAppsCellHeight="142"
+ launcher:allAppsCellWidthLandscape="126"
+ launcher:allAppsCellHeightLandscape="126"
launcher:allAppsIconSize="60"
launcher:allAppsIconTextSize="14"
- launcher:allAppsCellSpacingDps="16"
+ launcher:allAppsBorderSpaceHorizontal="8"
+ launcher:allAppsBorderSpaceVertical="16"
+ launcher:allAppsBorderSpaceLandscape="16"
+ launcher:hotseatBorderSpace="58"
+ launcher:hotseatBorderSpaceLandscape="50.4"
launcher:canBeDefault="true" />
</grid-option>
diff --git a/res/xml/grayscale_icon_map.xml b/res/xml/grayscale_icon_map.xml
new file mode 100644
index 0000000..f6383ce
--- /dev/null
+++ b/res/xml/grayscale_icon_map.xml
@@ -0,0 +1,17 @@
+<?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.
+-->
+<icons></icons>
diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml
index 90de498..8a0c909 100644
--- a/res/xml/launcher_preferences.xml
+++ b/res/xml/launcher_preferences.xml
@@ -53,7 +53,7 @@
<androidx.preference.PreferenceScreen
android:key="pref_developer_options"
android:persistent="false"
- android:title="Developer Options"
+ android:title="@string/developer_options_title"
android:fragment="com.android.launcher3.settings.DeveloperOptionsFragment"/>
</androidx.preference.PreferenceScreen>
diff --git a/res/xml/paddings_6x5.xml b/res/xml/paddings_6x5.xml
new file mode 100644
index 0000000..a72f554
--- /dev/null
+++ b/res/xml/paddings_6x5.xml
@@ -0,0 +1,76 @@
+<?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.
+ -->
+
+<device-paddings xmlns:launcher="http://schemas.android.com/apk/res-auto" >
+
+ <!-- Some non default screen sizes -->
+ <device-padding
+ launcher:maxEmptySpace="30dp">
+ <workspaceTopPadding
+ launcher:a="0.34"
+ launcher:b="0"/>
+ <workspaceBottomPadding
+ launcher:a="0.26"
+ launcher:b="0"/>
+ <hotseatBottomPadding
+ launcher:a="0.4"
+ launcher:b="0"/>
+ </device-padding>
+
+ <device-padding
+ launcher:maxEmptySpace="170dp">
+ <workspaceTopPadding
+ launcher:a="0"
+ launcher:b="20dp"/>
+ <workspaceBottomPadding
+ launcher:a="0.4"
+ launcher:b="0"
+ launcher:c="20dp"/>
+ <hotseatBottomPadding
+ launcher:a="0.6"
+ launcher:b="0"
+ launcher:c="20dp"/>
+ </device-padding>
+
+ <device-padding
+ launcher:maxEmptySpace="410dp">
+ <workspaceTopPadding
+ launcher:a="0"
+ launcher:b="112dp"/>
+ <workspaceBottomPadding
+ launcher:a="0.4"
+ launcher:b="0"
+ launcher:c="112dp"/>
+ <hotseatBottomPadding
+ launcher:a="0.6"
+ launcher:b="0"
+ launcher:c="112dp"/>
+ </device-padding>
+
+ <device-padding
+ launcher:maxEmptySpace="9999dp">
+ <workspaceTopPadding
+ launcher:a="0.40"
+ launcher:c="36dp"/>
+ <workspaceBottomPadding
+ launcher:a="0.60"
+ launcher:c="36dp"/>
+ <hotseatBottomPadding
+ launcher:a="0"
+ launcher:b="36dp"/>
+ </device-padding>
+</device-paddings>
\ No newline at end of file
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index e3cfb59..21dbc5f 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -65,7 +65,9 @@
TYPE_ICON_SURFACE,
TYPE_PIN_WIDGET_FROM_EXTERNAL_POPUP,
TYPE_WIDGETS_EDUCATION_DIALOG,
- TYPE_TASKBAR_EDUCATION_DIALOG
+ TYPE_TASKBAR_EDUCATION_DIALOG,
+ TYPE_TASKBAR_ALL_APPS,
+ TYPE_OPTIONS_POPUP_DIALOG
})
@Retention(RetentionPolicy.SOURCE)
public @interface FloatingViewType {}
@@ -85,23 +87,27 @@
public static final int TYPE_TASK_MENU = 1 << 11;
public static final int TYPE_OPTIONS_POPUP = 1 << 12;
public static final int TYPE_ICON_SURFACE = 1 << 13;
+ public static final int TYPE_OPTIONS_POPUP_DIALOG = 1 << 18;
public static final int TYPE_PIN_WIDGET_FROM_EXTERNAL_POPUP = 1 << 14;
public static final int TYPE_WIDGETS_EDUCATION_DIALOG = 1 << 15;
public static final int TYPE_TASKBAR_EDUCATION_DIALOG = 1 << 16;
+ public static final int TYPE_TASKBAR_ALL_APPS = 1 << 17;
+ public static final int TYPE_ADD_TO_HOME_CONFIRMATION = 1 << 18;
public static final int TYPE_ALL = TYPE_FOLDER | TYPE_ACTION_POPUP
| TYPE_WIDGETS_BOTTOM_SHEET | TYPE_WIDGET_RESIZE_FRAME | TYPE_WIDGETS_FULL_SHEET
| TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE | TYPE_TASK_MENU
| TYPE_OPTIONS_POPUP | TYPE_SNACKBAR | TYPE_LISTENER | TYPE_ALL_APPS_EDU
| TYPE_ICON_SURFACE | TYPE_DRAG_DROP_POPUP | TYPE_PIN_WIDGET_FROM_EXTERNAL_POPUP
- | TYPE_WIDGETS_EDUCATION_DIALOG | TYPE_TASKBAR_EDUCATION_DIALOG;
+ | TYPE_WIDGETS_EDUCATION_DIALOG | TYPE_TASKBAR_EDUCATION_DIALOG | TYPE_TASKBAR_ALL_APPS
+ | TYPE_OPTIONS_POPUP_DIALOG | TYPE_ADD_TO_HOME_CONFIRMATION;
// Type of popups which should be kept open during launcher rebind
public static final int TYPE_REBIND_SAFE = TYPE_WIDGETS_FULL_SHEET
| TYPE_WIDGETS_BOTTOM_SHEET | TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE
| TYPE_ALL_APPS_EDU | TYPE_ICON_SURFACE | TYPE_WIDGETS_EDUCATION_DIALOG
- | TYPE_TASKBAR_EDUCATION_DIALOG;
+ | TYPE_TASKBAR_EDUCATION_DIALOG | TYPE_TASKBAR_ALL_APPS | TYPE_OPTIONS_POPUP_DIALOG;
// Usually we show the back button when a floating view is open. Instead, hide for these types.
public static final int TYPE_HIDE_BACK_BUTTON = TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE
@@ -203,6 +209,13 @@
}
/**
+ * Returns whether there is at least one view of the given type where {@link #isOpen()} == true.
+ */
+ public static boolean hasOpenView(ActivityContext activity, @FloatingViewType int type) {
+ return getOpenView(activity, type) != null;
+ }
+
+ /**
* Returns a view matching FloatingViewType, and {@link #isOpen()} may be false (if animating
* closed).
*/
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index 300f22b..4b4a017 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -383,7 +383,7 @@
// Handle invalid resize across CellLayouts in the two panel UI.
if (mCellLayout.getParent() instanceof Workspace) {
- Workspace workspace = (Workspace) mCellLayout.getParent();
+ Workspace<?> workspace = (Workspace<?>) mCellLayout.getParent();
CellLayout pairedCellLayout = workspace.getScreenPair(mCellLayout);
if (pairedCellLayout != null) {
Rect focusedCellLayoutBound = sTmpRect;
@@ -570,7 +570,7 @@
final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
final CellLayout pairedCellLayout;
if (mCellLayout.getParent() instanceof Workspace) {
- Workspace workspace = (Workspace) mCellLayout.getParent();
+ Workspace<?> workspace = (Workspace<?>) mCellLayout.getParent();
pairedCellLayout = workspace.getScreenPair(mCellLayout);
} else {
pairedCellLayout = null;
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index 5b655a4..64666b0 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -27,9 +27,7 @@
import android.database.sqlite.SQLiteDatabase;
import android.graphics.drawable.Drawable;
import android.net.Uri;
-import android.os.Build.VERSION;
import android.os.Bundle;
-import android.os.Process;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.AttributeSet;
@@ -449,7 +447,7 @@
// Auto installs should always support the current platform version.
LauncherIcons li = LauncherIcons.obtain(mContext);
mValues.put(LauncherSettings.Favorites.ICON, GraphicsUtils.flattenBitmap(
- li.createBadgedIconBitmap(icon, Process.myUserHandle(), VERSION.SDK_INT).icon));
+ li.createBadgedIconBitmap(icon).icon));
li.recycle();
mValues.put(Favorites.ICON_PACKAGE, mIconRes.getResourcePackageName(iconId));
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index ec96c6d..73d3e33 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -16,7 +16,6 @@
package com.android.launcher3;
-import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS;
import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -25,30 +24,28 @@
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
-import android.content.pm.LauncherApps;
import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.util.Log;
import androidx.annotation.IntDef;
+import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.ViewCache;
-import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.AppLauncher;
import com.android.launcher3.views.ScrimView;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.util.ArrayList;
+import java.util.List;
/**
* Launcher BaseActivity
*/
-public abstract class BaseActivity extends Activity implements ActivityContext {
+public abstract class BaseActivity extends Activity implements AppLauncher,
+ DeviceProfileListenable {
private static final String TAG = "BaseActivity";
@@ -142,6 +139,11 @@
return mDeviceProfile;
}
+ @Override
+ public List<OnDeviceProfileChangeListener> getOnDeviceProfileChangeListeners() {
+ return mDPChangeListeners;
+ }
+
/**
* Returns {@link StatsLogManager} for user event logging.
*/
@@ -261,20 +263,6 @@
protected void onActivityFlagsChanged(int changeBits) { }
- public void addOnDeviceProfileChangeListener(OnDeviceProfileChangeListener listener) {
- mDPChangeListeners.add(listener);
- }
-
- public void removeOnDeviceProfileChangeListener(OnDeviceProfileChangeListener listener) {
- mDPChangeListeners.remove(listener);
- }
-
- protected void dispatchDeviceProfileChanged() {
- for (int i = mDPChangeListeners.size() - 1; i >= 0; i--) {
- mDPChangeListeners.get(i).onDeviceProfileChanged(mDeviceProfile);
- }
- }
-
public void addMultiWindowModeChangedListener(MultiWindowModeChangedListener listener) {
mMultiWindowModeChangedListeners.add(listener);
}
@@ -320,22 +308,6 @@
writer.println(prefix + "mForceInvisible: " + mForceInvisible);
}
- /**
- * A wrapper around the platform method with Launcher specific checks
- */
- public void startShortcut(String packageName, String id, Rect sourceBounds,
- Bundle startActivityOptions, UserHandle user) {
- if (GO_DISABLE_WIDGETS) {
- return;
- }
- try {
- getSystemService(LauncherApps.class).startShortcut(packageName, id, sourceBounds,
- startActivityOptions, user);
- } catch (SecurityException | IllegalStateException e) {
- Log.e(TAG, "Failed to start shortcut", e);
- }
- }
-
public static <T extends BaseActivity> T fromContext(Context context) {
if (context instanceof BaseActivity) {
return (T) context;
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index dd56ca3..6de3884 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -16,53 +16,33 @@
package com.android.launcher3;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import android.app.ActivityOptions;
import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.app.WallpaperManager.OnColorsChangedListener;
-import android.content.ActivityNotFoundException;
import android.content.Context;
-import android.content.Intent;
-import android.content.pm.LauncherApps;
import android.content.res.Configuration;
-import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import android.os.Process;
-import android.os.StrictMode;
-import android.os.UserHandle;
-import android.util.Log;
import android.view.ActionMode;
import android.view.Display;
import android.view.View;
-import android.view.WindowInsets.Type;
-import android.view.WindowMetrics;
-import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.allapps.search.DefaultSearchAdapterProvider;
import com.android.launcher3.allapps.search.SearchAdapterProvider;
-import com.android.launcher3.logging.InstanceId;
-import com.android.launcher3.logging.InstanceIdSequence;
-import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.ActivityOptionsWrapper;
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.PackageManagerHelper;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.TraceHelper;
@@ -165,108 +145,12 @@
// no-op
}
+ @Override
@NonNull
public ActivityOptionsWrapper getActivityLaunchOptions(View v, @Nullable ItemInfo item) {
- int left = 0, top = 0;
- int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();
- if (v instanceof BubbleTextView) {
- // Launch from center of icon, not entire view
- Drawable icon = ((BubbleTextView) v).getIcon();
- if (icon != null) {
- Rect bounds = icon.getBounds();
- left = (width - bounds.width()) / 2;
- top = v.getPaddingTop();
- width = bounds.width();
- height = bounds.height();
- }
- }
- ActivityOptions options =
- ActivityOptions.makeClipRevealAnimation(v, left, top, width, height);
- RunnableList callback = new RunnableList();
- addOnResumeCallback(callback::executeAllAndDestroy);
- return new ActivityOptionsWrapper(options, callback);
- }
-
- public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item) {
- if (mIsSafeModeEnabled && !PackageManagerHelper.isSystemApp(this, intent)) {
- Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
- return false;
- }
-
- Bundle optsBundle = (v != null) ? getActivityLaunchOptions(v, item).toBundle() : null;
- UserHandle user = item == null ? null : item.user;
-
- // Prepare intent
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- if (v != null) {
- intent.setSourceBounds(Utilities.getViewBounds(v));
- }
- try {
- boolean isShortcut = (item instanceof WorkspaceItemInfo)
- && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
- || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
- && !((WorkspaceItemInfo) item).isPromise();
- if (isShortcut) {
- // Shortcuts need some special checks due to legacy reasons.
- startShortcutIntentSafely(intent, optsBundle, item);
- } else if (user == null || user.equals(Process.myUserHandle())) {
- // Could be launching some bookkeeping activity
- startActivity(intent, optsBundle);
- } else {
- getSystemService(LauncherApps.class).startMainActivity(
- intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
- }
- if (item != null) {
- InstanceId instanceId = new InstanceIdSequence().newInstanceId();
- logAppLaunch(getStatsLogManager(), item, instanceId);
- }
- return true;
- } catch (NullPointerException | ActivityNotFoundException | SecurityException e) {
- Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
- Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
- }
- return false;
- }
-
- /**
- * Creates and logs a new app launch event.
- */
- public void logAppLaunch(StatsLogManager statsLogManager, ItemInfo info,
- InstanceId instanceId) {
- statsLogManager.logger().withItemInfo(info).withInstanceId(instanceId)
- .log(LAUNCHER_APP_LAUNCH_TAP);
- }
-
- private 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
- startActivity(intent, optsBundle);
- }
- } finally {
- StrictMode.setVmPolicy(oldPolicy);
- }
- } catch (SecurityException e) {
- if (!onErrorStartingShortcut(intent, info)) {
- throw e;
- }
- }
- }
-
- protected boolean onErrorStartingShortcut(Intent intent, ItemInfo info) {
- return false;
+ ActivityOptionsWrapper wrapper = super.getActivityLaunchOptions(v, item);
+ addOnResumeCallback(wrapper.onEndCallback::executeAllAndDestroy);
+ return wrapper;
}
@Override
@@ -318,11 +202,7 @@
protected WindowBounds getMultiWindowDisplaySize() {
if (Utilities.ATLEAST_R) {
- WindowMetrics wm = getWindowManager().getCurrentWindowMetrics();
-
- Insets insets = wm.getWindowInsets().getInsets(Type.systemBars());
- return new WindowBounds(wm.getBounds(),
- new Rect(insets.left, insets.top, insets.right, insets.bottom));
+ return WindowBounds.fromWindowMetrics(getWindowManager().getCurrentWindowMetrics());
}
// Note: Calls to getSize() can't rely on our cached DefaultDisplay since it can return
// the app window size
@@ -336,7 +216,14 @@
* Creates and returns {@link SearchAdapterProvider} for build variant specific search result
* views
*/
- public SearchAdapterProvider createSearchAdapterProvider(AllAppsContainerView allapps) {
- return new DefaultSearchAdapterProvider(this, allapps);
+ @Override
+ public SearchAdapterProvider<?> createSearchAdapterProvider(
+ ActivityAllAppsContainerView<?> allApps) {
+ return new DefaultSearchAdapterProvider(this);
+ }
+
+ @Override
+ public boolean isAppBlockedForSafeMode() {
+ return mIsSafeModeEnabled;
}
}
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 163b442..5fb8925 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -18,6 +18,8 @@
import static com.android.launcher3.config.FeatureFlags.ENABLE_ICON_LABEL_AUTO_SCALING;
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;
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import android.animation.Animator;
@@ -49,11 +51,11 @@
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
-import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
+import com.android.launcher3.accessibility.BaseAccessibilityDelegate;
import com.android.launcher3.dot.DotInfo;
+import com.android.launcher3.dragndrop.DragOptions.PreDragCondition;
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.folder.FolderIcon;
-import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.graphics.IconShape;
import com.android.launcher3.graphics.PreloadIconDrawable;
import com.android.launcher3.icons.DotRenderer;
@@ -64,12 +66,11 @@
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
-import com.android.launcher3.model.data.PackageItemInfo;
-import com.android.launcher3.model.data.SearchActionItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.util.SafeCloseable;
+import com.android.launcher3.util.ShortcutUtil;
import com.android.launcher3.views.ActivityContext;
-import com.android.launcher3.views.BubbleTextHolder;
import com.android.launcher3.views.IconLabelDotView;
import java.text.NumberFormat;
@@ -95,7 +96,6 @@
private static final int MAX_SEARCH_LOOP_COUNT = 20;
private static final int[] STATE_PRESSED = new int[]{android.R.attr.state_pressed};
- private static final float HIGHLIGHT_SCALE = 1.16f;
private final PointF mTranslationForReorderBounce = new PointF(0, 0);
private final PointF mTranslationForReorderPreview = new PointF(0, 0);
@@ -146,10 +146,14 @@
private final int mIconSize;
@ViewDebug.ExportedProperty(category = "launcher")
+ private boolean mHideBadge = false;
+ @ViewDebug.ExportedProperty(category = "launcher")
private boolean mIsIconVisible = true;
@ViewDebug.ExportedProperty(category = "launcher")
private int mTextColor;
@ViewDebug.ExportedProperty(category = "launcher")
+ private ColorStateList mTextColorStateList;
+ @ViewDebug.ExportedProperty(category = "launcher")
private float mTextAlpha = 1;
@ViewDebug.ExportedProperty(category = "launcher")
@@ -170,7 +174,6 @@
private HandlerRunnable mIconLoadRequest;
private boolean mEnableIconUpdateAnimation = false;
- private BubbleTextHolder mBubbleTextHolder;
public BubbleTextView(Context context) {
this(context, null, 0);
@@ -240,16 +243,27 @@
super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
+ public void setHideBadge(boolean hideBadge) {
+ mHideBadge = hideBadge;
+ }
+
/**
* Resets the view so it can be recycled.
*/
public void reset() {
mDotInfo = null;
- mDotParams.color = Color.TRANSPARENT;
+ mDotParams.dotColor = Color.TRANSPARENT;
+ mDotParams.appColor = Color.TRANSPARENT;
cancelDotScaleAnim();
mDotParams.scale = 0f;
mForceHideDot = false;
setBackground(null);
+
+ setTag(null);
+ if (mIconLoadRequest != null) {
+ mIconLoadRequest.cancel();
+ mIconLoadRequest = null;
+ }
}
private void cancelDotScaleAnim() {
@@ -295,7 +309,7 @@
@Override
public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
- if (delegate instanceof LauncherAccessibilityDelegate) {
+ if (delegate instanceof BaseAccessibilityDelegate) {
super.setAccessibilityDelegate(delegate);
} else {
// NO-OP
@@ -347,25 +361,22 @@
setDownloadStateContentDescription(info, info.getProgressLevel());
}
- private void setItemInfo(ItemInfoWithIcon itemInfo) {
+ protected void setItemInfo(ItemInfoWithIcon itemInfo) {
setTag(itemInfo);
- if (mBubbleTextHolder != null) {
- mBubbleTextHolder.onItemInfoUpdated(itemInfo);
- }
- }
-
- public void setBubbleTextHolder(
- BubbleTextHolder bubbleTextHolder) {
- mBubbleTextHolder = bubbleTextHolder;
}
@UiThread
protected void applyIconAndLabel(ItemInfoWithIcon info) {
boolean useTheme = mDisplay == DISPLAY_WORKSPACE || mDisplay == DISPLAY_FOLDER
|| mDisplay == DISPLAY_TASKBAR;
- FastBitmapDrawable iconDrawable = info.newIcon(getContext(), useTheme);
- mDotParams.color = IconPalette.getMutedColor(iconDrawable.getIconColor(), 0.54f);
-
+ int flags = useTheme ? FLAG_THEMED : 0;
+ if (mHideBadge) {
+ flags |= FLAG_NO_BADGE;
+ }
+ FastBitmapDrawable iconDrawable = info.newIcon(getContext(), flags);
+ mDotParams.appColor = iconDrawable.getIconColor();
+ mDotParams.dotColor = getContext().getResources()
+ .getColor(android.R.color.system_accent3_200, getContext().getTheme());
setIcon(iconDrawable);
applyLabel(info);
}
@@ -631,12 +642,14 @@
@Override
public void setTextColor(int color) {
mTextColor = color;
+ mTextColorStateList = null;
super.setTextColor(getModifiedColor());
}
@Override
public void setTextColor(ColorStateList colors) {
mTextColor = colors.getDefaultColor();
+ mTextColorStateList = colors;
if (Float.compare(mTextAlpha, 1) == 0) {
super.setTextColor(colors);
} else {
@@ -658,7 +671,11 @@
private void setTextAlpha(float alpha) {
mTextAlpha = alpha;
- super.setTextColor(getModifiedColor());
+ if (mTextColorStateList != null) {
+ setTextColor(mTextColorStateList);
+ } else {
+ super.setTextColor(getModifiedColor());
+ }
}
private int getModifiedColor() {
@@ -847,6 +864,11 @@
}
protected void applyCompoundDrawables(Drawable icon) {
+ if (icon == null) {
+ // Icon can be null when we use the BubbleTextView for text only.
+ return;
+ }
+
// If we had already set an icon before, disable relayout as the icon size is the
// same as before.
mDisableRelayout = mIcon != null;
@@ -890,10 +912,8 @@
} else if (info instanceof WorkspaceItemInfo) {
applyFromWorkspaceItem((WorkspaceItemInfo) info);
mActivity.invalidateParent(info);
- } else if (info instanceof PackageItemInfo) {
- applyFromItemInfoWithIcon((PackageItemInfo) info);
- } else if (info instanceof SearchActionItemInfo) {
- applyFromItemInfoWithIcon((SearchActionItemInfo) info);
+ } else if (info != null) {
+ applyFromItemInfoWithIcon(info);
}
mDisableRelayout = false;
@@ -997,19 +1017,6 @@
getIconBounds(mIconSize, bounds);
}
- private int getIconSizeForDisplay(int display) {
- DeviceProfile grid = mActivity.getDeviceProfile();
- switch (display) {
- case DISPLAY_ALL_APPS:
- return grid.allAppsIconSizePx;
- case DISPLAY_FOLDER:
- return grid.folderChildIconSizePx;
- case DISPLAY_WORKSPACE:
- default:
- return grid.iconSizePx;
- }
- }
-
public void getSourceVisualDragBounds(Rect bounds) {
getIconBounds(mIconSize, bounds);
}
@@ -1022,8 +1029,8 @@
}
private void resetIconScale() {
- if (mIcon instanceof FastBitmapDrawable) {
- ((FastBitmapDrawable) mIcon).resetScale();
+ if (mIcon != null) {
+ mIcon.resetScale();
}
}
@@ -1044,4 +1051,19 @@
args.put("count", notificationCount);
return icuCountFormat.format(args);
}
+
+ /**
+ * Starts a long press action and returns the corresponding pre-drag condition
+ */
+ public PreDragCondition startLongPressAction() {
+ PopupContainerWithArrow popup = PopupContainerWithArrow.showForIcon(this);
+ return popup != null ? popup.createPreDragCondition(true) : null;
+ }
+
+ /**
+ * Returns true if the view can show long-press popup
+ */
+ public boolean canShowLongPressPopup() {
+ return getTag() instanceof ItemInfo && ShortcutUtil.supportsShortcuts((ItemInfo) getTag());
+ }
}
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 38d5077..3b24df2 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -24,6 +24,7 @@
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.text.InputType;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -49,6 +50,8 @@
private static final int[] sTempCords = new int[2];
private static final int DRAG_VIEW_DROP_DURATION = 285;
private static final float DRAG_VIEW_HOVER_OVER_OPACITY = 0.65f;
+ private static final int MAX_LINES_TEXT_MULTI_LINE = 2;
+ private static final int MAX_LINES_TEXT_SINGLE_LINE = 1;
public static final int TOOLTIP_DEFAULT = 0;
public static final int TOOLTIP_LEFT = 1;
@@ -72,6 +75,8 @@
protected CharSequence mText;
protected Drawable mDrawable;
private boolean mTextVisible = true;
+ private boolean mIconVisible = true;
+ private boolean mTextMultiLine = true;
private PopupWindow mToolTip;
private int mToolTipLocation;
@@ -109,8 +114,7 @@
// drawableLeft and drawableStart.
mDrawable = getContext().getDrawable(resId).mutate();
mDrawable.setTintList(getTextColors());
- centerIcon();
- setCompoundDrawablesRelative(mDrawable, null, null, null);
+ updateIconVisibility();
}
public void setDropTargetBar(DropTargetBar dropTargetBar) {
@@ -140,7 +144,7 @@
y = -getMeasuredHeight();
message.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
if (mToolTipLocation == TOOLTIP_LEFT) {
- x = - getMeasuredWidth() - message.getMeasuredWidth() / 2;
+ x = -getMeasuredWidth() - message.getMeasuredWidth() / 2;
} else {
x = getMeasuredWidth() / 2 + message.getMeasuredWidth() / 2;
}
@@ -175,7 +179,12 @@
@Override
public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
- mActive = !options.isKeyboardDrag && supportsDrop(dragObject.dragInfo);
+ if (options.isKeyboardDrag) {
+ mActive = false;
+ } else {
+ setupItemInfo(dragObject.dragInfo);
+ mActive = supportsDrop(dragObject.dragInfo);
+ }
setVisibility(mActive ? View.VISIBLE : View.GONE);
mAccessibleDrag = options.isAccessibleDrag;
@@ -187,6 +196,11 @@
return supportsDrop(dragObject.dragInfo);
}
+ /**
+ * Setups button for the specified ItemInfo.
+ */
+ protected abstract void setupItemInfo(ItemInfo info);
+
protected abstract boolean supportsDrop(ItemInfo info);
public abstract boolean supportsAccessibilityDrop(ItemInfo info, View view);
@@ -218,6 +232,7 @@
final Rect to = getIconRect(d);
final float scale = (float) to.width() / dragView.getMeasuredWidth();
dragView.detachContentView(/* reattachToPreviousParent= */ true);
+
mDropTargetBar.deferOnDragEnd();
Runnable onAnimationEndRunnable = () -> {
@@ -305,13 +320,49 @@
if (mTextVisible != isVisible || !TextUtils.equals(newText, getText())) {
mTextVisible = isVisible;
setText(newText);
- centerIcon();
- setCompoundDrawablesRelative(mDrawable, null, null, null);
- int drawablePadding = mTextVisible ? mDrawablePadding : 0;
- setCompoundDrawablePadding(drawablePadding);
+ updateIconVisibility();
}
}
+ /**
+ * Display button text over multiple lines when isMultiLine is true, single line otherwise.
+ */
+ public void setTextMultiLine(boolean isMultiLine) {
+ if (mTextMultiLine != isMultiLine) {
+ mTextMultiLine = isMultiLine;
+ setSingleLine(!isMultiLine);
+ setMaxLines(isMultiLine ? MAX_LINES_TEXT_MULTI_LINE : MAX_LINES_TEXT_SINGLE_LINE);
+ int inputType = InputType.TYPE_CLASS_TEXT;
+ if (isMultiLine) {
+ inputType |= InputType.TYPE_TEXT_FLAG_MULTI_LINE;
+
+ }
+ setInputType(inputType);
+ }
+ }
+
+ protected boolean isTextMultiLine() {
+ return mTextMultiLine;
+ }
+
+ /**
+ * Sets the button icon visible when isVisible is true, hides it otherwise.
+ */
+ public void setIconVisible(boolean isVisible) {
+ if (mIconVisible != isVisible) {
+ mIconVisible = isVisible;
+ updateIconVisibility();
+ }
+ }
+
+ private void updateIconVisibility() {
+ if (mIconVisible) {
+ centerIcon();
+ }
+ setCompoundDrawablesRelative(mIconVisible ? mDrawable : null, null, null, null);
+ setCompoundDrawablePadding(mIconVisible && mTextVisible ? mDrawablePadding : 0);
+ }
+
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index adb1613..300e7bf 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -65,6 +65,7 @@
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.folder.PreviewBackground;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.util.CellAndSpan;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.ParcelableSparseArray;
@@ -93,7 +94,7 @@
private int mFixedCellWidth;
private int mFixedCellHeight;
@ViewDebug.ExportedProperty(category = "launcher")
- private final Point mBorderSpace;
+ private Point mBorderSpace;
@ViewDebug.ExportedProperty(category = "launcher")
private int mCountX;
@@ -148,7 +149,6 @@
private boolean mVisualizeDropLocation = true;
private RectF mVisualizeGridRect = new RectF();
private Paint mVisualizeGridPaint = new Paint();
- private int mGridVisualizationPadding;
private int mGridVisualizationRoundingRadius;
private float mGridAlpha = 0f;
private int mGridColor = 0;
@@ -238,12 +238,7 @@
mActivity = ActivityContext.lookupContext(context);
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
- mBorderSpace = mContainerType == FOLDER
- ? new Point(deviceProfile.folderCellLayoutBorderSpacePx)
- : new Point(deviceProfile.cellLayoutBorderSpacePx);
-
- mCellWidth = mCellHeight = -1;
- mFixedCellWidth = mFixedCellHeight = -1;
+ resetCellSizeInternal(deviceProfile);
mCountX = deviceProfile.inv.numColumns;
mCountY = deviceProfile.inv.numRows;
@@ -265,8 +260,6 @@
mBackground.setAlpha(0);
mGridColor = Themes.getAttrColor(getContext(), R.attr.workspaceAccentColor);
- mGridVisualizationPadding =
- res.getDimensionPixelSize(R.dimen.grid_visualization_cell_spacing);
mGridVisualizationRoundingRadius =
res.getDimensionPixelSize(R.dimen.grid_visualization_rounding_radius);
mReorderPreviewAnimationMagnitude = (REORDER_PREVIEW_MAGNITUDE * deviceProfile.iconSizePx);
@@ -292,7 +285,7 @@
for (int i = 0; i < mDragOutlineAnims.length; i++) {
final InterruptibleInOutAnimator anim =
- new InterruptibleInOutAnimator(duration, fromAlphaValue, toAlphaValue);
+ new InterruptibleInOutAnimator(duration, fromAlphaValue, toAlphaValue);
anim.getAnimator().setInterpolator(mEaseOutInterpolator);
final int thisIndex = i;
anim.getAnimator().addUpdateListener(new AnimatorUpdateListener() {
@@ -366,6 +359,12 @@
return mShortcutsAndWidgets.getLayerType() == LAYER_TYPE_HARDWARE;
}
+ /**
+ * Change sizes of cells
+ *
+ * @param width the new width of the cells
+ * @param height the new height of the cells
+ */
public void setCellDimensions(int width, int height) {
mFixedCellWidth = mCellWidth = width;
mFixedCellHeight = mCellHeight = height;
@@ -373,6 +372,33 @@
mBorderSpace);
}
+ private void resetCellSizeInternal(DeviceProfile deviceProfile) {
+ switch (mContainerType) {
+ case FOLDER:
+ mBorderSpace = new Point(deviceProfile.folderCellLayoutBorderSpacePx);
+ break;
+ case HOTSEAT:
+ mBorderSpace = new Point(deviceProfile.hotseatBorderSpace,
+ deviceProfile.hotseatBorderSpace);
+ break;
+ case WORKSPACE:
+ default:
+ mBorderSpace = new Point(deviceProfile.cellLayoutBorderSpacePx);
+ break;
+ }
+
+ mCellWidth = mCellHeight = -1;
+ mFixedCellWidth = mFixedCellHeight = -1;
+ }
+
+ /**
+ * Reset the cell sizes and border space
+ */
+ public void resetCellSize(DeviceProfile deviceProfile) {
+ resetCellSizeInternal(deviceProfile);
+ requestLayout();
+ }
+
public void setGridSize(int x, int y) {
mCountX = x;
mCountY = y;
@@ -563,8 +589,8 @@
protected void visualizeGrid(Canvas canvas) {
DeviceProfile dp = mActivity.getDeviceProfile();
- int paddingX = (int) Math.min((mCellWidth - dp.iconSizePx) / 2, mGridVisualizationPadding);
- int paddingY = (int) Math.min((mCellHeight - dp.iconSizePx) / 2, mGridVisualizationPadding);
+ int paddingX = Math.min((mCellWidth - dp.iconSizePx) / 2, dp.gridVisualizationPaddingX);
+ int paddingY = Math.min((mCellHeight - dp.iconSizePx) / 2, dp.gridVisualizationPaddingY);
mVisualizeGridRect.set(paddingX, paddingY,
mCellWidth - paddingX,
mCellHeight - paddingY);
@@ -1159,9 +1185,7 @@
// Apply local extracted color if the DragView is an AppWidgetHostViewDrawable.
View view = dragObject.dragView.getContentView();
if (view instanceof LauncherAppWidgetHostView) {
- Launcher launcher = Launcher.getLauncher(getContext());
- Workspace workspace = launcher.getWorkspace();
- int screenId = workspace.getIdForScreen(this);
+ int screenId = getWorkspace().getIdForScreen(this);
cellToRect(targetCell[0], targetCell[1], spanX, spanY, mTempRect);
((LauncherAppWidgetHostView) view).handleDrag(mTempRect, this, screenId);
@@ -1174,11 +1198,24 @@
return getContext().getString(R.string.move_to_hotseat_position,
Math.max(cellX, cellY) + 1);
} else {
- return getContext().getString(R.string.move_to_empty_cell,
- cellY + 1, cellX + 1);
+ Workspace<?> workspace = getWorkspace();
+ int row = cellY + 1;
+ int col = workspace.mIsRtl ? mCountX - cellX : cellX + 1;
+ int panelCount = workspace.getPanelCount();
+ if (panelCount > 1) {
+ // Increment the column if the target is on the right side of a two panel home
+ int screenId = workspace.getIdForScreen(this);
+ int pageIndex = workspace.getPageIndexForScreenId(screenId);
+ col += (pageIndex % panelCount) * mCountX;
+ }
+ return getContext().getString(R.string.move_to_empty_cell, row, col);
}
}
+ private Workspace<?> getWorkspace() {
+ return Launcher.cast(mActivity).getWorkspace();
+ }
+
public void clearDragOutlines() {
final int oldIndex = mDragOutlineCurrent;
mDragOutlineAnims[oldIndex].animateOut();
@@ -2233,7 +2270,7 @@
private void commitTempPlacement(View dragView) {
mTmpOccupied.copyTo(mOccupied);
- int screenId = Launcher.cast(mActivity).getWorkspace().getIdForScreen(this);
+ int screenId = getWorkspace().getIdForScreen(this);
int container = Favorites.CONTAINER_DESKTOP;
if (mContainerType == HOTSEAT) {
@@ -2398,7 +2435,7 @@
// First we determine if things have moved enough to cause a different layout
ItemConfiguration swapSolution = findReorderSolution(pixelXY[0], pixelXY[1], spanX, spanY,
- spanX, spanY, direction, dragView, true, new ItemConfiguration());
+ spanX, spanY, direction, dragView, true, new ItemConfiguration());
setUseTempCoords(true);
if (swapSolution != null && swapSolution.isSolution) {
@@ -2435,7 +2472,7 @@
// direction vector, since we want the solution to match the preview, and it's possible
// that the exact position of the item has changed to result in a new reordering outcome.
if ((mode == MODE_ON_DROP || mode == MODE_ON_DROP_EXTERNAL || mode == MODE_ACCEPT_DROP)
- && mPreviousReorderDirection[0] != INVALID_DIRECTION) {
+ && mPreviousReorderDirection[0] != INVALID_DIRECTION) {
mDirectionVector[0] = mPreviousReorderDirection[0];
mDirectionVector[1] = mPreviousReorderDirection[1];
// We reset this vector after drop
@@ -2451,7 +2488,7 @@
// Find a solution involving pushing / displacing any items in the way
ItemConfiguration swapSolution = findReorderSolution(pixelX, pixelY, minSpanX, minSpanY,
- spanX, spanY, mDirectionVector, dragView, true, new ItemConfiguration());
+ spanX, spanY, mDirectionVector, dragView, true, new ItemConfiguration());
// We attempt the approach which doesn't shuffle views at all
ItemConfiguration noShuffleSolution = findConfigurationNoShuffle(pixelX, pixelY, minSpanX,
@@ -2691,12 +2728,24 @@
}
public void markCellsAsOccupiedForView(View view) {
+ if (view instanceof LauncherAppWidgetHostView
+ && view.getTag() instanceof LauncherAppWidgetInfo) {
+ LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) view.getTag();
+ mOccupied.markCells(info.cellX, info.cellY, info.spanX, info.spanY, true);
+ return;
+ }
if (view == null || view.getParent() != mShortcutsAndWidgets) return;
LayoutParams lp = (LayoutParams) view.getLayoutParams();
mOccupied.markCells(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, true);
}
public void markCellsAsUnoccupiedForView(View view) {
+ if (view instanceof LauncherAppWidgetHostView
+ && view.getTag() instanceof LauncherAppWidgetInfo) {
+ LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) view.getTag();
+ mOccupied.markCells(info.cellX, info.cellY, info.spanX, info.spanY, false);
+ return;
+ }
if (view == null || view.getParent() != mShortcutsAndWidgets) return;
LayoutParams lp = (LayoutParams) view.getLayoutParams();
mOccupied.markCells(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, false);
diff --git a/src/com/android/launcher3/DefaultLayoutParser.java b/src/com/android/launcher3/DefaultLayoutParser.java
index af85594..4daca8b 100644
--- a/src/com/android/launcher3/DefaultLayoutParser.java
+++ b/src/com/android/launcher3/DefaultLayoutParser.java
@@ -7,15 +7,19 @@
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.os.Bundle;
+import android.os.Process;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.Thunk;
import org.xmlpull.v1.XmlPullParser;
@@ -23,6 +27,7 @@
import java.io.IOException;
import java.net.URISyntaxException;
+import java.util.Collections;
import java.util.List;
/**
@@ -43,6 +48,8 @@
private static final String ATTR_CONTAINER = "container";
private static final String ATTR_SCREEN = "screen";
private static final String ATTR_FOLDER_ITEMS = "folderItems";
+ private static final String ATTR_SHORTCUT_ID = "shortcutId";
+ private static final String ATTR_PACKAGE_NAME = "packageName";
// TODO: Remove support for this broadcast, instead use widget options to send bind time options
private static final String ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE =
@@ -178,7 +185,6 @@
}
}
-
/**
* Shortcut parser which allows any uri and not just web urls.
*/
@@ -189,6 +195,35 @@
}
@Override
+ public int parseAndAdd(XmlPullParser parser) {
+ final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
+ final String shortcutId = getAttributeValue(parser, ATTR_SHORTCUT_ID);
+ if (!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(shortcutId)) {
+ return parseAndAddDeepShortcut(shortcutId, packageName);
+ }
+ return super.parseAndAdd(parser);
+ }
+
+ /**
+ * This method parses and adds a deep shortcut.
+ * @return item id if the shortcut is successfully added else -1
+ */
+ private int parseAndAddDeepShortcut(String shortcutId, String packageName) {
+ try {
+ LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class);
+ launcherApps.pinShortcuts(packageName, Collections.singletonList(shortcutId),
+ Process.myUserHandle());
+ Intent intent = ShortcutKey.makeIntent(shortcutId, packageName);
+ mValues.put(Favorites.RESTORED, WorkspaceItemInfo.FLAG_RESTORED_ICON);
+ return addShortcut(null, intent, Favorites.ITEM_TYPE_DEEP_SHORTCUT);
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to pin the shortcut for shortcut id = " + shortcutId
+ + " and package name = " + packageName);
+ }
+ return -1;
+ }
+
+ @Override
protected Intent parseIntent(XmlPullParser parser) {
String uri = null;
try {
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 477964a..95d3ad9 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -85,6 +85,9 @@
}
@Override
+ protected void setupItemInfo(ItemInfo info) {}
+
+ @Override
protected boolean supportsDrop(ItemInfo info) {
return true;
}
@@ -160,7 +163,7 @@
// Remove the item from launcher and the db, we can ignore the containerInfo in this call
// because we already remove the drag view from the folder (if the drag originated from
// a folder) in Folder.beginDrag()
- mLauncher.removeItem(view, item, true /* deleteFromDb */);
+ mLauncher.removeItem(view, item, true /* deleteFromDb */, "removed by accessibility drop");
mLauncher.getWorkspace().stripEmptyScreens();
mLauncher.getDragLayer()
.announceForAccessibility(getContext().getString(R.string.item_removed));
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index d2b9dfe..b276397 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -16,6 +16,10 @@
package com.android.launcher3;
+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.ResourceUtils.pxFromDp;
import static com.android.launcher3.Utilities.dpiFromPx;
import static com.android.launcher3.Utilities.pxFromSp;
@@ -34,7 +38,6 @@
import com.android.launcher3.CellLayout.ContainerType;
import com.android.launcher3.DevicePaddings.DevicePadding;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.IconNormalizer;
@@ -44,13 +47,14 @@
import com.android.launcher3.util.WindowBounds;
import java.io.PrintWriter;
+import java.util.List;
@SuppressLint("NewApi")
public class DeviceProfile {
private static final int DEFAULT_DOT_SIZE = 100;
// Ratio of empty space, qsb should take up to appear visually centered.
- private static final float QSB_CENTER_FACTOR = .325f;
+ private final float mQsbCenterFactor;
public final InvariantDeviceProfile inv;
private final Info mInfo;
@@ -61,10 +65,12 @@
public final boolean isPhone;
public final boolean transposeLayoutWithOrientation;
public final boolean isTwoPanels;
+ public final boolean isQsbInline;
// Device properties in current orientation
public final boolean isLandscape;
public final boolean isMultiWindowMode;
+ public final boolean isGestureMode;
public final int windowX;
public final int windowY;
@@ -72,6 +78,7 @@
public final int heightPx;
public final int availableWidthPx;
public final int availableHeightPx;
+ public final int rotationHint;
public final float aspectRatio;
@@ -90,19 +97,20 @@
private static final float TALL_DEVICE_EXTRA_SPACE_THRESHOLD_DP = 252;
private static final float TALL_DEVICE_MORE_EXTRA_SPACE_THRESHOLD_DP = 268;
- // To evenly space the icons, increase the left/right margins for tablets in portrait mode.
- private static final int PORTRAIT_TABLET_LEFT_RIGHT_PADDING_MULTIPLIER = 4;
-
// Workspace
public final int desiredWorkspaceHorizontalMarginOriginalPx;
public int desiredWorkspaceHorizontalMarginPx;
+ public int gridVisualizationPaddingX;
+ public int gridVisualizationPaddingY;
public Point cellLayoutBorderSpaceOriginalPx;
public Point cellLayoutBorderSpacePx;
- public final int cellLayoutPaddingLeftRightPx;
- public final int cellLayoutBottomPaddingPx;
+ public Rect cellLayoutPaddingPx = new Rect();
+
public final int edgeMarginPx;
- public float workspaceSpringLoadShrinkFactor;
+ public float workspaceSpringLoadShrunkTop;
+ public float workspaceSpringLoadShrunkBottom;
public final int workspaceSpringLoadedBottomSpace;
+ public final int workspaceSpringLoadedMinNextPageVisiblePx;
private final int extraSpace;
public int workspaceTopPadding;
@@ -153,40 +161,45 @@
public final int numShownHotseatIcons;
public int hotseatCellHeightPx;
private final int hotseatExtraVerticalSize;
+ private final boolean areNavButtonsInline;
// In portrait: size = height, in landscape: size = width
public int hotseatBarSizePx;
public int hotseatBarTopPaddingPx;
public final int hotseatBarBottomPaddingPx;
+ 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;
public final int hotseatQsbHeight;
+ public int hotseatBorderSpace;
public final float qsbBottomMarginOriginalPx;
public int qsbBottomMarginPx;
+ public int qsbWidth; // only used when isQsbInline
// All apps
- public Point allAppsCellSpacePx;
- public int allAppsOpenVerticalTranslate;
+ public Point allAppsBorderSpacePx;
+ public int allAppsShiftRange;
+ public int allAppsTopPadding;
+ public int bottomSheetTopPadding;
public int allAppsCellHeightPx;
public int allAppsCellWidthPx;
public int allAppsIconSizePx;
public int allAppsIconDrawablePaddingPx;
public int allAppsLeftRightPadding;
+ public int allAppsLeftRightMargin;
public final int numShownAllAppsColumns;
public float allAppsIconTextSizePx;
// Overview
- public final boolean overviewShowAsGrid;
public int overviewTaskMarginPx;
public int overviewTaskMarginGridPx;
public int overviewTaskIconSizePx;
public int overviewTaskIconDrawableSizePx;
public int overviewTaskIconDrawableSizeGridPx;
public int overviewTaskThumbnailTopMarginPx;
- public final int overviewActionsMarginThreeButtonPx;
- public final int overviewActionsTopMarginGesturePx;
- public final int overviewActionsBottomMarginGesturePx;
+ public final int overviewActionsHeight;
+ public final int overviewActionsTopMarginPx;
public final int overviewActionsButtonSpacing;
public int overviewPageSpacing;
public int overviewRowSpacing;
@@ -197,8 +210,14 @@
// Drop Target
public int dropTargetBarSizePx;
+ public int dropTargetBarTopMarginPx;
+ public int dropTargetBarBottomMarginPx;
public int dropTargetDragPaddingPx;
public int dropTargetTextSizePx;
+ public int dropTargetHorizontalPaddingPx;
+ public int dropTargetVerticalPaddingPx;
+ public int dropTargetGapPx;
+ public int dropTargetButtonWorkspaceEdgeGapPx;
// Insets
private final Rect mInsets = new Rect();
@@ -216,6 +235,7 @@
// Whether Taskbar will inset the bottom of apps by taskbarSize.
public boolean isTaskbarPresentInApps;
public int taskbarSize;
+ public int stashedTaskbarSize;
// DragController
public int flingToDeleteThresholdVelocity;
@@ -223,98 +243,94 @@
/** TODO: Once we fully migrate to staged split, remove "isMultiWindowMode" */
DeviceProfile(Context context, InvariantDeviceProfile inv, Info info, WindowBounds windowBounds,
boolean isMultiWindowMode, boolean transposeLayoutWithOrientation,
- boolean useTwoPanels) {
+ boolean useTwoPanels, boolean isGestureMode) {
this.inv = inv;
this.isLandscape = windowBounds.isLandscape();
this.isMultiWindowMode = isMultiWindowMode;
this.transposeLayoutWithOrientation = transposeLayoutWithOrientation;
+ this.isGestureMode = isGestureMode;
windowX = windowBounds.bounds.left;
windowY = windowBounds.bounds.top;
+ this.rotationHint = windowBounds.rotationHint;
+ mInsets.set(windowBounds.insets);
isScalableGrid = inv.isScalable && !isVerticalBarLayout() && !isMultiWindowMode;
+ // Determine device posture.
+ mInfo = info;
+ isTablet = info.isTablet(windowBounds);
+ isPhone = !isTablet;
+ isTwoPanels = isTablet && useTwoPanels;
+ isTaskbarPresent = isTablet && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS;
+
+ // Some more constants.
+ context = getContext(context, info, isVerticalBarLayout() || (isTablet && isLandscape)
+ ? Configuration.ORIENTATION_LANDSCAPE
+ : Configuration.ORIENTATION_PORTRAIT,
+ windowBounds);
+ final Resources res = context.getResources();
+ mMetrics = res.getDisplayMetrics();
// Determine sizes.
widthPx = windowBounds.bounds.width();
heightPx = windowBounds.bounds.height();
availableWidthPx = windowBounds.availableSize.x;
- availableHeightPx = windowBounds.availableSize.y;
-
- mInfo = info;
- isTablet = info.isTablet(windowBounds);
- isPhone = !isTablet;
- isTwoPanels = isTablet && useTwoPanels;
+ availableHeightPx = windowBounds.availableSize.y;
aspectRatio = ((float) Math.max(widthPx, heightPx)) / Math.min(widthPx, heightPx);
boolean isTallDevice = Float.compare(aspectRatio, TALL_DEVICE_ASPECT_RATIO_THRESHOLD) >= 0;
-
- // Some more constants
- context = getContext(context, info, isVerticalBarLayout()
- ? Configuration.ORIENTATION_LANDSCAPE
- : Configuration.ORIENTATION_PORTRAIT);
- mMetrics = context.getResources().getDisplayMetrics();
- final Resources res = context.getResources();
+ mQsbCenterFactor = res.getFloat(R.dimen.qsb_center_factor);
if (isTwoPanels) {
if (isLandscape) {
- mTypeIndex = InvariantDeviceProfile.INDEX_TWO_PANEL_LANDSCAPE;
+ mTypeIndex = INDEX_TWO_PANEL_LANDSCAPE;
} else {
- mTypeIndex = InvariantDeviceProfile.INDEX_TWO_PANEL_PORTRAIT;
+ mTypeIndex = INDEX_TWO_PANEL_PORTRAIT;
}
} else {
if (isLandscape) {
- mTypeIndex = InvariantDeviceProfile.INDEX_LANDSCAPE;
+ mTypeIndex = INDEX_LANDSCAPE;
} else {
- mTypeIndex = InvariantDeviceProfile.INDEX_DEFAULT;
+ mTypeIndex = INDEX_DEFAULT;
}
}
- hotseatQsbHeight = res.getDimensionPixelSize(R.dimen.qsb_widget_height);
- isTaskbarPresent = isTablet && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS
- && FeatureFlags.ENABLE_TASKBAR.get();
if (isTaskbarPresent) {
taskbarSize = res.getDimensionPixelSize(R.dimen.taskbar_size);
+ stashedTaskbarSize = res.getDimensionPixelSize(R.dimen.taskbar_stashed_size);
}
edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
desiredWorkspaceHorizontalMarginPx = getHorizontalMarginPx(inv, res);
desiredWorkspaceHorizontalMarginOriginalPx = desiredWorkspaceHorizontalMarginPx;
+ gridVisualizationPaddingX = res.getDimensionPixelSize(
+ R.dimen.grid_visualization_horizontal_cell_spacing);
+ gridVisualizationPaddingY = res.getDimensionPixelSize(
+ R.dimen.grid_visualization_vertical_cell_spacing);
- allAppsOpenVerticalTranslate = res.getDimensionPixelSize(
- R.dimen.all_apps_open_vertical_translate);
+ bottomSheetTopPadding = mInsets.top // statusbar height
+ + res.getDimensionPixelSize(R.dimen.bottom_sheet_extra_top_padding)
+ + (isTablet ? 0 : edgeMarginPx); // phones need edgeMarginPx additional padding
+ allAppsTopPadding = isTablet ? bottomSheetTopPadding : 0;
+ allAppsShiftRange = isTablet
+ ? heightPx - allAppsTopPadding
+ : res.getDimensionPixelSize(R.dimen.all_apps_starting_vertical_translate);
folderLabelTextScale = res.getFloat(R.dimen.folder_label_text_scale);
folderContentPaddingLeftRight =
res.getDimensionPixelSize(R.dimen.folder_content_padding_left_right);
folderContentPaddingTop = res.getDimensionPixelSize(R.dimen.folder_content_padding_top);
cellLayoutBorderSpacePx = getCellLayoutBorderSpace(inv);
- allAppsCellSpacePx = new Point(
- pxFromDp(inv.borderSpaces[InvariantDeviceProfile.INDEX_ALL_APPS].x, mMetrics, 1f),
- pxFromDp(inv.borderSpaces[InvariantDeviceProfile.INDEX_ALL_APPS].y, mMetrics, 1f));
+ allAppsBorderSpacePx = new Point(
+ pxFromDp(inv.allAppsBorderSpaces[mTypeIndex].x, mMetrics),
+ pxFromDp(inv.allAppsBorderSpaces[mTypeIndex].y, mMetrics));
cellLayoutBorderSpaceOriginalPx = new Point(cellLayoutBorderSpacePx);
- folderCellLayoutBorderSpaceOriginalPx = pxFromDp(inv.folderBorderSpace, mMetrics, 1f);
+ folderCellLayoutBorderSpaceOriginalPx = pxFromDp(inv.folderBorderSpace, mMetrics);
folderCellLayoutBorderSpacePx = new Point(folderCellLayoutBorderSpaceOriginalPx,
folderCellLayoutBorderSpaceOriginalPx);
- int cellLayoutPaddingLeftRightMultiplier = !isVerticalBarLayout() && isTablet
- ? PORTRAIT_TABLET_LEFT_RIGHT_PADDING_MULTIPLIER : 1;
- int cellLayoutPadding = isScalableGrid
- ? 0
- : res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_layout_padding);
-
- if (isTwoPanels) {
- cellLayoutPaddingLeftRightPx = 0;
- cellLayoutBottomPaddingPx = 0;
- } else if (isLandscape) {
- cellLayoutPaddingLeftRightPx = 0;
- cellLayoutBottomPaddingPx = cellLayoutPadding;
- } else {
- cellLayoutPaddingLeftRightPx = cellLayoutPaddingLeftRightMultiplier * cellLayoutPadding;
- cellLayoutBottomPaddingPx = 0;
- }
-
workspacePageIndicatorHeight = res.getDimensionPixelSize(
R.dimen.workspace_page_indicator_height);
mWorkspacePageIndicatorOverlapWorkspace =
@@ -324,41 +340,73 @@
res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
dropTargetBarSizePx = res.getDimensionPixelSize(R.dimen.dynamic_grid_drop_target_size);
+ dropTargetBarTopMarginPx = res.getDimensionPixelSize(R.dimen.drop_target_top_margin);
+ dropTargetBarBottomMarginPx = res.getDimensionPixelSize(R.dimen.drop_target_bottom_margin);
dropTargetDragPaddingPx = res.getDimensionPixelSize(R.dimen.drop_target_drag_padding);
dropTargetTextSizePx = res.getDimensionPixelSize(R.dimen.drop_target_text_size);
+ dropTargetHorizontalPaddingPx = res.getDimensionPixelSize(
+ R.dimen.drop_target_button_drawable_horizontal_padding);
+ dropTargetVerticalPaddingPx = res.getDimensionPixelSize(
+ R.dimen.drop_target_button_drawable_vertical_padding);
+ dropTargetGapPx = res.getDimensionPixelSize(R.dimen.drop_target_button_gap);
+ dropTargetButtonWorkspaceEdgeGapPx = res.getDimensionPixelSize(
+ R.dimen.drop_target_button_workspace_edge_gap);
workspaceSpringLoadedBottomSpace =
res.getDimensionPixelSize(R.dimen.dynamic_grid_min_spring_loaded_space);
+ workspaceSpringLoadedMinNextPageVisiblePx = res.getDimensionPixelSize(
+ R.dimen.dynamic_grid_spring_loaded_min_next_space_visible);
workspaceCellPaddingXPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_padding_x);
- numShownHotseatIcons =
- isTwoPanels ? inv.numDatabaseHotseatIcons : inv.numShownHotseatIcons;
+ hotseatQsbHeight = res.getDimensionPixelSize(R.dimen.qsb_widget_height);
+ // Whether QSB might be inline in appropriate orientation (e.g. landscape).
+ boolean canQsbInline = (isTwoPanels ? inv.inlineQsb[INDEX_TWO_PANEL_PORTRAIT]
+ || inv.inlineQsb[INDEX_TWO_PANEL_LANDSCAPE]
+ : inv.inlineQsb[INDEX_DEFAULT] || inv.inlineQsb[INDEX_LANDSCAPE])
+ && hotseatQsbHeight > 0;
+ isQsbInline = inv.inlineQsb[mTypeIndex] && canQsbInline;
+
+ // We shrink hotseat sizes regardless of orientation, if nav buttons are inline and QSB
+ // might be inline in either orientations, to keep hotseat size consistent across rotation.
+ areNavButtonsInline = isTaskbarPresent && !isGestureMode;
+ if (areNavButtonsInline && canQsbInline) {
+ numShownHotseatIcons = inv.numShrunkenHotseatIcons;
+ } else {
+ numShownHotseatIcons =
+ isTwoPanels ? inv.numDatabaseHotseatIcons : inv.numShownHotseatIcons;
+ }
+
numShownAllAppsColumns =
isTwoPanels ? inv.numDatabaseAllAppsColumns : inv.numAllAppsColumns;
hotseatBarSizeExtraSpacePx = 0;
hotseatBarTopPaddingPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_top_padding);
- hotseatBarBottomPaddingPx = (isTallDevice ? 0
- : res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_non_tall_padding))
- + res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
+ if (isQsbInline) {
+ hotseatBarBottomPaddingPx = res.getDimensionPixelSize(R.dimen.inline_qsb_bottom_margin);
+ } else {
+ hotseatBarBottomPaddingPx = (isTallDevice ? res.getDimensionPixelSize(
+ R.dimen.dynamic_grid_hotseat_bottom_tall_padding)
+ : res.getDimensionPixelSize(
+ R.dimen.dynamic_grid_hotseat_bottom_non_tall_padding))
+ + res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
+ }
+
+ 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;
hotseatExtraVerticalSize =
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size);
- updateHotseatIconSize(
- pxFromDp(inv.iconSize[InvariantDeviceProfile.INDEX_DEFAULT], mMetrics, 1f));
+ updateHotseatIconSize(pxFromDp(inv.iconSize[INDEX_DEFAULT], mMetrics));
qsbBottomMarginOriginalPx = isScalableGrid
? res.getDimensionPixelSize(R.dimen.scalable_grid_qsb_bottom_margin)
: 0;
- overviewShowAsGrid = isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get();
- overviewTaskMarginPx = overviewShowAsGrid
- ? res.getDimensionPixelSize(R.dimen.overview_task_margin_focused)
- : res.getDimensionPixelSize(R.dimen.overview_task_margin);
+ overviewTaskMarginPx = res.getDimensionPixelSize(R.dimen.overview_task_margin);
overviewTaskMarginGridPx = res.getDimensionPixelSize(R.dimen.overview_task_margin_grid);
overviewTaskIconSizePx = res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_size);
overviewTaskIconDrawableSizePx =
@@ -366,34 +414,14 @@
overviewTaskIconDrawableSizeGridPx =
res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_drawable_size_grid);
overviewTaskThumbnailTopMarginPx = overviewTaskIconSizePx + overviewTaskMarginPx * 2;
- if (overviewShowAsGrid) {
- if (isLandscape) {
- overviewActionsTopMarginGesturePx = res.getDimensionPixelSize(
- R.dimen.overview_actions_top_margin_gesture_grid_landscape);
- overviewActionsBottomMarginGesturePx = res.getDimensionPixelSize(
- R.dimen.overview_actions_bottom_margin_gesture_grid_landscape);
- overviewPageSpacing = res.getDimensionPixelSize(
- R.dimen.overview_page_spacing_grid_landscape);
- } else {
- overviewActionsTopMarginGesturePx = res.getDimensionPixelSize(
- R.dimen.overview_actions_top_margin_gesture_grid_portrait);
- overviewActionsBottomMarginGesturePx = res.getDimensionPixelSize(
- R.dimen.overview_actions_bottom_margin_gesture_grid_portrait);
- overviewPageSpacing = res.getDimensionPixelSize(
- R.dimen.overview_page_spacing_grid_portrait);
- }
- overviewActionsButtonSpacing = res.getDimensionPixelSize(
- R.dimen.overview_actions_button_spacing_grid);
- } else {
- overviewActionsTopMarginGesturePx = res.getDimensionPixelSize(
- R.dimen.overview_actions_margin_gesture);
- overviewActionsBottomMarginGesturePx = overviewActionsTopMarginGesturePx;
- overviewActionsButtonSpacing = res.getDimensionPixelSize(
- R.dimen.overview_actions_button_spacing);
- overviewPageSpacing = res.getDimensionPixelSize(R.dimen.overview_page_spacing);
- }
- overviewActionsMarginThreeButtonPx = res.getDimensionPixelSize(
- R.dimen.overview_actions_margin_three_button);
+ // In vertical bar, use the smaller task margin for the top regardless of mode.
+ overviewActionsTopMarginPx = isVerticalBarLayout()
+ ? overviewTaskMarginPx
+ : 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);
+ overviewActionsHeight = res.getDimensionPixelSize(R.dimen.overview_actions_height);
// Grid task's top margin is only overviewTaskIconSizePx + overviewTaskMarginGridPx, but
// overviewTaskThumbnailTopMarginPx is applied to all TaskThumbnailView, so exclude the
// extra margin when calculating row spacing.
@@ -401,9 +429,7 @@
- overviewTaskMarginGridPx;
overviewRowSpacing = res.getDimensionPixelSize(R.dimen.overview_grid_row_spacing)
- extraTopMargin;
- overviewGridSideMargin = isLandscape
- ? res.getDimensionPixelSize(R.dimen.overview_grid_side_margin_landscape)
- : res.getDimensionPixelSize(R.dimen.overview_grid_side_margin_portrait);
+ overviewGridSideMargin = res.getDimensionPixelSize(R.dimen.overview_grid_side_margin);
// Calculate all of the remaining variables.
extraSpace = updateAvailableDimensions(res);
@@ -457,8 +483,18 @@
// Recalculate the available dimensions using the new hotseat size.
updateAvailableDimensions(res);
}
+
+ int cellLayoutPadding =
+ isTwoPanels ? cellLayoutBorderSpacePx.x / 2 : res.getDimensionPixelSize(
+ R.dimen.cell_layout_padding);
+ cellLayoutPaddingPx = new Rect(cellLayoutPadding, cellLayoutPadding, cellLayoutPadding,
+ cellLayoutPadding);
updateWorkspacePadding();
+ // Hotseat and QSB width depends on updated cellSize and workspace padding
+ hotseatBorderSpace = calculateHotseatBorderSpace();
+ qsbWidth = calculateQsbWidth();
+
flingToDeleteThresholdVelocity = res.getDimensionPixelSize(
R.dimen.drag_flingToDeleteMinVelocity);
@@ -469,6 +505,28 @@
new DotRenderer(allAppsIconSizePx, dotPath, DEFAULT_DOT_SIZE);
}
+ /**
+ * QSB width is always calculated because when in 3 button nav the width doesn't follow the
+ * width of the hotseat.
+ */
+ private int calculateQsbWidth() {
+ if (isQsbInline) {
+ int columns = getPanelCount() * inv.numColumns;
+ return getIconToIconWidthForColumns(columns)
+ - iconSizePx * numShownHotseatIcons
+ - hotseatBorderSpace * numShownHotseatIcons;
+ } else {
+ int columns = inv.hotseatColumnSpan[mTypeIndex];
+ return getIconToIconWidthForColumns(columns);
+ }
+ }
+
+ private int getIconToIconWidthForColumns(int columns) {
+ return columns * getCellSize().x
+ + (columns - 1) * cellLayoutBorderSpacePx.x
+ - (getCellSize().x - iconSizePx); // left and right cell space
+ }
+
private int getHorizontalMarginPx(InvariantDeviceProfile idp, Resources res) {
if (isVerticalBarLayout()) {
return 0;
@@ -493,21 +551,21 @@
}
private Point getCellLayoutBorderSpace(InvariantDeviceProfile idp) {
+ return getCellLayoutBorderSpace(idp, 1f);
+
+ }
+
+ private Point getCellLayoutBorderSpace(InvariantDeviceProfile idp, float scale) {
if (!isScalableGrid) {
return new Point(0, 0);
}
- int horizontalSpacePx = pxFromDp(idp.borderSpaces[mTypeIndex].x, mMetrics);
- int verticalSpacePx = pxFromDp(idp.borderSpaces[mTypeIndex].y, mMetrics);
+ int horizontalSpacePx = pxFromDp(idp.borderSpaces[mTypeIndex].x, mMetrics, scale);
+ int verticalSpacePx = pxFromDp(idp.borderSpaces[mTypeIndex].y, mMetrics, scale);
return new Point(horizontalSpacePx, verticalSpacePx);
}
- private Point getCellLayoutBorderSpaceScaled(InvariantDeviceProfile idp, float scale) {
- Point original = getCellLayoutBorderSpace(idp);
- return new Point((int) (original.x * scale), (int) (original.y * scale));
- }
-
public Info getDisplayInfo() {
return mInfo;
}
@@ -529,13 +587,15 @@
}
public Builder toBuilder(Context context) {
- WindowBounds bounds =
- new WindowBounds(widthPx, heightPx, availableWidthPx, availableHeightPx);
+ WindowBounds bounds = new WindowBounds(
+ widthPx, heightPx, availableWidthPx, availableHeightPx, rotationHint);
bounds.bounds.offsetTo(windowX, windowY);
+ bounds.insets.set(mInsets);
return new Builder(context, inv, mInfo)
.setWindowBounds(bounds)
.setUseTwoPanels(isTwoPanels)
- .setMultiWindowMode(isMultiWindowMode);
+ .setMultiWindowMode(isMultiWindowMode)
+ .setGestureMode(isGestureMode);
}
public DeviceProfile copy(Context context) {
@@ -558,7 +618,6 @@
float appWidgetScaleX = (float) profile.getCellSize().x / getCellSize().x;
float appWidgetScaleY = (float) profile.getCellSize().y / getCellSize().y;
profile.appWidgetScale.set(appWidgetScaleX, appWidgetScaleY);
- profile.updateWorkspacePadding();
return profile;
}
@@ -592,14 +651,20 @@
+ textHeight + (topBottomPadding * 2);
}
- private void updateAllAppsWidth() {
- if (isTwoPanels) {
+ private void updateAllAppsContainerWidth(Resources res) {
+ int cellLayoutHorizontalPadding =
+ (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right) / 2;
+ if (isTablet) {
+ allAppsLeftRightPadding =
+ res.getDimensionPixelSize(R.dimen.all_apps_bottom_sheet_horizontal_padding);
+
int usedWidth = (allAppsCellWidthPx * numShownAllAppsColumns)
- + (allAppsCellSpacePx.x * (numShownAllAppsColumns + 1));
- allAppsLeftRightPadding = Math.max(1, (availableWidthPx - usedWidth) / 2);
+ + (allAppsBorderSpacePx.x * (numShownAllAppsColumns - 1))
+ + allAppsLeftRightPadding * 2;
+ allAppsLeftRightMargin = Math.max(1, (availableWidthPx - usedWidth) / 2);
} else {
allAppsLeftRightPadding =
- desiredWorkspaceHorizontalMarginPx + cellLayoutPaddingLeftRightPx;
+ desiredWorkspaceHorizontalMarginPx + cellLayoutHorizontalPadding;
}
}
@@ -609,11 +674,11 @@
private int updateAvailableDimensions(Resources res) {
updateIconSize(1f, res);
- Point workspacePadding = getTotalWorkspacePadding();
+ updateWorkspacePadding();
// Check to see if the icons fit within the available height.
- float usedHeight = getCellLayoutHeight();
- final int maxHeight = availableHeightPx - workspacePadding.y;
+ float usedHeight = getCellLayoutHeightSpecification();
+ final int maxHeight = getCellLayoutHeight();
float extraHeight = Math.max(0, maxHeight - usedHeight);
float scaleY = maxHeight / usedHeight;
boolean shouldScale = scaleY < 1f;
@@ -623,10 +688,8 @@
// 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.
- int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
- float usedWidth = (cellWidthPx * numColumns)
- + (cellLayoutBorderSpacePx.x * (numColumns - 1))
- + (desiredWorkspaceHorizontalMarginPx * 2);
+ float usedWidth =
+ getCellLayoutWidthSpecification() + (desiredWorkspaceHorizontalMarginPx * 2);
// We do not subtract padding here, as we also scale the workspace padding if needed.
scaleX = availableWidthPx / usedWidth;
shouldScale = true;
@@ -635,15 +698,22 @@
if (shouldScale) {
float scale = Math.min(scaleX, scaleY);
updateIconSize(scale, res);
- extraHeight = Math.max(0, maxHeight - getCellLayoutHeight());
+ extraHeight = Math.max(0, maxHeight - getCellLayoutHeightSpecification());
}
updateAvailableFolderCellDimensions(res);
return Math.round(extraHeight);
}
- private int getCellLayoutHeight() {
- return (cellHeightPx * inv.numRows) + (cellLayoutBorderSpacePx.y * (inv.numRows - 1));
+ private int getCellLayoutHeightSpecification() {
+ return (cellHeightPx * inv.numRows) + (cellLayoutBorderSpacePx.y * (inv.numRows - 1))
+ + cellLayoutPaddingPx.top + cellLayoutPaddingPx.bottom;
+ }
+
+ private int getCellLayoutWidthSpecification() {
+ int numColumns = getPanelCount() * inv.numColumns;
+ return (cellWidthPx * numColumns) + (cellLayoutBorderSpacePx.x * (numColumns - 1))
+ + cellLayoutPaddingPx.left + cellLayoutPaddingPx.right;
}
/**
@@ -665,7 +735,7 @@
iconTextSizePx = (int) (pxFromSp(invIconTextSizeSp, mMetrics) * iconScale);
iconDrawablePaddingPx = (int) (iconDrawablePaddingOriginalPx * iconScale);
- cellLayoutBorderSpacePx = getCellLayoutBorderSpaceScaled(inv, scale);
+ cellLayoutBorderSpacePx = getCellLayoutBorderSpace(inv, scale);
if (isScalableGrid) {
cellWidthPx = pxFromDp(inv.minCellSize[mTypeIndex].x, mMetrics, scale);
@@ -692,46 +762,68 @@
}
// All apps
- if (numShownAllAppsColumns != inv.numColumns) {
- allAppsIconSizePx =
- pxFromDp(inv.iconSize[InvariantDeviceProfile.INDEX_ALL_APPS], mMetrics);
- allAppsIconTextSizePx =
- pxFromSp(inv.iconTextSize[InvariantDeviceProfile.INDEX_ALL_APPS], mMetrics);
- allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx;
- autoResizeAllAppsCells();
- } else {
- allAppsIconSizePx = iconSizePx;
- allAppsIconTextSizePx = iconTextSizePx;
- allAppsIconDrawablePaddingPx = iconDrawablePaddingPx;
- allAppsCellHeightPx = getCellSize().y;
- }
- allAppsCellWidthPx = allAppsIconSizePx + allAppsIconDrawablePaddingPx;
- updateAllAppsWidth();
+ updateAllAppsIconSize(scale, res);
- if (isVerticalLayout) {
- hideWorkspaceLabelsIfNotEnoughSpace();
- }
-
- // Hotseat
updateHotseatIconSize(iconSizePx);
- if (!isVerticalLayout) {
- int expectedWorkspaceHeight = availableHeightPx - hotseatBarSizePx
- - workspacePageIndicatorHeight - edgeMarginPx;
- float minRequiredHeight = dropTargetBarSizePx + workspaceSpringLoadedBottomSpace;
- workspaceSpringLoadShrinkFactor = Math.min(
- res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f,
- 1 - (minRequiredHeight / expectedWorkspaceHeight));
- } else {
- workspaceSpringLoadShrinkFactor =
- res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f;
- }
-
// Folder icon
folderIconSizePx = IconNormalizer.getNormalizedCircleSize(iconSizePx);
folderIconOffsetYPx = (iconSizePx - folderIconSizePx) / 2;
}
+ /**
+ * Hotseat width spans a certain number of columns on scalable grids.
+ * This method calculates the space between the icons to achieve that width.
+ */
+ private int calculateHotseatBorderSpace() {
+ if (!isScalableGrid) return 0;
+ //TODO(http://b/228998082) remove this when 3 button spaces are fixed
+ if (areNavButtonsInline) {
+ return pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics);
+ } else {
+ int columns = inv.hotseatColumnSpan[mTypeIndex];
+ float hotseatWidthPx = getIconToIconWidthForColumns(columns);
+ float hotseatIconsTotalPx = iconSizePx * numShownHotseatIcons;
+ return (int) (hotseatWidthPx - hotseatIconsTotalPx) / (numShownHotseatIcons - 1);
+ }
+ }
+
+
+ /**
+ * Updates the iconSize for allApps* variants.
+ */
+ private void updateAllAppsIconSize(float scale, Resources res) {
+ allAppsBorderSpacePx = new Point(
+ pxFromDp(inv.allAppsBorderSpaces[mTypeIndex].x, mMetrics, scale),
+ pxFromDp(inv.allAppsBorderSpaces[mTypeIndex].y, mMetrics, scale));
+ // AllApps cells don't have real space between cells,
+ // so we add the border space to the cell height
+ allAppsCellHeightPx = pxFromDp(inv.allAppsCellSize[mTypeIndex].y, mMetrics, scale)
+ + allAppsBorderSpacePx.y;
+ // but width is just the cell,
+ // the border is added in #updateAllAppsContainerWidth
+ allAppsCellWidthPx = pxFromDp(inv.allAppsCellSize[mTypeIndex].x, mMetrics, scale);
+ if (isScalableGrid) {
+ allAppsIconSizePx =
+ pxFromDp(inv.allAppsIconSize[mTypeIndex], mMetrics, scale);
+ allAppsIconTextSizePx =
+ pxFromSp(inv.allAppsIconTextSize[mTypeIndex], mMetrics, scale);
+ allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx;
+ } else {
+ float invIconSizeDp = inv.allAppsIconSize[mTypeIndex];
+ float invIconTextSizeSp = inv.allAppsIconTextSize[mTypeIndex];
+ allAppsIconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mMetrics, scale));
+ allAppsIconTextSizePx = (int) (pxFromSp(invIconTextSizeSp, mMetrics) * scale);
+ allAppsIconDrawablePaddingPx =
+ res.getDimensionPixelSize(R.dimen.all_apps_icon_drawable_padding);
+ }
+
+ updateAllAppsContainerWidth(res);
+ if (isVerticalBarLayout()) {
+ hideWorkspaceLabelsIfNotEnoughSpace();
+ }
+ }
+
private void updateAvailableFolderCellDimensions(Resources res) {
updateFolderCellSize(1f, res);
@@ -763,11 +855,11 @@
private void updateFolderCellSize(float scale, Resources res) {
float invIconSizeDp = isVerticalBarLayout()
- ? inv.iconSize[InvariantDeviceProfile.INDEX_LANDSCAPE]
- : inv.iconSize[InvariantDeviceProfile.INDEX_DEFAULT];
+ ? inv.iconSize[INDEX_LANDSCAPE]
+ : inv.iconSize[INDEX_DEFAULT];
folderChildIconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mMetrics, scale));
folderChildTextSizePx =
- pxFromSp(inv.iconTextSize[InvariantDeviceProfile.INDEX_DEFAULT], mMetrics, scale);
+ pxFromSp(inv.iconTextSize[INDEX_DEFAULT], mMetrics, scale);
folderLabelTextSizePx = (int) (folderChildTextSizePx * folderLabelTextScale);
int textHeight = Utilities.calculateTextHeight(folderChildTextSizePx);
@@ -799,7 +891,6 @@
public void updateInsets(Rect insets) {
mInsets.set(insets);
- updateWorkspacePadding();
}
/**
@@ -819,30 +910,97 @@
result = new Point();
}
- // Since we are only concerned with the overall padding, layout direction does
- // not matter.
- Point padding = getTotalWorkspacePadding();
-
- int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
- int screenWidthPx = getWorkspaceWidth(padding);
- result.x = calculateCellWidth(screenWidthPx, cellLayoutBorderSpacePx.x, numColumns);
- result.y = calculateCellHeight(availableHeightPx - padding.y
- - cellLayoutBottomPaddingPx, cellLayoutBorderSpacePx.y, inv.numRows);
+ int shortcutAndWidgetContainerWidth =
+ getCellLayoutWidth() - (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right);
+ result.x = calculateCellWidth(shortcutAndWidgetContainerWidth, cellLayoutBorderSpacePx.x,
+ inv.numColumns);
+ int shortcutAndWidgetContainerHeight =
+ getCellLayoutHeight() - (cellLayoutPaddingPx.top + cellLayoutPaddingPx.bottom);
+ result.y = calculateCellHeight(shortcutAndWidgetContainerHeight, cellLayoutBorderSpacePx.y,
+ inv.numRows);
return result;
}
- public int getWorkspaceWidth() {
- return getWorkspaceWidth(getTotalWorkspacePadding());
+ /**
+ * Gets the number of panels within the workspace.
+ */
+ public int getPanelCount() {
+ return isTwoPanels ? 2 : 1;
}
- public int getWorkspaceWidth(Point workspacePadding) {
- int cellLayoutTotalPadding =
- isTwoPanels ? 4 * cellLayoutPaddingLeftRightPx : 2 * cellLayoutPaddingLeftRightPx;
- return availableWidthPx - workspacePadding.x - cellLayoutTotalPadding;
+ /**
+ * Gets the space in px from the bottom of last item in the vertical-bar hotseat to the
+ * bottom of the screen.
+ */
+ public int getVerticalHotseatLastItemBottomOffset() {
+ int cellHeight = calculateCellHeight(
+ heightPx - mHotseatPadding.top - mHotseatPadding.bottom, hotseatBorderSpace,
+ numShownHotseatIcons);
+ int hotseatSize = (cellHeight * numShownHotseatIcons)
+ + (hotseatBorderSpace * (numShownHotseatIcons - 1));
+ int extraHotseatEndSpacing = (heightPx - hotseatSize) / 2;
+ int extraIconEndSpacing = (cellHeight - iconSizePx) / 2;
+ return extraHotseatEndSpacing + extraIconEndSpacing + mHotseatPadding.bottom;
+ }
+
+ /**
+ * Gets the scaled top of the workspace in px for the spring-loaded edit state.
+ */
+ public float getCellLayoutSpringLoadShrunkTop() {
+ workspaceSpringLoadShrunkTop = mInsets.top + dropTargetBarTopMarginPx + dropTargetBarSizePx
+ + dropTargetBarBottomMarginPx;
+ return workspaceSpringLoadShrunkTop;
+ }
+
+ /**
+ * Gets the scaled bottom of the workspace in px for the spring-loaded edit state.
+ */
+ private float getCellLayoutSpringLoadShrunkBottom() {
+ int topOfHotseat = hotseatBarSizePx + springLoadedHotseatBarTopMarginPx;
+ workspaceSpringLoadShrunkBottom =
+ heightPx - (isVerticalBarLayout() ? getVerticalHotseatLastItemBottomOffset()
+ : topOfHotseat);
+ return workspaceSpringLoadShrunkBottom;
+ }
+
+ /**
+ * Gets the scale of the workspace for the spring-loaded edit state.
+ */
+ public float getWorkspaceSpringLoadScale() {
+ float scale = (getCellLayoutSpringLoadShrunkBottom() - getCellLayoutSpringLoadShrunkTop())
+ / getCellLayoutHeight();
+ scale = Math.min(scale, 1f);
+
+ // Reduce scale if next pages would not be visible after scaling the workspace
+ int workspaceWidth = availableWidthPx;
+ float scaledWorkspaceWidth = workspaceWidth * scale;
+ float maxAvailableWidth = workspaceWidth - (2 * workspaceSpringLoadedMinNextPageVisiblePx);
+ if (scaledWorkspaceWidth > maxAvailableWidth) {
+ scale *= maxAvailableWidth / scaledWorkspaceWidth;
+ }
+ return scale;
+ }
+
+ /**
+ * Gets the width of a single Cell Layout, aka a single panel within a Workspace.
+ *
+ * <p>This is the width of a Workspace, less its horizontal padding. Note that two-panel
+ * layouts have two Cell Layouts per workspace.
+ */
+ public int getCellLayoutWidth() {
+ return (availableWidthPx - getTotalWorkspacePadding().x) / getPanelCount();
+ }
+
+ /**
+ * Gets the height of a single Cell Layout, aka a single panel within a Workspace.
+ *
+ * <p>This is the height of a Workspace, less its vertical padding.
+ */
+ public int getCellLayoutHeight() {
+ return availableHeightPx - getTotalWorkspacePadding().y;
}
public Point getTotalWorkspacePadding() {
- updateWorkspacePadding();
return new Point(workspacePadding.left + workspacePadding.right,
workspacePadding.top + workspacePadding.bottom);
}
@@ -868,12 +1026,26 @@
int hotseatTop = hotseatBarSizePx;
int paddingBottom = hotseatTop + workspacePageIndicatorHeight
+ workspaceBottomPadding - mWorkspacePageIndicatorOverlapWorkspace;
+ int paddingTop = workspaceTopPadding + (isScalableGrid ? 0 : edgeMarginPx);
+ int paddingSide = desiredWorkspaceHorizontalMarginPx;
- padding.set(desiredWorkspaceHorizontalMarginPx,
- workspaceTopPadding + (isScalableGrid ? 0 : edgeMarginPx),
- desiredWorkspaceHorizontalMarginPx,
- paddingBottom);
+ padding.set(paddingSide, paddingTop, paddingSide, paddingBottom);
}
+ insetPadding(workspacePadding, cellLayoutPaddingPx);
+ }
+
+ private void insetPadding(Rect paddings, Rect insets) {
+ insets.left = Math.min(insets.left, paddings.left);
+ paddings.left -= insets.left;
+
+ insets.top = Math.min(insets.top, paddings.top);
+ paddings.top -= insets.top;
+
+ insets.right = Math.min(insets.right, paddings.right);
+ paddings.right -= insets.right;
+
+ insets.bottom = Math.min(insets.bottom, paddings.bottom);
+ paddings.bottom -= insets.bottom;
}
/**
@@ -881,37 +1053,62 @@
*/
public Rect getHotseatLayoutPadding(Context context) {
if (isVerticalBarLayout()) {
+ // The hotseat icons will be placed in the middle of the hotseat cells.
+ // Changing the hotseatCellHeightPx is not affecting hotseat icon positions
+ // 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;
+ int paddingTop = Math.max((int) (mInsets.top + cellLayoutPaddingPx.top
+ - diffOverlapFactor), 0);
+ int paddingBottom = Math.max((int) (mInsets.bottom + cellLayoutPaddingPx.bottom
+ + diffOverlapFactor), 0);
+
if (isSeascape()) {
- mHotseatPadding.set(mInsets.left + hotseatBarSidePaddingStartPx,
- mInsets.top, hotseatBarSidePaddingEndPx, mInsets.bottom);
+ mHotseatPadding.set(mInsets.left + hotseatBarSidePaddingStartPx, paddingTop,
+ hotseatBarSidePaddingEndPx, paddingBottom);
} else {
- mHotseatPadding.set(hotseatBarSidePaddingEndPx, mInsets.top,
- mInsets.right + hotseatBarSidePaddingStartPx, mInsets.bottom);
+ mHotseatPadding.set(hotseatBarSidePaddingEndPx, paddingTop,
+ mInsets.right + hotseatBarSidePaddingStartPx, paddingBottom);
}
} else if (isTaskbarPresent) {
- int hotseatHeight = workspacePadding.bottom;
- int taskbarOffset = getTaskbarOffsetY();
- int hotseatTopDiff = hotseatHeight - taskbarOffset;
+ // Center the QSB vertically with hotseat
+ int hotseatBottomPadding = getHotseatBottomPadding();
+ int hotseatTopPadding =
+ workspacePadding.bottom - hotseatBottomPadding - hotseatCellHeightPx;
+ // Push icons to the side
+ int additionalQsbSpace = isQsbInline ? qsbWidth + hotseatBorderSpace : 0;
+ int requiredWidth = iconSizePx * numShownHotseatIcons
+ + hotseatBorderSpace * (numShownHotseatIcons - 1)
+ + additionalQsbSpace;
int endOffset = ApiWrapper.getHotseatEndOffset(context);
- int requiredWidth = iconSizePx * numShownHotseatIcons;
+ int hotseatWidth = Math.min(requiredWidth, availableWidthPx - endOffset);
+ int sideSpacing = (availableWidthPx - hotseatWidth) / 2;
- Resources res = context.getResources();
- float taskbarIconSize = res.getDimension(R.dimen.taskbar_icon_size);
- float taskbarIconSpacing = 2 * res.getDimension(R.dimen.taskbar_icon_spacing);
- int maxSize = (int) (requiredWidth
- * (taskbarIconSize + taskbarIconSpacing) / taskbarIconSize);
- int hotseatSize = Math.min(maxSize, availableWidthPx - endOffset);
- int sideSpacing = (availableWidthPx - hotseatSize) / 2;
- mHotseatPadding.set(sideSpacing, hotseatTopDiff, sideSpacing, taskbarOffset);
+ mHotseatPadding.set(sideSpacing, hotseatTopPadding, sideSpacing, hotseatBottomPadding);
+
+ boolean isRtl = Utilities.isRtl(context.getResources());
+ if (isRtl) {
+ mHotseatPadding.right += additionalQsbSpace;
+ } else {
+ mHotseatPadding.left += additionalQsbSpace;
+ }
if (endOffset > sideSpacing) {
- int diff = Utilities.isRtl(context.getResources())
+ int diff = isRtl
? sideSpacing - endOffset
: endOffset - sideSpacing;
mHotseatPadding.left -= diff;
mHotseatPadding.right += diff;
}
+ } else if (isScalableGrid) {
+ int sideSpacing = (availableWidthPx - qsbWidth) / 2;
+ mHotseatPadding.set(sideSpacing,
+ hotseatBarTopPaddingPx,
+ sideSpacing,
+ hotseatBarSizePx - hotseatCellHeightPx - hotseatBarTopPaddingPx
+ + mInsets.bottom);
} else {
// We want the edges of the hotseat to line up with the edges of the workspace, but the
// icons in the hotseat are a different size, and so don't line up perfectly. To account
@@ -920,14 +1117,12 @@
float workspaceCellWidth = (float) widthPx / inv.numColumns;
float hotseatCellWidth = (float) widthPx / numShownHotseatIcons;
int hotseatAdjustment = Math.round((workspaceCellWidth - hotseatCellWidth) / 2);
- mHotseatPadding.set(
- hotseatAdjustment + workspacePadding.left + cellLayoutPaddingLeftRightPx
- + mInsets.left,
- hotseatBarTopPaddingPx,
- hotseatAdjustment + workspacePadding.right + cellLayoutPaddingLeftRightPx
+ mHotseatPadding.set(hotseatAdjustment + workspacePadding.left + cellLayoutPaddingPx.left
+ + mInsets.left, hotseatBarTopPaddingPx,
+ hotseatAdjustment + workspacePadding.right + cellLayoutPaddingPx.right
+ mInsets.right,
hotseatBarSizePx - hotseatCellHeightPx - hotseatBarTopPaddingPx
- + cellLayoutBottomPaddingPx + mInsets.bottom);
+ + mInsets.bottom);
}
return mHotseatPadding;
}
@@ -936,6 +1131,10 @@
* Returns the number of pixels the QSB is translated from the bottom of the screen.
*/
public int getQsbOffsetY() {
+ if (isQsbInline) {
+ return hotseatBarBottomPaddingPx;
+ }
+
int freeSpace = isTaskbarPresent
? workspacePadding.bottom
: hotseatBarSizePx - hotseatCellHeightPx - hotseatQsbHeight;
@@ -944,16 +1143,45 @@
// Note that taskbarSize = 0 unless isTaskbarPresent.
return Math.min(qsbBottomMarginPx + taskbarSize, freeSpace);
} else {
- return (int) (freeSpace * QSB_CENTER_FACTOR)
+ return (int) (freeSpace * mQsbCenterFactor)
+ (isTaskbarPresent ? taskbarSize : mInsets.bottom);
}
}
+ private int getHotseatBottomPadding() {
+ if (isQsbInline) {
+ return getQsbOffsetY() - (Math.abs(hotseatQsbHeight - hotseatCellHeightPx) / 2);
+ } else {
+ return (getQsbOffsetY() - taskbarSize) / 2;
+ }
+ }
+
/**
* Returns the number of pixels the taskbar is translated from the bottom of the screen.
*/
public int getTaskbarOffsetY() {
- return (getQsbOffsetY() - taskbarSize) / 2;
+ int taskbarIconBottomSpace = (taskbarSize - iconSizePx) / 2;
+ int launcherIconBottomSpace =
+ Math.min((hotseatCellHeightPx - iconSizePx) / 2, gridVisualizationPaddingY);
+ return getHotseatBottomPadding() + launcherIconBottomSpace - taskbarIconBottomSpace;
+ }
+
+ /**
+ * Returns the number of pixels required below OverviewActions excluding insets.
+ */
+ public int getOverviewActionsClaimedSpaceBelow() {
+ if (isTaskbarPresent && !isGestureMode) {
+ // Align vertically to where nav buttons are.
+ return ((taskbarSize - overviewActionsHeight) / 2) + getTaskbarOffsetY();
+ }
+
+ return isTaskbarPresent ? stashedTaskbarSize : mInsets.bottom;
+ }
+
+ /** Gets the space that the overview actions will take, including bottom margin. */
+ public int getOverviewActionsClaimedSpace() {
+ return overviewActionsTopMarginPx + overviewActionsHeight
+ + getOverviewActionsClaimedSpaceBelow();
}
/**
@@ -1003,6 +1231,8 @@
.getInfo().rotation == Surface.ROTATION_270;
if (mIsSeascape != isSeascape) {
mIsSeascape = isSeascape;
+ // Hotseat changing sides requires updating workspace left/right paddings
+ updateWorkspacePadding();
return true;
}
}
@@ -1045,6 +1275,7 @@
writer.println(prefix + "\tisPhone:" + isPhone);
writer.println(prefix + "\ttransposeLayoutWithOrientation:"
+ transposeLayoutWithOrientation);
+ writer.println(prefix + "\tisGestureMode:" + isGestureMode);
writer.println(prefix + "\tisLandscape:" + isLandscape);
writer.println(prefix + "\tisMultiWindowMode:" + isMultiWindowMode);
@@ -1054,16 +1285,21 @@
writer.println(prefix + pxToDpStr("windowY", windowY));
writer.println(prefix + pxToDpStr("widthPx", widthPx));
writer.println(prefix + pxToDpStr("heightPx", heightPx));
-
writer.println(prefix + pxToDpStr("availableWidthPx", availableWidthPx));
writer.println(prefix + pxToDpStr("availableHeightPx", availableHeightPx));
+ writer.println(prefix + pxToDpStr("mInsets.left", mInsets.left));
+ writer.println(prefix + pxToDpStr("mInsets.top", mInsets.top));
+ writer.println(prefix + pxToDpStr("mInsets.right", mInsets.right));
+ writer.println(prefix + pxToDpStr("mInsets.bottom", mInsets.bottom));
writer.println(prefix + "\taspectRatio:" + aspectRatio);
writer.println(prefix + "\tisScalableGrid:" + isScalableGrid);
- writer.println(prefix + "\tinv.numColumns: " + inv.numColumns);
writer.println(prefix + "\tinv.numRows: " + inv.numRows);
+ writer.println(prefix + "\tinv.numColumns: " + inv.numColumns);
+ writer.println(prefix + "\tinv.numSearchContainerColumns: "
+ + inv.numSearchContainerColumns);
writer.println(prefix + "\tminCellSize: " + inv.minCellSize[mTypeIndex] + "dp");
@@ -1077,6 +1313,11 @@
cellLayoutBorderSpacePx.x));
writer.println(prefix + pxToDpStr("cellLayoutBorderSpacePx Vertical",
cellLayoutBorderSpacePx.y));
+ writer.println(prefix + pxToDpStr("cellLayoutPaddingPx.left", cellLayoutPaddingPx.left));
+ writer.println(prefix + pxToDpStr("cellLayoutPaddingPx.top", cellLayoutPaddingPx.top));
+ writer.println(prefix + pxToDpStr("cellLayoutPaddingPx.right", cellLayoutPaddingPx.right));
+ writer.println(
+ prefix + pxToDpStr("cellLayoutPaddingPx.bottom", cellLayoutPaddingPx.bottom));
writer.println(prefix + pxToDpStr("iconSizePx", iconSizePx));
writer.println(prefix + pxToDpStr("iconTextSizePx", iconTextSizePx));
@@ -1095,14 +1336,23 @@
writer.println(prefix + pxToDpStr("folderCellLayoutBorderSpacePx Vertical",
folderCellLayoutBorderSpacePx.y));
+ writer.println(prefix + pxToDpStr("bottomSheetTopPadding", bottomSheetTopPadding));
+
+ writer.println(prefix + pxToDpStr("allAppsShiftRange", allAppsShiftRange));
+ writer.println(prefix + pxToDpStr("allAppsTopPadding", allAppsTopPadding));
writer.println(prefix + pxToDpStr("allAppsIconSizePx", allAppsIconSizePx));
writer.println(prefix + pxToDpStr("allAppsIconTextSizePx", allAppsIconTextSizePx));
writer.println(prefix + pxToDpStr("allAppsIconDrawablePaddingPx",
allAppsIconDrawablePaddingPx));
writer.println(prefix + pxToDpStr("allAppsCellHeightPx", allAppsCellHeightPx));
+ writer.println(prefix + pxToDpStr("allAppsCellWidthPx", allAppsCellWidthPx));
+ writer.println(prefix + pxToDpStr("allAppsBorderSpacePx", allAppsBorderSpacePx.x));
writer.println(prefix + "\tnumShownAllAppsColumns: " + numShownAllAppsColumns);
+ writer.println(prefix + pxToDpStr("allAppsLeftRightPadding", allAppsLeftRightPadding));
+ writer.println(prefix + pxToDpStr("allAppsLeftRightMargin", allAppsLeftRightMargin));
writer.println(prefix + pxToDpStr("hotseatBarSizePx", hotseatBarSizePx));
+ writer.println(prefix + "\tinv.hotseatColumnSpan: " + inv.hotseatColumnSpan[mTypeIndex]);
writer.println(prefix + pxToDpStr("hotseatCellHeightPx", hotseatCellHeightPx));
writer.println(prefix + pxToDpStr("hotseatBarTopPaddingPx", hotseatBarTopPaddingPx));
writer.println(prefix + pxToDpStr("hotseatBarBottomPaddingPx", hotseatBarBottomPaddingPx));
@@ -1110,7 +1360,16 @@
hotseatBarSidePaddingStartPx));
writer.println(prefix + pxToDpStr("hotseatBarSidePaddingEndPx",
hotseatBarSidePaddingEndPx));
+ writer.println(prefix + pxToDpStr("springLoadedHotseatBarTopMarginPx",
+ springLoadedHotseatBarTopMarginPx));
+ writer.println(prefix + pxToDpStr("mHotseatPadding.top", mHotseatPadding.top));
+ writer.println(prefix + pxToDpStr("mHotseatPadding.bottom", mHotseatPadding.bottom));
+ writer.println(prefix + pxToDpStr("mHotseatPadding.left", mHotseatPadding.left));
+ writer.println(prefix + pxToDpStr("mHotseatPadding.right", mHotseatPadding.right));
writer.println(prefix + "\tnumShownHotseatIcons: " + numShownHotseatIcons);
+ writer.println(prefix + pxToDpStr("hotseatBorderSpace", hotseatBorderSpace));
+ writer.println(prefix + "\tisQsbInline: " + isQsbInline);
+ writer.println(prefix + pxToDpStr("qsbWidth", qsbWidth));
writer.println(prefix + "\tisTaskbarPresent:" + isTaskbarPresent);
writer.println(prefix + "\tisTaskbarPresentInApps:" + isTaskbarPresentInApps);
@@ -1136,12 +1395,48 @@
writer.println(prefix + pxToDpStr("workspaceTopPadding", workspaceTopPadding));
writer.println(prefix + pxToDpStr("workspaceBottomPadding", workspaceBottomPadding));
writer.println(prefix + pxToDpStr("extraHotseatBottomPadding", extraHotseatBottomPadding));
+
+ writer.println(prefix + pxToDpStr("overviewTaskMarginPx", overviewTaskMarginPx));
+ writer.println(prefix + pxToDpStr("overviewTaskMarginGridPx", overviewTaskMarginGridPx));
+ writer.println(prefix + pxToDpStr("overviewTaskIconSizePx", overviewTaskIconSizePx));
+ writer.println(prefix + pxToDpStr("overviewTaskIconDrawableSizePx",
+ overviewTaskIconDrawableSizePx));
+ writer.println(prefix + pxToDpStr("overviewTaskIconDrawableSizeGridPx",
+ overviewTaskIconDrawableSizeGridPx));
+ writer.println(prefix + pxToDpStr("overviewTaskThumbnailTopMarginPx",
+ overviewTaskThumbnailTopMarginPx));
+ writer.println(prefix + pxToDpStr("overviewActionsTopMarginPx",
+ overviewActionsTopMarginPx));
+ writer.println(prefix + pxToDpStr("overviewActionsHeight",
+ overviewActionsHeight));
+ writer.println(prefix + pxToDpStr("overviewActionsButtonSpacing",
+ overviewActionsButtonSpacing));
+ writer.println(prefix + pxToDpStr("overviewPageSpacing", overviewPageSpacing));
+ writer.println(prefix + pxToDpStr("overviewRowSpacing", overviewRowSpacing));
+ writer.println(prefix + pxToDpStr("overviewGridSideMargin", overviewGridSideMargin));
+
+ writer.println(prefix + pxToDpStr("dropTargetBarTopMarginPx", dropTargetBarTopMarginPx));
+ writer.println(prefix + pxToDpStr("dropTargetBarSizePx", dropTargetBarSizePx));
+ writer.println(
+ prefix + pxToDpStr("dropTargetBarBottomMarginPx", dropTargetBarBottomMarginPx));
+
+ writer.println(
+ prefix + pxToDpStr("workspaceSpringLoadShrunkTop", workspaceSpringLoadShrunkTop));
+ writer.println(prefix + pxToDpStr("workspaceSpringLoadShrunkBottom",
+ workspaceSpringLoadShrunkBottom));
+ writer.println(prefix + pxToDpStr("workspaceSpringLoadedBottomSpace",
+ workspaceSpringLoadedBottomSpace));
+ writer.println(prefix + pxToDpStr("workspaceSpringLoadedMinNextPageVisiblePx",
+ workspaceSpringLoadedMinNextPageVisiblePx));
+ writer.println(
+ prefix + pxToDpStr("getWorkspaceSpringLoadScale()", getWorkspaceSpringLoadScale()));
}
- private static Context getContext(Context c, Info info, int orientation) {
+ private static Context getContext(Context c, Info info, int orientation, WindowBounds bounds) {
Configuration config = new Configuration(c.getResources().getConfiguration());
config.orientation = orientation;
- config.densityDpi = info.densityDpi;
+ config.densityDpi = info.getDensityDpi();
+ config.smallestScreenWidthDp = (int) info.smallestSizeDp(bounds);
return c.createConfigurationContext(config);
}
@@ -1159,6 +1454,35 @@
void onDeviceProfileChanged(DeviceProfile dp);
}
+ /** Allows registering listeners for {@link DeviceProfile} changes. */
+ public interface DeviceProfileListenable {
+
+ /** The current device profile. */
+ DeviceProfile getDeviceProfile();
+
+ /** Registered {@link OnDeviceProfileChangeListener} instances. */
+ List<OnDeviceProfileChangeListener> getOnDeviceProfileChangeListeners();
+
+ /** Notifies listeners of a {@link DeviceProfile} change. */
+ default void dispatchDeviceProfileChanged() {
+ DeviceProfile deviceProfile = getDeviceProfile();
+ List<OnDeviceProfileChangeListener> listeners = getOnDeviceProfileChangeListeners();
+ for (int i = listeners.size() - 1; i >= 0; i--) {
+ listeners.get(i).onDeviceProfileChanged(deviceProfile);
+ }
+ }
+
+ /** Register listener for {@link DeviceProfile} changes. */
+ default void addOnDeviceProfileChangeListener(OnDeviceProfileChangeListener listener) {
+ getOnDeviceProfileChangeListeners().add(listener);
+ }
+
+ /** Unregister listener for {@link DeviceProfile} changes. */
+ default void removeOnDeviceProfileChangeListener(OnDeviceProfileChangeListener listener) {
+ getOnDeviceProfileChangeListeners().remove(listener);
+ }
+ }
+
public static class Builder {
private Context mContext;
private InvariantDeviceProfile mInv;
@@ -1169,6 +1493,7 @@
private boolean mIsMultiWindowMode = false;
private Boolean mTransposeLayoutWithOrientation;
+ private Boolean mIsGestureMode;
public Builder(Context context, InvariantDeviceProfile inv, Info info) {
mContext = context;
@@ -1197,6 +1522,11 @@
return this;
}
+ public Builder setGestureMode(boolean isGestureMode) {
+ mIsGestureMode = isGestureMode;
+ return this;
+ }
+
public DeviceProfile build() {
if (mWindowBounds == null) {
throw new IllegalArgumentException("Window bounds not set");
@@ -1204,8 +1534,11 @@
if (mTransposeLayoutWithOrientation == null) {
mTransposeLayoutWithOrientation = !mInfo.isTablet(mWindowBounds);
}
- return new DeviceProfile(mContext, mInv, mInfo, mWindowBounds,
- mIsMultiWindowMode, mTransposeLayoutWithOrientation, mUseTwoPanels);
+ if (mIsGestureMode == null) {
+ mIsGestureMode = DisplayController.getNavigationMode(mContext).hasGestures;
+ }
+ return new DeviceProfile(mContext, mInv, mInfo, mWindowBounds, mIsMultiWindowMode,
+ mTransposeLayoutWithOrientation, mUseTwoPanels, mIsGestureMode);
}
}
diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java
index 9fb14f6..d908440 100644
--- a/src/com/android/launcher3/DropTargetBar.java
+++ b/src/com/android/launcher3/DropTargetBar.java
@@ -17,8 +17,6 @@
package com.android.launcher3;
import static com.android.launcher3.ButtonDropTarget.TOOLTIP_DEFAULT;
-import static com.android.launcher3.ButtonDropTarget.TOOLTIP_LEFT;
-import static com.android.launcher3.ButtonDropTarget.TOOLTIP_RIGHT;
import static com.android.launcher3.anim.AlphaUpdateListener.updateVisibility;
import android.animation.TimeInterpolator;
@@ -53,6 +51,8 @@
private final Runnable mFadeAnimationEndRunnable =
() -> updateVisibility(DropTargetBar.this);
+ private final Launcher mLauncher;
+
@ViewDebug.ExportedProperty(category = "launcher")
protected boolean mDeferOnDragEnd;
@@ -60,16 +60,19 @@
protected boolean mVisible = false;
private ButtonDropTarget[] mDropTargets;
+ private ButtonDropTarget[] mTempTargets;
private ViewPropertyAnimator mCurrentAnimation;
private boolean mIsVertical = true;
public DropTargetBar(Context context, AttributeSet attrs) {
super(context, attrs);
+ mLauncher = Launcher.getLauncher(context);
}
public DropTargetBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ mLauncher = Launcher.getLauncher(context);
}
@Override
@@ -80,12 +83,13 @@
mDropTargets[i] = (ButtonDropTarget) getChildAt(i);
mDropTargets[i].setDropTargetBar(this);
}
+ mTempTargets = new ButtonDropTarget[getChildCount()];
}
@Override
public void setInsets(Rect insets) {
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
- DeviceProfile grid = Launcher.getLauncher(getContext()).getDeviceProfile();
+ DeviceProfile grid = mLauncher.getDeviceProfile();
mIsVertical = grid.isVerticalBarLayout();
lp.leftMargin = insets.left;
@@ -94,34 +98,37 @@
lp.rightMargin = insets.right;
int tooltipLocation = TOOLTIP_DEFAULT;
- if (grid.isVerticalBarLayout()) {
- lp.width = grid.dropTargetBarSizePx;
- lp.height = grid.availableHeightPx - 2 * grid.edgeMarginPx;
- lp.gravity = grid.isSeascape() ? Gravity.RIGHT : Gravity.LEFT;
- tooltipLocation = grid.isSeascape() ? TOOLTIP_LEFT : TOOLTIP_RIGHT;
+ int horizontalMargin;
+ if (grid.isTablet) {
+ // XXX: If the icon size changes across orientations, we will have to take
+ // that into account here too.
+ horizontalMargin = ((grid.widthPx - 2 * grid.edgeMarginPx
+ - (grid.inv.numColumns * grid.cellWidthPx))
+ / (2 * (grid.inv.numColumns + 1)))
+ + grid.edgeMarginPx;
} else {
- int gap;
- if (grid.isTablet) {
- // XXX: If the icon size changes across orientations, we will have to take
- // that into account here too.
- gap = ((grid.widthPx - 2 * grid.edgeMarginPx
- - (grid.inv.numColumns * grid.cellWidthPx))
- / (2 * (grid.inv.numColumns + 1)))
- + grid.edgeMarginPx;
- } else {
- gap = getContext().getResources()
- .getDimensionPixelSize(R.dimen.drop_target_bar_margin_horizontal);
- }
- lp.width = grid.availableWidthPx - 2 * gap;
-
- lp.topMargin += grid.edgeMarginPx;
- lp.height = grid.dropTargetBarSizePx;
- lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
+ horizontalMargin = getContext().getResources()
+ .getDimensionPixelSize(R.dimen.drop_target_bar_margin_horizontal);
}
+ lp.topMargin += grid.dropTargetBarTopMarginPx;
+ lp.bottomMargin += grid.dropTargetBarBottomMarginPx;
+ lp.width = grid.availableWidthPx - 2 * horizontalMargin;
+ if (mIsVertical) {
+ lp.leftMargin = (grid.widthPx - lp.width) / 2;
+ lp.rightMargin = (grid.widthPx - lp.width) / 2;
+ }
+ lp.height = grid.dropTargetBarSizePx;
+ lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
+
+ DeviceProfile dp = mLauncher.getDeviceProfile();
+ int horizontalPadding = dp.dropTargetHorizontalPaddingPx;
+ int verticalPadding = dp.dropTargetVerticalPaddingPx;
setLayoutParams(lp);
for (ButtonDropTarget button : mDropTargets) {
button.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.dropTargetTextSizePx);
button.setToolTipLocation(tooltipLocation);
+ button.setPadding(horizontalPadding, verticalPadding, horizontalPadding,
+ verticalPadding);
}
}
@@ -137,35 +144,76 @@
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
+ int heightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
- int visibleCount = getVisibleButtonsCount();
- if (visibleCount == 0) {
- // do nothing
- } else if (mIsVertical) {
- int widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
- int heightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
+ int visibleCount = getVisibleButtons(mTempTargets);
+ if (visibleCount == 1) {
+ int widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST);
- for (ButtonDropTarget button : mDropTargets) {
- if (button.getVisibility() != GONE) {
- button.setTextVisible(false);
- button.measure(widthSpec, heightSpec);
- }
- }
- } else {
- int availableWidth = width / visibleCount;
- boolean textVisible = true;
- for (ButtonDropTarget buttons : mDropTargets) {
- if (buttons.getVisibility() != GONE) {
- textVisible = textVisible && !buttons.isTextTruncated(availableWidth);
- }
+ ButtonDropTarget firstButton = mTempTargets[0];
+ firstButton.setTextVisible(true);
+ firstButton.setIconVisible(true);
+ firstButton.measure(widthSpec, heightSpec);
+ } else if (visibleCount == 2) {
+ DeviceProfile dp = mLauncher.getDeviceProfile();
+ int verticalPadding = dp.dropTargetVerticalPaddingPx;
+ int horizontalPadding = dp.dropTargetHorizontalPaddingPx;
+
+ ButtonDropTarget firstButton = mTempTargets[0];
+ firstButton.setTextVisible(true);
+ firstButton.setIconVisible(true);
+ firstButton.setTextMultiLine(false);
+ // Reset second button padding in case it was previously changed to multi-line text.
+ firstButton.setPadding(horizontalPadding, verticalPadding, horizontalPadding,
+ verticalPadding);
+
+ ButtonDropTarget secondButton = mTempTargets[1];
+ secondButton.setTextVisible(true);
+ secondButton.setIconVisible(true);
+ secondButton.setTextMultiLine(false);
+ // Reset second button padding in case it was previously changed to multi-line text.
+ secondButton.setPadding(horizontalPadding, verticalPadding, horizontalPadding,
+ verticalPadding);
+
+ float scale = dp.getWorkspaceSpringLoadScale();
+ int scaledPanelWidth = (int) (dp.getCellLayoutWidth() * scale);
+
+ int availableWidth;
+ if (dp.isTwoPanels) {
+ // Both buttons for two panel fit to the width of one Cell Layout (less
+ // half of the center gap between the buttons).
+ int halfButtonGap = dp.dropTargetGapPx / 2;
+ availableWidth = scaledPanelWidth - halfButtonGap / 2;
+ } else {
+ // Both buttons plus the button gap do not display past the edge of the scaled
+ // workspace, less a pre-defined gap from the edge of the workspace.
+ availableWidth = scaledPanelWidth - dp.dropTargetGapPx
+ - 2 * dp.dropTargetButtonWorkspaceEdgeGapPx;
}
int widthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST);
- int heightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
- for (ButtonDropTarget button : mDropTargets) {
- if (button.getVisibility() != GONE) {
- button.setTextVisible(textVisible);
- button.measure(widthSpec, heightSpec);
+ firstButton.measure(widthSpec, heightSpec);
+ if (!mIsVertical) {
+ // Remove icons and put the button's text on two lines if text is truncated.
+ if (firstButton.isTextTruncated(availableWidth)) {
+ firstButton.setIconVisible(false);
+ firstButton.setTextMultiLine(true);
+ firstButton.setPadding(horizontalPadding, verticalPadding / 2,
+ horizontalPadding, verticalPadding / 2);
+ }
+ }
+
+ if (!dp.isTwoPanels) {
+ availableWidth -= firstButton.getMeasuredWidth() + dp.dropTargetGapPx;
+ widthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST);
+ }
+ secondButton.measure(widthSpec, heightSpec);
+ if (!mIsVertical) {
+ if (secondButton.isTextTruncated(availableWidth)) {
+ secondButton.setIconVisible(false);
+ secondButton.setTextMultiLine(true);
+ secondButton.setPadding(horizontalPadding, verticalPadding / 2,
+ horizontalPadding, verticalPadding / 2);
}
}
}
@@ -174,41 +222,66 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- int visibleCount = getVisibleButtonsCount();
+ int visibleCount = getVisibleButtons(mTempTargets);
if (visibleCount == 0) {
- // do nothing
- } else if (mIsVertical) {
- int gap = getResources().getDimensionPixelSize(R.dimen.drop_target_vertical_gap);
- int start = gap;
- int end;
+ return;
+ }
- for (ButtonDropTarget button : mDropTargets) {
- if (button.getVisibility() != GONE) {
- end = start + button.getMeasuredHeight();
- button.layout(0, start, button.getMeasuredWidth(), end);
- start = end + gap;
- }
- }
+ DeviceProfile dp = mLauncher.getDeviceProfile();
+ // Center vertical bar over scaled workspace, accounting for hotseat offset.
+ float scale = dp.getWorkspaceSpringLoadScale();
+ Workspace<?> ws = mLauncher.getWorkspace();
+ int barCenter;
+ if (dp.isTwoPanels) {
+ barCenter = (right - left) / 2;
} else {
- int frameSize = (right - left) / visibleCount;
+ int workspaceCenter = (ws.getLeft() + ws.getRight()) / 2;
+ int cellLayoutCenter = ((dp.getInsets().left + dp.workspacePadding.left) + (dp.widthPx
+ - dp.getInsets().right - dp.workspacePadding.right)) / 2;
+ int cellLayoutCenterOffset = (int) ((cellLayoutCenter - workspaceCenter) * scale);
+ barCenter = workspaceCenter + cellLayoutCenterOffset - left;
+ }
- int start = frameSize / 2;
- int halfWidth;
- for (ButtonDropTarget button : mDropTargets) {
- if (button.getVisibility() != GONE) {
- halfWidth = button.getMeasuredWidth() / 2;
- button.layout(start - halfWidth, 0,
- start + halfWidth, button.getMeasuredHeight());
- start = start + frameSize;
- }
+ if (visibleCount == 1) {
+ ButtonDropTarget button = mTempTargets[0];
+ button.layout(barCenter - (button.getMeasuredWidth() / 2), 0,
+ barCenter + (button.getMeasuredWidth() / 2), button.getMeasuredHeight());
+ } else if (visibleCount == 2) {
+ int buttonGap = dp.dropTargetGapPx;
+
+ ButtonDropTarget leftButton = mTempTargets[0];
+ ButtonDropTarget rightButton = mTempTargets[1];
+ if (dp.isTwoPanels) {
+ leftButton.layout(barCenter - leftButton.getMeasuredWidth() - (buttonGap / 2), 0,
+ barCenter - (buttonGap / 2), leftButton.getMeasuredHeight());
+ rightButton.layout(barCenter + (buttonGap / 2), 0,
+ barCenter + (buttonGap / 2) + rightButton.getMeasuredWidth(),
+ rightButton.getMeasuredHeight());
+ } else {
+ int scaledPanelWidth = (int) (dp.getCellLayoutWidth() * scale);
+
+ int leftButtonWidth = leftButton.getMeasuredWidth();
+ int rightButtonWidth = rightButton.getMeasuredWidth();
+ int extraSpace = scaledPanelWidth - leftButtonWidth - rightButtonWidth - buttonGap;
+
+ int leftButtonStart = barCenter - (scaledPanelWidth / 2) + extraSpace / 2;
+ int leftButtonEnd = leftButtonStart + leftButtonWidth;
+ int rightButtonStart = leftButtonEnd + buttonGap;
+ int rightButtonEnd = rightButtonStart + rightButtonWidth;
+
+ leftButton.layout(leftButtonStart, 0, leftButtonEnd,
+ leftButton.getMeasuredHeight());
+ rightButton.layout(rightButtonStart, 0, rightButtonEnd,
+ rightButton.getMeasuredHeight());
}
}
}
- private int getVisibleButtonsCount() {
+ private int getVisibleButtons(ButtonDropTarget[] outVisibleButtons) {
int visibleCount = 0;
- for (ButtonDropTarget buttons : mDropTargets) {
- if (buttons.getVisibility() != GONE) {
+ for (ButtonDropTarget button : mDropTargets) {
+ if (button.getVisibility() != GONE) {
+ outVisibleButtons[visibleCount] = button;
visibleCount++;
}
}
@@ -269,7 +342,7 @@
}
public ButtonDropTarget[] getDropTargets() {
- return mDropTargets;
+ return getVisibility() == View.VISIBLE ? mDropTargets : new ButtonDropTarget[0];
}
@Override
diff --git a/src/com/android/launcher3/ExtendedEditText.java b/src/com/android/launcher3/ExtendedEditText.java
index 3b5b454..4629ca7 100644
--- a/src/com/android/launcher3/ExtendedEditText.java
+++ b/src/com/android/launcher3/ExtendedEditText.java
@@ -104,6 +104,7 @@
public void hideKeyboard() {
hideKeyboardAsync(ActivityContext.lookupContext(getContext()), getWindowToken());
+ clearFocus();
}
private boolean showSoftInput() {
diff --git a/src/com/android/launcher3/BaseRecyclerView.java b/src/com/android/launcher3/FastScrollRecyclerView.java
similarity index 89%
rename from src/com/android/launcher3/BaseRecyclerView.java
rename to src/com/android/launcher3/FastScrollRecyclerView.java
index 9369bdc..f117069 100644
--- a/src/com/android/launcher3/BaseRecyclerView.java
+++ b/src/com/android/launcher3/FastScrollRecyclerView.java
@@ -23,7 +23,7 @@
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
-import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.android.launcher3.compat.AccessibilityManagerCompat;
@@ -37,19 +37,19 @@
* <li> Enable fast scroller.
* </ul>
*/
-public abstract class BaseRecyclerView extends RecyclerView {
+public abstract class FastScrollRecyclerView extends RecyclerView {
protected RecyclerViewFastScroller mScrollbar;
- public BaseRecyclerView(Context context) {
+ public FastScrollRecyclerView(Context context) {
this(context, null);
}
- public BaseRecyclerView(Context context, AttributeSet attrs) {
+ public FastScrollRecyclerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
- public BaseRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ public FastScrollRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@@ -66,6 +66,7 @@
onUpdateScrollbar(0);
}
+ @Nullable
public RecyclerViewFastScroller getScrollbar() {
return mScrollbar;
}
@@ -197,13 +198,6 @@
if (mScrollbar != null) {
mScrollbar.reattachThumbToScroll();
}
- if (getLayoutManager() instanceof LinearLayoutManager) {
- LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
- if (layoutManager.findFirstCompletelyVisibleItemPosition() == 0) {
- // We are at the top, so don't scrollToPosition (would cause unnecessary relayout).
- return;
- }
- }
scrollToPosition(0);
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/launcher3/FirstFrameAnimatorHelper.java b/src/com/android/launcher3/FirstFrameAnimatorHelper.java
index a199a57..fdf0101 100644
--- a/src/com/android/launcher3/FirstFrameAnimatorHelper.java
+++ b/src/com/android/launcher3/FirstFrameAnimatorHelper.java
@@ -15,7 +15,7 @@
*/
package com.android.launcher3;
-import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
+import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
diff --git a/src/com/android/launcher3/GestureNavContract.java b/src/com/android/launcher3/GestureNavContract.java
index 2a7e629..c782dca 100644
--- a/src/com/android/launcher3/GestureNavContract.java
+++ b/src/com/android/launcher3/GestureNavContract.java
@@ -18,20 +18,30 @@
import static android.content.Intent.EXTRA_COMPONENT_NAME;
import static android.content.Intent.EXTRA_USER;
+import static com.android.launcher3.AbstractFloatingView.TYPE_ICON_SURFACE;
+
import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Intent;
import android.graphics.RectF;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
+import android.os.Messenger;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.view.SurfaceControl;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.launcher3.views.ActivityContext;
+
+import java.lang.ref.WeakReference;
+
/**
* Class to encapsulate the handshake protocol between Launcher and gestureNav.
*/
@@ -43,6 +53,7 @@
public static final String EXTRA_ICON_POSITION = "gesture_nav_contract_icon_position";
public static final String EXTRA_ICON_SURFACE = "gesture_nav_contract_surface_control";
public static final String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK";
+ public static final String EXTRA_ON_FINISH_CALLBACK = "gesture_nav_contract_finish_callback";
public final ComponentName componentName;
public final UserHandle user;
@@ -59,10 +70,15 @@
* Sends the position information to the receiver
*/
@TargetApi(Build.VERSION_CODES.R)
- public void sendEndPosition(RectF position, @Nullable SurfaceControl surfaceControl) {
+ public void sendEndPosition(RectF position, ActivityContext context,
+ @Nullable SurfaceControl surfaceControl) {
Bundle result = new Bundle();
result.putParcelable(EXTRA_ICON_POSITION, position);
result.putParcelable(EXTRA_ICON_SURFACE, surfaceControl);
+ if (sMessageReceiver == null) {
+ sMessageReceiver = new StaticMessageReceiver();
+ }
+ result.putParcelable(EXTRA_ON_FINISH_CALLBACK, sMessageReceiver.setCurrentContext(context));
Message callback = Message.obtain();
callback.copyFrom(mCallback);
@@ -98,4 +114,42 @@
}
return null;
}
+
+ /**
+ * Message used for receiving gesture nav contract information. We use a static messenger to
+ * avoid leaking too make binders in case the receiving launcher does not handle the contract
+ * properly.
+ */
+ private static StaticMessageReceiver sMessageReceiver = null;
+
+ private static class StaticMessageReceiver implements Handler.Callback {
+
+ private static final int MSG_CLOSE_LAST_TARGET = 0;
+
+ private final Messenger mMessenger =
+ new Messenger(new Handler(Looper.getMainLooper(), this));
+
+ private WeakReference<ActivityContext> mLastTarget = new WeakReference<>(null);
+
+ public Message setCurrentContext(ActivityContext context) {
+ mLastTarget = new WeakReference<>(context);
+
+ Message msg = Message.obtain();
+ msg.replyTo = mMessenger;
+ msg.what = MSG_CLOSE_LAST_TARGET;
+ return msg;
+ }
+
+ @Override
+ public boolean handleMessage(@NonNull Message message) {
+ if (message.what == MSG_CLOSE_LAST_TARGET) {
+ ActivityContext lastContext = mLastTarget.get();
+ if (lastContext != null) {
+ AbstractFloatingView.closeOpenViews(lastContext, false, TYPE_ICON_SURFACE);
+ }
+ return true;
+ }
+ return false;
+ }
+ }
}
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index ffe3816..76106fc 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -41,7 +41,7 @@
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mHasVerticalHotseat;
- private Workspace mWorkspace;
+ private Workspace<?> mWorkspace;
private boolean mSendTouchToWorkspace;
@Nullable
private Consumer<Boolean> mOnVisibilityAggregatedCallback;
@@ -84,6 +84,7 @@
removeAllViewsInLayout();
mHasVerticalHotseat = hasVerticalHotseat;
DeviceProfile dp = mActivity.getDeviceProfile();
+ resetCellSize(dp);
if (hasVerticalHotseat) {
setGridSize(1, dp.numShownHotseatIcons);
} else {
@@ -110,10 +111,9 @@
mQsb.setVisibility(View.VISIBLE);
lp.gravity = Gravity.BOTTOM;
lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
- lp.height = (grid.isTaskbarPresent
+ lp.height = grid.isTaskbarPresent
? grid.workspacePadding.bottom
- : grid.hotseatBarSizePx)
- + (grid.isTaskbarPresent ? grid.taskbarSize : insets.bottom);
+ : grid.hotseatBarSizePx + insets.bottom;
}
Rect padding = grid.getHotseatLayoutPadding(getContext());
@@ -122,7 +122,7 @@
InsettableFrameLayout.dispatchInsets(this, insets);
}
- public void setWorkspace(Workspace w) {
+ public void setWorkspace(Workspace<?> w) {
mWorkspace = w;
}
@@ -173,8 +173,9 @@
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- int width = getShortcutsAndWidgets().getMeasuredWidth();
- mQsb.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ int qsbWidth = mActivity.getDeviceProfile().qsbWidth;
+
+ mQsb.measure(MeasureSpec.makeMeasureSpec(qsbWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mQsbHeight, MeasureSpec.EXACTLY));
}
@@ -183,7 +184,14 @@
super.onLayout(changed, l, t, r, b);
int qsbWidth = mQsb.getMeasuredWidth();
- int left = (r - l - qsbWidth) / 2;
+ int left;
+ if (mActivity.getDeviceProfile().isQsbInline) {
+ int qsbSpace = mActivity.getDeviceProfile().hotseatBorderSpace;
+ left = Utilities.isRtl(getResources()) ? r - getPaddingRight() + qsbSpace
+ : l + getPaddingLeft() - qsbWidth - qsbSpace;
+ } else {
+ left = (r - l - qsbWidth) / 2;
+ }
int right = left + qsbWidth;
int bottom = b - t - mActivity.getDeviceProfile().getQsbOffsetY();
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index ff7a90c..db43b44 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -19,6 +19,7 @@
import static com.android.launcher3.Utilities.dpiFromPx;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TWO_PANEL_HOME;
import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
+import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
import static com.android.launcher3.util.DisplayController.CHANGE_SUPPORTED_BOUNDS;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -54,11 +55,14 @@
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.WindowBounds;
+import com.android.launcher3.util.window.WindowManagerProxy;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -94,18 +98,18 @@
// Used for arrays to specify different sizes (e.g. border spaces, width/height) in different
// constraints
- static final int COUNT_SIZES = 5;
+ static final int COUNT_SIZES = 4;
static final int INDEX_DEFAULT = 0;
static final int INDEX_LANDSCAPE = 1;
static final int INDEX_TWO_PANEL_PORTRAIT = 2;
static final int INDEX_TWO_PANEL_LANDSCAPE = 3;
- static final int INDEX_ALL_APPS = 4;
/**
* Number of icons per row and column in the workspace.
*/
public int numRows;
public int numColumns;
+ public int numSearchContainerColumns;
/**
* Number of icons per row and column in the folder.
@@ -122,15 +126,26 @@
public PointF[] borderSpaces;
public float folderBorderSpace;
+ public float[] hotseatBorderSpaces;
public float[] horizontalMargin;
+ public PointF[] allAppsCellSize;
+ public float[] allAppsIconSize;
+ public float[] allAppsIconTextSize;
+ public PointF[] allAppsBorderSpaces;
+
private SparseArray<TypedValue> mExtraAttrs;
/**
* Number of icons inside the hotseat area.
*/
- protected int numShownHotseatIcons;
+ public int numShownHotseatIcons;
+
+ /**
+ * Number of icons inside the hotseat area when using 3 buttons navigation.
+ */
+ public int numShrunkenHotseatIcons;
/**
* Number of icons inside the hotseat area that is stored in the database. This is greater than
@@ -139,6 +154,8 @@
*/
public int numDatabaseHotseatIcons;
+ public int[] hotseatColumnSpan;
+
/**
* Number of columns in the all apps list.
*/
@@ -154,6 +171,7 @@
public String dbFile;
public int defaultLayoutId;
int demoModeLayoutId;
+ boolean[] inlineQsb = new boolean[COUNT_SIZES];
/**
* An immutable list of supported profiles.
@@ -169,8 +187,7 @@
private final ArrayList<OnIDPChangeListener> mChangeListeners = new ArrayList<>();
@VisibleForTesting
- public InvariantDeviceProfile() {
- }
+ public InvariantDeviceProfile() { }
@TargetApi(23)
private InvariantDeviceProfile(Context context) {
@@ -183,7 +200,8 @@
DisplayController.INSTANCE.get(context).setPriorityListener(
(displayContext, info, flags) -> {
- if ((flags & (CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS)) != 0) {
+ if ((flags & (CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS
+ | CHANGE_NAVIGATION_MODE)) != 0) {
onConfigChanged(displayContext);
}
});
@@ -237,6 +255,8 @@
COUNT_SIZES);
System.arraycopy(defaultDisplayOption.borderSpaces, 0, result.borderSpaces, 0,
COUNT_SIZES);
+ System.arraycopy(defaultDisplayOption.inlineQsb, 0, result.inlineQsb, 0,
+ COUNT_SIZES);
initGrid(context, myInfo, result, deviceType);
}
@@ -245,11 +265,12 @@
* Reinitialize the current grid after a restore, where some grids might now be disabled.
*/
public void reinitializeAfterRestore(Context context) {
+ String currentGridName = getCurrentGridName(context);
String currentDbFile = dbFile;
- String gridName = getCurrentGridName(context);
- String newGridName = initGrid(context, gridName);
- if (!newGridName.equals(gridName)) {
- Log.d(TAG, "Restored grid is disabled : " + gridName
+ String newGridName = initGrid(context, currentGridName);
+ String newDbFile = dbFile;
+ if (!newDbFile.equals(currentDbFile)) {
+ Log.d(TAG, "Restored grid is disabled : " + currentGridName
+ ", migrating to: " + newGridName
+ ", removing all other grid db files");
for (String gridDbFile : LauncherFiles.GRID_DB_FILES) {
@@ -260,16 +281,21 @@
Log.d(TAG, "Removed old grid db file: " + gridDbFile);
}
}
- setCurrentGrid(context, gridName);
+ setCurrentGrid(context, newGridName);
}
}
private static @DeviceType int getDeviceType(Info displayInfo) {
- // Each screen has two profiles (portrait/landscape), so devices with four or more
- // supported profiles implies two or more internal displays.
- if (displayInfo.supportedBounds.size() >= 4 && ENABLE_TWO_PANEL_HOME.get()) {
+ int flagPhone = 1 << 0;
+ int flagTablet = 1 << 1;
+
+ 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()) {
+ // device has profiles supporting both phone and table modes
return TYPE_MULTI_DISPLAY;
- } else if (displayInfo.supportedBounds.stream().allMatch(displayInfo::isTablet)) {
+ } else if (type == flagTablet) {
return TYPE_TABLET;
} else {
return TYPE_PHONE;
@@ -300,6 +326,7 @@
GridOption closestProfile = displayOption.grid;
numRows = closestProfile.numRows;
numColumns = closestProfile.numColumns;
+ numSearchContainerColumns = closestProfile.numSearchContainerColumns;
dbFile = closestProfile.dbFile;
defaultLayoutId = closestProfile.defaultLayoutId;
demoModeLayoutId = closestProfile.demoModeLayoutId;
@@ -329,22 +356,31 @@
horizontalMargin = displayOption.horizontalMargin;
numShownHotseatIcons = closestProfile.numHotseatIcons;
+ numShrunkenHotseatIcons = closestProfile.numShrunkenHotseatIcons;
numDatabaseHotseatIcons = deviceType == TYPE_MULTI_DISPLAY
? closestProfile.numDatabaseHotseatIcons : closestProfile.numHotseatIcons;
+ hotseatColumnSpan = closestProfile.hotseatColumnSpan;
+ hotseatBorderSpaces = displayOption.hotseatBorderSpaces;
numAllAppsColumns = closestProfile.numAllAppsColumns;
numDatabaseAllAppsColumns = deviceType == TYPE_MULTI_DISPLAY
? closestProfile.numDatabaseAllAppsColumns : closestProfile.numAllAppsColumns;
+ allAppsCellSize = displayOption.allAppsCellSize;
+ allAppsBorderSpaces = displayOption.allAppsBorderSpaces;
+ allAppsIconSize = displayOption.allAppsIconSizes;
+ allAppsIconTextSize = displayOption.allAppsIconTextSizes;
if (!Utilities.isGridOptionsEnabled(context)) {
- iconSize[INDEX_ALL_APPS] = iconSize[INDEX_DEFAULT];
- iconTextSize[INDEX_ALL_APPS] = iconTextSize[INDEX_DEFAULT];
+ allAppsIconSize = iconSize;
+ allAppsIconTextSize = iconTextSize;
}
if (devicePaddingId != 0) {
devicePaddings = new DevicePaddings(context, devicePaddingId);
}
+ inlineQsb = displayOption.inlineQsb;
+
// If the partner customization apk contains any grid overrides, apply them
// Supported overrides: numRows, numColumns, iconSize
applyPartnerDeviceProfileOverrides(context, metrics);
@@ -354,7 +390,8 @@
for (WindowBounds bounds : displayInfo.supportedBounds) {
localSupportedProfiles.add(new DeviceProfile.Builder(context, this, displayInfo)
.setUseTwoPanels(deviceType == TYPE_MULTI_DISPLAY)
- .setWindowBounds(bounds).build());
+ .setWindowBounds(bounds)
+ .build());
// Wallpaper size should be the maximum of the all possible sizes Launcher expects
int displayWidth = bounds.bounds.width();
@@ -364,7 +401,8 @@
// We need to ensure that there is enough extra space in the wallpaper
// for the intended parallax effects
float parallaxFactor =
- dpiFromPx(Math.min(displayWidth, displayHeight), displayInfo.densityDpi) < 720
+ dpiFromPx(Math.min(displayWidth, displayHeight), displayInfo.getDensityDpi())
+ < 720
? 2
: wallpaperTravelToScreenWidthRatio(displayWidth, displayHeight);
defaultWallpaperSize.x =
@@ -393,8 +431,8 @@
private Object[] toModelState() {
return new Object[]{
- numColumns, numRows, numDatabaseHotseatIcons, iconBitmapSize, fillResIconDpi,
- numDatabaseAllAppsColumns, dbFile};
+ numColumns, numRows, numSearchContainerColumns, numDatabaseHotseatIcons,
+ iconBitmapSize, fillResIconDpi, numDatabaseAllAppsColumns, dbFile};
}
private void onConfigChanged(Context context) {
@@ -553,8 +591,8 @@
}
}
- float width = dpiFromPx(minWidthPx, displayInfo.densityDpi);
- float height = dpiFromPx(minHeightPx, displayInfo.densityDpi);
+ float width = dpiFromPx(minWidthPx, displayInfo.getDensityDpi());
+ float height = dpiFromPx(minHeightPx, displayInfo.getDensityDpi());
// Sort the profiles based on the closeness to the device size
Collections.sort(points, (a, b) ->
@@ -593,10 +631,27 @@
float screenWidth = config.screenWidthDp * res.getDisplayMetrics().density;
float screenHeight = config.screenHeightDp * res.getDisplayMetrics().density;
- return getBestMatch(screenWidth, screenHeight);
+ int rotation = WindowManagerProxy.INSTANCE.get(context).getRotation(context);
+
+ if (Utilities.IS_DEBUG_DEVICE) {
+ StringWriter stringWriter = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(stringWriter);
+ DisplayController.INSTANCE.get(context).dump(printWriter);
+ printWriter.flush();
+ Log.d("b/231312158", "getDeviceProfile -"
+ + "\nconfig: " + config
+ + "\ndisplayMetrics: " + res.getDisplayMetrics()
+ + "\nrotation: " + rotation
+ + "\n" + stringWriter.toString(),
+ new Exception());
+ }
+ return getBestMatch(screenWidth, screenHeight, rotation);
}
- public DeviceProfile getBestMatch(float screenWidth, float screenHeight) {
+ /**
+ * Returns the device profile matching the provided screen configuration
+ */
+ public DeviceProfile getBestMatch(float screenWidth, float screenHeight, int rotation) {
DeviceProfile bestMatch = supportedProfiles.get(0);
float minDiff = Float.MAX_VALUE;
@@ -606,6 +661,8 @@
if (diff < minDiff) {
minDiff = diff;
bestMatch = profile;
+ } else if (diff == minDiff && profile.rotationHint == rotation) {
+ bestMatch = profile;
}
}
return bestMatch;
@@ -671,6 +728,7 @@
public final String name;
public final int numRows;
public final int numColumns;
+ public final int numSearchContainerColumns;
public final boolean isEnabled;
private final int numFolderRows;
@@ -679,7 +737,9 @@
private final int numAllAppsColumns;
private final int numDatabaseAllAppsColumns;
private final int numHotseatIcons;
+ private final int numShrunkenHotseatIcons;
private final int numDatabaseHotseatIcons;
+ private final int[] hotseatColumnSpan = new int[COUNT_SIZES];
private final String dbFile;
@@ -697,6 +757,8 @@
name = a.getString(R.styleable.GridDisplayOption_name);
numRows = a.getInt(R.styleable.GridDisplayOption_numRows, 0);
numColumns = a.getInt(R.styleable.GridDisplayOption_numColumns, 0);
+ numSearchContainerColumns = a.getInt(
+ R.styleable.GridDisplayOption_numSearchContainerColumns, numColumns);
dbFile = a.getString(R.styleable.GridDisplayOption_dbFile);
defaultLayoutId = a.getResourceId(deviceType == TYPE_MULTI_DISPLAY && a.hasValue(
@@ -713,8 +775,20 @@
numHotseatIcons = a.getInt(
R.styleable.GridDisplayOption_numHotseatIcons, numColumns);
+ numShrunkenHotseatIcons = a.getInt(
+ R.styleable.GridDisplayOption_numShrunkenHotseatIcons, numHotseatIcons / 2);
numDatabaseHotseatIcons = a.getInt(
R.styleable.GridDisplayOption_numExtendedHotseatIcons, 2 * numHotseatIcons);
+ hotseatColumnSpan[INDEX_DEFAULT] = a.getInt(
+ R.styleable.GridDisplayOption_hotseatColumnSpan, numColumns);
+ hotseatColumnSpan[INDEX_LANDSCAPE] = a.getInt(
+ R.styleable.GridDisplayOption_hotseatColumnSpanLandscape, numColumns);
+ hotseatColumnSpan[INDEX_TWO_PANEL_LANDSCAPE] = a.getInt(
+ R.styleable.GridDisplayOption_hotseatColumnSpanTwoPanelLandscape,
+ numColumns);
+ hotseatColumnSpan[INDEX_TWO_PANEL_PORTRAIT] = a.getInt(
+ R.styleable.GridDisplayOption_hotseatColumnSpanTwoPanelPortrait,
+ numColumns);
numFolderRows = a.getInt(
R.styleable.GridDisplayOption_numFolderRows, numRows);
@@ -744,22 +818,35 @@
@VisibleForTesting
static final class DisplayOption {
+ private static final int INLINE_QSB_FOR_PORTRAIT = 1 << 0;
+ private static final int INLINE_QSB_FOR_LANDSCAPE = 1 << 1;
+ private static final int INLINE_QSB_FOR_TWO_PANEL_PORTRAIT = 1 << 2;
+ private static final int INLINE_QSB_FOR_TWO_PANEL_LANDSCAPE = 1 << 3;
+ private static final int DONT_INLINE_QSB = 0;
public final GridOption grid;
private final float minWidthDps;
private final float minHeightDps;
private final boolean canBeDefault;
+ private final boolean[] inlineQsb = new boolean[COUNT_SIZES];
private final PointF[] minCellSize = new PointF[COUNT_SIZES];
private float folderBorderSpace;
private final PointF[] borderSpaces = new PointF[COUNT_SIZES];
private final float[] horizontalMargin = new float[COUNT_SIZES];
+ //TODO(http://b/228998082) remove this when 3 button spaces are fixed
+ private final float[] hotseatBorderSpaces = new float[COUNT_SIZES];
private final float[] iconSizes = new float[COUNT_SIZES];
private final float[] textSizes = new float[COUNT_SIZES];
+ private final PointF[] allAppsCellSize = new PointF[COUNT_SIZES];
+ private final float[] allAppsIconSizes = new float[COUNT_SIZES];
+ private final float[] allAppsIconTextSizes = new float[COUNT_SIZES];
+ private final PointF[] allAppsBorderSpaces = new PointF[COUNT_SIZES];
+
DisplayOption(GridOption grid, Context context, AttributeSet attrs) {
this.grid = grid;
@@ -770,100 +857,212 @@
canBeDefault = a.getBoolean(R.styleable.ProfileDisplayOption_canBeDefault, false);
+ int inlineForRotation = a.getInt(R.styleable.ProfileDisplayOption_inlineQsb,
+ DONT_INLINE_QSB);
+ inlineQsb[INDEX_DEFAULT] =
+ (inlineForRotation & INLINE_QSB_FOR_PORTRAIT) == INLINE_QSB_FOR_PORTRAIT;
+ inlineQsb[INDEX_LANDSCAPE] =
+ (inlineForRotation & INLINE_QSB_FOR_LANDSCAPE) == INLINE_QSB_FOR_LANDSCAPE;
+ inlineQsb[INDEX_TWO_PANEL_PORTRAIT] =
+ (inlineForRotation & INLINE_QSB_FOR_TWO_PANEL_PORTRAIT)
+ == INLINE_QSB_FOR_TWO_PANEL_PORTRAIT;
+ inlineQsb[INDEX_TWO_PANEL_LANDSCAPE] =
+ (inlineForRotation & INLINE_QSB_FOR_TWO_PANEL_LANDSCAPE)
+ == INLINE_QSB_FOR_TWO_PANEL_LANDSCAPE;
+
float x;
float y;
- x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthDps, 0);
- y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightDps, 0);
+ x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidth, 0);
+ y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeight, 0);
minCellSize[INDEX_DEFAULT] = new PointF(x, y);
- minCellSize[INDEX_LANDSCAPE] = new PointF(x, y);
- minCellSize[INDEX_ALL_APPS] = new PointF(x, y);
- x = a.getFloat(R.styleable.ProfileDisplayOption_twoPanelPortraitMinCellWidthDps,
+ x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthLandscape,
minCellSize[INDEX_DEFAULT].x);
- y = a.getFloat(R.styleable.ProfileDisplayOption_twoPanelPortraitMinCellHeightDps,
+ y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightLandscape,
+ minCellSize[INDEX_DEFAULT].y);
+ minCellSize[INDEX_LANDSCAPE] = new PointF(x, y);
+
+ x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthTwoPanelPortrait,
+ minCellSize[INDEX_DEFAULT].x);
+ y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightTwoPanelPortrait,
minCellSize[INDEX_DEFAULT].y);
minCellSize[INDEX_TWO_PANEL_PORTRAIT] = new PointF(x, y);
- x = a.getFloat(R.styleable.ProfileDisplayOption_twoPanelLandscapeMinCellWidthDps,
+ x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthTwoPanelLandscape,
minCellSize[INDEX_DEFAULT].x);
- y = a.getFloat(R.styleable.ProfileDisplayOption_twoPanelLandscapeMinCellHeightDps,
+ y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightTwoPanelLandscape,
minCellSize[INDEX_DEFAULT].y);
minCellSize[INDEX_TWO_PANEL_LANDSCAPE] = new PointF(x, y);
- float borderSpace = a.getFloat(R.styleable.ProfileDisplayOption_borderSpaceDps, 0);
- float twoPanelPortraitBorderSpaceDps = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelPortraitBorderSpaceDps, borderSpace);
- float twoPanelLandscapeBorderSpaceDps = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelLandscapeBorderSpaceDps, borderSpace);
+ float borderSpace = a.getFloat(R.styleable.ProfileDisplayOption_borderSpace, 0);
+ float borderSpaceLandscape = a.getFloat(
+ R.styleable.ProfileDisplayOption_borderSpaceLandscape, borderSpace);
+ float borderSpaceTwoPanelPortrait = a.getFloat(
+ R.styleable.ProfileDisplayOption_borderSpaceTwoPanelPortrait, borderSpace);
+ float borderSpaceTwoPanelLandscape = a.getFloat(
+ R.styleable.ProfileDisplayOption_borderSpaceTwoPanelLandscape, borderSpace);
- x = a.getFloat(R.styleable.ProfileDisplayOption_borderSpaceHorizontalDps, borderSpace);
- y = a.getFloat(R.styleable.ProfileDisplayOption_borderSpaceVerticalDps, borderSpace);
+ x = a.getFloat(R.styleable.ProfileDisplayOption_borderSpaceHorizontal, borderSpace);
+ y = a.getFloat(R.styleable.ProfileDisplayOption_borderSpaceVertical, borderSpace);
borderSpaces[INDEX_DEFAULT] = new PointF(x, y);
+
+ x = a.getFloat(R.styleable.ProfileDisplayOption_borderSpaceLandscapeHorizontal,
+ borderSpaceLandscape);
+ y = a.getFloat(R.styleable.ProfileDisplayOption_borderSpaceLandscapeVertical,
+ borderSpaceLandscape);
borderSpaces[INDEX_LANDSCAPE] = new PointF(x, y);
x = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelPortraitBorderSpaceHorizontalDps,
- twoPanelPortraitBorderSpaceDps);
+ R.styleable.ProfileDisplayOption_borderSpaceTwoPanelPortraitHorizontal,
+ borderSpaceTwoPanelPortrait);
y = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelPortraitBorderSpaceVerticalDps,
- twoPanelPortraitBorderSpaceDps);
+ R.styleable.ProfileDisplayOption_borderSpaceTwoPanelPortraitVertical,
+ borderSpaceTwoPanelPortrait);
borderSpaces[INDEX_TWO_PANEL_PORTRAIT] = new PointF(x, y);
x = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelLandscapeBorderSpaceHorizontalDps,
- twoPanelLandscapeBorderSpaceDps);
+ R.styleable.ProfileDisplayOption_borderSpaceTwoPanelLandscapeHorizontal,
+ borderSpaceTwoPanelLandscape);
y = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelLandscapeBorderSpaceVerticalDps,
- twoPanelLandscapeBorderSpaceDps);
+ R.styleable.ProfileDisplayOption_borderSpaceTwoPanelLandscapeVertical,
+ borderSpaceTwoPanelLandscape);
borderSpaces[INDEX_TWO_PANEL_LANDSCAPE] = new PointF(x, y);
- x = y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellSpacingDps,
- borderSpace);
- borderSpaces[INDEX_ALL_APPS] = new PointF(x, y);
folderBorderSpace = borderSpace;
+ x = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellWidth,
+ minCellSize[INDEX_DEFAULT].x);
+ y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellHeight,
+ minCellSize[INDEX_DEFAULT].y);
+ allAppsCellSize[INDEX_DEFAULT] = new PointF(x, y);
+
+ x = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellWidthLandscape,
+ allAppsCellSize[INDEX_DEFAULT].x);
+ y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellHeightLandscape,
+ allAppsCellSize[INDEX_DEFAULT].y);
+ allAppsCellSize[INDEX_LANDSCAPE] = new PointF(x, y);
+
+ x = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellWidthTwoPanelPortrait,
+ allAppsCellSize[INDEX_DEFAULT].x);
+ y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellHeightTwoPanelPortrait,
+ allAppsCellSize[INDEX_DEFAULT].y);
+ allAppsCellSize[INDEX_TWO_PANEL_PORTRAIT] = new PointF(x, y);
+
+ x = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellWidthTwoPanelLandscape,
+ allAppsCellSize[INDEX_DEFAULT].x);
+ y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellHeightTwoPanelLandscape,
+ allAppsCellSize[INDEX_DEFAULT].y);
+ allAppsCellSize[INDEX_TWO_PANEL_LANDSCAPE] = new PointF(x, y);
+
+ float allAppsBorderSpace = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsBorderSpace, borderSpace);
+ float allAppsBorderSpaceLandscape = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsBorderSpaceLandscape,
+ allAppsBorderSpace);
+ float allAppsBorderSpaceTwoPanelPortrait = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsBorderSpaceTwoPanelPortrait,
+ allAppsBorderSpace);
+ float allAppsBorderSpaceTwoPanelLandscape = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsBorderSpaceTwoPanelLandscape,
+ allAppsBorderSpace);
+
+ x = a.getFloat(R.styleable.ProfileDisplayOption_allAppsBorderSpaceHorizontal,
+ allAppsBorderSpace);
+ y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsBorderSpaceVertical,
+ allAppsBorderSpace);
+ allAppsBorderSpaces[INDEX_DEFAULT] = new PointF(x, y);
+
+ x = a.getFloat(R.styleable.ProfileDisplayOption_allAppsBorderSpaceLandscapeHorizontal,
+ allAppsBorderSpaceLandscape);
+ y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsBorderSpaceLandscapeVertical,
+ allAppsBorderSpaceLandscape);
+ allAppsBorderSpaces[INDEX_LANDSCAPE] = new PointF(x, y);
+
+ x = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsBorderSpaceTwoPanelPortraitHorizontal,
+ allAppsBorderSpaceTwoPanelPortrait);
+ y = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsBorderSpaceTwoPanelPortraitVertical,
+ allAppsBorderSpaceTwoPanelPortrait);
+ allAppsBorderSpaces[INDEX_TWO_PANEL_PORTRAIT] = new PointF(x, y);
+
+ x = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsBorderSpaceTwoPanelLandscapeHorizontal,
+ allAppsBorderSpaceTwoPanelLandscape);
+ y = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsBorderSpaceTwoPanelLandscapeVertical,
+ allAppsBorderSpaceTwoPanelLandscape);
+ allAppsBorderSpaces[INDEX_TWO_PANEL_LANDSCAPE] = new PointF(x, y);
+
iconSizes[INDEX_DEFAULT] =
a.getFloat(R.styleable.ProfileDisplayOption_iconImageSize, 0);
iconSizes[INDEX_LANDSCAPE] =
- a.getFloat(R.styleable.ProfileDisplayOption_landscapeIconSize,
- iconSizes[INDEX_DEFAULT]);
- iconSizes[INDEX_ALL_APPS] =
- a.getFloat(R.styleable.ProfileDisplayOption_allAppsIconSize,
+ a.getFloat(R.styleable.ProfileDisplayOption_iconSizeLandscape,
iconSizes[INDEX_DEFAULT]);
iconSizes[INDEX_TWO_PANEL_PORTRAIT] =
- a.getFloat(R.styleable.ProfileDisplayOption_twoPanelPortraitIconSize,
+ a.getFloat(R.styleable.ProfileDisplayOption_iconSizeTwoPanelPortrait,
iconSizes[INDEX_DEFAULT]);
iconSizes[INDEX_TWO_PANEL_LANDSCAPE] =
- a.getFloat(R.styleable.ProfileDisplayOption_twoPanelLandscapeIconSize,
+ a.getFloat(R.styleable.ProfileDisplayOption_iconSizeTwoPanelLandscape,
iconSizes[INDEX_DEFAULT]);
+ allAppsIconSizes[INDEX_DEFAULT] = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsIconSize, iconSizes[INDEX_DEFAULT]);
+ allAppsIconSizes[INDEX_LANDSCAPE] = allAppsIconSizes[INDEX_DEFAULT];
+ allAppsIconSizes[INDEX_TWO_PANEL_PORTRAIT] = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsIconSizeTwoPanelPortrait,
+ allAppsIconSizes[INDEX_DEFAULT]);
+ allAppsIconSizes[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsIconSizeTwoPanelLandscape,
+ allAppsIconSizes[INDEX_DEFAULT]);
+
textSizes[INDEX_DEFAULT] =
a.getFloat(R.styleable.ProfileDisplayOption_iconTextSize, 0);
textSizes[INDEX_LANDSCAPE] =
- a.getFloat(R.styleable.ProfileDisplayOption_landscapeIconTextSize,
- textSizes[INDEX_DEFAULT]);
- textSizes[INDEX_ALL_APPS] =
- a.getFloat(R.styleable.ProfileDisplayOption_allAppsIconTextSize,
+ a.getFloat(R.styleable.ProfileDisplayOption_iconTextSizeLandscape,
textSizes[INDEX_DEFAULT]);
textSizes[INDEX_TWO_PANEL_PORTRAIT] =
- a.getFloat(R.styleable.ProfileDisplayOption_twoPanelPortraitIconTextSize,
+ a.getFloat(R.styleable.ProfileDisplayOption_iconTextSizeTwoPanelPortrait,
textSizes[INDEX_DEFAULT]);
textSizes[INDEX_TWO_PANEL_LANDSCAPE] =
- a.getFloat(R.styleable.ProfileDisplayOption_twoPanelLandscapeIconTextSize,
+ a.getFloat(R.styleable.ProfileDisplayOption_iconTextSizeTwoPanelLandscape,
textSizes[INDEX_DEFAULT]);
+ allAppsIconTextSizes[INDEX_DEFAULT] = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsIconTextSize, textSizes[INDEX_DEFAULT]);
+ allAppsIconTextSizes[INDEX_LANDSCAPE] = allAppsIconTextSizes[INDEX_DEFAULT];
+ allAppsIconTextSizes[INDEX_TWO_PANEL_PORTRAIT] = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsIconTextSizeTwoPanelPortrait,
+ allAppsIconTextSizes[INDEX_DEFAULT]);
+ allAppsIconTextSizes[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
+ R.styleable.ProfileDisplayOption_allAppsIconTextSizeTwoPanelLandscape,
+ allAppsIconTextSizes[INDEX_DEFAULT]);
+
horizontalMargin[INDEX_DEFAULT] = a.getFloat(
R.styleable.ProfileDisplayOption_horizontalMargin, 0);
- horizontalMargin[INDEX_LANDSCAPE] = horizontalMargin[INDEX_DEFAULT];
- horizontalMargin[INDEX_ALL_APPS] = horizontalMargin[INDEX_DEFAULT];
+ horizontalMargin[INDEX_LANDSCAPE] = a.getFloat(
+ R.styleable.ProfileDisplayOption_horizontalMarginLandscape,
+ horizontalMargin[INDEX_DEFAULT]);
horizontalMargin[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelLandscapeHorizontalMargin,
+ R.styleable.ProfileDisplayOption_horizontalMarginTwoPanelLandscape,
horizontalMargin[INDEX_DEFAULT]);
horizontalMargin[INDEX_TWO_PANEL_PORTRAIT] = a.getFloat(
- R.styleable.ProfileDisplayOption_twoPanelPortraitHorizontalMargin,
+ R.styleable.ProfileDisplayOption_horizontalMarginTwoPanelPortrait,
horizontalMargin[INDEX_DEFAULT]);
+ hotseatBorderSpaces[INDEX_DEFAULT] = a.getFloat(
+ R.styleable.ProfileDisplayOption_hotseatBorderSpace, borderSpace);
+ hotseatBorderSpaces[INDEX_LANDSCAPE] = a.getFloat(
+ R.styleable.ProfileDisplayOption_hotseatBorderSpaceLandscape,
+ hotseatBorderSpaces[INDEX_DEFAULT]);
+ hotseatBorderSpaces[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
+ R.styleable.ProfileDisplayOption_hotseatBorderSpaceTwoPanelLandscape,
+ hotseatBorderSpaces[INDEX_DEFAULT]);
+ hotseatBorderSpaces[INDEX_TWO_PANEL_PORTRAIT] = a.getFloat(
+ R.styleable.ProfileDisplayOption_hotseatBorderSpaceTwoPanelPortrait,
+ hotseatBorderSpaces[INDEX_DEFAULT]);
+
a.recycle();
}
@@ -881,6 +1080,11 @@
textSizes[i] = 0;
borderSpaces[i] = new PointF();
minCellSize[i] = new PointF();
+ allAppsCellSize[i] = new PointF();
+ allAppsIconSizes[i] = 0;
+ allAppsIconTextSizes[i] = 0;
+ allAppsBorderSpaces[i] = new PointF();
+ inlineQsb[i] = false;
}
}
@@ -893,6 +1097,13 @@
minCellSize[i].x *= w;
minCellSize[i].y *= w;
horizontalMargin[i] *= w;
+ hotseatBorderSpaces[i] *= w;
+ allAppsCellSize[i].x *= w;
+ allAppsCellSize[i].y *= w;
+ allAppsIconSizes[i] *= w;
+ allAppsIconTextSizes[i] *= w;
+ allAppsBorderSpaces[i].x *= w;
+ allAppsBorderSpaces[i].y *= w;
}
folderBorderSpace *= w;
@@ -909,6 +1120,14 @@
minCellSize[i].x += p.minCellSize[i].x;
minCellSize[i].y += p.minCellSize[i].y;
horizontalMargin[i] += p.horizontalMargin[i];
+ hotseatBorderSpaces[i] += p.hotseatBorderSpaces[i];
+ allAppsCellSize[i].x += p.allAppsCellSize[i].x;
+ allAppsCellSize[i].y += p.allAppsCellSize[i].y;
+ allAppsIconSizes[i] += p.allAppsIconSizes[i];
+ allAppsIconTextSizes[i] += p.allAppsIconTextSizes[i];
+ allAppsBorderSpaces[i].x += p.allAppsBorderSpaces[i].x;
+ allAppsBorderSpaces[i].y += p.allAppsBorderSpaces[i].y;
+ inlineQsb[i] |= p.inlineQsb[i];
}
folderBorderSpace += p.folderBorderSpace;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 87eb222..ebed31b 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import static android.app.PendingIntent.FLAG_IMMUTABLE;
+import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
@@ -40,8 +42,7 @@
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.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
-import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOAD;
+import static com.android.launcher3.logging.StatsLogManager.EventEnum;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_ENTRY;
@@ -63,7 +64,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.app.Notification;
@@ -107,6 +107,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver.OnPreDrawListener;
import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.OvershootInterpolator;
@@ -120,13 +121,14 @@
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.accessibility.BaseAccessibilityDelegate.LauncherAction;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
-import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.LauncherAction;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
+import com.android.launcher3.allapps.AllAppsRecyclerView;
import com.android.launcher3.allapps.AllAppsStore;
import com.android.launcher3.allapps.AllAppsTransitionController;
+import com.android.launcher3.allapps.BaseAllAppsContainerView;
import com.android.launcher3.allapps.DiscoveryBounce;
-import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.PropertyListBuilder;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
@@ -142,6 +144,8 @@
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
import com.android.launcher3.logger.LauncherAtom;
+import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
+import com.android.launcher3.logger.LauncherAtom.WorkspaceContainer;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
@@ -150,6 +154,7 @@
import com.android.launcher3.model.ItemInstallQueue;
import com.android.launcher3.model.ModelUtils;
import com.android.launcher3.model.ModelWriter;
+import com.android.launcher3.model.StringCache;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
@@ -178,9 +183,6 @@
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
-import com.android.launcher3.util.ItemInfoMatcher;
-import com.android.launcher3.util.MultiValueAlpha;
-import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.PackageUserKey;
@@ -195,6 +197,7 @@
import com.android.launcher3.util.UiThreadHelper;
import com.android.launcher3.util.ViewOnDrawExecutor;
import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.FloatingIconView;
import com.android.launcher3.views.FloatingSurfaceView;
import com.android.launcher3.views.OptionsPopupView;
import com.android.launcher3.views.ScrimView;
@@ -209,7 +212,7 @@
import com.android.launcher3.widget.custom.CustomWidgetManager;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.widget.picker.WidgetsFullSheet;
-import com.android.systemui.plugins.OverlayPlugin;
+import com.android.systemui.plugins.LauncherOverlayPlugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.shared.LauncherExterns;
import com.android.systemui.plugins.shared.LauncherOverlayManager;
@@ -224,6 +227,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Optional;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
@@ -231,9 +235,9 @@
/**
* Default launcher application.
*/
-public class Launcher extends StatefulActivity<LauncherState> implements LauncherExterns,
- Callbacks, InvariantDeviceProfile.OnIDPChangeListener, PluginListener<OverlayPlugin>,
- LauncherOverlayCallbacks {
+public class Launcher extends StatefulActivity<LauncherState>
+ implements LauncherExterns, Callbacks, InvariantDeviceProfile.OnIDPChangeListener,
+ PluginListener<LauncherOverlayPlugin>, LauncherOverlayCallbacks {
public static final String TAG = "Launcher";
public static final ActivityTracker<Launcher> ACTIVITY_TRACKER = new ActivityTracker<>();
@@ -298,7 +302,7 @@
private Configuration mOldConfig;
@Thunk
- Workspace mWorkspace;
+ Workspace<?> mWorkspace;
@Thunk
DragLayer mDragLayer;
private DragController mDragController;
@@ -315,7 +319,7 @@
// Main container view for the all apps screen.
@Thunk
- AllAppsContainerView mAppsView;
+ ActivityAllAppsContainerView<Launcher> mAppsView;
AllAppsTransitionController mAllAppsController;
// Scrim view for the all apps and overview state.
@@ -333,6 +337,7 @@
private Runnable mOnDeferredActivityLaunchCallback;
private ViewOnDrawExecutor mPendingExecutor;
+ private OnPreDrawListener mOnInitialBindListener;
private LauncherModel mModel;
private ModelWriter mModelWriter;
@@ -347,7 +352,7 @@
// We only want to get the SharedPreferences once since it does an FS stat each time we get
// it from the context.
private SharedPreferences mSharedPrefs;
- private OnboardingPrefs mOnboardingPrefs;
+ private OnboardingPrefs<? extends Launcher> mOnboardingPrefs;
// Activity result which needs to be processed after workspace has loaded.
private ActivityResultInfo mPendingActivityResult;
@@ -380,6 +385,8 @@
protected InstanceId mAllAppsSessionLogId;
private LauncherState mPrevLauncherState;
+ private StringCache mStringCache;
+
@Override
@TargetApi(Build.VERSION_CODES.S)
protected void onCreate(Bundle savedInstanceState) {
@@ -426,8 +433,7 @@
shareIntent.putExtra(Intent.EXTRA_TEXT, stackTrace);
shareIntent = Intent.createChooser(shareIntent, null);
PendingIntent sharePendingIntent = PendingIntent.getActivity(
- this, 0, shareIntent, PendingIntent.FLAG_UPDATE_CURRENT
- );
+ this, 0, shareIntent, FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE);
Notification notification = new Notification.Builder(this, notificationChannelId)
.setSmallIcon(android.R.drawable.ic_menu_close_clear_cancel)
@@ -494,11 +500,10 @@
if (!mModel.addCallbacksAndLoad(this)) {
if (!internalStateHandled) {
- Log.d(BAD_STATE, "Launcher onCreate not binding sync, setting DragLayer alpha "
- + "ALPHA_INDEX_LAUNCHER_LOAD to 0");
- // If we are not binding synchronously, show a fade in animation when
- // the first page bind completes.
- mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD).setValue(0);
+ Log.d(BAD_STATE, "Launcher onCreate not binding sync, prevent drawing");
+ // If we are not binding synchronously, pause drawing until initial bind complete,
+ // so that the system could continue to show the device loading prompt
+ mOnInitialBindListener = Boolean.FALSE::booleanValue;
}
}
@@ -506,6 +511,9 @@
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
setContentView(getRootView());
+ if (mOnInitialBindListener != null) {
+ getRootView().getViewTreeObserver().addOnPreDrawListener(mOnInitialBindListener);
+ }
getRootView().dispatchInsets();
// Listen for broadcasts
@@ -519,7 +527,7 @@
}
mOverlayManager = getDefaultOverlay();
PluginManagerWrapper.INSTANCE.get(this).addPluginListener(this,
- OverlayPlugin.class, false /* allowedMultiple */);
+ LauncherOverlayPlugin.class, false /* allowedMultiple */);
mRotationHelper.initialize();
TraceHelper.INSTANCE.endSection(traceToken);
@@ -530,27 +538,29 @@
if (Utilities.ATLEAST_R) {
getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
}
+ setTitle(R.string.home_screen);
}
protected LauncherOverlayManager getDefaultOverlay() {
return new LauncherOverlayManager() { };
}
- protected OnboardingPrefs createOnboardingPrefs(SharedPreferences sharedPrefs) {
+ protected OnboardingPrefs<? extends Launcher> createOnboardingPrefs(
+ SharedPreferences sharedPrefs) {
return new OnboardingPrefs<>(this, sharedPrefs);
}
- public OnboardingPrefs getOnboardingPrefs() {
+ public OnboardingPrefs<? extends Launcher> getOnboardingPrefs() {
return mOnboardingPrefs;
}
@Override
- public void onPluginConnected(OverlayPlugin overlayManager, Context context) {
+ public void onPluginConnected(LauncherOverlayPlugin overlayManager, Context context) {
switchOverlay(() -> overlayManager.createOverlayManager(this, this));
}
@Override
- public void onPluginDisconnected(OverlayPlugin plugin) {
+ public void onPluginDisconnected(LauncherOverlayPlugin plugin) {
switchOverlay(this::getDefaultOverlay);
}
@@ -567,7 +577,7 @@
}
@Override
- protected void dispatchDeviceProfileChanged() {
+ public void dispatchDeviceProfileChanged() {
super.dispatchDeviceProfileChanged();
mOverlayManager.onDeviceProvideChanged();
}
@@ -576,7 +586,13 @@
public void onEnterAnimationComplete() {
super.onEnterAnimationComplete();
mRotationHelper.setCurrentTransitionRequest(REQUEST_NONE);
- AbstractFloatingView.closeOpenViews(this, false, TYPE_ICON_SURFACE);
+ // Starting with Android S, onEnterAnimationComplete is sent immediately
+ // causing the surface to get removed before the animation completed (b/175345344).
+ // Instead we rely on next user touch event to remove the view and optionally a callback
+ // from system from Android T onwards.
+ if (!Utilities.ATLEAST_S) {
+ AbstractFloatingView.closeOpenViews(this, false, TYPE_ICON_SURFACE);
+ }
}
@Override
@@ -623,7 +639,7 @@
mDragLayer.onOneHandedModeStateChanged(activated);
}
- private void initDeviceProfile(InvariantDeviceProfile idp) {
+ protected void initDeviceProfile(InvariantDeviceProfile idp) {
// Load configuration-specific DeviceProfile
mDeviceProfile = idp.getDeviceProfile(this);
if (isInMultiWindowMode()) {
@@ -677,6 +693,8 @@
return !isWorkspaceLoading();
}
+ @NonNull
+ @Override
public PopupDataProvider getPopupDataProvider() {
return mPopupDataProvider;
}
@@ -956,7 +974,7 @@
hideKeyboard();
logStopAndResume(false /* isResume */);
mAppWidgetHost.setActivityStarted(false);
- NotificationListener.removeNotificationsChangedListener();
+ NotificationListener.removeNotificationsChangedListener(getPopupDataProvider());
}
@Override
@@ -985,13 +1003,10 @@
mModel.validateModelDataOnResume();
// Set the notification listener and fetch updated notifications when we resume
- NotificationListener.setNotificationsChangedListener(mPopupDataProvider);
+ NotificationListener.addNotificationsChangedListener(mPopupDataProvider);
DiscoveryBounce.showForHomeIfNeeded(this);
mAppWidgetHost.setActivityResumed(true);
-
- // Temporary workaround for apps using SHOW_FORCED IME flag.
- hideKeyboard();
}
private void logStopAndResume(boolean isResume) {
@@ -1087,14 +1102,25 @@
&& mAllAppsSessionLogId == null) {
// creates new instance ID since new all apps session is started.
mAllAppsSessionLogId = new InstanceIdSequence().newInstanceId();
- getStatsLogManager()
- .logger()
- .log(FeatureFlags.ENABLE_DEVICE_SEARCH.get()
- ? LAUNCHER_ALLAPPS_ENTRY_WITH_DEVICE_SEARCH
- : LAUNCHER_ALLAPPS_ENTRY);
+ if (getAllAppsEntryEvent().isPresent()) {
+ getStatsLogManager().logger()
+ .withContainerInfo(ContainerInfo.newBuilder()
+ .setWorkspace(WorkspaceContainer.newBuilder()
+ .setPageIndex(getWorkspace().getCurrentPage())).build())
+ .log(getAllAppsEntryEvent().get());
+ }
}
}
+ /**
+ * Returns {@link EventEnum} that should be logged when Launcher enters into AllApps state.
+ */
+ protected Optional<EventEnum> getAllAppsEntryEvent() {
+ return Optional.of(FeatureFlags.ENABLE_DEVICE_SEARCH.get()
+ ? LAUNCHER_ALLAPPS_ENTRY_WITH_DEVICE_SEARCH
+ : LAUNCHER_ALLAPPS_ENTRY);
+ }
+
@Override
public void onStateSetEnd(LauncherState state) {
super.onStateSetEnd(state);
@@ -1121,17 +1147,18 @@
// Making sure mAllAppsSessionLogId is not null to avoid double logging.
&& mAllAppsSessionLogId != null) {
getAppsView().reset(false);
- getStatsLogManager().logger()
- .withContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
- .setWorkspace(
- LauncherAtom.WorkspaceContainer.newBuilder()
- .setPageIndex(getWorkspace().getCurrentPage()))
- .build())
- .log(LAUNCHER_ALLAPPS_EXIT);
+ getAllAppsExitEvent().ifPresent(getStatsLogManager().logger()::log);
mAllAppsSessionLogId = null;
}
}
+ /**
+ * Returns {@link EventEnum} that should be logged when Launcher exists from AllApps state.
+ */
+ protected Optional<EventEnum> getAllAppsExitEvent() {
+ return Optional.of(LAUNCHER_ALLAPPS_EXIT);
+ }
+
@Override
protected void onResume() {
Object traceToken = TraceHelper.INSTANCE.beginSection(ON_RESUME_EVT,
@@ -1144,6 +1171,8 @@
mOverlayManager.onActivityResumed(this);
}
+ AbstractFloatingView.closeAllOpenViewsExcept(this, false, TYPE_REBIND_SAFE);
+ DragView.removeAllViews(this);
TraceHelper.INSTANCE.endSection(traceToken);
}
@@ -1254,13 +1283,16 @@
* @param info The data structure describing the shortcut.
*/
View createShortcut(WorkspaceItemInfo info) {
- return createShortcut((ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()), info);
+ // This can be called before PagedView#pageScrollsInitialized returns true, so use the
+ // first page, which we always assume to be present.
+ return createShortcut((ViewGroup) mWorkspace.getChildAt(0), info);
}
/**
* Creates a view representing a shortcut inflated from the specified resource.
*
- * @param parent The group the shortcut belongs to.
+ * @param parent The group the shortcut belongs to. This is not necessarily the group where
+ * the shortcut should be added.
* @param info The data structure describing the shortcut.
* @return A View inflated from layoutResId.
*/
@@ -1476,11 +1508,12 @@
return mDragLayer;
}
- public AllAppsContainerView getAppsView() {
+ @Override
+ public ActivityAllAppsContainerView<Launcher> getAppsView() {
return mAppsView;
}
- public Workspace getWorkspace() {
+ public Workspace<?> getWorkspace() {
return mWorkspace;
}
@@ -1550,6 +1583,7 @@
boolean isActionMain = Intent.ACTION_MAIN.equals(intent.getAction());
boolean internalStateHandled = ACTIVITY_TRACKER.handleNewIntent(this);
hideKeyboard();
+
if (isActionMain) {
if (!internalStateHandled) {
// In all these cases, only animate if we're already on home
@@ -1578,6 +1612,8 @@
handleGestureContract(intent);
} else if (Intent.ACTION_ALL_APPS.equals(intent.getAction())) {
showAllAppsFromIntent(alreadyOnHome);
+ } else if (Intent.ACTION_SHOW_WORK_APPS.equals(intent.getAction())) {
+ showAllAppsWorkTabFromIntent(alreadyOnHome);
}
TraceHelper.INSTANCE.endSection(traceToken);
@@ -1588,6 +1624,11 @@
getStateManager().goToState(ALL_APPS, alreadyOnHome);
}
+ private void showAllAppsWorkTabFromIntent(boolean alreadyOnHome) {
+ showAllAppsFromIntent(alreadyOnHome);
+ mAppsView.switchToTab(BaseAllAppsContainerView.AdapterHolder.WORK);
+ }
+
/**
* Handles gesture nav contract
*/
@@ -1638,13 +1679,8 @@
outState.remove(RUNTIME_STATE_WIDGET_PANEL);
}
- // We close any open folders and shortcut containers that are not safe for rebind,
- // and we need to make sure this state is reflected.
- AbstractFloatingView.closeOpenViews(this, false, TYPE_ALL & ~TYPE_REBIND_SAFE);
finishAutoCancelActionMode();
- DragView.removeAllViews(this);
-
if (mPendingRequestArgs != null) {
outState.putParcelable(RUNTIME_STATE_PENDING_REQUEST_ARGS, mPendingRequestArgs);
}
@@ -1744,6 +1780,11 @@
return mWorkspaceLoading;
}
+ @Override
+ public boolean isBindingItems() {
+ return mWorkspaceLoading;
+ }
+
private void setWorkspaceLoading(boolean value) {
mWorkspaceLoading = value;
}
@@ -1918,6 +1959,19 @@
* @param deleteFromDb whether or not to delete this item from the db.
*/
public boolean removeItem(View v, final ItemInfo itemInfo, boolean deleteFromDb) {
+ return removeItem(v, itemInfo, deleteFromDb, null);
+ }
+
+ /**
+ * Unbinds the view for the specified item, and removes the item and all its children.
+ *
+ * @param v the view being removed.
+ * @param itemInfo the {@link ItemInfo} for this view.
+ * @param deleteFromDb whether or not to delete this item from the db.
+ * @param reason the resaon for removal.
+ */
+ public boolean removeItem(View v, final ItemInfo itemInfo, boolean deleteFromDb,
+ @Nullable final String reason) {
if (itemInfo instanceof WorkspaceItemInfo) {
// Remove the shortcut from the folder before removing it from launcher
View folderIcon = mWorkspace.getHomescreenIconByItemId(itemInfo.container);
@@ -1927,7 +1981,7 @@
mWorkspace.removeWorkspaceItem(v);
}
if (deleteFromDb) {
- getModelWriter().deleteItemFromDatabase(itemInfo);
+ getModelWriter().deleteItemFromDatabase(itemInfo, reason);
}
} else if (itemInfo instanceof FolderInfo) {
final FolderInfo folderInfo = (FolderInfo) itemInfo;
@@ -1942,7 +1996,7 @@
final LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) itemInfo;
mWorkspace.removeWorkspaceItem(v);
if (deleteFromDb) {
- getModelWriter().deleteWidgetInfo(widgetInfo, getAppWidgetHost());
+ getModelWriter().deleteWidgetInfo(widgetInfo, getAppWidgetHost(), reason);
}
} else {
return false;
@@ -1994,13 +2048,16 @@
// Note: There should be at most one log per method call. This is enforced implicitly
// by using if-else statements.
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(this);
- if (topView != null && topView.onBackPressed()) {
- // Handled by the floating view.
- } else {
- mStateManager.getState().onBackPressed(this);
+ if (topView == null || !topView.onBackPressed()) {
+ // Not handled by the floating view.
+ onStateBack();
}
}
+ protected void onStateBack() {
+ mStateManager.getState().onBackPressed(this);
+ }
+
protected void onScreenOff() {
// Reset AllApps to its initial state only if we are not in the middle of
// processing a multi-step drop
@@ -2014,7 +2071,7 @@
@TargetApi(Build.VERSION_CODES.M)
@Override
- protected boolean onErrorStartingShortcut(Intent intent, ItemInfo info) {
+ public boolean onErrorStartingShortcut(Intent intent, ItemInfo info) {
// Due to legacy reasons, direct call shortcuts require Launchers to have the
// corresponding permission. Show the appropriate permission prompt if that
// is the case.
@@ -2305,7 +2362,7 @@
// Get the list of added items and intersect them with the set of items here
final Collection<Animator> bounceAnims = new ArrayList<>();
boolean canAnimatePageChange = canAnimatePageChange();
- Workspace workspace = mWorkspace;
+ Workspace<?> workspace = mWorkspace;
int newItemsScreenId = -1;
int end = items.size();
View newView = null;
@@ -2352,14 +2409,20 @@
CellLayout cl = mWorkspace.getScreenWithId(item.screenId);
if (cl != null && cl.isOccupied(item.cellX, item.cellY)) {
View v = cl.getChildAt(item.cellX, item.cellY);
+ if (v == null) {
+ Log.e(TAG, "bindItems failed when removing colliding item=" + item);
+ }
Object tag = v.getTag();
String desc = "Collision while binding workspace item: " + item
+ ". Collides with " + tag;
if (FeatureFlags.IS_STUDIO_BUILD) {
throw (new RuntimeException(desc));
} else {
- Log.d(TAG, desc);
- getModelWriter().deleteItemFromDatabase(item);
+ getModelWriter().deleteItemFromDatabase(item, desc);
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON,
+ TAG + "bindItems failed for item=" + item);
+ }
continue;
}
}
@@ -2435,7 +2498,8 @@
if (item.hasOptionFlag(LauncherAppWidgetInfo.OPTION_SEARCH_WIDGET)) {
item.providerName = QsbContainerView.getSearchComponentName(this);
if (item.providerName == null) {
- getModelWriter().deleteItemFromDatabase(item);
+ getModelWriter().deleteItemFromDatabase(item,
+ "search widget removed because search component cannot be found");
return null;
}
}
@@ -2486,10 +2550,10 @@
if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
&& (item.restoreStatus != LauncherAppWidgetInfo.RESTORE_COMPLETED)) {
if (appWidgetInfo == null) {
- FileLog.d(TAG, "Removing restored widget: id=" + item.appWidgetId
+ getModelWriter().deleteItemFromDatabase(item,
+ "Removing restored widget: id=" + item.appWidgetId
+ " belongs to component " + item.providerName + " user " + item.user
+ ", as the provider is null and " + removalReason);
- getModelWriter().deleteItemFromDatabase(item);
return null;
}
@@ -2559,7 +2623,7 @@
// Verify that we own the widget
if (appWidgetInfo == null) {
FileLog.e(TAG, "Removing invalid widget: id=" + item.appWidgetId);
- getModelWriter().deleteWidgetInfo(item, getAppWidgetHost());
+ getModelWriter().deleteWidgetInfo(item, getAppWidgetHost(), removalReason);
return null;
}
@@ -2629,36 +2693,12 @@
AllAppsStore.DEFER_UPDATES_NEXT_DRAW));
}
- AlphaProperty property = mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD);
- if (property.getValue() < 1) {
- ObjectAnimator anim = ObjectAnimator.ofFloat(property, MultiValueAlpha.VALUE, 1);
-
- Log.d(BAD_STATE, "Launcher onInitialBindComplete toAlpha=" + 1);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- Log.d(BAD_STATE, "Launcher onInitialBindComplete onStart");
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- float alpha = mDragLayer == null
- ? -1
- : mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD).getValue();
- Log.d(BAD_STATE, "Launcher onInitialBindComplete onCancel, alpha=" + alpha);
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- Log.d(BAD_STATE, "Launcher onInitialBindComplete onEnd");
- }
- });
-
- anim.addListener(AnimatorListeners.forEndCallback(executor::onLoadAnimationCompleted));
- anim.start();
- } else {
- executor.onLoadAnimationCompleted();
+ if (mOnInitialBindListener != null) {
+ getRootView().getViewTreeObserver().removeOnPreDrawListener(mOnInitialBindListener);
+ mOnInitialBindListener = null;
}
+
+ executor.onLoadAnimationCompleted();
executor.attachTo(this);
if (Utilities.ATLEAST_S) {
Trace.endAsyncSection(DISPLAY_WORKSPACE_TRACE_METHOD_NAME,
@@ -2719,11 +2759,11 @@
* @param supportsAllAppsState If true and we are in All Apps state, looks for view in All Apps.
* Else we only looks on the workspace.
*/
- public View getFirstMatchForAppClose(int preferredItemId, String packageName, UserHandle user,
- boolean supportsAllAppsState) {
- final ItemInfoMatcher preferredItem = (info, cn) ->
+ public @Nullable View getFirstMatchForAppClose(int preferredItemId, String packageName,
+ UserHandle user, boolean supportsAllAppsState) {
+ final Predicate<ItemInfo> preferredItem = info ->
info != null && info.id == preferredItemId;
- final ItemInfoMatcher packageAndUserAndApp = (info, cn) ->
+ final Predicate<ItemInfo> packageAndUserAndApp = info ->
info != null
&& info.itemType == ITEM_TYPE_APPLICATION
&& info.user.equals(user)
@@ -2732,8 +2772,21 @@
packageName);
if (supportsAllAppsState && isInState(LauncherState.ALL_APPS)) {
- return getFirstMatch(Collections.singletonList(mAppsView.getActiveRecyclerView()),
+ AllAppsRecyclerView activeRecyclerView = mAppsView.getActiveRecyclerView();
+ View v = getFirstMatch(Collections.singletonList(activeRecyclerView),
preferredItem, packageAndUserAndApp);
+
+ if (v != null && activeRecyclerView.getCurrentScrollY() > 0) {
+ RectF locationBounds = new RectF();
+ FloatingIconView.getLocationBoundsForView(this, v, false, locationBounds,
+ new Rect());
+ if (locationBounds.top < mAppsView.getHeaderBottom()) {
+ // Icon is covered by scrim, return null to play fallback animation.
+ return null;
+ }
+ }
+
+ return v;
} else {
List<ViewGroup> containers = new ArrayList<>(mWorkspace.getPanelCount() + 1);
containers.add(mWorkspace.getHotseat().getShortcutsAndWidgets());
@@ -2741,14 +2794,8 @@
-> containers.add(((CellLayout) page).getShortcutsAndWidgets()));
// Order: Preferred item by itself or in folder, then by matching package/user
- if (ADAPTIVE_ICON_WINDOW_ANIM.get()) {
- return getFirstMatch(containers, preferredItem, forFolderMatch(preferredItem),
- packageAndUserAndApp, forFolderMatch(packageAndUserAndApp));
- } else {
- // Do not use Folder as a criteria, since it'll cause a crash when trying to draw
- // FolderAdaptiveIcon as the background.
- return getFirstMatch(containers, preferredItem, packageAndUserAndApp);
- }
+ return getFirstMatch(containers, preferredItem, forFolderMatch(preferredItem),
+ packageAndUserAndApp, forFolderMatch(packageAndUserAndApp));
}
}
@@ -2757,9 +2804,10 @@
* @param containers List of ViewGroups to scan, in order of preference.
* @param operators List of operators, in order starting from best matching operator.
*/
+ @Nullable
private static View getFirstMatch(Iterable<ViewGroup> containers,
- final ItemInfoMatcher... operators) {
- for (ItemInfoMatcher operator : operators) {
+ final Predicate<ItemInfo>... operators) {
+ for (Predicate<ItemInfo> operator : operators) {
for (ViewGroup container : containers) {
View match = mapOverViewGroup(container, operator);
if (match != null) {
@@ -2774,11 +2822,12 @@
* Returns the first view matching the operator in the given ViewGroups, or null if none.
* Forward iteration matters.
*/
- private static View mapOverViewGroup(ViewGroup container, ItemInfoMatcher op) {
+ @Nullable
+ private static View mapOverViewGroup(ViewGroup container, Predicate<ItemInfo> op) {
final int itemCount = container.getChildCount();
for (int itemIdx = 0; itemIdx < itemCount; itemIdx++) {
View item = container.getChildAt(itemIdx);
- if (op.matchesInfo((ItemInfo) item.getTag())) {
+ if (op.test((ItemInfo) item.getTag())) {
return item;
}
}
@@ -2798,6 +2847,17 @@
}
/**
+ * Informs us that the overlay (-1 screen, typically), has either become visible or invisible.
+ */
+ public void onOverlayVisibilityChanged(boolean visible) {}
+
+ /**
+ * Informs us that the page transition has ended, so that we can react to the newly selected
+ * page if we want to.
+ */
+ public void onPageEndTransition() {}
+
+ /**
* Add the icons for all apps.
*
* Implementation of the method from LauncherModel.Callbacks.
@@ -2864,7 +2924,7 @@
* package-removal should clear all items by package name.
*/
@Override
- public void bindWorkspaceComponentsRemoved(final ItemInfoMatcher matcher) {
+ public void bindWorkspaceComponentsRemoved(Predicate<ItemInfo> matcher) {
mWorkspace.removeItemsByMatcher(matcher);
mDragController.onAppsRemoved(matcher);
PopupContainerWithArrow.dismissInvalidPopup(this);
@@ -2875,6 +2935,16 @@
mPopupDataProvider.setAllWidgets(allWidgets);
}
+ @Override
+ public void bindStringCache(StringCache cache) {
+ mStringCache = cache;
+ }
+
+ @Override
+ public StringCache getStringCache() {
+ return mStringCache;
+ }
+
/**
* @param packageUser if null, refreshes all widgets and shortcuts, otherwise only
* refreshes the widgets and shortcuts associated with the given package/user
@@ -3135,6 +3205,24 @@
return new DragOptions();
}
+ /**
+ * Animates Launcher elements during a transition to the All Apps page.
+ *
+ * @param progress Transition progress from 0 to 1; where 0 => home and 1 => all apps.
+ */
+ public void onAllAppsTransition(float progress) {
+ // No-Op
+ }
+
+ /**
+ * Animates Launcher elements during a transition to the Widgets pages.
+ *
+ * @param progress Transition progress from 0 to 1; where 0 => home and 1 => widgets.
+ */
+ public void onWidgetsTransition(float progress) {
+ // No-Op
+ }
+
private static class NonConfigInstance {
public Configuration config;
public Bitmap snapshot;
@@ -3153,4 +3241,29 @@
public ArrowPopup<?> getOptionsPopup() {
return findViewById(R.id.popup_container);
}
+
+ /** Pauses view updates that should not be run during the app launch animation. */
+ public void pauseExpensiveViewUpdates() {
+ // Pause page indicator animations as they lead to layer trashing.
+ getWorkspace().getPageIndicator().pauseAnimations();
+
+ getWorkspace().mapOverItems((info, view) -> {
+ if (view instanceof LauncherAppWidgetHostView) {
+ ((LauncherAppWidgetHostView) view).beginDeferringUpdates();
+ }
+ return false; // Return false to continue iterating through all the items.
+ });
+ }
+
+ /** Resumes view updates at the end of the app launch animation. */
+ public void resumeExpensiveViewUpdates() {
+ getWorkspace().getPageIndicator().skipAnimationsToEnd();
+
+ getWorkspace().mapOverItems((info, view) -> {
+ if (view instanceof LauncherAppWidgetHostView) {
+ ((LauncherAppWidgetHostView) view).endDeferringUpdates();
+ }
+ return false; // Return false to continue iterating through all the items.
+ });
+ }
}
diff --git a/src/com/android/launcher3/LauncherAnimUtils.java b/src/com/android/launcher3/LauncherAnimUtils.java
index b56c012..808bf96 100644
--- a/src/com/android/launcher3/LauncherAnimUtils.java
+++ b/src/com/android/launcher3/LauncherAnimUtils.java
@@ -27,6 +27,8 @@
import android.view.View;
import android.view.ViewGroup.LayoutParams;
+import com.android.launcher3.util.MultiScalePropertyFactory;
+
public class LauncherAnimUtils {
/**
* Durations for various state animations. These are not defined in resources to allow
@@ -36,6 +38,7 @@
// Progress after which the transition is assumed to be a success
public static final float SUCCESS_TRANSITION_PROGRESS = 0.5f;
+ public static final float TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS = 0.3f;
public static final IntProperty<Drawable> DRAWABLE_ALPHA =
new IntProperty<Drawable>("drawableAlpha") {
@@ -64,6 +67,23 @@
}
};
+ /**
+ * Property to set the scale of workspace. The value is based on a combination
+ * of all the ones set, to have a smooth experience even in the case of overlapping scaling
+ * animation.
+ */
+ public static final MultiScalePropertyFactory<Workspace<?>> WORKSPACE_SCALE_PROPERTY_FACTORY =
+ new MultiScalePropertyFactory<Workspace<?>>("workspace_scale_property");
+
+ /** Property to set the scale of hotseat. */
+ public static final MultiScalePropertyFactory<Hotseat> HOTSEAT_SCALE_PROPERTY_FACTORY =
+ new MultiScalePropertyFactory<Hotseat>("hotseat_scale_property");
+
+ public static final int SCALE_INDEX_UNFOLD_ANIMATION = 1;
+ public static final int SCALE_INDEX_UNLOCK_ANIMATION = 2;
+ public static final int SCALE_INDEX_WORKSPACE_STATE = 3;
+ public static final int SCALE_INDEX_REVEAL_ANIM = 4;
+
/** Increase the duration if we prevented the fling, as we are going against a high velocity. */
public static int blockedFlingDurationFactor(float velocity) {
return (int) Utilities.boundToRange(Math.abs(velocity) / 2, 2f, 6f);
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 10023b4..597bc8d 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
+
import static com.android.launcher3.Utilities.getDevicePrefs;
import static com.android.launcher3.config.FeatureFlags.ENABLE_THEMED_ICONS;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -36,6 +38,7 @@
import com.android.launcher3.graphics.IconShape;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.icons.IconProvider;
+import com.android.launcher3.icons.LauncherIconProvider;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.pm.InstallSessionHelper;
@@ -61,7 +64,7 @@
private final Context mContext;
private final LauncherModel mModel;
- private final IconProvider mIconProvider;
+ private final LauncherIconProvider mIconProvider;
private final IconCache mIconCache;
private final InvariantDeviceProfile mInvariantDeviceProfile;
private final RunnableList mOnTerminateCallback = new RunnableList();
@@ -96,9 +99,10 @@
modelChangeReceiver.register(mContext, Intent.ACTION_LOCALE_CHANGED,
Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
- Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
+ Intent.ACTION_MANAGED_PROFILE_UNLOCKED,
+ ACTION_DEVICE_POLICY_RESOURCE_UPDATED);
if (FeatureFlags.IS_STUDIO_BUILD) {
- modelChangeReceiver.register(mContext, ACTION_FORCE_ROLOAD);
+ modelChangeReceiver.register(mContext, Context.RECEIVER_EXPORTED, ACTION_FORCE_ROLOAD);
}
mOnTerminateCallback.add(() -> mContext.unregisterReceiver(modelChangeReceiver));
@@ -138,7 +142,7 @@
mContext = context;
mInvariantDeviceProfile = InvariantDeviceProfile.INSTANCE.get(context);
- mIconProvider = new IconProvider(context, Themes.isThemedIconEnabled(context));
+ mIconProvider = new LauncherIconProvider(context);
mIconCache = new IconCache(mContext, mInvariantDeviceProfile,
iconCacheFileName, mIconProvider);
mModel = new LauncherModel(context, this, mIconCache, new AppFilter(mContext),
diff --git a/src/com/android/launcher3/LauncherBackupAgent.java b/src/com/android/launcher3/LauncherBackupAgent.java
index dc533f0..3d2700d 100644
--- a/src/com/android/launcher3/LauncherBackupAgent.java
+++ b/src/com/android/launcher3/LauncherBackupAgent.java
@@ -8,8 +8,13 @@
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.provider.RestoreDbTask;
+import java.io.File;
+import java.io.IOException;
+
public class LauncherBackupAgent extends BackupAgent {
+ private static final String TAG = "LauncherBackupAgent";
+
@Override
public void onCreate() {
super.onCreate();
@@ -24,6 +29,17 @@
}
@Override
+ public void onRestoreFile(ParcelFileDescriptor data, long size, File destination, int type,
+ long mode, long mtime) throws IOException {
+ // 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);
+ }
+ super.onRestoreFile(data, size, destination, type, mode, mtime);
+ }
+
+ @Override
public void onBackup(
ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) {
// Doesn't do incremental backup/restore
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index ee6f51e..de0d300 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
+
import static com.android.launcher3.LauncherAppState.ACTION_FORCE_ROLOAD;
import static com.android.launcher3.config.FeatureFlags.IS_STUDIO_BUILD;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -51,6 +53,7 @@
import com.android.launcher3.model.PackageIncrementalDownloadUpdatedTask;
import com.android.launcher3.model.PackageInstallStateChangedTask;
import com.android.launcher3.model.PackageUpdatedTask;
+import com.android.launcher3.model.ReloadStringCacheTask;
import com.android.launcher3.model.ShortcutsChangedTask;
import com.android.launcher3.model.UserLockStateChangedTask;
import com.android.launcher3.model.data.AppInfo;
@@ -278,6 +281,8 @@
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)) {
for (Callbacks cb : getCallbacks()) {
if (cb instanceof Launcher) {
@@ -472,7 +477,9 @@
}
if (!removedIds.isEmpty()) {
- deleteAndBindComponentsRemoved(ItemInfoMatcher.ofItemIds(removedIds));
+ deleteAndBindComponentsRemoved(
+ ItemInfoMatcher.ofItemIds(removedIds),
+ "removed because install session failed");
}
}
});
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 68e19cb..5aa8a46 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -97,11 +97,13 @@
* Represents the schema of the database. Changes in scheme need not be backwards compatible.
* When increasing the scheme version, ensure that downgrade_schema.json is updated
*/
- public static final int SCHEMA_VERSION = 30;
+ public static final int SCHEMA_VERSION = 31;
public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".settings";
public static final String KEY_LAYOUT_PROVIDER_AUTHORITY = "KEY_LAYOUT_PROVIDER_AUTHORITY";
+ private static final int TEST_WORKSPACE_LAYOUT_RES_XML = R.xml.default_test_workspace;
+
static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
protected DatabaseHelper mOpenHelper;
@@ -109,6 +111,8 @@
private long mLastRestoreTimestamp = 0L;
+ private boolean mUseTestWorkspaceLayout;
+
/**
* $ adb shell dumpsys activity provider com.android.launcher3
*/
@@ -158,6 +162,7 @@
private synchronized boolean prepForMigration(String dbFile, String targetTableName,
Supplier<DatabaseHelper> src, Supplier<DatabaseHelper> dst) {
if (TextUtils.equals(dbFile, mOpenHelper.getDatabaseName())) {
+ Log.e("b/198965093", "prepForMigration - target db is same as current: " + dbFile);
return false;
}
@@ -390,6 +395,14 @@
mOpenHelper.createEmptyDB(mOpenHelper.getWritableDatabase());
return null;
}
+ case LauncherSettings.Settings.METHOD_SET_USE_TEST_WORKSPACE_LAYOUT_FLAG: {
+ mUseTestWorkspaceLayout = true;
+ return null;
+ }
+ case LauncherSettings.Settings.METHOD_CLEAR_USE_TEST_WORKSPACE_LAYOUT_FLAG: {
+ mUseTestWorkspaceLayout = false;
+ return null;
+ }
case LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES: {
loadDefaultFavoritesIfNecessary();
return null;
@@ -427,7 +440,7 @@
Bundle result = new Bundle();
result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
prepForMigration(
- InvariantDeviceProfile.INSTANCE.get(getContext()).dbFile,
+ arg /* dbFile */,
Favorites.TMP_TABLE,
() -> mOpenHelper,
() -> DatabaseHelper.createDatabaseHelper(
@@ -609,7 +622,8 @@
private DefaultLayoutParser getDefaultLayoutParser(AppWidgetHost widgetHost) {
InvariantDeviceProfile idp = LauncherAppState.getIDP(getContext());
- int defaultLayout = idp.defaultLayoutId;
+ int defaultLayout = mUseTestWorkspaceLayout
+ ? TEST_WORKSPACE_LAYOUT_RES_XML : idp.defaultLayoutId;
if (getContext().getSystemService(UserManager.class).isDemoUser()
&& idp.demoModeLayoutId != 0) {
@@ -864,6 +878,19 @@
Favorites.SCREEN, IntArray.wrap(-777, -778)), null);
}
case 30: {
+ if (FeatureFlags.QSB_ON_FIRST_SCREEN) {
+ // Clean up first row in screen 0 as it might contain junk data.
+ Log.d(TAG, "Cleaning up first row");
+ db.delete(Favorites.TABLE_NAME,
+ String.format(Locale.ENGLISH,
+ "%1$s = %2$d AND %3$s = %4$d AND %5$s = %6$d",
+ Favorites.SCREEN, 0,
+ Favorites.CONTAINER, Favorites.CONTAINER_DESKTOP,
+ Favorites.CELLY, 0), null);
+ }
+ return;
+ }
+ case 31: {
// DB Upgraded successfully
return;
}
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index 5ef3690..a5c5c02 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -1,24 +1,19 @@
package com.android.launcher3;
-import static com.android.launcher3.ResourceUtils.INVALID_RESOURCE_HANDLE;
import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY;
import android.annotation.TargetApi;
import android.content.Context;
-import android.content.res.Resources;
import android.graphics.Canvas;
-import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.view.ViewDebug;
import android.view.WindowInsets;
-import androidx.annotation.RequiresApi;
-
import com.android.launcher3.graphics.SysUiScrim;
import com.android.launcher3.statemanager.StatefulActivity;
-import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.util.window.WindowManagerProxy;
import java.util.Collections;
import java.util.List;
@@ -60,73 +55,12 @@
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- if (Utilities.ATLEAST_R) {
- insets = updateInsetsDueToTaskbar(insets);
- Insets systemWindowInsets = insets.getInsetsIgnoringVisibility(
- WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
- mTempRect.set(systemWindowInsets.left, systemWindowInsets.top, systemWindowInsets.right,
- systemWindowInsets.bottom);
- } else {
- mTempRect.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
- insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
- }
+ insets = WindowManagerProxy.INSTANCE.get(getContext())
+ .normalizeWindowInsets(getContext(), insets, mTempRect);
handleSystemWindowInsets(mTempRect);
return insets;
}
- /**
- * Taskbar provides nav bar and tappable insets. However, taskbar is not attached immediately,
- * and can be destroyed and recreated. Thus, instead of relying on taskbar being present to
- * get its insets, we calculate them ourselves so they are stable regardless of whether taskbar
- * is currently attached.
- *
- * @param oldInsets The system-provided insets, which we are modifying.
- * @return The updated insets.
- */
- @RequiresApi(api = Build.VERSION_CODES.R)
- private WindowInsets updateInsetsDueToTaskbar(WindowInsets oldInsets) {
- if (!ApiWrapper.TASKBAR_DRAWN_IN_PROCESS) {
- // 3P launchers based on Launcher3 should still be inset like normal.
- return oldInsets;
- }
-
- WindowInsets.Builder updatedInsetsBuilder = new WindowInsets.Builder(oldInsets);
-
- DeviceProfile dp = mActivity.getDeviceProfile();
- Resources resources = getResources();
-
- Insets oldNavInsets = oldInsets.getInsets(WindowInsets.Type.navigationBars());
- Rect newNavInsets = new Rect(oldNavInsets.left, oldNavInsets.top, oldNavInsets.right,
- oldNavInsets.bottom);
-
- if (dp.isLandscape) {
- boolean isGesturalMode = ResourceUtils.getIntegerByName(
- "config_navBarInteractionMode",
- resources,
- INVALID_RESOURCE_HANDLE) == 2;
- if (dp.isTablet || isGesturalMode) {
- newNavInsets.bottom = ResourceUtils.getNavbarSize(
- "navigation_bar_height_landscape", resources);
- } else {
- int navWidth = ResourceUtils.getNavbarSize("navigation_bar_width", resources);
- if (dp.isSeascape()) {
- newNavInsets.left = navWidth;
- } else {
- newNavInsets.right = navWidth;
- }
- }
- } else {
- newNavInsets.bottom = ResourceUtils.getNavbarSize("navigation_bar_height", resources);
- }
- updatedInsetsBuilder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(newNavInsets));
- updatedInsetsBuilder.setInsetsIgnoringVisibility(WindowInsets.Type.navigationBars(),
- Insets.of(newNavInsets));
-
- mActivity.updateWindowInsets(updatedInsetsBuilder, oldInsets);
-
- return updatedInsetsBuilder.build();
- }
-
@Override
public void setInsets(Rect insets) {
// If the insets haven't changed, this is a no-op. Avoid unnecessary layout caused by
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 048aaaa..66195f3 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -374,6 +374,12 @@
public static final String METHOD_CREATE_EMPTY_DB = "create_empty_db";
+ public static final String METHOD_SET_USE_TEST_WORKSPACE_LAYOUT_FLAG =
+ "set_use_test_workspace_layout_flag";
+
+ public static final String METHOD_CLEAR_USE_TEST_WORKSPACE_LAYOUT_FLAG =
+ "clear_use_test_workspace_layout_flag";
+
public static final String METHOD_LOAD_DEFAULT_FAVORITES = "load_default_favorites";
public static final String METHOD_REMOVE_GHOST_WIDGETS = "remove_ghost_widgets";
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index be2cd88..ea6a919 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -16,6 +16,7 @@
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.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
@@ -79,6 +80,9 @@
public static final int FLAG_CLOSE_POPUPS = BaseState.getFlag(6);
public static final int FLAG_OVERVIEW_UI = BaseState.getFlag(7);
+ // Flag indicating that hotseat and its contents are not accessible.
+ public static final int FLAG_HOTSEAT_INACCESSIBLE = BaseState.getFlag(8);
+
public static final float NO_OFFSET = 0;
public static final float NO_SCALE = 1;
@@ -91,6 +95,14 @@
}
};
+ protected static final PageTranslationProvider DEFAULT_PAGE_TRANSLATION_PROVIDER =
+ new PageTranslationProvider(DEACCEL_2) {
+ @Override
+ public float getPageTranslation(int pageIndex) {
+ return 0;
+ }
+ };
+
private static final LauncherState[] sAllStates = new LauncherState[10];
/**
@@ -101,7 +113,7 @@
FLAG_DISABLE_RESTORE | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_HIDE_BACK_BUTTON |
FLAG_HAS_SYS_UI_SCRIM) {
@Override
- public int getTransitionDuration(Context context) {
+ public int getTransitionDuration(Context context, boolean isToState) {
// Arbitrary duration, when going to NORMAL we use the state we're coming from instead.
return 0;
}
@@ -288,6 +300,25 @@
};
}
+ /**
+ * Gets the translation provider for workspace pages.
+ */
+ public PageTranslationProvider getWorkspacePageTranslationProvider(Launcher launcher) {
+ if (this != SPRING_LOADED || !launcher.getDeviceProfile().isTwoPanels) {
+ return DEFAULT_PAGE_TRANSLATION_PROVIDER;
+ }
+ final float quarterPageSpacing = launcher.getWorkspace().getPageSpacing() / 4f;
+ return new PageTranslationProvider(DEACCEL_2) {
+ @Override
+ public float getPageTranslation(int pageIndex) {
+ boolean isRtl = launcher.getWorkspace().mIsRtl;
+ boolean isFirstPage = pageIndex % 2 == 0;
+ return ((isFirstPage && !isRtl) || (!isFirstPage && isRtl)) ? -quarterPageSpacing
+ : quarterPageSpacing;
+ }
+ };
+ }
+
@Override
public LauncherState getHistoryForState(LauncherState previousState) {
// No history is supported
@@ -318,6 +349,23 @@
public abstract float getPageAlpha(int pageIndex);
}
+ /**
+ * Provider for the translation and animation interpolation of workspace pages.
+ */
+ public abstract static class PageTranslationProvider {
+
+ public final Interpolator interpolator;
+
+ public PageTranslationProvider(Interpolator interpolator) {
+ this.interpolator = interpolator;
+ }
+
+ /**
+ * Gets the translation of the workspace page at the provided page index.
+ */
+ public abstract float getPageTranslation(int pageIndex);
+ }
+
public static class ScaleAndTranslation {
public float scale;
public float translationX;
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 2c14f07..cba0b7d 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -28,6 +28,8 @@
import android.animation.LayoutTransition;
import android.annotation.SuppressLint;
import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
@@ -78,27 +80,19 @@
public static final int INVALID_PAGE = -1;
protected static final ComputePageScrollsLogic SIMPLE_SCROLL_LOGIC = (v) -> v.getVisibility() != GONE;
- public static final int PAGE_SNAP_ANIMATION_DURATION = 750;
-
private static final float RETURN_TO_ORIGINAL_PAGE_THRESHOLD = 0.33f;
// The page is moved more than halfway, automatically move to the next page on touch up.
private static final float SIGNIFICANT_MOVE_THRESHOLD = 0.4f;
private static final float MAX_SCROLL_PROGRESS = 1.0f;
- // The following constants need to be scaled based on density. The scaled versions will be
- // assigned to the corresponding member variables below.
- private static final int FLING_THRESHOLD_VELOCITY = 500;
- private static final int EASY_FLING_THRESHOLD_VELOCITY = 400;
- private static final int MIN_SNAP_VELOCITY = 1500;
- private static final int MIN_FLING_VELOCITY = 250;
-
private boolean mFreeScroll = false;
- protected final int mFlingThresholdVelocity;
- protected final int mEasyFlingThresholdVelocity;
- protected final int mMinFlingVelocity;
- protected final int mMinSnapVelocity;
+ private int mFlingThresholdVelocity;
+ private int mEasyFlingThresholdVelocity;
+ private int mMinFlingVelocity;
+ private int mMinSnapVelocity;
+ private int mPageSnapAnimationDuration;
protected boolean mFirstLayout = true;
@@ -129,7 +123,10 @@
private boolean mAllowEasyFling;
protected PagedOrientationHandler mOrientationHandler = PagedOrientationHandler.PORTRAIT;
- protected int[] mPageScrolls;
+ private final ArrayList<Runnable> mOnPageScrollsInitializedCallbacks = new ArrayList<>();
+
+ // We should always check pageScrollsInitialized() is true when using mPageScrolls.
+ @Nullable protected int[] mPageScrolls = null;
private boolean mIsBeingDragged;
// The amount of movement to begin scrolling
@@ -189,11 +186,7 @@
mPageSlop = configuration.getScaledPagingTouchSlop();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
- float density = getResources().getDisplayMetrics().density;
- mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * density);
- mEasyFlingThresholdVelocity = (int) (EASY_FLING_THRESHOLD_VELOCITY * density);
- mMinFlingVelocity = (int) (MIN_FLING_VELOCITY * density);
- mMinSnapVelocity = (int) (MIN_SNAP_VELOCITY * density);
+ updateVelocityValues();
initEdgeEffect();
setDefaultFocusHighlightEnabled(false);
@@ -625,6 +618,22 @@
- mInsets.left - mInsets.right;
}
+ private void updateVelocityValues() {
+ Resources res = getResources();
+ mFlingThresholdVelocity = res.getDimensionPixelSize(R.dimen.fling_threshold_velocity);
+ mEasyFlingThresholdVelocity =
+ res.getDimensionPixelSize(R.dimen.easy_fling_threshold_velocity);
+ mMinFlingVelocity = res.getDimensionPixelSize(R.dimen.min_fling_velocity);
+ mMinSnapVelocity = res.getDimensionPixelSize(R.dimen.min_page_snap_velocity);
+ mPageSnapAnimationDuration = res.getInteger(R.integer.config_pageSnapAnimationDuration);
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ updateVelocityValues();
+ }
+
@Override
public void requestLayout() {
mIsLayoutValid = false;
@@ -684,26 +693,48 @@
setMeasuredDimension(widthSize, heightSize);
}
+ /** Returns true iff this PagedView's scroll amounts are initialized to each page index. */
+ protected boolean pageScrollsInitialized() {
+ return mPageScrolls != null && mPageScrolls.length == getChildCount();
+ }
+
+ /**
+ * Queues the given callback to be run once {@code mPageScrolls} has been initialized.
+ */
+ public void runOnPageScrollsInitialized(Runnable callback) {
+ mOnPageScrollsInitializedCallbacks.add(callback);
+ if (pageScrollsInitialized()) {
+ onPageScrollsInitialized();
+ }
+ }
+
+ private void onPageScrollsInitialized() {
+ for (Runnable callback : mOnPageScrollsInitializedCallbacks) {
+ callback.run();
+ }
+ mOnPageScrollsInitializedCallbacks.clear();
+ }
+
@SuppressLint("DrawAllocation")
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
mIsLayoutValid = true;
final int childCount = getChildCount();
+ int[] pageScrolls = mPageScrolls;
boolean pageScrollChanged = false;
- if (mPageScrolls == null || childCount != mPageScrolls.length) {
- mPageScrolls = new int[childCount];
+ if (!pageScrollsInitialized()) {
+ pageScrolls = new int[childCount];
pageScrollChanged = true;
}
- if (childCount == 0) {
- return;
- }
-
if (DEBUG) Log.d(TAG, "PagedView.onLayout()");
- boolean isScrollChanged = getPageScrolls(mPageScrolls, true, SIMPLE_SCROLL_LOGIC);
- if (isScrollChanged) {
- pageScrollChanged = true;
+ pageScrollChanged |= getPageScrolls(pageScrolls, true, SIMPLE_SCROLL_LOGIC);
+ mPageScrolls = pageScrolls;
+
+ if (childCount == 0) {
+ onPageScrollsInitialized();
+ return;
}
final LayoutTransition transition = getLayoutTransition();
@@ -738,6 +769,7 @@
if (mScroller.isFinished() && pageScrollChanged) {
setCurrentPage(getNextPage());
}
+ onPageScrollsInitialized();
}
/**
@@ -775,7 +807,7 @@
pageScrollChanged = true;
outPageScrolls[i] = pageScroll;
}
- childStart += primaryDimension + getChildGap();
+ childStart += primaryDimension + getChildGap(i, i + delta);
// This makes sure that the space is added after the page, not after each panel
int lastPanel = mIsRtl ? 0 : panelCount - 1;
@@ -799,7 +831,7 @@
return pageScrollChanged;
}
- protected int getChildGap() {
+ protected int getChildGap(int fromIndex, int toIndex) {
return 0;
}
@@ -849,8 +881,10 @@
@Override
public void onViewRemoved(View child) {
super.onViewRemoved(child);
- mCurrentPage = validateNewPage(mCurrentPage);
- mCurrentScrollOverPage = mCurrentPage;
+ runOnPageScrollsInitialized(() -> {
+ mCurrentPage = validateNewPage(mCurrentPage);
+ mCurrentScrollOverPage = mCurrentPage;
+ });
dispatchPageCountChanged();
}
@@ -1153,6 +1187,8 @@
}
public int getScrollForPage(int index) {
+ // TODO(b/233112195): Use !pageScrollsInitialized() instead of mPageScrolls == null, once we
+ // root cause where we should be using runOnPageScrollsInitialized().
if (mPageScrolls == null || index >= mPageScrolls.length || index < 0) {
return 0;
} else {
@@ -1163,7 +1199,7 @@
// While layout transitions are occurring, a child's position may stray from its baseline
// position. This method returns the magnitude of this stray at any given time.
public int getLayoutTransitionOffsetForPage(int index) {
- if (mPageScrolls == null || index >= mPageScrolls.length || index < 0) {
+ if (!pageScrollsInitialized() || index >= mPageScrolls.length || index < 0) {
return 0;
} else {
View child = getChildAt(index);
@@ -1195,8 +1231,8 @@
mAllowOverScroll = enable;
}
- protected float getSignificantMoveThreshold() {
- return SIGNIFICANT_MOVE_THRESHOLD;
+ protected boolean isSignificantMove(float absoluteDelta, int pageOrientedSize) {
+ return absoluteDelta > pageOrientedSize * SIGNIFICANT_MOVE_THRESHOLD;
}
@Override
@@ -1322,13 +1358,12 @@
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int velocity = (int) mOrientationHandler.getPrimaryVelocity(velocityTracker,
- mActivePointerId);
+ mActivePointerId);
float delta = primaryDirection - mDownMotionPrimary;
- delta /= mOrientationHandler.getPrimaryScale(this);
- int pageOrientedSize = mOrientationHandler.getMeasuredSize(getPageAt(mCurrentPage));
-
- boolean isSignificantMove = Math.abs(delta)
- > pageOrientedSize * getSignificantMoveThreshold();
+ int pageOrientedSize = (int) (mOrientationHandler.getMeasuredSize(
+ getPageAt(mCurrentPage))
+ * mOrientationHandler.getPrimaryScale(this));
+ boolean isSignificantMove = isSignificantMove(Math.abs(delta), pageOrientedSize);
mTotalMotion += Math.abs(mLastMotion + mLastMotionRemainder - primaryDirection);
boolean passedSlop = mAllowEasyFling || mTotalMotion > mPageSlop;
@@ -1441,7 +1476,7 @@
return Math.abs(velocity) > threshold;
}
- private void resetTouchState() {
+ protected void resetTouchState() {
releaseVelocityTracker();
mIsBeingDragged = false;
mActivePointerId = INVALID_POINTER;
@@ -1590,7 +1625,7 @@
}
protected void snapToDestination() {
- snapToPage(getDestinationPage(), PAGE_SNAP_ANIMATION_DURATION);
+ snapToPage(getDestinationPage(), mPageSnapAnimationDuration);
}
// We want the duration of the page snap animation to be influenced by the distance that
@@ -1614,7 +1649,7 @@
if (Math.abs(velocity) < mMinFlingVelocity) {
// If the velocity is low enough, then treat this more as an automatic page advance
// as opposed to an apparent physical response to flinging
- return snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
+ return snapToPage(whichPage, mPageSnapAnimationDuration);
}
// Here we compute a "distance" that will be used in the computation of the overall
@@ -1637,11 +1672,11 @@
}
public boolean snapToPage(int whichPage) {
- return snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
+ return snapToPage(whichPage, mPageSnapAnimationDuration);
}
public boolean snapToPageImmediately(int whichPage) {
- return snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION, true);
+ return snapToPage(whichPage, mPageSnapAnimationDuration, true);
}
public boolean snapToPage(int whichPage, int duration) {
diff --git a/src/com/android/launcher3/ResourceUtils.java b/src/com/android/launcher3/ResourceUtils.java
index ece123d..f709aca 100644
--- a/src/com/android/launcher3/ResourceUtils.java
+++ b/src/com/android/launcher3/ResourceUtils.java
@@ -28,6 +28,13 @@
public static final String NAVBAR_BOTTOM_GESTURE_LARGER_SIZE =
"navigation_bar_gesture_larger_height";
+ public static final String NAVBAR_HEIGHT = "navigation_bar_height";
+ public static final String NAVBAR_HEIGHT_LANDSCAPE = "navigation_bar_height_landscape";
+
+ public static final String STATUS_BAR_HEIGHT = "status_bar_height";
+ public static final String STATUS_BAR_HEIGHT_LANDSCAPE = "status_bar_height_landscape";
+ public static final String STATUS_BAR_HEIGHT_PORTRAIT = "status_bar_height_portrait";
+
public static int getNavbarSize(String resName, Resources res) {
return getDimenByName(resName, res, DEFAULT_NAVBAR_VALUE);
}
diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java
index cd06414..f8bc1f4 100644
--- a/src/com/android/launcher3/SecondaryDropTarget.java
+++ b/src/com/android/launcher3/SecondaryDropTarget.java
@@ -6,8 +6,10 @@
import static com.android.launcher3.Launcher.REQUEST_RECONFIGURE_APPWIDGET;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP;
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.DISMISS_PREDICTION;
+import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.INVALID;
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.RECONFIGURE;
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.UNINSTALL;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DISMISS_PREDICTION_UNDO;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_UNINSTALL;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_UNINSTALL_CANCELLED;
@@ -46,6 +48,7 @@
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.PendingRequestArgs;
+import com.android.launcher3.views.Snackbar;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import java.net.URISyntaxException;
@@ -67,6 +70,7 @@
private boolean mHadPendingAlarm;
protected int mCurrentAccessibilityAction = -1;
+
public SecondaryDropTarget(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -132,24 +136,33 @@
}
@Override
+ protected void setupItemInfo(ItemInfo info) {
+ int buttonType = getButtonType(info, getViewUnderDrag(info));
+ if (buttonType != INVALID) {
+ setupUi(buttonType);
+ }
+ }
+
+ @Override
protected boolean supportsDrop(ItemInfo info) {
- return supportsAccessibilityDrop(info, getViewUnderDrag(info));
+ return getButtonType(info, getViewUnderDrag(info)) != INVALID;
}
@Override
public boolean supportsAccessibilityDrop(ItemInfo info, View view) {
+ return getButtonType(info, view) != INVALID;
+ }
+
+ private int getButtonType(ItemInfo info, View view) {
if (view instanceof AppWidgetHostView) {
if (getReconfigurableWidgetId(view) != INVALID_APPWIDGET_ID) {
- setupUi(RECONFIGURE);
- return true;
+ return RECONFIGURE;
}
- return false;
+ return INVALID;
} else if (FeatureFlags.ENABLE_PREDICTION_DISMISS.get() && info.isPredictedItem()) {
- setupUi(DISMISS_PREDICTION);
- return true;
+ return DISMISS_PREDICTION;
}
- setupUi(UNINSTALL);
Boolean uninstallDisabled = mUninstallDisabledCache.get(info.user);
if (uninstallDisabled == null) {
UserManager userManager =
@@ -163,16 +176,20 @@
mCacheExpireAlarm.setAlarm(CACHE_EXPIRE_TIMEOUT);
mCacheExpireAlarm.setOnAlarmListener(this);
if (uninstallDisabled) {
- return false;
+ return INVALID;
}
if (info instanceof ItemInfoWithIcon) {
ItemInfoWithIcon iconInfo = (ItemInfoWithIcon) info;
- if ((iconInfo.runtimeStatusFlags & FLAG_SYSTEM_MASK) != 0) {
- return (iconInfo.runtimeStatusFlags & FLAG_SYSTEM_NO) != 0;
+ if ((iconInfo.runtimeStatusFlags & FLAG_SYSTEM_MASK) != 0
+ && (iconInfo.runtimeStatusFlags & FLAG_SYSTEM_NO) == 0) {
+ return INVALID;
}
}
- return getUninstallTarget(info) != null;
+ if (getUninstallTarget(info) == null) {
+ return INVALID;
+ }
+ return UNINSTALL;
}
/**
@@ -220,7 +237,8 @@
@Override
public void completeDrop(final DragObject d) {
- ComponentName target = performDropAction(getViewUnderDrag(d.dragInfo), d.dragInfo);
+ ComponentName target = performDropAction(getViewUnderDrag(d.dragInfo), d.dragInfo,
+ d.logInstanceId);
if (d.dragSource instanceof DeferredOnComplete) {
DeferredOnComplete deferred = (DeferredOnComplete) d.dragSource;
if (target != null) {
@@ -264,7 +282,7 @@
* Performs the drop action and returns the target component for the dragObject or null if
* the action was not performed.
*/
- protected ComponentName performDropAction(View view, ItemInfo info) {
+ protected ComponentName performDropAction(View view, ItemInfo info, InstanceId instanceId) {
if (mCurrentAccessibilityAction == RECONFIGURE) {
int widgetId = getReconfigurableWidgetId(view);
if (widgetId != INVALID_APPWIDGET_ID) {
@@ -276,7 +294,16 @@
return null;
}
if (mCurrentAccessibilityAction == DISMISS_PREDICTION) {
- // We sent the log event, nothing else left to do
+ if (FeatureFlags.ENABLE_DISMISS_PREDICTION_UNDO.get()) {
+ mLauncher.getDragLayer()
+ .announceForAccessibility(getContext().getString(R.string.item_removed));
+ Snackbar.show(mLauncher, R.string.item_removed, R.string.undo, () -> { }, () -> {
+ mStatsLogManager.logger()
+ .withInstanceId(instanceId)
+ .withItemInfo(info)
+ .log(LAUNCHER_DISMISS_PREDICTION_UNDO);
+ });
+ }
return null;
}
// else: mCurrentAccessibilityAction == UNINSTALL
@@ -303,8 +330,9 @@
@Override
public void onAccessibilityDrop(View view, ItemInfo item) {
- doLog(new InstanceIdSequence().newInstanceId(), item);
- performDropAction(view, item);
+ InstanceId instanceId = new InstanceIdSequence().newInstanceId();
+ doLog(instanceId, item);
+ performDropAction(view, item, instanceId);
}
/**
diff --git a/src/com/android/launcher3/SessionCommitReceiver.java b/src/com/android/launcher3/SessionCommitReceiver.java
index 558538c..b81637f 100644
--- a/src/com/android/launcher3/SessionCommitReceiver.java
+++ b/src/com/android/launcher3/SessionCommitReceiver.java
@@ -24,12 +24,14 @@
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.Log;
import androidx.annotation.WorkerThread;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.ItemInstallQueue;
import com.android.launcher3.pm.InstallSessionHelper;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.Executors;
/**
@@ -51,6 +53,9 @@
private static void processIntent(Context context, Intent intent) {
if (!isEnabled(context)) {
// User has decided to not add icons on homescreen.
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + " not enabled");
+ }
return;
}
@@ -59,6 +64,9 @@
if (!PackageInstaller.ACTION_SESSION_COMMITTED.equals(intent.getAction())
|| info == null || user == null) {
// Invalid intent.
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + " invalid intent");
+ }
return;
}
@@ -68,6 +76,15 @@
|| info.getInstallReason() != PackageManager.INSTALL_REASON_USER
|| packageInstallerCompat.promiseIconAddedForId(info.getSessionId())) {
packageInstallerCompat.removePromiseIconId(info.getSessionId());
+ if (TestProtocol.sDebugTracing) {
+ int id = info.getSessionId();
+ Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG
+ + ", TextUtils.isEmpty=" + TextUtils.isEmpty(info.getAppPackageName())
+ + ", info.getInstallReason()=" + info.getInstallReason()
+ + ", INSTALL_REASON_USER=" + PackageManager.INSTALL_REASON_USER
+ + ", icon added=" + packageInstallerCompat.promiseIconAddedForId(id)
+ );
+ }
return;
}
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index fec1d68..5583eae 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -19,6 +19,7 @@
import static android.view.MotionEvent.ACTION_DOWN;
import static com.android.launcher3.CellLayout.FOLDER;
+import static com.android.launcher3.CellLayout.HOTSEAT;
import static com.android.launcher3.CellLayout.WORKSPACE;
import android.app.WallpaperManager;
@@ -146,7 +147,8 @@
// No need to add padding when cell layout border spacing is present.
boolean noPaddingX =
(dp.cellLayoutBorderSpacePx.x > 0 && mContainerType == WORKSPACE)
- || (dp.folderCellLayoutBorderSpacePx.x > 0 && mContainerType == FOLDER);
+ || (dp.folderCellLayoutBorderSpacePx.x > 0 && mContainerType == FOLDER)
+ || (dp.hotseatBorderSpace > 0 && mContainerType == HOTSEAT);
int cellPaddingX = noPaddingX
? 0
: mContainerType == WORKSPACE
@@ -251,7 +253,7 @@
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
// While the folder is open, the position of the icon cannot change.
lp.canReorder = false;
- if (mContainerType == CellLayout.HOTSEAT) {
+ if (mContainerType == HOTSEAT) {
CellLayout cl = (CellLayout) getParent();
cl.setFolderLeaveBehindCell(lp.cellX, lp.cellY);
}
@@ -260,7 +262,7 @@
@Override
public void clearFolderLeaveBehind(FolderIcon child) {
((CellLayout.LayoutParams) child.getLayoutParams()).canReorder = true;
- if (mContainerType == CellLayout.HOTSEAT) {
+ if (mContainerType == HOTSEAT) {
CellLayout cl = (CellLayout) getParent();
cl.clearFolderLeaveBehind();
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 63313f7..7b96838 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -16,7 +16,11 @@
package com.android.launcher3;
+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.app.ActivityManager;
@@ -36,7 +40,6 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
-import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.LightingColorFilter;
@@ -48,12 +51,13 @@
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.InsetDrawable;
import android.net.Uri;
import android.os.Build;
+import android.os.Build.VERSION_CODES;
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.Message;
+import android.os.Process;
import android.os.TransactionTooLargeException;
import android.provider.Settings;
import android.text.Spannable;
@@ -69,17 +73,15 @@
import android.view.animation.Interpolator;
import android.widget.LinearLayout;
+import androidx.annotation.ChecksSdkIntAtLeast;
import androidx.annotation.NonNull;
import androidx.core.graphics.ColorUtils;
-import androidx.core.os.BuildCompat;
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
import com.android.launcher3.graphics.GridCustomizationsProvider;
import com.android.launcher3.graphics.TintedDrawableSpan;
-import com.android.launcher3.icons.BitmapInfo;
-import com.android.launcher3.icons.FastBitmapDrawable;
-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;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.SearchActionItemInfo;
@@ -88,11 +90,14 @@
import com.android.launcher3.shortcuts.ShortcutRequest;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
+import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import java.lang.reflect.Method;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
@@ -110,8 +115,6 @@
private static final Pattern sTrimPattern =
Pattern.compile("^[\\s|\\p{javaSpaceChar}]*(.*)[\\s|\\p{javaSpaceChar}]*$");
- private static final float[] sTmpFloatArray = new float[4];
-
private static final int[] sLoc0 = new int[2];
private static final int[] sLoc1 = new int[2];
private static final Matrix sMatrix = new Matrix();
@@ -120,14 +123,20 @@
public static final String[] EMPTY_STRING_ARRAY = new String[0];
public static final Person[] EMPTY_PERSON_ARRAY = new Person[0];
+ @ChecksSdkIntAtLeast(api = VERSION_CODES.P)
public static final boolean ATLEAST_P = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
+ @ChecksSdkIntAtLeast(api = VERSION_CODES.Q)
public static final boolean ATLEAST_Q = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
+ @ChecksSdkIntAtLeast(api = VERSION_CODES.R)
public static final boolean ATLEAST_R = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R;
- public static final boolean ATLEAST_S = BuildCompat.isAtLeastS()
- || Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;
+ @ChecksSdkIntAtLeast(api = VERSION_CODES.S)
+ public static final boolean ATLEAST_S = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;
+
+ @ChecksSdkIntAtLeast(api = VERSION_CODES.TIRAMISU, codename = "T")
+ public static final boolean ATLEAST_T = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU;
/**
* Set on a motion event dispatched from the nav bar. See {@link MotionEvent#setEdgeFlags(int)}.
@@ -231,7 +240,7 @@
offsetPoints(coord, v.getLeft(), v.getTop());
scale *= v.getScaleX();
- v = (View) v.getParent();
+ v = v.getParent() instanceof View ? (View) v.getParent() : null;
}
return scale;
}
@@ -264,6 +273,16 @@
}
/**
+ * Similar to {@link #mapCoordInSelfToDescendant(View descendant, View root, float[] coord)}
+ * but accepts a Rect instead of float[].
+ */
+ public static void mapRectInSelfToDescendant(View descendant, View root, Rect rect) {
+ float[] coords = new float[]{rect.left, rect.top, rect.right, rect.bottom};
+ mapCoordInSelfToDescendant(descendant, root, coords);
+ rect.set((int) coords[0], (int) coords[1], (int) coords[2], (int) coords[3]);
+ }
+
+ /**
* Inverse of {@link #getDescendantCoordRelativeToAncestor(View, View, float[], boolean)}.
*/
public static void mapCoordInSelfToDescendant(View descendant, View root, float[] coord) {
@@ -485,6 +504,11 @@
return res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
}
+ /** Converts a pixel value (px) to scale pixel value (SP) for the current device. */
+ public static float pxToSp(float size) {
+ return size / Resources.getSystem().getDisplayMetrics().scaledDensity;
+ }
+
public static float dpiFromPx(float size, int densityDpi) {
float densityRatio = (float) densityDpi / DisplayMetrics.DENSITY_DEFAULT;
return (size / densityRatio);
@@ -610,6 +634,10 @@
LauncherFiles.DEVICE_PREFERENCES_KEY, Context.MODE_PRIVATE);
}
+ public static boolean isWallpaperSupported(Context context) {
+ return context.getSystemService(WallpaperManager.class).isWallpaperSupported();
+ }
+
public static boolean isWallpaperAllowed(Context context) {
return context.getSystemService(WallpaperManager.class).isSetWallpaperAllowed();
}
@@ -673,14 +701,23 @@
/**
* Returns the full drawable for info without any flattening or pre-processing.
*
- * @param outObj this is set to the internal data associated with {@param info},
+ * @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}.
*/
+ @TargetApi(Build.VERSION_CODES.TIRAMISU)
public static Drawable getFullDrawable(Context context, ItemInfo info, int width, int height,
- Object[] outObj) {
+ boolean shouldThemeIcon, Object[] outObj) {
Drawable icon = loadFullDrawableWithoutTheme(context, info, width, height, outObj);
- if (icon instanceof BitmapInfo.Extender) {
- icon = ((BitmapInfo.Extender) icon).getThemedDrawable(context);
+ 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);
+ }
}
return icon;
}
@@ -723,8 +760,7 @@
return icon;
} else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SEARCH_ACTION
&& info instanceof SearchActionItemInfo) {
- return new AdaptiveIconDrawable(
- new FastBitmapDrawable(((SearchActionItemInfo) info).bitmap), null);
+ return ((SearchActionItemInfo) info).bitmap.newIcon(context);
} else {
return null;
}
@@ -739,27 +775,23 @@
@TargetApi(Build.VERSION_CODES.O)
public static Drawable getBadge(Context context, ItemInfo info, Object obj) {
LauncherAppState appState = LauncherAppState.getInstance(context);
- int iconSize = appState.getInvariantDeviceProfile().iconBitmapSize;
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 FixedSizeEmptyDrawable(iconSize);
+ return new ColorDrawable(Color.TRANSPARENT);
}
ShortcutInfo si = (ShortcutInfo) obj;
- Bitmap badge = LauncherAppState.getInstance(appState.getContext())
- .getIconCache().getShortcutInfoBadge(si).icon;
- float badgeSize = LauncherIcons.getBadgeSizeForIconSize(iconSize);
- float insetFraction = (iconSize - badgeSize) / iconSize;
- return new InsetDrawable(new FastBitmapDrawable(badge),
- insetFraction, insetFraction, 0, 0);
+ 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 context.getPackageManager()
- .getUserBadgedIcon(new FixedSizeEmptyDrawable(iconSize), info.user);
+ return Process.myUserHandle().equals(info.user)
+ ? new ColorDrawable(Color.TRANSPARENT)
+ : context.getDrawable(R.drawable.ic_work_app_badge);
}
}
@@ -866,23 +898,38 @@
return new Rect(pos[0], pos[1], pos[0] + v.getWidth(), pos[1] + v.getHeight());
}
- private static class FixedSizeEmptyDrawable extends ColorDrawable {
-
- private final int mSize;
-
- public FixedSizeEmptyDrawable(int size) {
- super(Color.TRANSPARENT);
- mSize = size;
+ /**
+ * Returns a list of screen-splitting options depending on the device orientation (split top for
+ * portrait, split left for landscape, split left and right for landscape tablets, etc.)
+ */
+ public static List<SplitPositionOption> getSplitPositionOptions(
+ DeviceProfile dp) {
+ List<SplitPositionOption> options = new ArrayList<>();
+ // Add both left and right options if we're in tablet mode
+ if (dp.isTablet && dp.isLandscape) {
+ options.add(new SplitPositionOption(
+ R.drawable.ic_split_left, R.string.split_screen_position_left,
+ STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
+ options.add(new SplitPositionOption(
+ R.drawable.ic_split_right, R.string.split_screen_position_right,
+ STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_MAIN));
+ } else {
+ if (dp.isSeascape()) {
+ // Add left/right options
+ options.add(new SplitPositionOption(
+ R.drawable.ic_split_right, R.string.split_screen_position_right,
+ STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_MAIN));
+ } else if (dp.isLandscape) {
+ options.add(new SplitPositionOption(
+ R.drawable.ic_split_left, R.string.split_screen_position_left,
+ STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
+ } else {
+ // Only add top option
+ options.add(new SplitPositionOption(
+ R.drawable.ic_split_top, R.string.split_screen_position_top,
+ STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
+ }
}
-
- @Override
- public int getIntrinsicHeight() {
- return mSize;
- }
-
- @Override
- public int getIntrinsicWidth() {
- return mSize;
- }
+ return options;
}
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index f18ff3b..4903d77 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -50,7 +50,6 @@
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
-import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
@@ -86,14 +85,12 @@
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
-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.SearchActionItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemFactory;
import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.pageindicators.WorkspacePageIndicator;
-import com.android.launcher3.popup.PopupContainerWithArrow;
+import com.android.launcher3.pageindicators.PageIndicator;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
@@ -103,7 +100,6 @@
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.IntSparseArrayMap;
-import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LauncherBindableItemsContainer;
import com.android.launcher3.util.OverlayEdgeEffect;
import com.android.launcher3.util.PackageUserKey;
@@ -113,6 +109,7 @@
import com.android.launcher3.widget.LauncherAppWidgetHost;
import com.android.launcher3.widget.LauncherAppWidgetHost.ProviderChangedListener;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.android.launcher3.widget.NavigableAppWidgetHostView;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.PendingAppWidgetHostView;
@@ -122,7 +119,6 @@
import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlay;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
@@ -133,8 +129,9 @@
* The workspace is a wide area with a wallpaper and a finite number of pages.
* Each page contains a number of icons, folders or widgets the user can
* interact with. A workspace is meant to be used with a fixed width only.
+ * @param <T> Class that extends View and PageIndicator
*/
-public class Workspace extends PagedView<WorkspacePageIndicator>
+public class Workspace<T extends View & PageIndicator> extends PagedView<T>
implements DropTarget, DragSource, View.OnTouchListener,
DragController.DragListener, Insettable, StateHandler<LauncherState>,
WorkspaceLayoutManager, LauncherBindableItemsContainer {
@@ -147,6 +144,8 @@
* {@link #isFinishedSwitchingState()} ()} to return true. */
private static final float FINISHED_SWITCHING_STATE_TRANSITION_PROGRESS = 0.5f;
+ private static final float SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE = 0.15f;
+
private static final boolean ENFORCE_DRAG_EVENT_ORDER = false;
private static final int ADJACENT_SCREEN_DROP_DURATION = 300;
@@ -198,6 +197,7 @@
private final int[] mTempXY = new int[2];
private final float[] mTempFXY = new float[2];
+ private final Rect mTempRect = new Rect();
@Thunk float[] mDragViewVisualCenter = new float[2];
private SpringLoadedDragController mSpringLoadedDragController;
@@ -324,37 +324,14 @@
setPageSpacing(Math.max(maxInsets, maxPadding));
}
- updateWorkspaceScreensPadding();
+ updateCellLayoutPadding();
updateWorkspaceWidgetsSizes();
}
- private void updateWorkspaceScreensPadding() {
- DeviceProfile grid = mLauncher.getDeviceProfile();
- int paddingLeftRight = grid.cellLayoutPaddingLeftRightPx;
- int paddingBottom = grid.cellLayoutBottomPaddingPx;
-
- int panelCount = getPanelCount();
- int rightPanelModulus = mIsRtl ? 0 : panelCount - 1;
- int leftPanelModulus = mIsRtl ? panelCount - 1 : 0;
- int numberOfScreens = mScreenOrder.size();
- for (int i = 0; i < numberOfScreens; i++) {
- int paddingLeft = paddingLeftRight;
- int paddingRight = paddingLeftRight;
- // Add missing cellLayout border in-between panels.
- if (panelCount > 1) {
- if (i % panelCount == leftPanelModulus) {
- paddingRight += grid.cellLayoutBorderSpacePx.x / 2;
- } else if (i % panelCount == rightPanelModulus) { // right side panel
- paddingLeft += grid.cellLayoutBorderSpacePx.x / 2;
- } else { // middle panel
- paddingLeft += grid.cellLayoutBorderSpacePx.x / 2;
- paddingRight += grid.cellLayoutBorderSpacePx.x / 2;
- }
- }
- // SparseArrayMap doesn't keep the order
- mWorkspaceScreens.get(mScreenOrder.get(i))
- .setPadding(paddingLeft, 0, paddingRight, paddingBottom);
- }
+ private void updateCellLayoutPadding() {
+ Rect padding = mLauncher.getDeviceProfile().cellLayoutPaddingPx;
+ mWorkspaceScreens.forEach(
+ s -> s.setPadding(padding.left, padding.top, padding.right, padding.bottom));
}
private void updateWorkspaceWidgetsSizes() {
@@ -586,8 +563,8 @@
int cellVSpan = FeatureFlags.EXPANDED_SMARTSPACE.get()
? EXPANDED_SMARTSPACE_HEIGHT : DEFAULT_SMARTSPACE_HEIGHT;
- CellLayout.LayoutParams lp = new CellLayout.LayoutParams(0, 0, firstPage.getCountX(),
- cellVSpan);
+ int cellHSpan = mLauncher.getDeviceProfile().inv.numSearchContainerColumns;
+ CellLayout.LayoutParams lp = new CellLayout.LayoutParams(0, 0, cellHSpan, cellVSpan);
lp.canReorder = false;
if (!firstPage.addViewToCellLayout(mQsb, 0, R.id.search_container_workspace, lp, true)) {
Log.e(TAG, "Failed to add to item at (0, 0) to CellLayout");
@@ -652,7 +629,7 @@
mLauncher.getStateManager().getState(), newScreen, insertIndex);
updatePageScrollValues();
- updateWorkspaceScreensPadding();
+ updateCellLayoutPadding();
return newScreen;
}
@@ -927,7 +904,11 @@
* two panel UI is enabled.
*/
public int getScreenPair(int screenId) {
- if (screenId % 2 == 0) {
+ if (screenId == EXTRA_EMPTY_SCREEN_ID) {
+ return EXTRA_EMPTY_SCREEN_SECOND_ID;
+ } else if (screenId == EXTRA_EMPTY_SCREEN_SECOND_ID) {
+ return EXTRA_EMPTY_SCREEN_ID;
+ } else if (screenId % 2 == 0) {
return screenId + 1;
} else {
return screenId - 1;
@@ -1136,6 +1117,10 @@
stripEmptyScreens();
mStripScreensOnPageStopMoving = false;
}
+
+ // Inform the Launcher activity that the page transition ended so that it can react to the
+ // newly visible page if it wants to.
+ mLauncher.onPageEndTransition();
}
public void setLauncherOverlay(LauncherOverlay overlay) {
@@ -1212,6 +1197,10 @@
.log(LAUNCHER_SWIPELEFT);
}
mOverlayShown = true;
+
+ // Let the Launcher activity know that the overlay is now visible.
+ mLauncher.onOverlayVisibilityChanged(mOverlayShown);
+
// Not announcing the overlay page for accessibility since it announces itself.
} else if (Float.compare(scroll, 0f) == 0) {
if (mOverlayShown) {
@@ -1235,6 +1224,10 @@
announcePageForAccessibility();
}
mOverlayShown = false;
+
+ // Let the Launcher activity know that the overlay is no longer visible.
+ mLauncher.onOverlayVisibilityChanged(mOverlayShown);
+
tryRunOverlayCallback();
}
@@ -1685,11 +1678,7 @@
}
if (child instanceof BubbleTextView && !dragOptions.isAccessibleDrag) {
- PopupContainerWithArrow<Launcher> popupContainer = PopupContainerWithArrow
- .showForIcon((BubbleTextView) child);
- if (popupContainer != null) {
- dragOptions.preDragCondition = popupContainer.createPreDragCondition(true);
- }
+ dragOptions.preDragCondition = ((BubbleTextView) child).startLongPressAction();
}
final DragView dv;
@@ -1739,7 +1728,7 @@
// If it's an external drop (e.g. from All Apps), check if it should be accepted
CellLayout dropTargetLayout = mDropToLayout;
if (d.dragSource != this) {
- // Don't accept the drop if we're not over a screen at time of drop
+ // Don't accept the drop if we're not over a valid drop target at time of drop
if (dropTargetLayout == null) {
return false;
}
@@ -2122,7 +2111,7 @@
final Runnable onCompleteCallback = onCompleteRunnable;
mLauncher.getDragController().animateDragViewToOriginalPosition(
/* onComplete= */ callbackList::executeAllAndDestroy, cell,
- SPRING_LOADED.getTransitionDuration(mLauncher));
+ SPRING_LOADED.getTransitionDuration(mLauncher, true /* isToState */));
mLauncher.getStateManager().goToState(NORMAL, /* delay= */ 0,
onCompleteCallback == null
? null
@@ -2340,17 +2329,6 @@
xy[1] = xy[1] - v.getTop();
}
- boolean isPointInSelfOverHotseat(int x, int y) {
- mTempFXY[0] = x;
- mTempFXY[1] = y;
- mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, mTempFXY, true);
- View hotseat = mLauncher.getHotseat();
- return mTempFXY[0] >= hotseat.getLeft()
- && mTempFXY[0] <= hotseat.getRight()
- && mTempFXY[1] >= hotseat.getTop()
- && mTempFXY[1] <= hotseat.getBottom();
- }
-
/**
* Updates the point in {@param xy} to point to the co-ordinate space of {@param layout}
* @param layout either hotseat of a page in workspace
@@ -2388,7 +2366,7 @@
final View child = (mDragInfo == null) ? null : mDragInfo.cell;
if (setDropLayoutForDragObject(d, mDragViewVisualCenter[0], mDragViewVisualCenter[1])) {
- if (mLauncher.isHotseatLayout(mDragTargetLayout)) {
+ if (mDragTargetLayout == null || mLauncher.isHotseatLayout(mDragTargetLayout)) {
mSpringLoadedDragController.cancel();
} else {
mSpringLoadedDragController.setAlarm(mDragTargetLayout);
@@ -2467,42 +2445,25 @@
*/
private boolean setDropLayoutForDragObject(DragObject d, float centerX, float centerY) {
CellLayout layout = null;
- // Test to see if we are over the hotseat first
- if (mLauncher.getHotseat() != null && !isDragWidget(d)) {
- if (isPointInSelfOverHotseat(d.x, d.y)) {
- layout = mLauncher.getHotseat();
+ if (shouldUseHotseatAsDropLayout(d)) {
+ layout = mLauncher.getHotseat();
+ } else if (!isDragObjectOverSmartSpace(d)) {
+ // If the object is over qsb/smartspace, we don't want to highlight anything.
+
+ // Check neighbour pages
+ layout = checkDragObjectIsOverNeighbourPages(d, centerX);
+
+ if (layout == null) {
+ // Check visible pages
+ IntSet visiblePageIndices = getVisiblePageIndices();
+ for (int visiblePageIndex : visiblePageIndices) {
+ layout = verifyInsidePage(visiblePageIndex, d.x, d.y);
+ if (layout != null) break;
+ }
}
}
- int nextPage = getNextPage();
- IntSet pageIndexesToVerify = IntSet.wrap(nextPage - 1, nextPage + 1);
- if (isTwoPanelEnabled()) {
- // If two panel is enabled, users can also drag items to nextPage + 2
- pageIndexesToVerify.add(nextPage + 2);
- }
-
- int touchX = (int) Math.min(centerX, d.x);
- int touchY = d.y;
-
- // Go through the pages and check if the dragged item is inside one of them
- for (int pageIndex : pageIndexesToVerify) {
- if (layout != null || isPageInTransition()) {
- break;
- }
- layout = verifyInsidePage(pageIndex, touchX, touchY);
- }
-
- // If the dragged item isn't located in one of the pages above, the icon will stay on the
- // current screen. For two panel pick the closest panel on the current screen,
- // on one panel just choose the current page.
- if (layout == null && nextPage >= 0 && nextPage < getPageCount()) {
- if (isTwoPanelEnabled()) {
- nextPage = getScreenCenter(getScrollX()) > touchX
- ? (mIsRtl ? nextPage + 1 : nextPage) // left side
- : (mIsRtl ? nextPage : nextPage + 1); // right side
- }
- layout = (CellLayout) getChildAt(nextPage);
- }
+ // Update the current drop layout if the target changed
if (layout != mDragTargetLayout) {
setCurrentDropLayout(layout);
setCurrentDragOverlappingLayout(layout);
@@ -2511,6 +2472,69 @@
return false;
}
+ private boolean shouldUseHotseatAsDropLayout(DragObject dragObject) {
+ if (mLauncher.getHotseat() == null
+ || mLauncher.getHotseat().getShortcutsAndWidgets() == null
+ || isDragWidget(dragObject)) {
+ return false;
+ }
+ View hotseatShortcuts = mLauncher.getHotseat().getShortcutsAndWidgets();
+ getViewBoundsRelativeToWorkspace(hotseatShortcuts, mTempRect);
+ return mTempRect.contains(dragObject.x, dragObject.y);
+ }
+
+ private boolean isDragObjectOverSmartSpace(DragObject dragObject) {
+ if (mQsb == null) {
+ return false;
+ }
+ getViewBoundsRelativeToWorkspace(mQsb, mTempRect);
+ return mTempRect.contains(dragObject.x, dragObject.y);
+ }
+
+ private CellLayout checkDragObjectIsOverNeighbourPages(DragObject d, float centerX) {
+ if (isPageInTransition()) {
+ return null;
+ }
+
+ // Check the workspace pages whether the object is over any of them
+
+ // Note, centerX represents the center of the object that is being dragged, visually.
+ // d.x represents the location of the finger within the dragged item.
+ float touchX;
+ float touchY = d.y;
+
+ // Go through the pages and check if the dragged item is inside one of them. This block
+ // is responsible for determining whether we need to snap to a different screen.
+ int nextPage = getNextPage();
+ IntSet pageIndexesToVerify = IntSet.wrap(nextPage - 1,
+ nextPage + (isTwoPanelEnabled() ? 2 : 1));
+
+ for (int pageIndex : pageIndexesToVerify) {
+ // When deciding whether to perform a page switch, we need to consider the most
+ // extreme X coordinate between the finger location and the center of the object
+ // being dragged. This is either the max or the min of the two depending on whether
+ // dragging to the left / right, respectively.
+ touchX = (((pageIndex < nextPage) && !mIsRtl) || (pageIndex > nextPage && mIsRtl))
+ ? Math.min(d.x, centerX) : Math.max(d.x, centerX);
+ CellLayout layout = verifyInsidePage(pageIndex, touchX, touchY);
+ if (layout != null) {
+ return layout;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the given view's bounds relative to Workspace
+ */
+ private void getViewBoundsRelativeToWorkspace(View view, Rect outRect) {
+ mLauncher.getDragLayer()
+ .getDescendantRectRelativeToSelf(view, mTempRect);
+ // map draglayer relative bounds to workspace
+ mLauncher.getDragLayer().mapRectInSelfToDescendant(this, mTempRect);
+ outRect.set(mTempRect);
+ }
+
/**
* Returns the child CellLayout if the point is inside the page coordinates, null otherwise.
*/
@@ -2747,14 +2771,15 @@
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_SEARCH_ACTION:
- if (info instanceof AppInfo) {
+ if (info instanceof WorkspaceItemFactory) {
// Came from all apps -- make a copy
- info = ((AppInfo) info).makeWorkspaceItem();
+ info = ((WorkspaceItemFactory) info).makeWorkspaceItem(mLauncher);
d.dragInfo = info;
}
- if (info instanceof SearchActionItemInfo) {
- info = ((SearchActionItemInfo) info).createWorkspaceItem(
- mLauncher.getModel());
+ if (info instanceof WorkspaceItemInfo
+ && info.container == LauncherSettings.Favorites.CONTAINER_PREDICTION) {
+ // Came from all apps prediction row -- make a copy
+ info = new WorkspaceItemInfo((WorkspaceItemInfo) info);
d.dragInfo = info;
}
view = mLauncher.createShortcut(cellLayout, (WorkspaceItemInfo) info);
@@ -2832,7 +2857,8 @@
}
private void getFinalPositionForDropAnimation(int[] loc, float[] scaleXY,
- DragView dragView, CellLayout layout, ItemInfo info, int[] targetCell, boolean scale) {
+ DragView dragView, CellLayout layout, ItemInfo info, int[] targetCell, boolean scale,
+ final View finalView) {
// Now we animate the dragView, (ie. the widget or shortcut preview) into its final
// location and size on the home screen.
int spanX = info.spanX;
@@ -2841,6 +2867,14 @@
Rect r = estimateItemPosition(layout, targetCell[0], targetCell[1], spanX, spanY);
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET) {
DeviceProfile profile = mLauncher.getDeviceProfile();
+ if (profile.shouldInsetWidgets() && finalView instanceof NavigableAppWidgetHostView) {
+ Rect widgetPadding = new Rect();
+ ((NavigableAppWidgetHostView) finalView).getWidgetInset(profile, widgetPadding);
+ r.left -= widgetPadding.left;
+ r.right += widgetPadding.right;
+ r.top -= widgetPadding.top;
+ r.bottom += widgetPadding.bottom;
+ }
Utilities.shrinkRect(r, profile.appWidgetScale.x, profile.appWidgetScale.y);
}
@@ -2887,7 +2921,7 @@
float scaleXY[] = new float[2];
boolean scalePreview = !(info instanceof PendingAddShortcutInfo);
getFinalPositionForDropAnimation(finalPos, scaleXY, dragView, cellLayout, info, mTargetCell,
- scalePreview);
+ scalePreview, finalView);
Resources res = mLauncher.getResources();
final int duration = res.getInteger(R.integer.config_dropAnimMaxDuration) - 200;
@@ -3034,7 +3068,8 @@
if (info instanceof LauncherAppWidgetInfo) {
LauncherAppWidgetInfo appWidgetInfo = (LauncherAppWidgetInfo) info;
if (appWidgetInfo.appWidgetId == appWidgetId) {
- mLauncher.removeItem(view, appWidgetInfo, true);
+ mLauncher.removeItem(view, appWidgetInfo, true,
+ "widget is removed in response to widget remove broadcast");
return true;
}
}
@@ -3189,7 +3224,7 @@
* as a part of an update, this is called to ensure that other widgets and application
* shortcuts are not removed.
*/
- public void removeItemsByMatcher(final ItemInfoMatcher matcher) {
+ public void removeItemsByMatcher(final Predicate<ItemInfo> matcher) {
for (CellLayout layout : getWorkspaceAndHotseatCellLayouts()) {
ShortcutAndWidgetContainer container = layout.getShortcutsAndWidgets();
// Iterate in reverse order as we are removing items
@@ -3197,7 +3232,7 @@
View child = container.getChildAt(i);
ItemInfo info = (ItemInfo) child.getTag();
- if (matcher.matchesInfo(info)) {
+ if (matcher.test(info)) {
layout.removeViewInLayout(child);
if (child instanceof DropTarget) {
mDragController.removeDropTarget((DropTarget) child);
@@ -3205,7 +3240,7 @@
} else if (child instanceof FolderIcon) {
FolderInfo folderInfo = (FolderInfo) info;
List<WorkspaceItemInfo> matches = folderInfo.contents.stream()
- .filter(matcher::matchesInfo)
+ .filter(matcher)
.collect(Collectors.toList());
if (!matches.isEmpty()) {
folderInfo.removeAll(matches, false);
@@ -3230,7 +3265,11 @@
}
}
- private View mapOverCellLayout(CellLayout layout, ItemOperator op) {
+ /**
+ * Perform {param operator} over all the items in a given {param layout}.
+ * @return The first item that satisfies the operator or null.
+ */
+ public View mapOverCellLayout(CellLayout layout, ItemOperator operator) {
// TODO(b/128460496) Potential race condition where layout is not yet loaded
if (layout == null) {
return null;
@@ -3240,7 +3279,7 @@
final int itemCount = container.getChildCount();
for (int itemIdx = 0; itemIdx < itemCount; itemIdx++) {
View item = container.getChildAt(itemIdx);
- if (op.evaluate((ItemInfo) item.getTag(), item)) {
+ if (operator.evaluate((ItemInfo) item.getTag(), item)) {
return item;
}
}
@@ -3279,10 +3318,14 @@
}
}
- public void removeAbandonedPromise(String packageName, UserHandle user) {
- ItemInfoMatcher matcher = ItemInfoMatcher.ofPackages(
- Collections.singleton(packageName), user);
- mLauncher.getModelWriter().deleteItemsFromDatabase(matcher);
+ /**
+ * Remove workspace icons & widget information related to items in matcher.
+ *
+ * @param matcher the matcher generated by the caller.
+ */
+ public void persistRemoveItemsByMatcher(Predicate<ItemInfo> matcher,
+ @Nullable final String reason) {
+ mLauncher.getModelWriter().deleteItemsFromDatabase(matcher, reason);
removeItemsByMatcher(matcher);
}
@@ -3388,7 +3431,21 @@
// When the workspace is not loaded, we do not know how many screen will be bound.
return getContext().getString(R.string.home_screen);
}
- return getContext().getString(R.string.workspace_scroll_format, page + 1, nScreens);
+ int panelCount = getPanelCount();
+ int currentPage = (page / panelCount) + 1;
+ int totalPages = nScreens / panelCount + nScreens % panelCount;
+ return getContext().getString(R.string.workspace_scroll_format, currentPage, totalPages);
+ }
+
+ @Override
+ protected boolean isSignificantMove(float absoluteDelta, int pageOrientedSize) {
+ DeviceProfile deviceProfile = mLauncher.getDeviceProfile();
+ if (!deviceProfile.isTablet) {
+ return super.isSignificantMove(absoluteDelta, pageOrientedSize);
+ }
+
+ return absoluteDelta
+ > deviceProfile.availableWidthPx * SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE;
}
/**
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 1b9647a..a991c2f 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -18,11 +18,14 @@
import static androidx.dynamicanimation.animation.DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE;
-import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+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;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
+import static com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY;
import static com.android.launcher3.LauncherState.FLAG_HAS_SYS_UI_SCRIM;
+import static com.android.launcher3.LauncherState.FLAG_HOTSEAT_INACCESSIBLE;
import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.LauncherState.NORMAL;
@@ -33,19 +36,23 @@
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;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_PAGE_TRANSLATE_X;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_SCRIM;
import android.animation.ValueAnimator;
+import android.util.FloatProperty;
import android.view.View;
import android.view.animation.Interpolator;
import com.android.launcher3.LauncherState.PageAlphaProvider;
+import com.android.launcher3.LauncherState.PageTranslationProvider;
import com.android.launcher3.LauncherState.ScaleAndTranslation;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
@@ -62,12 +69,18 @@
*/
public class WorkspaceStateTransitionAnimation {
+ private static final FloatProperty<Workspace<?>> WORKSPACE_SCALE_PROPERTY =
+ WORKSPACE_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_WORKSPACE_STATE);
+
+ private static final FloatProperty<Hotseat> HOTSEAT_SCALE_PROPERTY =
+ HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_WORKSPACE_STATE);
+
private final Launcher mLauncher;
- private final Workspace mWorkspace;
+ private final Workspace<?> mWorkspace;
private float mNewScale;
- public WorkspaceStateTransitionAnimation(Launcher launcher, Workspace workspace) {
+ public WorkspaceStateTransitionAnimation(Launcher launcher, Workspace<?> workspace) {
mLauncher = launcher;
mWorkspace = workspace;
}
@@ -105,8 +118,6 @@
}
int elements = state.getVisibleElements(mLauncher);
- Interpolator fadeInterpolator = config.getInterpolator(ANIM_WORKSPACE_FADE,
- pageAlphaProvider.interpolator);
Hotseat hotseat = mWorkspace.getHotseat();
Interpolator scaleInterpolator = config.getInterpolator(ANIM_WORKSPACE_SCALE, ZOOM_OUT);
LauncherState fromState = mLauncher.getStateManager().getState();
@@ -115,28 +126,40 @@
&& fromState == HINT_STATE && state == NORMAL;
if (shouldSpring) {
((PendingAnimation) propertySetter).add(getSpringScaleAnimator(mLauncher,
- mWorkspace, mNewScale));
+ mWorkspace, mNewScale, WORKSPACE_SCALE_PROPERTY));
} else {
- propertySetter.setFloat(mWorkspace, SCALE_PROPERTY, mNewScale, scaleInterpolator);
+ propertySetter.setFloat(mWorkspace, WORKSPACE_SCALE_PROPERTY, mNewScale,
+ scaleInterpolator);
}
mWorkspace.setPivotToScaleWithSelf(hotseat);
float hotseatScale = hotseatScaleAndTranslation.scale;
if (shouldSpring) {
PendingAnimation pa = (PendingAnimation) propertySetter;
- pa.add(getSpringScaleAnimator(mLauncher, hotseat, hotseatScale));
+ pa.add(getSpringScaleAnimator(mLauncher, hotseat, hotseatScale,
+ HOTSEAT_SCALE_PROPERTY));
} else {
Interpolator hotseatScaleInterpolator = config.getInterpolator(ANIM_HOTSEAT_SCALE,
scaleInterpolator);
- propertySetter.setFloat(hotseat, SCALE_PROPERTY, hotseatScale,
+ propertySetter.setFloat(hotseat, HOTSEAT_SCALE_PROPERTY, hotseatScale,
hotseatScaleInterpolator);
}
- float hotseatIconsAlpha = (elements & HOTSEAT_ICONS) != 0 ? 1 : 0;
- propertySetter.setViewAlpha(hotseat, hotseatIconsAlpha, fadeInterpolator);
+ Interpolator workspaceFadeInterpolator = config.getInterpolator(ANIM_WORKSPACE_FADE,
+ pageAlphaProvider.interpolator);
float workspacePageIndicatorAlpha = (elements & WORKSPACE_PAGE_INDICATOR) != 0 ? 1 : 0;
propertySetter.setViewAlpha(mLauncher.getWorkspace().getPageIndicator(),
- workspacePageIndicatorAlpha, fadeInterpolator);
+ workspacePageIndicatorAlpha, workspaceFadeInterpolator);
+ Interpolator hotseatFadeInterpolator = config.getInterpolator(ANIM_HOTSEAT_FADE,
+ workspaceFadeInterpolator);
+ float hotseatIconsAlpha = (elements & HOTSEAT_ICONS) != 0 ? 1 : 0;
+ propertySetter.setViewAlpha(hotseat, hotseatIconsAlpha, hotseatFadeInterpolator);
+
+ // Update the accessibility flags for hotseat based on launcher state.
+ hotseat.setImportantForAccessibility(
+ state.hasFlag(FLAG_HOTSEAT_INACCESSIBLE)
+ ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+ : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
Interpolator translationInterpolator =
config.getInterpolator(ANIM_WORKSPACE_TRANSLATE, ZOOM_OUT);
@@ -144,6 +167,12 @@
scaleAndTranslation.translationX, translationInterpolator);
propertySetter.setFloat(mWorkspace, VIEW_TRANSLATE_Y,
scaleAndTranslation.translationY, translationInterpolator);
+ PageTranslationProvider pageTranslationProvider = state.getWorkspacePageTranslationProvider(
+ mLauncher);
+ for (int i = 0; i < childCount; i++) {
+ applyPageTranslation((CellLayout) mWorkspace.getChildAt(i), i, pageTranslationProvider,
+ propertySetter, config);
+ }
Interpolator hotseatTranslationInterpolator = config.getInterpolator(
ANIM_HOTSEAT_TRANSLATE, translationInterpolator);
@@ -191,10 +220,29 @@
pageAlpha, fadeInterpolator);
}
+ private void applyPageTranslation(CellLayout cellLayout, int childIndex,
+ PageTranslationProvider pageTranslationProvider, PropertySetter propertySetter,
+ StateAnimationConfig config) {
+ float pageTranslation = pageTranslationProvider.getPageTranslation(childIndex);
+ Interpolator translationInterpolator = config.getInterpolator(
+ ANIM_WORKSPACE_PAGE_TRANSLATE_X, pageTranslationProvider.interpolator);
+ propertySetter.setFloat(cellLayout, VIEW_TRANSLATE_X, pageTranslation,
+ translationInterpolator);
+ }
+
+ /**
+ * Returns a spring based animator for the scale property of {@param workspace}.
+ */
+ public static ValueAnimator getWorkspaceSpringScaleAnimator(Launcher launcher,
+ Workspace<?> workspace, float scale) {
+ return getSpringScaleAnimator(launcher, workspace, scale, WORKSPACE_SCALE_PROPERTY);
+ }
+
/**
* Returns a spring based animator for the scale property of {@param v}.
*/
- public static ValueAnimator getSpringScaleAnimator(Launcher launcher, View v, float scale) {
+ public static <T extends View> ValueAnimator getSpringScaleAnimator(Launcher launcher, T v,
+ float scale, FloatProperty<T> property) {
ResourceProvider rp = DynamicResource.provider(launcher);
float damping = rp.getFloat(R.dimen.hint_scale_damping_ratio);
float stiffness = rp.getFloat(R.dimen.hint_scale_stiffness);
@@ -205,9 +253,9 @@
.setDampingRatio(damping)
.setMinimumVisibleChange(MIN_VISIBLE_CHANGE_SCALE)
.setEndValue(scale)
- .setStartValue(SCALE_PROPERTY.get(v))
+ .setStartValue(property.get(v))
.setStartVelocity(velocityPxPerS)
- .build(v, SCALE_PROPERTY);
+ .build(v, property);
}
}
\ No newline at end of file
diff --git a/src/com/android/launcher3/accessibility/BaseAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/BaseAccessibilityDelegate.java
new file mode 100644
index 0000000..19d0421
--- /dev/null
+++ b/src/com/android/launcher3/accessibility/BaseAccessibilityDelegate.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.accessibility;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.SparseArray;
+import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.DropTarget;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.dragndrop.DragController;
+import com.android.launcher3.dragndrop.DragOptions;
+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.util.Thunk;
+import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.BubbleTextHolder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class BaseAccessibilityDelegate<T extends Context & ActivityContext>
+ extends View.AccessibilityDelegate implements DragController.DragListener {
+
+ public enum DragType {
+ ICON,
+ FOLDER,
+ WIDGET
+ }
+
+ public static class DragInfo {
+ public DragType dragType;
+ public ItemInfo info;
+ public View item;
+ }
+
+ protected final SparseArray<LauncherAction> mActions = new SparseArray<>();
+ protected final T mContext;
+
+ protected DragInfo mDragInfo = null;
+
+ protected BaseAccessibilityDelegate(T context) {
+ mContext = context;
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ if (host.getTag() instanceof ItemInfo) {
+ ItemInfo item = (ItemInfo) host.getTag();
+
+ List<LauncherAction> actions = new ArrayList<>();
+ getSupportedActions(host, item, actions);
+ actions.forEach(la -> info.addAction(la.accessibilityAction));
+
+ if (!itemSupportsLongClick(host)) {
+ info.setLongClickable(false);
+ info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK);
+ }
+ }
+ }
+
+ /**
+ * Adds all the accessibility actions that can be handled.
+ */
+ protected abstract void getSupportedActions(View host, ItemInfo item, List<LauncherAction> out);
+
+ private boolean itemSupportsLongClick(View host) {
+ if (host instanceof BubbleTextView) {
+ return ((BubbleTextView) host).canShowLongPressPopup();
+ } else if (host instanceof BubbleTextHolder) {
+ BubbleTextHolder holder = (BubbleTextHolder) host;
+ return holder.getBubbleText() != null && holder.getBubbleText().canShowLongPressPopup();
+ } else {
+ return false;
+ }
+ }
+
+ protected boolean itemSupportsAccessibleDrag(ItemInfo item) {
+ if (item instanceof WorkspaceItemInfo) {
+ // Support the action unless the item is in a context menu.
+ return item.screenId >= 0
+ && item.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
+ }
+ return (item instanceof LauncherAppWidgetInfo)
+ || (item instanceof FolderInfo);
+ }
+
+ @Override
+ public boolean performAccessibilityAction(View host, int action, Bundle args) {
+ if ((host.getTag() instanceof ItemInfo)
+ && performAction(host, (ItemInfo) host.getTag(), action, false)) {
+ return true;
+ }
+ return super.performAccessibilityAction(host, action, args);
+ }
+
+ protected abstract boolean performAction(
+ View host, ItemInfo item, int action, boolean fromKeyboard);
+
+ @Thunk
+ protected void announceConfirmation(String confirmation) {
+ mContext.getDragLayer().announceForAccessibility(confirmation);
+ }
+
+ public boolean isInAccessibleDrag() {
+ return mDragInfo != null;
+ }
+
+ public DragInfo getDragInfo() {
+ return mDragInfo;
+ }
+
+ /**
+ * @param clickedTarget the actual view that was clicked
+ * @param dropLocation relative to {@param clickedTarget}. If provided, its center is used
+ * as the actual drop location otherwise the views center is used.
+ */
+ public void handleAccessibleDrop(View clickedTarget, Rect dropLocation,
+ String confirmation) {
+ if (!isInAccessibleDrag()) return;
+
+ int[] loc = new int[2];
+ if (dropLocation == null) {
+ loc[0] = clickedTarget.getWidth() / 2;
+ loc[1] = clickedTarget.getHeight() / 2;
+ } else {
+ loc[0] = dropLocation.centerX();
+ loc[1] = dropLocation.centerY();
+ }
+
+ mContext.getDragLayer().getDescendantCoordRelativeToSelf(clickedTarget, loc);
+ mContext.getDragController().completeAccessibleDrag(loc);
+
+ if (!TextUtils.isEmpty(confirmation)) {
+ announceConfirmation(confirmation);
+ }
+ }
+
+ protected abstract boolean beginAccessibleDrag(View item, ItemInfo info, boolean fromKeyboard);
+
+
+ @Override
+ public void onDragEnd() {
+ mContext.getDragController().removeDragListener(this);
+ mDragInfo = null;
+ }
+
+ @Override
+ public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
+ // No-op
+ }
+
+ public class LauncherAction {
+ public final int keyCode;
+ public final AccessibilityNodeInfo.AccessibilityAction accessibilityAction;
+
+ private final BaseAccessibilityDelegate<T> mDelegate;
+
+ public LauncherAction(int id, int labelRes, int keyCode) {
+ this.keyCode = keyCode;
+ accessibilityAction = new AccessibilityNodeInfo.AccessibilityAction(
+ id, mContext.getString(labelRes));
+ mDelegate = BaseAccessibilityDelegate.this;
+ }
+
+ /**
+ * Invokes the action for the provided host
+ */
+ public boolean invokeFromKeyboard(View host) {
+ if (host != null && host.getTag() instanceof ItemInfo) {
+ return mDelegate.performAction(
+ host, (ItemInfo) host.getTag(), accessibilityAction.getId(), true);
+ } else {
+ return false;
+ }
+ }
+ }
+}
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index 157df5d..79214e8 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -10,35 +10,28 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
-import android.os.Bundle;
import android.os.Handler;
-import android.text.TextUtils;
import android.util.Log;
-import android.util.SparseArray;
import android.view.KeyEvent;
import android.view.View;
-import android.view.View.AccessibilityDelegate;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.ButtonDropTarget;
import com.android.launcher3.CellLayout;
-import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.LauncherSettings;
import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.R;
import com.android.launcher3.Workspace;
-import com.android.launcher3.dragndrop.DragController.DragListener;
import com.android.launcher3.dragndrop.DragOptions;
+import com.android.launcher3.dragndrop.DragOptions.PreDragCondition;
import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.keyboard.KeyboardDragAndDropView;
-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.WorkspaceItemFactory;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.popup.ArrowPopup;
@@ -48,6 +41,7 @@
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.ShortcutUtil;
import com.android.launcher3.util.Thunk;
+import com.android.launcher3.views.BubbleTextHolder;
import com.android.launcher3.views.OptionsPopupView;
import com.android.launcher3.views.OptionsPopupView.OptionItem;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
@@ -57,7 +51,7 @@
import java.util.Collections;
import java.util.List;
-public class LauncherAccessibilityDelegate extends AccessibilityDelegate implements DragListener {
+public class LauncherAccessibilityDelegate extends BaseAccessibilityDelegate<Launcher> {
private static final String TAG = "LauncherAccessibilityDelegate";
@@ -66,6 +60,7 @@
public static final int DISMISS_PREDICTION = R.id.action_dismiss_prediction;
public static final int PIN_PREDICTION = R.id.action_pin_prediction;
public static final int RECONFIGURE = R.id.action_reconfigure;
+ public static final int INVALID = -1;
protected static final int ADD_TO_WORKSPACE = R.id.action_add_to_workspace;
protected static final int MOVE = R.id.action_move;
protected static final int MOVE_TO_WORKSPACE = R.id.action_move_to_workspace;
@@ -73,25 +68,8 @@
public static final int DEEP_SHORTCUTS = R.id.action_deep_shortcuts;
public static final int SHORTCUTS_AND_NOTIFICATIONS = R.id.action_shortcuts_and_notifications;
- public enum DragType {
- ICON,
- FOLDER,
- WIDGET
- }
-
- public static class DragInfo {
- public DragType dragType;
- public ItemInfo info;
- public View item;
- }
-
- protected final SparseArray<LauncherAction> mActions = new SparseArray<>();
- protected final Launcher mLauncher;
-
- private DragInfo mDragInfo = null;
-
public LauncherAccessibilityDelegate(Launcher launcher) {
- mLauncher = launcher;
+ super(launcher);
mActions.put(REMOVE, new LauncherAction(
REMOVE, R.string.remove_drop_target_label, KeyEvent.KEYCODE_X));
@@ -116,25 +94,6 @@
}
@Override
- public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfo(host, info);
- if (host.getTag() instanceof ItemInfo) {
- ItemInfo item = (ItemInfo) host.getTag();
-
- List<LauncherAction> actions = new ArrayList<>();
- getSupportedActions(host, item, actions);
- actions.forEach(la -> info.addAction(la.accessibilityAction));
-
- if (!itemSupportsLongClick(host, item)) {
- info.setLongClickable(false);
- info.removeAction(AccessibilityAction.ACTION_LONG_CLICK);
- }
- }
- }
-
- /**
- * Adds all the accessibility actions that can be handled.
- */
protected void getSupportedActions(View host, ItemInfo item, List<LauncherAction> out) {
// If the request came from keyboard, do not add custom shortcuts as that is already
// exposed as a direct shortcut
@@ -143,7 +102,7 @@
? SHORTCUTS_AND_NOTIFICATIONS : DEEP_SHORTCUTS));
}
- for (ButtonDropTarget target : mLauncher.getDropTargetBar().getDropTargets()) {
+ for (ButtonDropTarget target : mContext.getDropTargetBar().getDropTargets()) {
if (target.supportsAccessibilityDrop(item, host)) {
out.add(mActions.get(target.getAccessibilityAction()));
}
@@ -162,7 +121,7 @@
}
}
- if ((item instanceof AppInfo) || (item instanceof WorkspaceItemInfo)
+ if ((item instanceof WorkspaceItemFactory) || (item instanceof WorkspaceItemInfo)
|| (item instanceof PendingAddItemInfo)) {
out.add(mActions.get(ADD_TO_WORKSPACE));
}
@@ -183,112 +142,44 @@
return result;
}
- private boolean itemSupportsLongClick(View host, ItemInfo info) {
- return PopupContainerWithArrow.canShow(host, info);
- }
-
- private boolean itemSupportsAccessibleDrag(ItemInfo item) {
- if (item instanceof WorkspaceItemInfo) {
- // Support the action unless the item is in a context menu.
- return item.screenId >= 0 && item.container != Favorites.CONTAINER_HOTSEAT_PREDICTION;
- }
- return (item instanceof LauncherAppWidgetInfo)
- || (item instanceof FolderInfo);
- }
-
@Override
- public boolean performAccessibilityAction(View host, int action, Bundle args) {
- if ((host.getTag() instanceof ItemInfo)
- && performAction(host, (ItemInfo) host.getTag(), action, false)) {
- return true;
- }
- return super.performAccessibilityAction(host, action, args);
- }
-
- /**
- * Performs the provided action on the host
- */
protected boolean performAction(final View host, final ItemInfo item, int action,
boolean fromKeyboard) {
if (action == ACTION_LONG_CLICK) {
- if (PopupContainerWithArrow.canShow(host, item)) {
- // Long press should be consumed for workspace items, and it should invoke the
- // Shortcuts / Notifications / Actions pop-up menu, and not start a drag as the
- // standard long press path does.
- PopupContainerWithArrow.showForIcon((BubbleTextView) host);
- return true;
+ PreDragCondition dragCondition = null;
+ // Long press should be consumed for workspace items, and it should invoke the
+ // Shortcuts / Notifications / Actions pop-up menu, and not start a drag as the
+ // standard long press path does.
+ if (host instanceof BubbleTextView) {
+ dragCondition = ((BubbleTextView) host).startLongPressAction();
+ } else if (host instanceof BubbleTextHolder) {
+ BubbleTextHolder holder = (BubbleTextHolder) host;
+ dragCondition = holder.getBubbleText() == null ? null
+ : holder.getBubbleText().startLongPressAction();
}
+ return dragCondition != null;
} else if (action == MOVE) {
return beginAccessibleDrag(host, item, fromKeyboard);
} else if (action == ADD_TO_WORKSPACE) {
- final int[] coordinates = new int[2];
- final int screenId = findSpaceOnWorkspace(item, coordinates);
- if (screenId == -1) {
- return false;
- }
- mLauncher.getStateManager().goToState(NORMAL, true, forSuccessCallback(() -> {
- if (item instanceof AppInfo) {
- WorkspaceItemInfo info = ((AppInfo) item).makeWorkspaceItem();
- mLauncher.getModelWriter().addItemToDatabase(info,
- Favorites.CONTAINER_DESKTOP,
- screenId, coordinates[0], coordinates[1]);
-
- mLauncher.bindItems(
- Collections.singletonList(info),
- /* forceAnimateIcons= */ true,
- /* focusFirstItemForAccessibility= */ true);
- announceConfirmation(R.string.item_added_to_workspace);
- } else if (item instanceof PendingAddItemInfo) {
- PendingAddItemInfo info = (PendingAddItemInfo) item;
- Workspace workspace = mLauncher.getWorkspace();
- workspace.snapToPage(workspace.getPageIndexForScreenId(screenId));
- mLauncher.addPendingItem(info, Favorites.CONTAINER_DESKTOP,
- screenId, coordinates, info.spanX, info.spanY);
- }
- else if (item instanceof WorkspaceItemInfo) {
- WorkspaceItemInfo info = ((WorkspaceItemInfo) item).clone();
- mLauncher.getModelWriter().addItemToDatabase(info,
- Favorites.CONTAINER_DESKTOP,
- screenId, coordinates[0], coordinates[1]);
- mLauncher.bindItems(Collections.singletonList(info), true, true);
- }
- }));
- return true;
+ return addToWorkspace(item, true);
} else if (action == MOVE_TO_WORKSPACE) {
- Folder folder = Folder.getOpen(mLauncher);
- folder.close(true);
- WorkspaceItemInfo info = (WorkspaceItemInfo) item;
- folder.getInfo().remove(info, false);
-
- final int[] coordinates = new int[2];
- final int screenId = findSpaceOnWorkspace(item, coordinates);
- if (screenId == -1) {
- return false;
- }
- mLauncher.getModelWriter().moveItemInDatabase(info,
- Favorites.CONTAINER_DESKTOP,
- screenId, coordinates[0], coordinates[1]);
-
- // Bind the item in next frame so that if a new workspace page was created,
- // it will get laid out.
- new Handler().post(() -> {
- mLauncher.bindItems(Collections.singletonList(item), true);
- announceConfirmation(R.string.item_moved);
- });
- return true;
+ return moveToWorkspace(item);
} else if (action == RESIZE) {
final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) item;
List<OptionItem> actions = getSupportedResizeActions(host, info);
Rect pos = new Rect();
- mLauncher.getDragLayer().getDescendantRectRelativeToSelf(host, pos);
- ArrowPopup popup = OptionsPopupView.show(mLauncher, new RectF(pos), actions, false);
+ mContext.getDragLayer().getDescendantRectRelativeToSelf(host, pos);
+ ArrowPopup popup = OptionsPopupView.show(mContext, new RectF(pos), actions, false);
popup.requestFocus();
popup.setOnCloseCallback(host::requestFocus);
return true;
} else if (action == DEEP_SHORTCUTS || action == SHORTCUTS_AND_NOTIFICATIONS) {
- return PopupContainerWithArrow.showForIcon((BubbleTextView) host) != null;
+ BubbleTextView btv = host instanceof BubbleTextView ? (BubbleTextView) host
+ : (host instanceof BubbleTextHolder
+ ? ((BubbleTextHolder) host).getBubbleText() : null);
+ return btv != null && PopupContainerWithArrow.showForIcon(btv) != null;
} else {
- for (ButtonDropTarget dropTarget : mLauncher.getDropTargetBar().getDropTargets()) {
+ for (ButtonDropTarget dropTarget : mContext.getDropTargetBar().getDropTargets()) {
if (dropTarget.supportsAccessibilityDrop(item, host)
&& action == dropTarget.getAccessibilityAction()) {
dropTarget.onAccessibilityDrop(host, item);
@@ -315,7 +206,7 @@
if ((providerInfo.resizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0) {
if (layout.isRegionVacant(info.cellX + info.spanX, info.cellY, 1, info.spanY) ||
layout.isRegionVacant(info.cellX - 1, info.cellY, 1, info.spanY)) {
- actions.add(new OptionItem(mLauncher,
+ actions.add(new OptionItem(mContext,
R.string.action_increase_width,
R.drawable.ic_widget_width_increase,
IGNORE,
@@ -323,7 +214,7 @@
}
if (info.spanX > info.minSpanX && info.spanX > 1) {
- actions.add(new OptionItem(mLauncher,
+ actions.add(new OptionItem(mContext,
R.string.action_decrease_width,
R.drawable.ic_widget_width_decrease,
IGNORE,
@@ -334,7 +225,7 @@
if ((providerInfo.resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0) {
if (layout.isRegionVacant(info.cellX, info.cellY + info.spanY, info.spanX, 1) ||
layout.isRegionVacant(info.cellX, info.cellY - 1, info.spanX, 1)) {
- actions.add(new OptionItem(mLauncher,
+ actions.add(new OptionItem(mContext,
R.string.action_increase_height,
R.drawable.ic_widget_height_increase,
IGNORE,
@@ -342,7 +233,7 @@
}
if (info.spanY > info.minSpanY && info.spanY > 1) {
- actions.add(new OptionItem(mLauncher,
+ actions.add(new OptionItem(mContext,
R.string.action_decrease_height,
R.drawable.ic_widget_height_decrease,
IGNORE,
@@ -382,58 +273,20 @@
}
layout.markCellsAsOccupiedForView(host);
- WidgetSizes.updateWidgetSizeRanges(((LauncherAppWidgetHostView) host), mLauncher,
+ WidgetSizes.updateWidgetSizeRanges(((LauncherAppWidgetHostView) host), mContext,
info.spanX, info.spanY);
host.requestLayout();
- mLauncher.getModelWriter().updateItemInDatabase(info);
- announceConfirmation(mLauncher.getString(R.string.widget_resized, info.spanX, info.spanY));
+ mContext.getModelWriter().updateItemInDatabase(info);
+ announceConfirmation(mContext.getString(R.string.widget_resized, info.spanX, info.spanY));
return true;
}
@Thunk void announceConfirmation(int resId) {
- announceConfirmation(mLauncher.getResources().getString(resId));
+ announceConfirmation(mContext.getResources().getString(resId));
}
- @Thunk void announceConfirmation(String confirmation) {
- mLauncher.getDragLayer().announceForAccessibility(confirmation);
-
- }
-
- public boolean isInAccessibleDrag() {
- return mDragInfo != null;
- }
-
- public DragInfo getDragInfo() {
- return mDragInfo;
- }
-
- /**
- * @param clickedTarget the actual view that was clicked
- * @param dropLocation relative to {@param clickedTarget}. If provided, its center is used
- * as the actual drop location otherwise the views center is used.
- */
- public void handleAccessibleDrop(View clickedTarget, Rect dropLocation,
- String confirmation) {
- if (!isInAccessibleDrag()) return;
-
- int[] loc = new int[2];
- if (dropLocation == null) {
- loc[0] = clickedTarget.getWidth() / 2;
- loc[1] = clickedTarget.getHeight() / 2;
- } else {
- loc[0] = dropLocation.centerX();
- loc[1] = dropLocation.centerY();
- }
-
- mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(clickedTarget, loc);
- mLauncher.getDragController().completeAccessibleDrag(loc);
-
- if (!TextUtils.isEmpty(confirmation)) {
- announceConfirmation(confirmation);
- }
- }
-
- private boolean beginAccessibleDrag(View item, ItemInfo info, boolean fromKeyboard) {
+ @Override
+ protected boolean beginAccessibleDrag(View item, ItemInfo info, boolean fromKeyboard) {
if (!itemSupportsAccessibleDrag(info)) {
return false;
}
@@ -449,8 +302,8 @@
}
Rect pos = new Rect();
- mLauncher.getDragLayer().getDescendantRectRelativeToSelf(item, pos);
- mLauncher.getDragController().addDragListener(this);
+ mContext.getDragLayer().getDescendantRectRelativeToSelf(item, pos);
+ mContext.getDragController().addDragListener(this);
DragOptions options = new DragOptions();
options.isAccessibleDrag = true;
@@ -458,31 +311,20 @@
options.simulatedDndStartPoint = new Point(pos.centerX(), pos.centerY());
if (fromKeyboard) {
- KeyboardDragAndDropView popup = (KeyboardDragAndDropView) mLauncher.getLayoutInflater()
- .inflate(R.layout.keyboard_drag_and_drop, mLauncher.getDragLayer(), false);
+ KeyboardDragAndDropView popup = (KeyboardDragAndDropView) mContext.getLayoutInflater()
+ .inflate(R.layout.keyboard_drag_and_drop, mContext.getDragLayer(), false);
popup.showForIcon(item, info, options);
} else {
- ItemLongClickListener.beginDrag(item, mLauncher, info, options);
+ ItemLongClickListener.beginDrag(item, mContext, info, options);
}
return true;
}
- @Override
- public void onDragStart(DragObject dragObject, DragOptions options) {
- // No-op
- }
-
- @Override
- public void onDragEnd() {
- mLauncher.getDragController().removeDragListener(this);
- mDragInfo = null;
- }
-
/**
* Find empty space on the workspace and returns the screenId.
*/
protected int findSpaceOnWorkspace(ItemInfo info, int[] outCoordinates) {
- Workspace workspace = mLauncher.getWorkspace();
+ Workspace<?> workspace = mContext.getWorkspace();
IntArray workspaceScreens = workspace.getScreenOrder();
int screenId;
@@ -521,28 +363,75 @@
return screenId;
}
- public class LauncherAction {
- public final int keyCode;
- public final AccessibilityAction accessibilityAction;
-
- private final LauncherAccessibilityDelegate mDelegate;
-
- public LauncherAction(int id, int labelRes, int keyCode) {
- this.keyCode = keyCode;
- accessibilityAction = new AccessibilityAction(id, mLauncher.getString(labelRes));
- mDelegate = LauncherAccessibilityDelegate.this;
+ /**
+ * Functionality to add the item {@link ItemInfo} to the workspace
+ * @param item item to be added
+ * @param accessibility true if the first item to be added to the workspace
+ * should be focused for accessibility.
+ *
+ * @return true if the item could be successfully added
+ */
+ public boolean addToWorkspace(ItemInfo item, boolean accessibility) {
+ final int[] coordinates = new int[2];
+ final int screenId = findSpaceOnWorkspace(item, coordinates);
+ if (screenId == -1) {
+ return false;
}
+ mContext.getStateManager().goToState(NORMAL, true, forSuccessCallback(() -> {
+ if (item instanceof WorkspaceItemFactory) {
+ WorkspaceItemInfo info = ((WorkspaceItemFactory) item).makeWorkspaceItem(mContext);
+ mContext.getModelWriter().addItemToDatabase(info,
+ LauncherSettings.Favorites.CONTAINER_DESKTOP,
+ screenId, coordinates[0], coordinates[1]);
- /**
- * Invokes the action for the provided host
- */
- public boolean invokeFromKeyboard(View host) {
- if (host != null && host.getTag() instanceof ItemInfo) {
- return mDelegate.performAction(
- host, (ItemInfo) host.getTag(), accessibilityAction.getId(), true);
- } else {
- return false;
+ mContext.bindItems(
+ Collections.singletonList(info),
+ /* forceAnimateIcons= */ true,
+ /* focusFirstItemForAccessibility= */ accessibility);
+ announceConfirmation(R.string.item_added_to_workspace);
+ } else if (item instanceof PendingAddItemInfo) {
+ PendingAddItemInfo info = (PendingAddItemInfo) item;
+ Workspace<?> workspace = mContext.getWorkspace();
+ workspace.snapToPage(workspace.getPageIndexForScreenId(screenId));
+ mContext.addPendingItem(info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
+ screenId, coordinates, info.spanX, info.spanY);
+ } else if (item instanceof WorkspaceItemInfo) {
+ WorkspaceItemInfo info = ((WorkspaceItemInfo) item).clone();
+ mContext.getModelWriter().addItemToDatabase(info,
+ LauncherSettings.Favorites.CONTAINER_DESKTOP,
+ screenId, coordinates[0], coordinates[1]);
+ mContext.bindItems(Collections.singletonList(info), true, accessibility);
}
+ }));
+ return true;
+ }
+ /**
+ * Functionality to move the item {@link ItemInfo} to the workspace
+ * @param item item to be moved
+ *
+ * @return true if the item could be successfully added
+ */
+ public boolean moveToWorkspace(ItemInfo item) {
+ Folder folder = Folder.getOpen(mContext);
+ folder.close(true);
+ WorkspaceItemInfo info = (WorkspaceItemInfo) item;
+ folder.getInfo().remove(info, false);
+
+ final int[] coordinates = new int[2];
+ final int screenId = findSpaceOnWorkspace(item, coordinates);
+ if (screenId == -1) {
+ return false;
}
+ mContext.getModelWriter().moveItemInDatabase(info,
+ LauncherSettings.Favorites.CONTAINER_DESKTOP,
+ screenId, coordinates[0], coordinates[1]);
+
+ // Bind the item in next frame so that if a new workspace page was created,
+ // it will get laid out.
+ new Handler().post(() -> {
+ mContext.bindItems(Collections.singletonList(item), true);
+ announceConfirmation(R.string.item_moved);
+ });
+ return true;
}
}
diff --git a/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java
index bf5a24b..fb847ec 100644
--- a/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java
@@ -71,12 +71,12 @@
if (screenId == -1) {
return false;
}
- mLauncher.getStateManager().goToState(NORMAL, true, forSuccessCallback(() -> {
- mLauncher.getModelWriter().addItemToDatabase(info,
+ mContext.getStateManager().goToState(NORMAL, true, forSuccessCallback(() -> {
+ mContext.getModelWriter().addItemToDatabase(info,
LauncherSettings.Favorites.CONTAINER_DESKTOP,
screenId, coordinates[0], coordinates[1]);
- mLauncher.bindItems(Collections.singletonList(info), true);
- AbstractFloatingView.closeAllOpenViews(mLauncher);
+ mContext.bindItems(Collections.singletonList(info), true);
+ AbstractFloatingView.closeAllOpenViews(mContext);
announceConfirmation(R.string.item_added_to_workspace);
}));
return true;
diff --git a/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java b/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java
index a331924..a8624dd 100644
--- a/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java
+++ b/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java
@@ -22,7 +22,7 @@
import com.android.launcher3.CellLayout;
import com.android.launcher3.R;
-import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.DragType;
+import com.android.launcher3.accessibility.BaseAccessibilityDelegate.DragType;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
new file mode 100644
index 0000000..53a6fd7
--- /dev/null
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -0,0 +1,306 @@
+/*
+ * 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.allapps;
+
+import android.content.Context;
+import android.content.Intent;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.RelativeLayout;
+
+import androidx.core.graphics.ColorUtils;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
+import com.android.launcher3.allapps.search.SearchAdapterProvider;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.views.AppLauncher;
+
+import java.util.ArrayList;
+import java.util.Objects;
+
+/**
+ * All apps container view with search support for use in a dragging activity.
+ *
+ * @param <T> Type of context inflating all apps.
+ */
+public class ActivityAllAppsContainerView<T extends Context & AppLauncher
+ & DeviceProfileListenable> extends BaseAllAppsContainerView<T> {
+
+ protected SearchUiManager mSearchUiManager;
+ /**
+ * View that defines the search box. Result is rendered inside the recycler view defined in the
+ * base class.
+ */
+ private View mSearchContainer;
+ /** {@code true} when rendered view is in search state instead of the scroll state. */
+ private boolean mIsSearching;
+
+ public ActivityAllAppsContainerView(Context context) {
+ this(context, null);
+ }
+
+ public ActivityAllAppsContainerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ActivityAllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public SearchUiManager getSearchUiManager() {
+ return mSearchUiManager;
+ }
+
+ public View getSearchView() {
+ return mSearchContainer;
+ }
+
+ /** Updates all apps container with the latest search query. */
+ public void setLastSearchQuery(String query) {
+ Intent marketSearchIntent = PackageManagerHelper.getMarketSearchIntent(
+ mActivityContext, query);
+ OnClickListener marketSearchClickListener = (v) -> mActivityContext.startActivitySafely(v,
+ marketSearchIntent, null);
+ for (int i = 0; i < mAH.size(); i++) {
+ mAH.get(i).mAdapter.setLastSearchQuery(query, marketSearchClickListener);
+ }
+ mIsSearching = true;
+ rebindAdapters();
+ mHeader.setCollapsed(true);
+ }
+
+ /** Invoke when the current search session is finished. */
+ public void onClearSearchResult() {
+ mIsSearching = false;
+ mHeader.setCollapsed(false);
+ rebindAdapters();
+ mHeader.reset(false);
+ }
+
+ /**
+ * Sets results list for search
+ */
+ public void setSearchResults(ArrayList<AdapterItem> results) {
+ if (getSearchResultList().setSearchResults(results)) {
+ for (int i = 0; i < mAH.size(); i++) {
+ if (mAH.get(i).mRecyclerView != null) {
+ mAH.get(i).mRecyclerView.onSearchResultsChanged();
+ }
+ }
+ }
+ }
+
+ @Override
+ protected final SearchAdapterProvider<?> createMainAdapterProvider() {
+ return mActivityContext.createSearchAdapterProvider(this);
+ }
+
+ @Override
+ public boolean shouldContainerScroll(MotionEvent ev) {
+ // IF the MotionEvent is inside the search box, and the container keeps on receiving
+ // touch input, container should move down.
+ if (mActivityContext.getDragLayer().isEventOverView(mSearchContainer, ev)) {
+ return true;
+ }
+ return super.shouldContainerScroll(ev);
+ }
+
+ @Override
+ public void reset(boolean animate) {
+ super.reset(animate);
+ // Reset the search bar after transitioning home.
+ mSearchUiManager.resetSearch();
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mSearchContainer = findViewById(R.id.search_container_all_apps);
+ mSearchUiManager = (SearchUiManager) mSearchContainer;
+ mSearchUiManager.initializeSearch(this);
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ mSearchUiManager.preDispatchKeyEvent(event);
+ return super.dispatchKeyEvent(event);
+ }
+
+ @Override
+ public String getDescription() {
+ if (!mUsingTabs && isSearching()) {
+ return getContext().getString(R.string.all_apps_search_results);
+ } else {
+ return super.getDescription();
+ }
+ }
+
+ @Override
+ protected boolean shouldShowTabs() {
+ return super.shouldShowTabs() && !isSearching();
+ }
+
+ @Override
+ public boolean isSearching() {
+ return mIsSearching;
+ }
+
+ @Override
+ protected void rebindAdapters(boolean force) {
+ super.rebindAdapters(force);
+ if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()
+ || getMainAdapterProvider().getDecorator() == null) {
+ return;
+ }
+
+ RecyclerView.ItemDecoration decoration = getMainAdapterProvider().getDecorator();
+ mAH.stream()
+ .map(adapterHolder -> adapterHolder.mRecyclerView)
+ .filter(Objects::nonNull)
+ .forEach(v -> {
+ v.removeItemDecoration(decoration); // Remove in case it is already added.
+ v.addItemDecoration(decoration);
+ });
+ }
+
+ @Override
+ protected View replaceAppsRVContainer(boolean showTabs) {
+ View rvContainer = super.replaceAppsRVContainer(showTabs);
+
+ removeCustomRules(rvContainer);
+ removeCustomRules(getSearchRecyclerView());
+ if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+ alignParentTop(rvContainer, showTabs);
+ alignParentTop(getSearchRecyclerView(), /* tabs= */ false);
+ layoutAboveSearchContainer(rvContainer);
+ layoutAboveSearchContainer(getSearchRecyclerView());
+ } else {
+ layoutBelowSearchContainer(rvContainer, showTabs);
+ layoutBelowSearchContainer(getSearchRecyclerView(), /* tabs= */ false);
+ }
+
+ return rvContainer;
+ }
+
+ @Override
+ void setupHeader() {
+ super.setupHeader();
+
+ removeCustomRules(mHeader);
+ if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+ alignParentTop(mHeader, false /* includeTabsMargin */);
+ } else {
+ layoutBelowSearchContainer(mHeader, false /* includeTabsMargin */);
+ }
+ }
+
+ @Override
+ protected void updateHeaderScroll(int scrolledOffset) {
+ super.updateHeaderScroll(scrolledOffset);
+ if (mSearchUiManager.getEditText() == null) {
+ return;
+ }
+
+ float prog = Utilities.boundToRange((float) scrolledOffset / mHeaderThreshold, 0f, 1f);
+ boolean bgVisible = mSearchUiManager.getBackgroundVisibility();
+ if (scrolledOffset == 0 && !isSearching()) {
+ bgVisible = true;
+ } else if (scrolledOffset > mHeaderThreshold) {
+ bgVisible = false;
+ }
+ mSearchUiManager.setBackgroundVisibility(bgVisible, 1 - prog);
+ }
+
+ @Override
+ protected int getHeaderColor(float blendRatio) {
+ return ColorUtils.setAlphaComponent(
+ super.getHeaderColor(blendRatio),
+ (int) (mSearchContainer.getAlpha() * 255));
+ }
+
+ @Override
+ public int getHeaderBottom() {
+ if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+ return super.getHeaderBottom();
+ }
+ return super.getHeaderBottom() + mSearchContainer.getBottom();
+ }
+
+ private void layoutBelowSearchContainer(View v, boolean includeTabsMargin) {
+ if (!(v.getLayoutParams() instanceof RelativeLayout.LayoutParams)) {
+ return;
+ }
+
+ RelativeLayout.LayoutParams layoutParams = (LayoutParams) v.getLayoutParams();
+ layoutParams.addRule(RelativeLayout.ALIGN_TOP, R.id.search_container_all_apps);
+
+ int topMargin = getContext().getResources().getDimensionPixelSize(
+ R.dimen.all_apps_header_top_margin);
+ if (includeTabsMargin) {
+ topMargin += getContext().getResources().getDimensionPixelSize(
+ R.dimen.all_apps_header_pill_height);
+ }
+ 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;
+ }
+
+ RelativeLayout.LayoutParams layoutParams = (LayoutParams) v.getLayoutParams();
+ layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ layoutParams.topMargin =
+ includeTabsMargin
+ ? getContext().getResources().getDimensionPixelSize(
+ R.dimen.all_apps_header_pill_height)
+ : 0;
+ }
+
+ private void removeCustomRules(View v) {
+ if (!(v.getLayoutParams() instanceof RelativeLayout.LayoutParams)) {
+ return;
+ }
+
+ RelativeLayout.LayoutParams layoutParams = (LayoutParams) v.getLayoutParams();
+ layoutParams.removeRule(RelativeLayout.ABOVE);
+ layoutParams.removeRule(RelativeLayout.ALIGN_TOP);
+ layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
+ }
+
+ @Override
+ protected BaseAllAppsAdapter<T> createAdapter(AlphabeticalAppsList<T> appsList,
+ BaseAdapterProvider[] adapterProviders) {
+ return new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), appsList,
+ adapterProviders);
+ }
+}
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
deleted file mode 100644
index 3ba6ea4..0000000
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ /dev/null
@@ -1,784 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.allapps;
-
-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 android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.os.Process;
-import android.os.UserManager;
-import android.text.SpannableStringBuilder;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowInsets;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.StringRes;
-import androidx.annotation.VisibleForTesting;
-import androidx.core.graphics.ColorUtils;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
-import com.android.launcher3.DragSource;
-import com.android.launcher3.DropTarget.DragObject;
-import com.android.launcher3.Insettable;
-import com.android.launcher3.InsettableFrameLayout;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.allapps.search.SearchAdapterProvider;
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.keyboard.FocusedItemDecorator;
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.util.ItemInfoMatcher;
-import com.android.launcher3.util.Themes;
-import com.android.launcher3.views.RecyclerViewFastScroller;
-import com.android.launcher3.views.ScrimView;
-import com.android.launcher3.views.SpringRelativeLayout;
-import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePageChangedListener;
-
-/**
- * The all apps view container.
- */
-public class AllAppsContainerView extends SpringRelativeLayout implements DragSource,
- Insettable, OnDeviceProfileChangeListener, OnActivePageChangedListener,
- ScrimView.ScrimDrawingController {
-
- private static final String BUNDLE_KEY_CURRENT_PAGE = "launcher.allapps.current_page";
-
- public static final float PULL_MULTIPLIER = .02f;
- public static final float FLING_VELOCITY_MULTIPLIER = 1200f;
-
- private final Paint mHeaderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- private final Rect mInsets = new Rect();
-
- protected final BaseDraggingActivity mLauncher;
- protected final AdapterHolder[] mAH;
- protected final ItemInfoMatcher mPersonalMatcher = ItemInfoMatcher.ofUser(
- Process.myUserHandle());
- private final AllAppsStore mAllAppsStore = new AllAppsStore();
-
- private final RecyclerView.OnScrollListener mScrollListener =
- new RecyclerView.OnScrollListener() {
- @Override
- public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
- updateHeaderScroll(((AllAppsRecyclerView) recyclerView).getCurrentScrollY());
- }
- };
- private final WorkProfileManager mWorkManager;
-
-
- private final Paint mNavBarScrimPaint;
- private int mNavBarScrimHeight = 0;
-
- protected SearchUiManager mSearchUiManager;
- private View mSearchContainer;
- private AllAppsPagedView mViewPager;
-
- protected FloatingHeaderView mHeader;
-
-
- private SpannableStringBuilder mSearchQueryBuilder = null;
-
- protected boolean mUsingTabs;
- private boolean mIsSearching;
- private boolean mHasWorkApps;
-
- protected RecyclerViewFastScroller mTouchHandler;
- protected final Point mFastScrollerOffset = new Point();
-
- private SearchAdapterProvider mSearchAdapterProvider;
- private final int mScrimColor;
- private final int mHeaderProtectionColor;
- private final float mHeaderThreshold;
- private ScrimView mScrimView;
- private int mHeaderColor;
- private int mTabsProtectionAlpha;
-
- public AllAppsContainerView(Context context) {
- this(context, null);
- }
-
- public AllAppsContainerView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public AllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
-
- mLauncher = BaseDraggingActivity.fromContext(context);
-
- mScrimColor = Themes.getAttrColor(context, R.attr.allAppsScrimColor);
- mHeaderThreshold = getResources().getDimensionPixelSize(
- R.dimen.dynamic_grid_cell_border_spacing);
- mHeaderProtectionColor = Themes.getAttrColor(context, R.attr.allappsHeaderProtectionColor);
-
- mLauncher.addOnDeviceProfileChangeListener(this);
-
- mSearchAdapterProvider = mLauncher.createSearchAdapterProvider(this);
-
- mAH = new AdapterHolder[2];
-
- mWorkManager = new WorkProfileManager(mLauncher.getSystemService(UserManager.class), this,
- Utilities.getPrefs(mLauncher));
- mAH[AdapterHolder.MAIN] = new AdapterHolder(false /* isWork */);
- mAH[AdapterHolder.WORK] = new AdapterHolder(true /* isWork */);
-
- mNavBarScrimPaint = new Paint();
- mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
-
- mAllAppsStore.addUpdateListener(this::onAppsUpdated);
- }
-
- @Override
- protected void dispatchRestoreInstanceState(SparseArray<Parcelable> sparseArray) {
- try {
- // Many slice view id is not properly assigned, and hence throws null
- // pointer exception in the underneath method. Catching the exception
- // simply doesn't restore these slice views. This doesn't have any
- // user visible effect because because we query them again.
- super.dispatchRestoreInstanceState(sparseArray);
- } catch (Exception e) {
- Log.e("AllAppsContainerView", "restoreInstanceState viewId = 0", e);
- }
-
- Bundle state = (Bundle) sparseArray.get(R.id.work_tab_state_id, null);
- if (state != null) {
- int currentPage = state.getInt(BUNDLE_KEY_CURRENT_PAGE, 0);
- if (currentPage != 0 && mViewPager != null) {
- mViewPager.setCurrentPage(currentPage);
- rebindAdapters();
- } else {
- reset(true);
- }
- }
-
- }
-
- @Override
- protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
- super.dispatchSaveInstanceState(container);
- Bundle state = new Bundle();
- state.putInt(BUNDLE_KEY_CURRENT_PAGE, getCurrentPage());
- 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.adapter.setOnIconLongClickListener(listener);
- }
- }
-
- public AllAppsStore getAppsStore() {
- return mAllAppsStore;
- }
-
- public WorkProfileManager getWorkManager() {
- return mWorkManager;
- }
-
- @Override
- public void onDeviceProfileChanged(DeviceProfile dp) {
- for (AdapterHolder holder : mAH) {
- holder.adapter.setAppsPerRow(dp.numShownAllAppsColumns);
- if (holder.recyclerView != null) {
- // Remove all views and clear the pool, while keeping the data same. After this
- // call, all the viewHolders will be recreated.
- holder.recyclerView.swapAdapter(holder.recyclerView.getAdapter(), true);
- holder.recyclerView.getRecycledViewPool().clear();
- }
- }
- }
-
- private void onAppsUpdated() {
- boolean hasWorkApps = false;
- for (AppInfo app : mAllAppsStore.getApps()) {
- if (mWorkManager.getMatcher().matches(app, null)) {
- hasWorkApps = true;
- break;
- }
- }
- mHasWorkApps = hasWorkApps;
- if (!mAH[AdapterHolder.MAIN].appsList.hasFilter()) {
- rebindAdapters();
- if (hasWorkApps) {
- mWorkManager.reset();
- }
- }
- }
-
- /**
- * Returns whether the view itself will handle the touch event or not.
- */
- public boolean shouldContainerScroll(MotionEvent ev) {
- // IF the MotionEvent is inside the search box, and the container keeps on receiving
- // touch input, container should move down.
- if (mLauncher.getDragLayer().isEventOverView(mSearchContainer, ev)) {
- return true;
- }
- AllAppsRecyclerView rv = getActiveRecyclerView();
- if (rv == null) {
- return true;
- }
- if (rv.getScrollbar().getThumbOffsetY() >= 0 &&
- mLauncher.getDragLayer().isEventOverView(rv.getScrollbar(), ev)) {
- return false;
- }
- return rv.shouldContainerScroll(ev, mLauncher.getDragLayer());
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- AllAppsRecyclerView rv = getActiveRecyclerView();
- if (rv != null &&
- rv.getScrollbar().isHitInParent(ev.getX(), ev.getY(), mFastScrollerOffset)) {
- mTouchHandler = rv.getScrollbar();
- } else {
- mTouchHandler = null;
- }
- }
- if (mTouchHandler != null) {
- return mTouchHandler.handleTouchEvent(ev, mFastScrollerOffset);
- }
- return false;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- AllAppsRecyclerView rv = getActiveRecyclerView();
- if (rv != null && rv.getScrollbar().isHitInParent(ev.getX(), ev.getY(),
- mFastScrollerOffset)) {
- mTouchHandler = rv.getScrollbar();
- } else {
- mTouchHandler = null;
-
- }
- }
- if (mTouchHandler != null) {
- mTouchHandler.handleTouchEvent(ev, mFastScrollerOffset);
- return true;
- }
- return false;
- }
-
- public String getDescription() {
- @StringRes int descriptionRes;
- if (mUsingTabs) {
- descriptionRes =
- mViewPager.getNextPage() == 0
- ? R.string.all_apps_button_personal_label
- : R.string.all_apps_button_work_label;
- } else if (mIsSearching) {
- descriptionRes = R.string.all_apps_search_results;
- } else {
- descriptionRes = R.string.all_apps_button_label;
- }
- return getContext().getString(descriptionRes);
- }
-
- public AllAppsRecyclerView getActiveRecyclerView() {
- if (!mUsingTabs || mViewPager.getNextPage() == 0) {
- return mAH[AdapterHolder.MAIN].recyclerView;
- } else {
- return mAH[AdapterHolder.WORK].recyclerView;
- }
- }
-
- public LayoutInflater getLayoutInflater() {
- return LayoutInflater.from(getContext());
- }
-
- /**
- * Resets the state of AllApps.
- */
- public void reset(boolean animate) {
- for (int i = 0; i < mAH.length; i++) {
- if (mAH[i].recyclerView != null) {
- mAH[i].recyclerView.scrollToTop();
- }
- }
- if (isHeaderVisible()) {
- mHeader.reset(animate);
- }
- // Reset the search bar and base recycler view after transitioning home
- mSearchUiManager.resetSearch();
- updateHeaderScroll(0);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- // This is a focus listener that proxies focus from a view into the list view. This is to
- // work around the search box from getting first focus and showing the cursor.
- setOnFocusChangeListener((v, hasFocus) -> {
- if (hasFocus && getActiveRecyclerView() != null) {
- getActiveRecyclerView().requestFocus();
- }
- });
-
- mHeader = findViewById(R.id.all_apps_header);
- rebindAdapters(true /* force */);
-
- mSearchContainer = findViewById(R.id.search_container_all_apps);
- mSearchUiManager = (SearchUiManager) mSearchContainer;
- mSearchUiManager.initializeSearch(this);
- }
-
- public SearchUiManager getSearchUiManager() {
- return mSearchUiManager;
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- mSearchUiManager.preDispatchKeyEvent(event);
- return super.dispatchKeyEvent(event);
- }
-
- @Override
- public void onDropCompleted(View target, DragObject d, boolean success) {
- }
-
- @Override
- public void setInsets(Rect insets) {
- mInsets.set(insets);
- DeviceProfile grid = mLauncher.getDeviceProfile();
-
- for (int i = 0; i < mAH.length; i++) {
- mAH[i].padding.bottom = insets.bottom;
- mAH[i].padding.left = mAH[i].padding.right = grid.allAppsLeftRightPadding;
- mAH[i].applyPadding();
- }
-
- ViewGroup.MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
- mlp.leftMargin = insets.left;
- mlp.rightMargin = insets.right;
- setLayoutParams(mlp);
-
- if (grid.isVerticalBarLayout()) {
- setPadding(grid.workspacePadding.left, 0, grid.workspacePadding.right, 0);
- } else {
- setPadding(0, 0, 0, 0);
- }
-
- InsettableFrameLayout.dispatchInsets(this, insets);
- }
-
- @Override
- public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
- if (Utilities.ATLEAST_Q) {
- mNavBarScrimHeight = insets.getTappableElementInsets().bottom;
- } else {
- mNavBarScrimHeight = insets.getStableInsetBottom();
- }
- return super.dispatchApplyWindowInsets(insets);
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
-
- if (mNavBarScrimHeight > 0) {
- canvas.drawRect(0, getHeight() - mNavBarScrimHeight, getWidth(), getHeight(),
- mNavBarScrimPaint);
- }
- }
-
- private void rebindAdapters() {
- rebindAdapters(false /* force */);
- }
-
- protected void rebindAdapters(boolean force) {
- boolean showTabs = mHasWorkApps && !mIsSearching;
- if (showTabs == mUsingTabs && !force) {
- return;
- }
- replaceRVContainer(showTabs);
- mUsingTabs = showTabs;
-
- mAllAppsStore.unregisterIconContainer(mAH[AdapterHolder.MAIN].recyclerView);
- mAllAppsStore.unregisterIconContainer(mAH[AdapterHolder.WORK].recyclerView);
-
- if (mUsingTabs) {
- mAH[AdapterHolder.MAIN].setup(mViewPager.getChildAt(0), mPersonalMatcher);
- mAH[AdapterHolder.WORK].setup(mViewPager.getChildAt(1), mWorkManager.getMatcher());
- mAH[AdapterHolder.WORK].recyclerView.setId(R.id.apps_list_view_work);
- mViewPager.getPageIndicator().setActiveMarker(AdapterHolder.MAIN);
- findViewById(R.id.tab_personal)
- .setOnClickListener((View view) -> {
- if (mViewPager.snapToPage(AdapterHolder.MAIN)) {
- mLauncher.getStatsLogManager().logger()
- .log(LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB);
- }
- });
- findViewById(R.id.tab_work)
- .setOnClickListener((View view) -> {
- if (mViewPager.snapToPage(AdapterHolder.WORK)) {
- mLauncher.getStatsLogManager().logger()
- .log(LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB);
- }
- });
- onActivePageChanged(mViewPager.getNextPage());
- } else {
- mAH[AdapterHolder.MAIN].setup(findViewById(R.id.apps_list_view), null);
- mAH[AdapterHolder.WORK].recyclerView = null;
- }
- setupHeader();
-
- mAllAppsStore.registerIconContainer(mAH[AdapterHolder.MAIN].recyclerView);
- mAllAppsStore.registerIconContainer(mAH[AdapterHolder.WORK].recyclerView);
- }
-
-
- private void replaceRVContainer(boolean showTabs) {
- for (AdapterHolder adapterHolder : mAH) {
- if (adapterHolder.recyclerView != null) {
- adapterHolder.recyclerView.setLayoutManager(null);
- adapterHolder.recyclerView.setAdapter(null);
- }
- }
- View oldView = getRecyclerViewContainer();
- int index = indexOfChild(oldView);
- removeView(oldView);
- int layout = showTabs ? R.layout.all_apps_tabs : R.layout.all_apps_rv_layout;
- View newView = getLayoutInflater().inflate(layout, this, false);
- addView(newView, index);
- if (showTabs) {
- mViewPager = (AllAppsPagedView) newView;
- mViewPager.initParentViews(this);
- mViewPager.getPageIndicator().setOnActivePageChangedListener(this);
- if (mWorkManager.attachWorkModeSwitch()) {
- mWorkManager.getWorkModeSwitch().post(() -> mAH[AdapterHolder.WORK].applyPadding());
- }
- } else {
- mWorkManager.detachWorkModeSwitch();
- mViewPager = null;
- }
- }
-
- public View getRecyclerViewContainer() {
- return mViewPager != null ? mViewPager : findViewById(R.id.apps_list_view);
- }
-
- @Override
- public void onActivePageChanged(int currentActivePage) {
- mHeader.setMainActive(currentActivePage == AdapterHolder.MAIN);
- if (mAH[currentActivePage].recyclerView != null) {
- mAH[currentActivePage].recyclerView.bindFastScrollbar();
- }
- reset(true /* animate */);
-
- mWorkManager.onActivePageChanged(currentActivePage);
- }
-
- // Used by tests only
- private boolean isDescendantViewVisible(int viewId) {
- final View view = findViewById(viewId);
- if (view == null) return false;
-
- if (!view.isShown()) return false;
-
- return view.getGlobalVisibleRect(new Rect());
- }
-
- @VisibleForTesting
- public boolean isPersonalTabVisible() {
- return isDescendantViewVisible(R.id.tab_personal);
- }
-
- // Used by tests only
- public boolean isWorkTabVisible() {
- return isDescendantViewVisible(R.id.tab_work);
- }
-
- public AlphabeticalAppsList getApps() {
- return mAH[AdapterHolder.MAIN].appsList;
- }
-
- public FloatingHeaderView getFloatingHeaderView() {
- return mHeader;
- }
-
- public View getSearchView() {
- return mSearchContainer;
- }
-
- public View getContentView() {
- return mViewPager == null ? getActiveRecyclerView() : mViewPager;
- }
-
- public int getCurrentPage() {
- return mViewPager != null ? mViewPager.getCurrentPage() : AdapterHolder.MAIN;
- }
-
- /**
- * Handles selection on focused view and returns success
- */
- public boolean launchHighlightedItem() {
- if (mSearchAdapterProvider == null) return false;
- return mSearchAdapterProvider.launchHighlightedItem();
- }
-
- public SearchAdapterProvider getSearchAdapterProvider() {
- return mSearchAdapterProvider;
- }
-
- public RecyclerViewFastScroller getScrollBar() {
- AllAppsRecyclerView rv = getActiveRecyclerView();
- return rv == null ? null : rv.getScrollbar();
- }
-
- public void setupHeader() {
- mHeader.setVisibility(View.VISIBLE);
- mHeader.setup(mAH, mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView == null);
-
- int padding = mHeader.getMaxTranslation();
- for (int i = 0; i < mAH.length; i++) {
- mAH[i].padding.top = padding;
- mAH[i].applyPadding();
- if (mAH[i].recyclerView != null) {
- mAH[i].recyclerView.scrollToTop();
- }
- }
- }
-
- public void setLastSearchQuery(String query) {
- for (int i = 0; i < mAH.length; i++) {
- mAH[i].adapter.setLastSearchQuery(query);
- }
- mIsSearching = true;
- rebindAdapters();
- mHeader.setCollapsed(true);
- }
-
- public void onClearSearchResult() {
- mIsSearching = false;
- mHeader.setCollapsed(false);
- rebindAdapters();
- mHeader.reset(false);
- }
-
- public void onSearchResultsChanged() {
- for (int i = 0; i < mAH.length; i++) {
- if (mAH[i].recyclerView != null) {
- mAH[i].recyclerView.onSearchResultsChanged();
- }
- }
- }
-
- public void setRecyclerViewVerticalFadingEdgeEnabled(boolean enabled) {
- for (int i = 0; i < mAH.length; i++) {
- mAH[i].applyVerticalFadingEdgeEnabled(enabled);
- }
- }
-
- public void addElevationController(RecyclerView.OnScrollListener scrollListener) {
- if (!mUsingTabs) {
- mAH[AdapterHolder.MAIN].recyclerView.addOnScrollListener(scrollListener);
- }
- }
-
- public boolean isHeaderVisible() {
- return mHeader != null && mHeader.getVisibility() == View.VISIBLE;
- }
-
- /**
- * Adds an update listener to {@param animator} that adds springs to the animation.
- */
- public void addSpringFromFlingUpdateListener(ValueAnimator animator,
- float velocity /* release velocity */,
- float progress /* portion of the distance to travel*/) {
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animator) {
- float distance = (float) ((1 - progress) * getHeight()); // px
- float settleVelocity = Math.min(0, distance
- / (AllAppsTransitionController.INTERP_COEFF * animator.getDuration())
- + velocity);
- absorbSwipeUpVelocity(Math.max(1000, Math.abs(
- Math.round(settleVelocity * FLING_VELOCITY_MULTIPLIER))));
- }
- });
- }
-
- public void onPull(float deltaDistance, float displacement) {
- absorbPullDeltaDistance(PULL_MULTIPLIER * deltaDistance, PULL_MULTIPLIER * displacement);
- // Current motion spec is to actually push and not pull
- // on this surface. However, until EdgeEffect.onPush (b/190612804) is
- // implemented at view level, we will simply pull
- }
-
- @Override
- public void getDrawingRect(Rect outRect) {
- super.getDrawingRect(outRect);
- outRect.offset(0, (int) getTranslationY());
- }
-
- @Override
- public void setTranslationY(float translationY) {
- super.setTranslationY(translationY);
- invalidateHeader();
- }
-
- public void setScrimView(ScrimView scrimView) {
- mScrimView = scrimView;
- }
-
- @Override
- public void drawOnScrim(Canvas canvas) {
- if (!mHeader.isHeaderProtectionSupported()) return;
- mHeaderPaint.setColor(mHeaderColor);
- mHeaderPaint.setAlpha((int) (getAlpha() * Color.alpha(mHeaderColor)));
- if (mHeaderPaint.getColor() != mScrimColor && mHeaderPaint.getColor() != 0) {
- int bottom = (int) (mSearchContainer.getBottom() + getTranslationY());
- canvas.drawRect(0, 0, canvas.getWidth(), bottom, mHeaderPaint);
- int tabsHeight = getFloatingHeaderView().getPeripheralProtectionHeight();
- if (mTabsProtectionAlpha > 0 && tabsHeight != 0) {
- mHeaderPaint.setAlpha((int) (getAlpha() * mTabsProtectionAlpha));
- canvas.drawRect(0, bottom, canvas.getWidth(), bottom + tabsHeight, mHeaderPaint);
- }
- }
- }
-
- public class AdapterHolder {
- public static final int MAIN = 0;
- public static final int WORK = 1;
-
- private final boolean mIsWork;
- public final AllAppsGridAdapter adapter;
- final LinearLayoutManager layoutManager;
- final AlphabeticalAppsList appsList;
- final Rect padding = new Rect();
- AllAppsRecyclerView recyclerView;
- boolean verticalFadingEdge;
-
-
- AdapterHolder(boolean isWork) {
- mIsWork = isWork;
- appsList = new AlphabeticalAppsList(mLauncher, mAllAppsStore,
- isWork ? mWorkManager.getAdapterProvider() : null);
-
- BaseAdapterProvider[] adapterProviders =
- isWork ? new BaseAdapterProvider[]{mSearchAdapterProvider,
- mWorkManager.getAdapterProvider()}
- : new BaseAdapterProvider[]{mSearchAdapterProvider};
-
- adapter = new AllAppsGridAdapter(mLauncher, getLayoutInflater(), appsList,
- adapterProviders);
- appsList.setAdapter(adapter);
- layoutManager = adapter.getLayoutManager();
- }
-
- void setup(@NonNull View rv, @Nullable ItemInfoMatcher matcher) {
- appsList.updateItemFilter(matcher);
- recyclerView = (AllAppsRecyclerView) rv;
- recyclerView.setEdgeEffectFactory(createEdgeEffectFactory());
- recyclerView.setApps(appsList);
- recyclerView.setLayoutManager(layoutManager);
- recyclerView.setAdapter(adapter);
- recyclerView.setHasFixedSize(true);
- // No animations will occur when changes occur to the items in this RecyclerView.
- recyclerView.setItemAnimator(null);
- recyclerView.addOnScrollListener(mScrollListener);
- FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(recyclerView);
- recyclerView.addItemDecoration(focusedItemDecorator);
- adapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
- applyVerticalFadingEdgeEnabled(verticalFadingEdge);
- applyPadding();
- if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
- recyclerView.addItemDecoration(mSearchAdapterProvider.getDecorator());
- }
- }
-
- void applyPadding() {
- if (recyclerView != null) {
- int bottomOffset = 0;
- if (mIsWork && mWorkManager.getWorkModeSwitch() != null) {
- bottomOffset = mInsets.bottom + mWorkManager.getWorkModeSwitch().getHeight();
- }
- recyclerView.setPadding(padding.left, padding.top, padding.right,
- padding.bottom + bottomOffset);
- }
- }
-
- public void applyVerticalFadingEdgeEnabled(boolean enabled) {
- verticalFadingEdge = enabled;
- mAH[AdapterHolder.MAIN].recyclerView.setVerticalFadingEdgeEnabled(!mUsingTabs
- && verticalFadingEdge);
- }
- }
-
-
- protected void updateHeaderScroll(int scrolledOffset) {
-
- float prog = Utilities.boundToRange((float) scrolledOffset / mHeaderThreshold, 0f, 1f);
- int viewBG = ColorUtils.blendARGB(mScrimColor, mHeaderProtectionColor, prog);
- int headerColor = ColorUtils.setAlphaComponent(viewBG,
- (int) (getSearchView().getAlpha() * 255));
- int tabsAlpha = mHeader.getPeripheralProtectionHeight() == 0 ? 0
- : (int) (Utilities.boundToRange(
- (scrolledOffset + mHeader.mSnappedScrolledY) / mHeaderThreshold, 0f, 1f)
- * 255);
- if (headerColor != mHeaderColor || mTabsProtectionAlpha != tabsAlpha) {
- mHeaderColor = headerColor;
- mTabsProtectionAlpha = tabsAlpha;
- invalidateHeader();
- }
- if (mSearchUiManager.getEditText() != null) {
- boolean bgVisible = mSearchUiManager.getBackgroundVisibility();
- if (scrolledOffset == 0 && !mIsSearching) {
- bgVisible = true;
- } else if (scrolledOffset > mHeaderThreshold) {
- bgVisible = false;
- }
- mSearchUiManager.setBackgroundVisibility(bgVisible, 1 - prog);
- }
- }
-
- /**
- * redraws header protection
- */
- public void invalidateHeader() {
- if (mScrimView != null && mHeader.isHeaderProtectionSupported()) {
- mScrimView.invalidate();
- }
- }
-}
diff --git a/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java b/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java
index f97eb28..7067fa2 100644
--- a/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java
+++ b/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java
@@ -37,10 +37,10 @@
* Smooth scrolls the recycler view to the given section.
*/
public void smoothScrollToSection(FastScrollSectionInfo info) {
- if (mTargetFastScrollPosition == info.fastScrollToItem.position) {
+ if (mTargetFastScrollPosition == info.position) {
return;
}
- mTargetFastScrollPosition = info.fastScrollToItem.position;
+ mTargetFastScrollPosition = info.position;
mRv.getLayoutManager().startSmoothScroll(new MyScroller(mTargetFastScrollPosition));
}
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index d5c9a53..33d2f2b 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -15,149 +15,48 @@
*/
package com.android.launcher3.allapps;
-import static com.android.launcher3.touch.ItemLongClickListener.INSTANCE_ALL_APPS;
-
import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.View.OnFocusChangeListener;
-import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
-import android.widget.TextView;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.core.view.accessibility.AccessibilityEventCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.core.view.accessibility.AccessibilityRecordCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.BubbleTextView;
-import com.android.launcher3.R;
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfoWithIcon;
-import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.views.ActivityContext;
-import java.util.Arrays;
import java.util.List;
/**
* The grid view adapter of all the apps.
+ *
+ * @param <T> Type of context inflating all apps.
*/
-public class AllAppsGridAdapter extends
- RecyclerView.Adapter<AllAppsGridAdapter.ViewHolder> {
+public class AllAppsGridAdapter<T extends Context & ActivityContext> extends
+ BaseAllAppsAdapter<T> {
public static final String TAG = "AppsGridAdapter";
+ private final GridLayoutManager mGridLayoutMgr;
+ private final GridSpanSizer mGridSizer;
- // A normal icon
- public static final int VIEW_TYPE_ICON = 1 << 1;
- // The message shown when there are no filtered results
- public static final int VIEW_TYPE_EMPTY_SEARCH = 1 << 2;
- // The message to continue to a market search when there are no filtered results
- public static final int VIEW_TYPE_SEARCH_MARKET = 1 << 3;
-
- // We use various dividers for various purposes. They share enough attributes to reuse layouts,
- // but differ in enough attributes to require different view types
-
- // A divider that separates the apps list and the search market button
- public static final int VIEW_TYPE_ALL_APPS_DIVIDER = 1 << 4;
-
- // Common view type masks
- public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
- public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON;
-
-
- private final BaseAdapterProvider[] mAdapterProviders;
-
- /**
- * ViewHolder for each icon.
- */
- public static class ViewHolder extends RecyclerView.ViewHolder {
-
- public ViewHolder(View v) {
- super(v);
- }
+ public AllAppsGridAdapter(T activityContext, LayoutInflater inflater,
+ AlphabeticalAppsList apps, BaseAdapterProvider[] adapterProviders) {
+ super(activityContext, inflater, apps, adapterProviders);
+ mGridSizer = new GridSpanSizer();
+ mGridLayoutMgr = new AppsGridLayoutManager(mActivityContext);
+ mGridLayoutMgr.setSpanSizeLookup(mGridSizer);
+ setAppsPerRow(activityContext.getDeviceProfile().numShownAllAppsColumns);
}
/**
- * Info about a particular adapter item (can be either section or app)
+ * Returns the grid layout manager.
*/
- public static class AdapterItem {
- /** Common properties */
- // The index of this adapter item in the list
- public int position;
- // The type of this item
- public int viewType;
-
- // The section name of this item. Note that there can be multiple items with different
- // sectionNames in the same section
- public String sectionName = null;
- // The row that this item shows up on
- public int rowIndex;
- // The index of this app in the row
- public int rowAppIndex;
- // The associated ItemInfoWithIcon for the item
- public ItemInfoWithIcon itemInfo = null;
- // The index of this app not including sections
- public int appIndex = -1;
- // Search section associated to result
- public DecorationInfo decorationInfo = null;
-
- /**
- * Factory method for AppIcon AdapterItem
- */
- public static AdapterItem asApp(int pos, String sectionName, AppInfo appInfo,
- int appIndex) {
- AdapterItem item = new AdapterItem();
- item.viewType = VIEW_TYPE_ICON;
- item.position = pos;
- item.sectionName = sectionName;
- item.itemInfo = appInfo;
- item.appIndex = appIndex;
- return item;
- }
-
- /**
- * Factory method for empty search results view
- */
- public static AdapterItem asEmptySearch(int pos) {
- AdapterItem item = new AdapterItem();
- item.viewType = VIEW_TYPE_EMPTY_SEARCH;
- item.position = pos;
- return item;
- }
-
- /**
- * Factory method for a dividerView in AllAppsSearch
- */
- public static AdapterItem asAllAppsDivider(int pos) {
- AdapterItem item = new AdapterItem();
- item.viewType = VIEW_TYPE_ALL_APPS_DIVIDER;
- item.position = pos;
- return item;
- }
-
- /**
- * Factory method for a market search button
- */
- public static AdapterItem asMarketSearch(int pos) {
- AdapterItem item = new AdapterItem();
- item.viewType = VIEW_TYPE_SEARCH_MARKET;
- item.position = pos;
- return item;
- }
-
- protected boolean isCountedForAccessibility() {
- return viewType == VIEW_TYPE_ICON || viewType == VIEW_TYPE_SEARCH_MARKET;
- }
+ public RecyclerView.LayoutManager getLayoutManager() {
+ return mGridLayoutMgr;
}
/**
@@ -217,9 +116,9 @@
*/
private int getRowsNotForAccessibility(int adapterPosition) {
List<AdapterItem> items = mApps.getAdapterItems();
- adapterPosition = Math.max(adapterPosition, mApps.getAdapterItems().size() - 1);
+ adapterPosition = Math.max(adapterPosition, items.size() - 1);
int extraRows = 0;
- for (int i = 0; i <= adapterPosition; i++) {
+ for (int i = 0; i <= adapterPosition && i < items.size(); i++) {
if (!isViewType(items.get(i).viewType, VIEW_TYPE_MASK_ICON)) {
extraRows++;
}
@@ -228,6 +127,20 @@
}
}
+ @Override
+ public void setAppsPerRow(int appsPerRow) {
+ mAppsPerRow = appsPerRow;
+ int totalSpans = mAppsPerRow;
+ for (BaseAdapterProvider adapterProvider : mAdapterProviders) {
+ for (int itemPerRow : adapterProvider.getSupportedItemsPerRowArray()) {
+ if (totalSpans % itemPerRow != 0) {
+ totalSpans *= itemPerRow;
+ }
+ }
+ }
+ mGridLayoutMgr.setSpanCount(totalSpans);
+ }
+
/**
* Helper class to size the grid items.
*/
@@ -255,201 +168,4 @@
}
}
}
-
- private final BaseDraggingActivity mLauncher;
- private final LayoutInflater mLayoutInflater;
- private final AlphabeticalAppsList mApps;
- private final GridLayoutManager mGridLayoutMgr;
- private final GridSpanSizer mGridSizer;
-
- private final OnClickListener mOnIconClickListener;
- private OnLongClickListener mOnIconLongClickListener = INSTANCE_ALL_APPS;
-
- private int mAppsPerRow;
-
- private OnFocusChangeListener mIconFocusListener;
-
- // The text to show when there are no search results and no market search handler.
- protected String mEmptySearchMessage;
- // The intent to send off to the market app, updated each time the search query changes.
- private Intent mMarketSearchIntent;
-
- private final int mExtraHeight;
-
- public AllAppsGridAdapter(BaseDraggingActivity launcher, LayoutInflater inflater,
- AlphabeticalAppsList apps, BaseAdapterProvider[] adapterProviders) {
- Resources res = launcher.getResources();
- mLauncher = launcher;
- mApps = apps;
- mEmptySearchMessage = res.getString(R.string.all_apps_loading_message);
- mGridSizer = new GridSpanSizer();
- mGridLayoutMgr = new AppsGridLayoutManager(launcher);
- mGridLayoutMgr.setSpanSizeLookup(mGridSizer);
- mLayoutInflater = inflater;
-
- mOnIconClickListener = launcher.getItemOnClickListener();
-
- mAdapterProviders = adapterProviders;
- setAppsPerRow(mLauncher.getDeviceProfile().numShownAllAppsColumns);
- mExtraHeight = launcher.getResources().getDimensionPixelSize(R.dimen.all_apps_height_extra);
- }
-
- public void setAppsPerRow(int appsPerRow) {
- mAppsPerRow = appsPerRow;
- int totalSpans = mAppsPerRow;
- for (BaseAdapterProvider adapterProvider : mAdapterProviders) {
- for (int itemPerRow : adapterProvider.getSupportedItemsPerRowArray()) {
- if (totalSpans % itemPerRow != 0) {
- totalSpans *= itemPerRow;
- }
- }
- }
- mGridLayoutMgr.setSpanCount(totalSpans);
- }
-
- /**
- * Sets the long click listener for icons
- */
- public void setOnIconLongClickListener(@Nullable OnLongClickListener listener) {
- mOnIconLongClickListener = listener;
- }
-
- public static boolean isDividerViewType(int viewType) {
- return isViewType(viewType, VIEW_TYPE_MASK_DIVIDER);
- }
-
- public static boolean isIconViewType(int viewType) {
- return isViewType(viewType, VIEW_TYPE_MASK_ICON);
- }
-
- public static boolean isViewType(int viewType, int viewTypeMask) {
- return (viewType & viewTypeMask) != 0;
- }
-
- public void setIconFocusListener(OnFocusChangeListener focusListener) {
- mIconFocusListener = focusListener;
- }
-
- /**
- * Sets the last search query that was made, used to show when there are no results and to also
- * seed the intent for searching the market.
- */
- public void setLastSearchQuery(String query) {
- Resources res = mLauncher.getResources();
- mEmptySearchMessage = res.getString(R.string.all_apps_no_search_results, query);
- mMarketSearchIntent = PackageManagerHelper.getMarketSearchIntent(mLauncher, query);
- }
-
- /**
- * Returns the grid layout manager.
- */
- public GridLayoutManager getLayoutManager() {
- return mGridLayoutMgr;
- }
-
- @Override
- 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;
- BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
- layout, parent, false);
- icon.setLongPressTimeoutFactor(1f);
- icon.setOnFocusChangeListener(mIconFocusListener);
- icon.setOnClickListener(mOnIconClickListener);
- icon.setOnLongClickListener(mOnIconLongClickListener);
- // Ensure the all apps icon height matches the workspace icons in portrait mode.
- icon.getLayoutParams().height = mLauncher.getDeviceProfile().allAppsCellHeightPx;
- if (FeatureFlags.ENABLE_TWOLINE_ALLAPPS.get()) {
- icon.getLayoutParams().height += mExtraHeight;
- }
- return new ViewHolder(icon);
- case VIEW_TYPE_EMPTY_SEARCH:
- return new ViewHolder(mLayoutInflater.inflate(R.layout.all_apps_empty_search,
- parent, false));
- case VIEW_TYPE_SEARCH_MARKET:
- View searchMarketView = mLayoutInflater.inflate(R.layout.all_apps_search_market,
- parent, false);
- searchMarketView.setOnClickListener(v -> mLauncher.startActivitySafely(
- v, mMarketSearchIntent, null));
- return new ViewHolder(searchMarketView);
- case VIEW_TYPE_ALL_APPS_DIVIDER:
- return new ViewHolder(mLayoutInflater.inflate(
- R.layout.all_apps_divider, parent, false));
- default:
- BaseAdapterProvider adapterProvider = getAdapterProvider(viewType);
- if (adapterProvider != null) {
- return adapterProvider.onCreateViewHolder(mLayoutInflater, parent, viewType);
- }
- throw new RuntimeException("Unexpected view type" + viewType);
- }
- }
-
- @Override
- public void onBindViewHolder(ViewHolder holder, int position) {
- switch (holder.getItemViewType()) {
- case VIEW_TYPE_ICON:
- AdapterItem adapterItem = mApps.getAdapterItems().get(position);
- BubbleTextView icon = (BubbleTextView) holder.itemView;
- icon.reset();
- if (adapterItem.itemInfo instanceof AppInfo) {
- icon.applyFromApplicationInfo((AppInfo) adapterItem.itemInfo);
- } else {
- icon.applyFromItemInfoWithIcon(adapterItem.itemInfo);
- }
- break;
- case VIEW_TYPE_EMPTY_SEARCH:
- TextView emptyViewText = (TextView) holder.itemView;
- emptyViewText.setText(mEmptySearchMessage);
- emptyViewText.setGravity(mApps.hasNoFilteredResults() ? Gravity.CENTER :
- Gravity.START | Gravity.CENTER_VERTICAL);
- break;
- case VIEW_TYPE_SEARCH_MARKET:
- TextView searchView = (TextView) holder.itemView;
- if (mMarketSearchIntent != null) {
- searchView.setVisibility(View.VISIBLE);
- } else {
- searchView.setVisibility(View.GONE);
- }
- break;
- case VIEW_TYPE_ALL_APPS_DIVIDER:
- // nothing to do
- break;
- default:
- BaseAdapterProvider adapterProvider = getAdapterProvider(holder.getItemViewType());
- if (adapterProvider != null) {
- adapterProvider.onBindView(holder, position);
- }
- }
- }
-
- @Override
- public void onViewRecycled(@NonNull ViewHolder holder) {
- super.onViewRecycled(holder);
- }
-
- @Override
- public boolean onFailedToRecycleView(ViewHolder holder) {
- // Always recycle and we will reset the view when it is bound
- return true;
- }
-
- @Override
- public int getItemCount() {
- return mApps.getAdapterItems().size();
- }
-
- @Override
- public int getItemViewType(int position) {
- AdapterItem item = mApps.getAdapterItems().get(position);
- return item.viewType;
- }
-
- @Nullable
- private BaseAdapterProvider getAdapterProvider(int viewType) {
- return Arrays.stream(mAdapterProviders).filter(
- adapterProvider -> adapterProvider.isViewSupported(viewType)).findFirst().orElse(
- null);
- }
}
diff --git a/src/com/android/launcher3/allapps/AllAppsPagedView.java b/src/com/android/launcher3/allapps/AllAppsPagedView.java
index 3cc9ce6..872503a 100644
--- a/src/com/android/launcher3/allapps/AllAppsPagedView.java
+++ b/src/com/android/launcher3/allapps/AllAppsPagedView.java
@@ -21,13 +21,13 @@
import android.content.Context;
import android.util.AttributeSet;
-import com.android.launcher3.Launcher;
import com.android.launcher3.PagedView;
+import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.workprofile.PersonalWorkPagedView;
/**
- * A {@link PagedView} for showing different views for the personal and work profile respectively
- * in the {@link AllAppsContainerView}.
+ * A {@link PagedView} for showing different views for the personal and work profile respectively
+ * in the {@link BaseAllAppsContainerView}.
*/
public class AllAppsPagedView extends PersonalWorkPagedView {
@@ -47,7 +47,7 @@
protected boolean snapToPageWithVelocity(int whichPage, int velocity) {
boolean resp = super.snapToPageWithVelocity(whichPage, velocity);
if (resp && whichPage != mCurrentPage) {
- Launcher.getLauncher(getContext()).getStatsLogManager().logger()
+ ActivityContext.lookupContext(getContext()).getStatsLogManager().logger()
.log(mCurrentPage < whichPage
? LAUNCHER_ALLAPPS_SWIPE_TO_WORK_TAB
: LAUNCHER_ALLAPPS_SWIPE_TO_PERSONAL_TAB);
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index bccd9b4..af17cf7 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -15,10 +15,9 @@
*/
package com.android.launcher3.allapps;
-import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.UNSPECIFIED;
-import static android.view.View.MeasureSpec.makeMeasureSpec;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_SCROLLED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_VERTICAL_SWIPE_BEGIN;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_VERTICAL_SWIPE_END;
import static com.android.launcher3.util.LogConfig.SEARCH_LOGGING;
@@ -36,9 +35,8 @@
import androidx.recyclerview.widget.RecyclerView;
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.BaseRecyclerView;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.FastScrollRecyclerView;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -47,19 +45,18 @@
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.RecyclerViewFastScroller;
-import java.util.ArrayList;
import java.util.List;
/**
* A RecyclerView with custom fast scroll support for the all apps view.
*/
-public class AllAppsRecyclerView extends BaseRecyclerView {
- private static final String TAG = "AllAppsContainerView";
+public class AllAppsRecyclerView extends FastScrollRecyclerView {
+ protected static final String TAG = "AllAppsRecyclerView";
private static final boolean DEBUG = false;
private static final boolean DEBUG_LATENCY = Utilities.isPropertyEnabled(SEARCH_LOGGING);
- private AlphabeticalAppsList mApps;
- private final int mNumAppsPerRow;
+ protected AlphabeticalAppsList<?> mApps;
+ protected final int mNumAppsPerRow;
// The specific view heights that we use to calculate scroll
private final SparseIntArray mViewHeights = new SparseIntArray();
@@ -71,13 +68,31 @@
public void onChanged() {
mCachedScrollPositions.clear();
}
+
+ @Override
+ public void onItemRangeChanged(int positionStart, int itemCount) {
+ onChanged();
+ }
+
+ @Override
+ public void onItemRangeInserted(int positionStart, int itemCount) {
+ onChanged();
+ }
+
+ @Override
+ public void onItemRangeRemoved(int positionStart, int itemCount) {
+ onChanged();
+ }
+
+ @Override
+ public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
+ onChanged();
+ }
};
// The empty-search result background
- private AllAppsBackgroundDrawable mEmptySearchBackground;
- private int mEmptySearchBackgroundTopOffset;
-
- private ArrayList<View> mAutoSizedOverlays = new ArrayList<>();
+ protected AllAppsBackgroundDrawable mEmptySearchBackground;
+ protected int mEmptySearchBackgroundTopOffset;
public AllAppsRecyclerView(Context context) {
this(context, null);
@@ -104,16 +119,16 @@
/**
* Sets the list of apps in this view, used to determine the fastscroll position.
*/
- public void setApps(AlphabeticalAppsList apps) {
+ public void setApps(AlphabeticalAppsList<?> apps) {
mApps = apps;
}
- public AlphabeticalAppsList getApps() {
+ public AlphabeticalAppsList<?> getApps() {
return mApps;
}
- private void updatePoolSize() {
- DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
+ protected void updatePoolSize() {
+ DeviceProfile grid = ActivityContext.lookupContext(getContext()).getDeviceProfile();
RecyclerView.RecycledViewPool pool = getRecycledViewPool();
int approxRows = (int) Math.ceil(grid.availableHeightPx / grid.allAppsIconSizePx);
pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_EMPTY_SEARCH, 1);
@@ -137,8 +152,8 @@
Log.d(TAG, "onDraw at = " + System.currentTimeMillis());
}
if (DEBUG_LATENCY) {
- Log.d(SEARCH_LOGGING,
- "-- Recycle view onDraw, time stamp = " + System.currentTimeMillis());
+ Log.d(SEARCH_LOGGING, getClass().getSimpleName() + " onDraw; time stamp = "
+ + System.currentTimeMillis());
}
super.onDraw(c);
}
@@ -152,30 +167,6 @@
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
updateEmptySearchBackgroundBounds();
updatePoolSize();
- for (int i = 0; i < mAutoSizedOverlays.size(); i++) {
- View overlay = mAutoSizedOverlays.get(i);
- overlay.measure(makeMeasureSpec(w, EXACTLY), makeMeasureSpec(w, EXACTLY));
- overlay.layout(0, 0, w, h);
- }
- }
-
- /**
- * Adds an overlay that automatically rescales with the recyclerview.
- */
- public void addAutoSizedOverlay(View overlay) {
- mAutoSizedOverlays.add(overlay);
- getOverlay().add(overlay);
- onSizeChanged(getWidth(), getHeight(), getWidth(), getHeight());
- }
-
- /**
- * Clears auto scaling overlay views added by #addAutoSizedOverlay
- */
- public void clearAutoSizedOverlays() {
- for (View v : mAutoSizedOverlays) {
- getOverlay().remove(v);
- }
- mAutoSizedOverlays.clear();
}
public void onSearchResultsChanged() {
@@ -201,12 +192,15 @@
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
- StatsLogManager mgr = BaseDraggingActivity.fromContext(getContext()).getStatsLogManager();
+ StatsLogManager mgr = ActivityContext.lookupContext(getContext()).getStatsLogManager();
switch (state) {
case SCROLL_STATE_DRAGGING:
+ mgr.logger().log(LAUNCHER_ALLAPPS_SCROLLED);
requestFocus();
mgr.logger().sendToInteractionJankMonitor(
LAUNCHER_ALLAPPS_VERTICAL_SWIPE_BEGIN, this);
+ hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
+ getApplicationWindowToken());
break;
case SCROLL_STATE_IDLE:
mgr.logger().sendToInteractionJankMonitor(
@@ -222,8 +216,6 @@
&& mEmptySearchBackground != null && mEmptySearchBackground.getAlpha() > 0) {
mEmptySearchBackground.setHotspot(e.getX(), e.getY());
}
- hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
- getApplicationWindowToken());
return result;
}
@@ -240,17 +232,14 @@
// Find the fastscroll section that maps to this touch fraction
List<AlphabeticalAppsList.FastScrollSectionInfo> fastScrollSections =
mApps.getFastScrollerSections();
- AlphabeticalAppsList.FastScrollSectionInfo lastInfo = fastScrollSections.get(0);
- for (int i = 1; i < fastScrollSections.size(); i++) {
- AlphabeticalAppsList.FastScrollSectionInfo info = fastScrollSections.get(i);
- if (info.touchFraction > touchFraction) {
- break;
- }
- lastInfo = info;
+ int count = fastScrollSections.size();
+ if (count == 0) {
+ return "";
}
-
- mFastScrollHelper.smoothScrollToSection(lastInfo);
- return lastInfo.sectionName;
+ int index = Utilities.boundToRange((int) (touchFraction * count), 0, count - 1);
+ AlphabeticalAppsList.FastScrollSectionInfo section = fastScrollSections.get(index);
+ mFastScrollHelper.smoothScrollToSection(section);
+ return section.sectionName;
}
@Override
@@ -271,12 +260,6 @@
}
@Override
- protected float getBottomFadingEdgeStrength() {
- // No bottom fading edge.
- return 0;
- }
-
- @Override
protected boolean isPaddingOffsetRequired() {
return true;
}
@@ -359,13 +342,6 @@
}
@Override
- public boolean supportsFastScrolling() {
- // Only allow fast scrolling when the user is not searching, since the results are not
- // grouped in a meaningful order
- return !mApps.hasFilter();
- }
-
- @Override
public int getCurrentScrollY() {
// Return early if there are no items or we haven't been measured
List<AllAppsGridAdapter.AdapterItem> items = mApps.getAdapterItems();
@@ -375,7 +351,7 @@
// Calculate the y and offset for the item
View child = getChildAt(0);
- int position = getChildPosition(child);
+ int position = getChildAdapterPosition(child);
if (position == NO_POSITION) {
return -1;
}
@@ -465,14 +441,4 @@
public boolean hasOverlappingRendering() {
return false;
}
-
- /**
- * Returns distance between left and right app icons
- */
- public int getTabWidth() {
- DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
- int totalWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
- int iconPadding = totalWidth / grid.numShownAllAppsColumns - grid.allAppsIconSizePx;
- return totalWidth - iconPadding - grid.allAppsIconDrawablePaddingPx;
- }
}
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index fc78bea..a4a2085 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -44,6 +44,9 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.util.MultiAdditivePropertyFactory;
+import com.android.launcher3.util.MultiValueAlpha;
+import com.android.launcher3.util.UiThreadHelper;
import com.android.launcher3.views.ScrimView;
/**
@@ -75,7 +78,57 @@
}
};
- private AllAppsContainerView mAppsView;
+ public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PULL_BACK_TRANSLATION =
+ new FloatProperty<AllAppsTransitionController>("allAppsPullBackTranslation") {
+
+ @Override
+ public Float get(AllAppsTransitionController controller) {
+ if (controller.mIsTablet) {
+ return controller.mAppsView.getActiveRecyclerView().getTranslationY();
+ } else {
+ return controller.getAppsViewPullbackTranslationY().get(
+ controller.mAppsView);
+ }
+ }
+
+ @Override
+ public void setValue(AllAppsTransitionController controller, float translation) {
+ if (controller.mIsTablet) {
+ controller.mAppsView.getActiveRecyclerView().setTranslationY(translation);
+ } else {
+ controller.getAppsViewPullbackTranslationY().set(controller.mAppsView,
+ translation);
+ }
+ }
+ };
+
+ public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PULL_BACK_ALPHA =
+ new FloatProperty<AllAppsTransitionController>("allAppsPullBackAlpha") {
+
+ @Override
+ public Float get(AllAppsTransitionController controller) {
+ if (controller.mIsTablet) {
+ return controller.mAppsView.getActiveRecyclerView().getAlpha();
+ } else {
+ return controller.getAppsViewPullbackAlpha().getValue();
+ }
+ }
+
+ @Override
+ public void setValue(AllAppsTransitionController controller, float alpha) {
+ if (controller.mIsTablet) {
+ controller.mAppsView.getActiveRecyclerView().setAlpha(alpha);
+ } else {
+ controller.getAppsViewPullbackAlpha().setValue(alpha);
+ }
+ }
+ };
+
+ private static final int INDEX_APPS_VIEW_PROGRESS = 0;
+ private static final int INDEX_APPS_VIEW_PULLBACK = 1;
+ private static final int APPS_VIEW_INDEX_COUNT = 2;
+
+ private ActivityAllAppsContainerView<Launcher> mAppsView;
private final Launcher mLauncher;
private boolean mIsVerticalLayout;
@@ -89,15 +142,22 @@
private float mShiftRange; // changes depending on the orientation
private float mProgress; // [0, 1], mShiftRange * mProgress = shiftCurrent
- private float mScrollRangeDelta = 0;
private ScrimView mScrimView;
+ private final MultiAdditivePropertyFactory<View>
+ mAppsViewTranslationYPropertyFactory = new MultiAdditivePropertyFactory<>(
+ "appsViewTranslationY", View.TRANSLATION_Y);
+ private MultiValueAlpha mAppsViewAlpha;
+
+ private boolean mIsTablet;
+
public AllAppsTransitionController(Launcher l) {
mLauncher = l;
- mShiftRange = mLauncher.getDeviceProfile().heightPx;
+ DeviceProfile dp = mLauncher.getDeviceProfile();
+ setShiftRange(dp.allAppsShiftRange);
mProgress = 1f;
-
- mIsVerticalLayout = mLauncher.getDeviceProfile().isVerticalBarLayout();
+ mIsVerticalLayout = dp.isVerticalBarLayout();
+ mIsTablet = dp.isTablet;
mLauncher.addOnDeviceProfileChangeListener(this);
}
@@ -108,12 +168,14 @@
@Override
public void onDeviceProfileChanged(DeviceProfile dp) {
mIsVerticalLayout = dp.isVerticalBarLayout();
- setScrollRangeDelta(mScrollRangeDelta);
+ setShiftRange(dp.allAppsShiftRange);
if (mIsVerticalLayout) {
mLauncher.getHotseat().setTranslationY(0);
mLauncher.getWorkspace().getPageIndicator().setTranslationY(0);
}
+
+ mIsTablet = dp.isTablet;
}
/**
@@ -126,13 +188,30 @@
*/
public void setProgress(float progress) {
mProgress = progress;
- mAppsView.setTranslationY(mProgress * mShiftRange);
+ getAppsViewProgressTranslationY().set(mAppsView, mProgress * mShiftRange);
+ mLauncher.onAllAppsTransition(1 - progress);
}
public float getProgress() {
return mProgress;
}
+ private FloatProperty<View> getAppsViewProgressTranslationY() {
+ return mAppsViewTranslationYPropertyFactory.get(INDEX_APPS_VIEW_PROGRESS);
+ }
+
+ private FloatProperty<View> getAppsViewPullbackTranslationY() {
+ return mAppsViewTranslationYPropertyFactory.get(INDEX_APPS_VIEW_PULLBACK);
+ }
+
+ private MultiValueAlpha.AlphaProperty getAppsViewProgressAlpha() {
+ return mAppsViewAlpha.getProperty(INDEX_APPS_VIEW_PROGRESS);
+ }
+
+ private MultiValueAlpha.AlphaProperty getAppsViewPullbackAlpha() {
+ return mAppsViewAlpha.getProperty(INDEX_APPS_VIEW_PULLBACK);
+ }
+
/**
* Sets the vertical transition progress to {@param state} and updates all the dependent UI
* accordingly.
@@ -151,6 +230,15 @@
@Override
public void setStateWithAnimation(LauncherState toState,
StateAnimationConfig config, PendingAnimation builder) {
+ if (NORMAL.equals(toState) && mLauncher.isInState(ALL_APPS)) {
+ UiThreadHelper.hideKeyboardAsync(mLauncher, mLauncher.getAppsView().getWindowToken());
+ builder.addEndListener(success -> {
+ // Reset pull back progress and alpha after switching states.
+ ALL_APPS_PULL_BACK_TRANSLATION.set(this, 0f);
+ ALL_APPS_PULL_BACK_ALPHA.set(this, 1f);
+ });
+ }
+
float targetProgress = toState.getVerticalProgress(mLauncher);
if (Float.compare(mProgress, targetProgress) == 0) {
setAlphas(toState, config, builder);
@@ -160,10 +248,10 @@
}
// need to decide depending on the release velocity
- Interpolator interpolator = (config.userControlled ? LINEAR : DEACCEL_1_7);
-
+ Interpolator verticalProgressInterpolator = config.getInterpolator(ANIM_VERTICAL_PROGRESS,
+ config.userControlled ? LINEAR : DEACCEL_1_7);
Animator anim = createSpringAnimation(mProgress, targetProgress);
- anim.setInterpolator(config.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator));
+ anim.setInterpolator(verticalProgressInterpolator);
anim.addListener(getProgressAnimatorListener());
builder.add(anim);
@@ -187,7 +275,8 @@
boolean hasAllAppsContent = (visibleElements & ALL_APPS_CONTENT) != 0;
Interpolator allAppsFade = config.getInterpolator(ANIM_ALL_APPS_FADE, LINEAR);
- setter.setViewAlpha(mAppsView, hasAllAppsContent ? 1 : 0, allAppsFade);
+ setter.setFloat(getAppsViewProgressAlpha(), MultiValueAlpha.VALUE,
+ hasAllAppsContent ? 1 : 0, allAppsFade);
boolean shouldProtectHeader =
ALL_APPS == state || mLauncher.getStateManager().getState() == ALL_APPS;
@@ -201,7 +290,7 @@
/**
* see Launcher#setupViews
*/
- public void setupViews(ScrimView scrimView, AllAppsContainerView appsView) {
+ public void setupViews(ScrimView scrimView, ActivityAllAppsContainerView<Launcher> appsView) {
mScrimView = scrimView;
mAppsView = appsView;
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && Utilities.ATLEAST_R) {
@@ -210,14 +299,15 @@
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
mAppsView.setScrimView(scrimView);
+ mAppsViewAlpha = new MultiValueAlpha(mAppsView, APPS_VIEW_INDEX_COUNT);
+ mAppsViewAlpha.setUpdateVisibility(true);
}
/**
* Updates the total scroll range but does not update the UI.
*/
- public void setScrollRangeDelta(float delta) {
- mScrollRangeDelta = delta;
- mShiftRange = mLauncher.getDeviceProfile().heightPx - mScrollRangeDelta;
+ public void setShiftRange(float shiftRange) {
+ mShiftRange = shiftRange;
}
/**
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index ce5c589..45a567d 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -15,35 +15,41 @@
*/
package com.android.launcher3.allapps;
+import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_ALL_APPS_DIVIDER;
+import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_EMPTY_SEARCH;
+import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_SEARCH_MARKET;
import android.content.Context;
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.DiffUtil;
+
+import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.util.ItemInfoMatcher;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.LabelComparator;
+import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Locale;
-import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* The alphabetically sorted list of applications.
+ *
+ * @param <T> Type of context inflating this view.
*/
-public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
+public class AlphabeticalAppsList<T extends Context & ActivityContext> implements
+ AllAppsStore.OnUpdateListener {
public static final String TAG = "AlphabeticalAppsList";
- private static final int FAST_SCROLL_FRACTION_DISTRIBUTE_BY_ROWS_FRACTION = 0;
- private static final int FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS = 1;
-
- private final int mFastScrollDistributionMode = FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS;
private final WorkAdapterProvider mWorkAdapterProvider;
/**
@@ -52,22 +58,22 @@
*/
public static class FastScrollSectionInfo {
// The section name
- public String sectionName;
- // The AdapterItem to scroll to for this section
- public AdapterItem fastScrollToItem;
- // The touch fraction that should map to this fast scroll section info
- public float touchFraction;
+ public final String sectionName;
+ // The item position
+ public final int position;
- public FastScrollSectionInfo(String sectionName) {
+ public FastScrollSectionInfo(String sectionName, int position) {
this.sectionName = sectionName;
+ this.position = position;
}
}
- private final BaseDraggingActivity mLauncher;
+ private final T mActivityContext;
// The set of apps from the system
private final List<AppInfo> mApps = new ArrayList<>();
+ @Nullable
private final AllAppsStore mAllAppsStore;
// The number of results in current adapter
@@ -78,24 +84,26 @@
private final List<FastScrollSectionInfo> mFastScrollerSections = new ArrayList<>();
// The of ordered component names as a result of a search query
- private ArrayList<AdapterItem> mSearchResults;
- private AllAppsGridAdapter mAdapter;
+ private final ArrayList<AdapterItem> mSearchResults = new ArrayList<>();
+ private BaseAllAppsAdapter<T> mAdapter;
private AppInfoComparator mAppNameComparator;
- private final int mNumAppsPerRow;
+ private final int mNumAppsPerRowAllApps;
private int mNumAppRowsInAdapter;
- private ItemInfoMatcher mItemFilter;
+ private Predicate<ItemInfo> mItemFilter;
- public AlphabeticalAppsList(Context context, AllAppsStore appsStore,
+ public AlphabeticalAppsList(Context context, @Nullable AllAppsStore appsStore,
WorkAdapterProvider adapterProvider) {
mAllAppsStore = appsStore;
- mLauncher = BaseDraggingActivity.fromContext(context);
+ mActivityContext = ActivityContext.lookupContext(context);
mAppNameComparator = new AppInfoComparator(context);
mWorkAdapterProvider = adapterProvider;
- mNumAppsPerRow = mLauncher.getDeviceProfile().inv.numColumns;
- mAllAppsStore.addUpdateListener(this);
+ mNumAppsPerRowAllApps = mActivityContext.getDeviceProfile().inv.numAllAppsColumns;
+ if (mAllAppsStore != null) {
+ mAllAppsStore.addUpdateListener(this);
+ }
}
- public void updateItemFilter(ItemInfoMatcher itemFilter) {
+ public void updateItemFilter(Predicate<ItemInfo> itemFilter) {
this.mItemFilter = itemFilter;
onAppsUpdated();
}
@@ -103,18 +111,11 @@
/**
* Sets the adapter to notify when this dataset changes.
*/
- public void setAdapter(AllAppsGridAdapter adapter) {
+ public void setAdapter(BaseAllAppsAdapter<T> adapter) {
mAdapter = adapter;
}
/**
- * Returns all the apps.
- */
- public List<AppInfo> getApps() {
- return mApps;
- }
-
- /**
* Returns fast scroller sections of all the current filtered applications.
*/
public List<FastScrollSectionInfo> getFastScrollerSections() {
@@ -165,50 +166,32 @@
}
/**
- * Returns whether there are is a filter set.
+ * Returns whether there are search results which will hide the A-Z list.
*/
- public boolean hasFilter() {
- return (mSearchResults != null);
+ public boolean hasSearchResults() {
+ return !mSearchResults.isEmpty();
}
/**
* Returns whether there are no filtered results.
*/
public boolean hasNoFilteredResults() {
- return (mSearchResults != null) && mAccessibilityResultsCount == 0;
+ return hasSearchResults() && mAccessibilityResultsCount == 0;
}
/**
* Sets results list for search
*/
public boolean setSearchResults(ArrayList<AdapterItem> results) {
- if (!Objects.equals(results, mSearchResults)) {
- mSearchResults = results;
- updateAdapterItems();
- return true;
+ if (Objects.equals(results, mSearchResults)) {
+ return false;
}
- return false;
- }
-
- public boolean appendSearchResults(ArrayList<AdapterItem> results) {
- if (mSearchResults != null && results != null && results.size() > 0) {
- updateSearchAdapterItems(results, mSearchResults.size());
- refreshRecyclerView();
- return true;
+ mSearchResults.clear();
+ if (results != null) {
+ mSearchResults.addAll(results);
}
- return false;
- }
-
- void updateSearchAdapterItems(ArrayList<AdapterItem> list, int offset) {
- for (int i = 0; i < list.size(); i++) {
- AdapterItem adapterItem = list.get(i);
- adapterItem.position = offset + i;
- mAdapterItems.add(adapterItem);
-
- if (adapterItem.isCountedForAccessibility()) {
- mAccessibilityResultsCount++;
- }
- }
+ updateAdapterItems();
+ return true;
}
/**
@@ -216,47 +199,37 @@
*/
@Override
public void onAppsUpdated() {
+ if (mAllAppsStore == null) {
+ return;
+ }
// Sort the list of apps
mApps.clear();
- for (AppInfo app : mAllAppsStore.getApps()) {
- if (mItemFilter == null || mItemFilter.matches(app, null) || hasFilter()) {
- mApps.add(app);
- }
+ Stream<AppInfo> appSteam = Stream.of(mAllAppsStore.getApps());
+ if (!hasSearchResults() && mItemFilter != null) {
+ appSteam = appSteam.filter(mItemFilter);
}
-
- Collections.sort(mApps, mAppNameComparator);
+ appSteam = appSteam.sorted(mAppNameComparator);
// As a special case for some languages (currently only Simplified Chinese), we may need to
// coalesce sections
- Locale curLocale = mLauncher.getResources().getConfiguration().locale;
+ Locale curLocale = mActivityContext.getResources().getConfiguration().locale;
boolean localeRequiresSectionSorting = curLocale.equals(Locale.SIMPLIFIED_CHINESE);
if (localeRequiresSectionSorting) {
// Compute the section headers. We use a TreeMap with the section name comparator to
// ensure that the sections are ordered when we iterate over it later
- TreeMap<String, ArrayList<AppInfo>> sectionMap = new TreeMap<>(new LabelComparator());
- for (AppInfo info : mApps) {
- // Add the section to the cache
- String sectionName = info.sectionName;
-
- // Add it to the mapping
- ArrayList<AppInfo> sectionApps = sectionMap.get(sectionName);
- if (sectionApps == null) {
- sectionApps = new ArrayList<>();
- sectionMap.put(sectionName, sectionApps);
- }
- sectionApps.add(info);
- }
-
- // Add each of the section apps to the list in order
- mApps.clear();
- for (Map.Entry<String, ArrayList<AppInfo>> entry : sectionMap.entrySet()) {
- mApps.addAll(entry.getValue());
- }
+ appSteam = appSteam.collect(Collectors.groupingBy(
+ info -> info.sectionName,
+ () -> new TreeMap<>(new LabelComparator()),
+ Collectors.toCollection(ArrayList::new)))
+ .values()
+ .stream()
+ .flatMap(ArrayList::stream);
}
+ appSteam.forEachOrdered(mApps::add);
// Recompose the set of adapter items from the current set of apps
- if (mSearchResults == null) {
+ if (mSearchResults.isEmpty()) {
updateAdapterItems();
}
}
@@ -266,71 +239,50 @@
* mCachedSectionNames to have been calculated for the set of all apps in mApps.
*/
public void updateAdapterItems() {
- refillAdapterItems();
- refreshRecyclerView();
- }
-
- private void refreshRecyclerView() {
- if (mAdapter != null) {
- mAdapter.notifyDataSetChanged();
- }
- }
-
- private void refillAdapterItems() {
- String lastSectionName = null;
- FastScrollSectionInfo lastFastScrollerSectionInfo = null;
- int position = 0;
- int appIndex = 0;
-
+ List<AdapterItem> oldItems = new ArrayList<>(mAdapterItems);
// Prepare to update the list of sections, filtered apps, etc.
- mAccessibilityResultsCount = 0;
mFastScrollerSections.clear();
mAdapterItems.clear();
+ mAccessibilityResultsCount = 0;
// Recreate the filtered and sectioned apps (for convenience for the grid layout) from the
// ordered set of sections
-
- if (!hasFilter()) {
- mAccessibilityResultsCount = mApps.size();
+ if (hasSearchResults()) {
+ mAdapterItems.addAll(mSearchResults);
+ if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
+ // Append the search market item
+ if (hasNoFilteredResults()) {
+ mAdapterItems.add(new AdapterItem(VIEW_TYPE_EMPTY_SEARCH));
+ } else {
+ mAdapterItems.add(new AdapterItem(VIEW_TYPE_ALL_APPS_DIVIDER));
+ }
+ mAdapterItems.add(new AdapterItem(VIEW_TYPE_SEARCH_MARKET));
+ }
+ } else {
+ int position = 0;
if (mWorkAdapterProvider != null) {
position += mWorkAdapterProvider.addWorkItems(mAdapterItems);
if (!mWorkAdapterProvider.shouldShowWorkApps()) {
return;
}
}
+ String lastSectionName = null;
for (AppInfo info : mApps) {
- String sectionName = info.sectionName;
+ mAdapterItems.add(AdapterItem.asApp(info));
+ String sectionName = info.sectionName;
// Create a new section if the section names do not match
if (!sectionName.equals(lastSectionName)) {
lastSectionName = sectionName;
- lastFastScrollerSectionInfo = new FastScrollSectionInfo(sectionName);
- mFastScrollerSections.add(lastFastScrollerSectionInfo);
+ mFastScrollerSections.add(new FastScrollSectionInfo(sectionName, position));
}
-
- // Create an app item
- AdapterItem appItem = AdapterItem.asApp(position++, sectionName, info,
- appIndex++);
- if (lastFastScrollerSectionInfo.fastScrollToItem == null) {
- lastFastScrollerSectionInfo.fastScrollToItem = appItem;
- }
-
- mAdapterItems.add(appItem);
- }
- } else {
- updateSearchAdapterItems(mSearchResults, 0);
- if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
- // Append the search market item
- if (hasNoFilteredResults()) {
- mAdapterItems.add(AdapterItem.asEmptySearch(position++));
- } else {
- mAdapterItems.add(AdapterItem.asAllAppsDivider(position++));
- }
- mAdapterItems.add(AdapterItem.asMarketSearch(position++));
-
+ position++;
}
}
- if (mNumAppsPerRow != 0) {
+ mAccessibilityResultsCount = (int) mAdapterItems.stream()
+ .filter(AdapterItem::isCountedForAccessibility).count();
+
+ if (mNumAppsPerRowAllApps != 0) {
// Update the number of rows in the adapter after we do all the merging (otherwise, we
// would have to shift the values again)
int numAppsInSection = 0;
@@ -338,10 +290,10 @@
int rowIndex = -1;
for (AdapterItem item : mAdapterItems) {
item.rowIndex = 0;
- if (AllAppsGridAdapter.isDividerViewType(item.viewType)) {
+ if (BaseAllAppsAdapter.isDividerViewType(item.viewType)) {
numAppsInSection = 0;
- } else if (AllAppsGridAdapter.isIconViewType(item.viewType)) {
- if (numAppsInSection % mNumAppsPerRow == 0) {
+ } else if (BaseAllAppsAdapter.isIconViewType(item.viewType)) {
+ if (numAppsInSection % mNumAppsPerRowAllApps == 0) {
numAppsInRow = 0;
rowIndex++;
}
@@ -352,36 +304,43 @@
}
}
mNumAppRowsInAdapter = rowIndex + 1;
+ }
- // Pre-calculate all the fast scroller fractions
- switch (mFastScrollDistributionMode) {
- case FAST_SCROLL_FRACTION_DISTRIBUTE_BY_ROWS_FRACTION:
- float rowFraction = 1f / mNumAppRowsInAdapter;
- for (FastScrollSectionInfo info : mFastScrollerSections) {
- AdapterItem item = info.fastScrollToItem;
- if (!AllAppsGridAdapter.isIconViewType(item.viewType)) {
- info.touchFraction = 0f;
- continue;
- }
-
- float subRowFraction = item.rowAppIndex * (rowFraction / mNumAppsPerRow);
- info.touchFraction = item.rowIndex * rowFraction + subRowFraction;
- }
- break;
- case FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS:
- float perSectionTouchFraction = 1f / mFastScrollerSections.size();
- float cumulativeTouchFraction = 0f;
- for (FastScrollSectionInfo info : mFastScrollerSections) {
- AdapterItem item = info.fastScrollToItem;
- if (!AllAppsGridAdapter.isIconViewType(item.viewType)) {
- info.touchFraction = 0f;
- continue;
- }
- info.touchFraction = cumulativeTouchFraction;
- cumulativeTouchFraction += perSectionTouchFraction;
- }
- break;
- }
+ if (mAdapter != null) {
+ DiffUtil.calculateDiff(new MyDiffCallback(oldItems, mAdapterItems), false)
+ .dispatchUpdatesTo(mAdapter);
}
}
+
+ private static class MyDiffCallback extends DiffUtil.Callback {
+
+ private final List<AdapterItem> mOldList;
+ private final List<AdapterItem> mNewList;
+
+ MyDiffCallback(List<AdapterItem> oldList, List<AdapterItem> newList) {
+ mOldList = oldList;
+ mNewList = newList;
+ }
+
+ @Override
+ public int getOldListSize() {
+ return mOldList.size();
+ }
+
+ @Override
+ public int getNewListSize() {
+ return mNewList.size();
+ }
+
+ @Override
+ public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
+ return mOldList.get(oldItemPosition).isSameAs(mNewList.get(newItemPosition));
+ }
+
+ @Override
+ public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
+ return mOldList.get(oldItemPosition).isContentSame(mNewList.get(newItemPosition));
+ }
+ }
+
}
diff --git a/src/com/android/launcher3/allapps/AppInfoComparator.java b/src/com/android/launcher3/allapps/AppInfoComparator.java
index 823f98e..311a40e 100644
--- a/src/com/android/launcher3/allapps/AppInfoComparator.java
+++ b/src/com/android/launcher3/allapps/AppInfoComparator.java
@@ -43,7 +43,9 @@
@Override
public int compare(AppInfo a, AppInfo b) {
// Order by the title in the current locale
- int result = mLabelComparator.compare(a.title.toString(), b.title.toString());
+ int result = mLabelComparator.compare(
+ a.title == null ? "" : a.title.toString(),
+ b.title == null ? "" : b.title.toString());
if (result != 0) {
return result;
}
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
new file mode 100644
index 0000000..fcba246
--- /dev/null
+++ b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
@@ -0,0 +1,303 @@
+/*
+ * 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.allapps;
+
+import static com.android.launcher3.touch.ItemLongClickListener.INSTANCE_ALL_APPS;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnFocusChangeListener;
+import android.view.View.OnLongClickListener;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.views.ActivityContext;
+
+import java.util.Arrays;
+
+/**
+ * Adapter for all the apps.
+ *
+ * @param <T> Type of context inflating all apps.
+ */
+public abstract class BaseAllAppsAdapter<T extends Context & ActivityContext> extends
+ RecyclerView.Adapter<BaseAllAppsAdapter.ViewHolder> {
+
+ public static final String TAG = "BaseAllAppsAdapter";
+
+ // A normal icon
+ public static final int VIEW_TYPE_ICON = 1 << 1;
+ // The message shown when there are no filtered results
+ public static final int VIEW_TYPE_EMPTY_SEARCH = 1 << 2;
+ // The message to continue to a market search when there are no filtered results
+ public static final int VIEW_TYPE_SEARCH_MARKET = 1 << 3;
+
+ // We use various dividers for various purposes. They share enough attributes to reuse layouts,
+ // but differ in enough attributes to require different view types
+
+ // A divider that separates the apps list and the search market button
+ public static final int VIEW_TYPE_ALL_APPS_DIVIDER = 1 << 4;
+
+ // Common view type masks
+ public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
+ public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON;
+
+
+ protected final BaseAdapterProvider[] mAdapterProviders;
+
+ /**
+ * ViewHolder for each icon.
+ */
+ public static class ViewHolder extends RecyclerView.ViewHolder {
+
+ public ViewHolder(View v) {
+ super(v);
+ }
+ }
+
+ /** Sets the number of apps to be displayed in one row of the all apps screen. */
+ public abstract void setAppsPerRow(int appsPerRow);
+
+ /**
+ * Info about a particular adapter item (can be either section or app)
+ */
+ public static class AdapterItem {
+ /** Common properties */
+ // The type of this item
+ public final int viewType;
+
+ // The row that this item shows up on
+ public int rowIndex;
+ // The index of this app in the row
+ public int rowAppIndex;
+ // The associated ItemInfoWithIcon for the item
+ public AppInfo itemInfo = null;
+
+ public AdapterItem(int viewType) {
+ this.viewType = viewType;
+ }
+
+ /**
+ * Factory method for AppIcon AdapterItem
+ */
+ public static AdapterItem asApp(AppInfo appInfo) {
+ AdapterItem item = new AdapterItem(VIEW_TYPE_ICON);
+ item.itemInfo = appInfo;
+ return item;
+ }
+
+ protected boolean isCountedForAccessibility() {
+ return viewType == VIEW_TYPE_ICON || viewType == VIEW_TYPE_SEARCH_MARKET;
+ }
+
+ /**
+ * Returns true if the items represent the same object
+ */
+ public boolean isSameAs(AdapterItem other) {
+ return (other.viewType == viewType) && (other.getClass() == getClass());
+ }
+
+ /**
+ * This is called only if {@link #isSameAs} returns true to check if the contents are same
+ * as well. Returning true will prevent redrawing of thee item.
+ */
+ public boolean isContentSame(AdapterItem other) {
+ return itemInfo == null && other.itemInfo == null;
+ }
+ }
+
+ protected final T mActivityContext;
+ protected final AlphabeticalAppsList<T> mApps;
+ // The text to show when there are no search results and no market search handler.
+ protected String mEmptySearchMessage;
+ protected int mAppsPerRow;
+
+ protected final LayoutInflater mLayoutInflater;
+ protected final OnClickListener mOnIconClickListener;
+ protected OnLongClickListener mOnIconLongClickListener = INSTANCE_ALL_APPS;
+ protected OnFocusChangeListener mIconFocusListener;
+ // The click listener to send off to the market app, updated each time the search query changes.
+ private OnClickListener mMarketSearchClickListener;
+ private final int mExtraHeight;
+
+ public BaseAllAppsAdapter(T activityContext, LayoutInflater inflater,
+ AlphabeticalAppsList<T> apps, BaseAdapterProvider[] adapterProviders) {
+ Resources res = activityContext.getResources();
+ mActivityContext = activityContext;
+ mApps = apps;
+ mEmptySearchMessage = res.getString(R.string.all_apps_loading_message);
+ mLayoutInflater = inflater;
+
+ mOnIconClickListener = mActivityContext.getItemOnClickListener();
+
+ mAdapterProviders = adapterProviders;
+ mExtraHeight = res.getDimensionPixelSize(R.dimen.all_apps_height_extra);
+ }
+
+ /**
+ * 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);
+ }
+
+ /** Checks if the passed viewType represents all apps icon. */
+ public static boolean isIconViewType(int viewType) {
+ return isViewType(viewType, VIEW_TYPE_MASK_ICON);
+ }
+
+ public void setIconFocusListener(OnFocusChangeListener focusListener) {
+ mIconFocusListener = focusListener;
+ }
+
+ /**
+ * Sets the last search query that was made, used to show when there are no results and to also
+ * seed the intent for searching the market.
+ */
+ public void setLastSearchQuery(String query, OnClickListener marketSearchClickListener) {
+ Resources res = mActivityContext.getResources();
+ mEmptySearchMessage = res.getString(R.string.all_apps_no_search_results, query);
+ mMarketSearchClickListener = marketSearchClickListener;
+ }
+
+ /**
+ * Returns the layout manager.
+ */
+ public abstract RecyclerView.LayoutManager getLayoutManager();
+
+ @Override
+ 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;
+ BubbleTextView icon = (BubbleTextView) mLayoutInflater.inflate(
+ layout, parent, false);
+ icon.setLongPressTimeoutFactor(1f);
+ icon.setOnFocusChangeListener(mIconFocusListener);
+ icon.setOnClickListener(mOnIconClickListener);
+ icon.setOnLongClickListener(mOnIconLongClickListener);
+ // 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()) {
+ icon.getLayoutParams().height += mExtraHeight;
+ }
+ return new ViewHolder(icon);
+ case VIEW_TYPE_EMPTY_SEARCH:
+ return new ViewHolder(mLayoutInflater.inflate(R.layout.all_apps_empty_search,
+ parent, false));
+ case VIEW_TYPE_SEARCH_MARKET:
+ View searchMarketView = mLayoutInflater.inflate(R.layout.all_apps_search_market,
+ parent, false);
+ searchMarketView.setOnClickListener(mMarketSearchClickListener);
+ return new ViewHolder(searchMarketView);
+ case VIEW_TYPE_ALL_APPS_DIVIDER:
+ return new ViewHolder(mLayoutInflater.inflate(
+ R.layout.all_apps_divider, parent, false));
+ default:
+ BaseAdapterProvider adapterProvider = getAdapterProvider(viewType);
+ if (adapterProvider != null) {
+ return adapterProvider.onCreateViewHolder(mLayoutInflater, parent, viewType);
+ }
+ throw new RuntimeException("Unexpected view type" + viewType);
+ }
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ switch (holder.getItemViewType()) {
+ case VIEW_TYPE_ICON:
+ AdapterItem adapterItem = mApps.getAdapterItems().get(position);
+ BubbleTextView icon = (BubbleTextView) holder.itemView;
+ icon.reset();
+ icon.applyFromApplicationInfo(adapterItem.itemInfo);
+ break;
+ case VIEW_TYPE_EMPTY_SEARCH:
+ TextView emptyViewText = (TextView) holder.itemView;
+ emptyViewText.setText(mEmptySearchMessage);
+ emptyViewText.setGravity(mApps.hasNoFilteredResults() ? Gravity.CENTER :
+ Gravity.START | Gravity.CENTER_VERTICAL);
+ break;
+ case VIEW_TYPE_SEARCH_MARKET:
+ TextView searchView = (TextView) holder.itemView;
+ if (mMarketSearchClickListener != null) {
+ searchView.setVisibility(View.VISIBLE);
+ } else {
+ searchView.setVisibility(View.GONE);
+ }
+ break;
+ case VIEW_TYPE_ALL_APPS_DIVIDER:
+ // nothing to do
+ break;
+ default:
+ BaseAdapterProvider adapterProvider = getAdapterProvider(holder.getItemViewType());
+ if (adapterProvider != null) {
+ adapterProvider.onBindView(holder, position);
+ }
+ }
+ }
+
+ @Override
+ public void onViewRecycled(@NonNull ViewHolder holder) {
+ super.onViewRecycled(holder);
+ }
+
+ @Override
+ public boolean onFailedToRecycleView(ViewHolder holder) {
+ // Always recycle and we will reset the view when it is bound
+ return true;
+ }
+
+ @Override
+ public int getItemCount() {
+ return mApps.getAdapterItems().size();
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ AdapterItem item = mApps.getAdapterItems().get(position);
+ return item.viewType;
+ }
+
+ protected static boolean isViewType(int viewType, int viewTypeMask) {
+ return (viewType & viewTypeMask) != 0;
+ }
+
+ @Nullable
+ protected BaseAdapterProvider getAdapterProvider(int viewType) {
+ return Arrays.stream(mAdapterProviders).filter(
+ adapterProvider -> adapterProvider.isViewSupported(viewType)).findFirst().orElse(
+ null);
+ }
+}
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
new file mode 100644
index 0000000..ecadec6
--- /dev/null
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -0,0 +1,850 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.allapps;
+
+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.util.UiThreadHelper.hideKeyboardAsync;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.os.Process;
+import android.os.UserManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowInsets;
+import android.widget.Button;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.core.graphics.ColorUtils;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
+import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
+import com.android.launcher3.DragSource;
+import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.Insettable;
+import com.android.launcher3.InsettableFrameLayout;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.allapps.search.SearchAdapterProvider;
+import com.android.launcher3.keyboard.FocusedItemDecorator;
+import com.android.launcher3.model.StringCache;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.util.ItemInfoMatcher;
+import com.android.launcher3.util.Themes;
+import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.BaseDragLayer;
+import com.android.launcher3.views.RecyclerViewFastScroller;
+import com.android.launcher3.views.ScrimView;
+import com.android.launcher3.views.SpringRelativeLayout;
+import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePageChangedListener;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+/**
+ * Base all apps view container.
+ *
+ * @param <T> Type of context inflating all apps.
+ */
+public abstract class BaseAllAppsContainerView<T extends Context & ActivityContext
+ & DeviceProfileListenable> extends SpringRelativeLayout implements DragSource, Insettable,
+ OnDeviceProfileChangeListener, OnActivePageChangedListener,
+ ScrimView.ScrimDrawingController {
+
+ protected static final String BUNDLE_KEY_CURRENT_PAGE = "launcher.allapps.current_page";
+
+ public static final float PULL_MULTIPLIER = .02f;
+ public static final float FLING_VELOCITY_MULTIPLIER = 1200f;
+
+ private final Paint mHeaderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final Rect mInsets = new Rect();
+
+ /** Context of an activity or window that is inflating this container. */
+ protected final T mActivityContext;
+ protected final List<AdapterHolder> mAH;
+ protected final Predicate<ItemInfo> mPersonalMatcher = ItemInfoMatcher.ofUser(
+ Process.myUserHandle());
+ private final SearchAdapterProvider<?> mMainAdapterProvider;
+ private final AllAppsStore mAllAppsStore = new AllAppsStore();
+
+ private final RecyclerView.OnScrollListener mScrollListener =
+ new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+ updateHeaderScroll(((AllAppsRecyclerView) recyclerView).getCurrentScrollY());
+ }
+ };
+ private final WorkProfileManager mWorkManager;
+
+ private final Paint mNavBarScrimPaint;
+ private int mNavBarScrimHeight = 0;
+
+ private AllAppsPagedView mViewPager;
+ private SearchRecyclerView mSearchRecyclerView;
+
+ protected FloatingHeaderView mHeader;
+ private View mBottomSheetBackground;
+ private View mBottomSheetHandleArea;
+
+ protected boolean mUsingTabs;
+ private boolean mHasWorkApps;
+
+ protected RecyclerViewFastScroller mTouchHandler;
+ protected final Point mFastScrollerOffset = new Point();
+
+ private final int mScrimColor;
+ private final int mHeaderProtectionColor;
+ protected final float mHeaderThreshold;
+ private int mHeaderBottomAdjustment;
+ private ScrimView mScrimView;
+ private int mHeaderColor;
+ private int mTabsProtectionAlpha;
+
+ protected BaseAllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mActivityContext = ActivityContext.lookupContext(context);
+ mMainAdapterProvider = createMainAdapterProvider();
+
+ mScrimColor = Themes.getAttrColor(context, R.attr.allAppsScrimColor);
+ mHeaderThreshold = getResources().getDimensionPixelSize(
+ R.dimen.dynamic_grid_cell_border_spacing);
+ mHeaderBottomAdjustment = getResources().getDimensionPixelSize(
+ R.dimen.all_apps_header_bottom_adjustment);
+ mHeaderProtectionColor = Themes.getAttrColor(context, R.attr.allappsHeaderProtectionColor);
+
+ mWorkManager = new WorkProfileManager(
+ mActivityContext.getSystemService(UserManager.class),
+ this,
+ Utilities.getPrefs(mActivityContext), mActivityContext.getDeviceProfile());
+ mAH = Arrays.asList(null, null, null);
+ mAH.set(AdapterHolder.MAIN, new AdapterHolder(AdapterHolder.MAIN));
+ mAH.set(AdapterHolder.WORK, new AdapterHolder(AdapterHolder.WORK));
+ mAH.set(AdapterHolder.SEARCH, new AdapterHolder(AdapterHolder.SEARCH));
+
+ mNavBarScrimPaint = new Paint();
+ mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
+
+ mAllAppsStore.addUpdateListener(this::onAppsUpdated);
+ mActivityContext.addOnDeviceProfileChangeListener(this);
+ }
+
+ /** Creates the adapter provider for the main section. */
+ protected abstract SearchAdapterProvider<?> createMainAdapterProvider();
+
+ /** The adapter provider for the main section. */
+ public final SearchAdapterProvider<?> getMainAdapterProvider() {
+ return mMainAdapterProvider;
+ }
+
+ @Override
+ protected void dispatchRestoreInstanceState(SparseArray<Parcelable> sparseArray) {
+ try {
+ // Many slice view id is not properly assigned, and hence throws null
+ // pointer exception in the underneath method. Catching the exception
+ // simply doesn't restore these slice views. This doesn't have any
+ // user visible effect because because we query them again.
+ super.dispatchRestoreInstanceState(sparseArray);
+ } catch (Exception e) {
+ Log.e("AllAppsContainerView", "restoreInstanceState viewId = 0", e);
+ }
+
+ Bundle state = (Bundle) sparseArray.get(R.id.work_tab_state_id, null);
+ if (state != null) {
+ int currentPage = state.getInt(BUNDLE_KEY_CURRENT_PAGE, 0);
+ if (currentPage == AdapterHolder.WORK && mViewPager != null) {
+ mViewPager.setCurrentPage(currentPage);
+ rebindAdapters();
+ } else {
+ reset(true);
+ }
+ }
+
+ }
+
+ @Override
+ protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
+ super.dispatchSaveInstanceState(container);
+ Bundle state = new Bundle();
+ state.putInt(BUNDLE_KEY_CURRENT_PAGE, getCurrentPage());
+ 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() {
+ return mAllAppsStore;
+ }
+
+ public WorkProfileManager getWorkManager() {
+ return mWorkManager;
+ }
+
+ @Override
+ public void onDeviceProfileChanged(DeviceProfile dp) {
+ for (AdapterHolder holder : mAH) {
+ holder.mAdapter.setAppsPerRow(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.
+ holder.mRecyclerView.swapAdapter(holder.mRecyclerView.getAdapter(), true);
+ holder.mRecyclerView.getRecycledViewPool().clear();
+ }
+ }
+ updateBackground(dp);
+ }
+
+ protected void updateBackground(DeviceProfile deviceProfile) {
+ mBottomSheetBackground.setVisibility(deviceProfile.isTablet ? View.VISIBLE : View.GONE);
+ }
+
+ private void onAppsUpdated() {
+ mHasWorkApps = Stream.of(mAllAppsStore.getApps()).anyMatch(mWorkManager.getMatcher());
+ if (!isSearching()) {
+ rebindAdapters();
+ if (mHasWorkApps) {
+ mWorkManager.reset();
+ }
+ }
+ }
+
+ /**
+ * Returns whether the view itself will handle the touch event or not.
+ */
+ public boolean shouldContainerScroll(MotionEvent ev) {
+ BaseDragLayer dragLayer = mActivityContext.getDragLayer();
+ // Scroll if not within the container view (e.g. over large-screen scrim).
+ if (!dragLayer.isEventOverView(this, ev)) {
+ return true;
+ }
+ if (dragLayer.isEventOverView(mBottomSheetHandleArea, ev)) {
+ return true;
+ }
+ AllAppsRecyclerView rv = getActiveRecyclerView();
+ if (rv == null) {
+ return true;
+ }
+ if (rv.getScrollbar() != null
+ && rv.getScrollbar().getThumbOffsetY() >= 0
+ && dragLayer.isEventOverView(rv.getScrollbar(), ev)) {
+ return false;
+ }
+ return rv.shouldContainerScroll(ev, dragLayer);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ AllAppsRecyclerView rv = getActiveRecyclerView();
+ if (rv != null && rv.getScrollbar() != null
+ && rv.getScrollbar().isHitInParent(ev.getX(), ev.getY(), mFastScrollerOffset)) {
+ mTouchHandler = rv.getScrollbar();
+ } else {
+ mTouchHandler = null;
+ }
+ }
+ if (mTouchHandler != null) {
+ return mTouchHandler.handleTouchEvent(ev, mFastScrollerOffset);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ AllAppsRecyclerView rv = getActiveRecyclerView();
+ if (rv != null && rv.getScrollbar() != null
+ && rv.getScrollbar().isHitInParent(ev.getX(), ev.getY(), mFastScrollerOffset)) {
+ mTouchHandler = rv.getScrollbar();
+ } else {
+ mTouchHandler = null;
+
+ }
+ }
+ if (mTouchHandler != null) {
+ mTouchHandler.handleTouchEvent(ev, mFastScrollerOffset);
+ return true;
+ }
+ if (isSearching()) {
+ // if in search state, consume touch event.
+ return true;
+ }
+ return false;
+ }
+
+ /** Description of the container view based on its current state. */
+ public String getDescription() {
+ StringCache cache = mActivityContext.getStringCache();
+ if (mUsingTabs) {
+ if (cache != null) {
+ return isPersonalTab()
+ ? cache.allAppsPersonalTabAccessibility
+ : cache.allAppsWorkTabAccessibility;
+ } else {
+ return isPersonalTab()
+ ? getContext().getString(R.string.all_apps_button_personal_label)
+ : getContext().getString(R.string.all_apps_button_work_label);
+ }
+ }
+ return getContext().getString(R.string.all_apps_button_label);
+ }
+
+ /** The current active recycler view (A-Z list from one of the profiles, or search results). */
+ public AllAppsRecyclerView getActiveRecyclerView() {
+ if (isSearching()) {
+ return getSearchRecyclerView();
+ }
+ return getActiveAppsRecyclerView();
+ }
+
+ /** The current apps recycler view in the container. */
+ private AllAppsRecyclerView getActiveAppsRecyclerView() {
+ if (!mUsingTabs || isPersonalTab()) {
+ return mAH.get(AdapterHolder.MAIN).mRecyclerView;
+ } else {
+ return mAH.get(AdapterHolder.WORK).mRecyclerView;
+ }
+ }
+
+ /**
+ * The container for A-Z apps (the ViewPager for main+work tabs, or main RV). This is currently
+ * hidden while searching.
+ **/
+ private View getAppsRecyclerViewContainer() {
+ return mViewPager != null ? mViewPager : findViewById(R.id.apps_list_view);
+ }
+
+ /** The RV for search results, which is hidden while A-Z apps are visible. */
+ public SearchRecyclerView getSearchRecyclerView() {
+ return mSearchRecyclerView;
+ }
+
+ protected boolean isPersonalTab() {
+ return mViewPager == null || mViewPager.getNextPage() == 0;
+ }
+
+ /**
+ * Switches the current page to the provided {@code tab} if tabs are supported, otherwise does
+ * nothing.
+ */
+ public void switchToTab(int tab) {
+ if (mUsingTabs) {
+ mViewPager.setCurrentPage(tab);
+ }
+ }
+
+ public LayoutInflater getLayoutInflater() {
+ return LayoutInflater.from(getContext());
+ }
+
+ /**
+ * Resets the state of AllApps.
+ */
+ public void reset(boolean animate) {
+ for (int i = 0; i < mAH.size(); i++) {
+ if (mAH.get(i).mRecyclerView != null) {
+ mAH.get(i).mRecyclerView.scrollToTop();
+ }
+ }
+ if (isHeaderVisible()) {
+ mHeader.reset(animate);
+ }
+ // Reset the base recycler view after transitioning home.
+ updateHeaderScroll(0);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ // This is a focus listener that proxies focus from a view into the list view. This is to
+ // work around the search box from getting first focus and showing the cursor.
+ setOnFocusChangeListener((v, hasFocus) -> {
+ if (hasFocus && getActiveRecyclerView() != null) {
+ getActiveRecyclerView().requestFocus();
+ }
+ });
+
+ mHeader = findViewById(R.id.all_apps_header);
+ mSearchRecyclerView = findViewById(R.id.search_results_list_view);
+ mAH.get(AdapterHolder.SEARCH).setup(mSearchRecyclerView,
+ /* Filter out A-Z apps */ itemInfo -> false);
+ rebindAdapters(true /* force */);
+
+ mBottomSheetBackground = findViewById(R.id.bottom_sheet_background);
+ updateBackground(mActivityContext.getDeviceProfile());
+
+ mBottomSheetHandleArea = findViewById(R.id.bottom_sheet_handle_area);
+ }
+
+ @Override
+ public void onDropCompleted(View target, DragObject d, boolean success) {}
+
+ @Override
+ public void setInsets(Rect insets) {
+ mInsets.set(insets);
+ DeviceProfile grid = mActivityContext.getDeviceProfile();
+
+ applyAdapterSideAndBottomPaddings(grid);
+
+ MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
+ mlp.leftMargin = insets.left;
+ mlp.rightMargin = insets.right;
+ setLayoutParams(mlp);
+
+ if (grid.isVerticalBarLayout()) {
+ setPadding(grid.workspacePadding.left, 0, grid.workspacePadding.right, 0);
+ } else {
+ setPadding(grid.allAppsLeftRightMargin, grid.allAppsTopPadding,
+ grid.allAppsLeftRightMargin, 0);
+ }
+
+ InsettableFrameLayout.dispatchInsets(this, insets);
+ }
+
+ /**
+ * Returns a padding in case a scrim is shown on the bottom of the view and a padding is needed.
+ */
+ protected int getNavBarScrimHeight(WindowInsets insets) {
+ return 0;
+ }
+
+ @Override
+ public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
+ mNavBarScrimHeight = getNavBarScrimHeight(insets);
+ applyAdapterSideAndBottomPaddings(mActivityContext.getDeviceProfile());
+ return super.dispatchApplyWindowInsets(insets);
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+
+ if (mNavBarScrimHeight > 0) {
+ canvas.drawRect(0, getHeight() - mNavBarScrimHeight, getWidth(), getHeight(),
+ mNavBarScrimPaint);
+ }
+ }
+
+ protected void rebindAdapters() {
+ rebindAdapters(false /* force */);
+ }
+
+ protected void rebindAdapters(boolean force) {
+ updateSearchResultsVisibility();
+
+ boolean showTabs = shouldShowTabs();
+ if (showTabs == mUsingTabs && !force) {
+ return;
+ }
+
+ if (isSearching()) {
+ mUsingTabs = showTabs;
+ mWorkManager.detachWorkModeSwitch();
+ return;
+ }
+
+ // replaceAppsRVcontainer() needs to use both mUsingTabs value to remove the old view AND
+ // showTabs value to create new view. Hence the mUsingTabs new value assignment MUST happen
+ // after this call.
+ replaceAppsRVContainer(showTabs);
+ mUsingTabs = showTabs;
+
+ mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.MAIN).mRecyclerView);
+ mAllAppsStore.unregisterIconContainer(mAH.get(AdapterHolder.WORK).mRecyclerView);
+
+ 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);
+ mViewPager.getPageIndicator().setActiveMarker(AdapterHolder.MAIN);
+ findViewById(R.id.tab_personal)
+ .setOnClickListener((View view) -> {
+ if (mViewPager.snapToPage(AdapterHolder.MAIN)) {
+ mActivityContext.getStatsLogManager().logger()
+ .log(LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB);
+ }
+ hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
+ getApplicationWindowToken());
+ });
+ findViewById(R.id.tab_work)
+ .setOnClickListener((View view) -> {
+ if (mViewPager.snapToPage(AdapterHolder.WORK)) {
+ mActivityContext.getStatsLogManager().logger()
+ .log(LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB);
+ }
+ hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
+ getApplicationWindowToken());
+ });
+ setDeviceManagementResources();
+ onActivePageChanged(mViewPager.getNextPage());
+ } else {
+ mAH.get(AdapterHolder.MAIN).setup(findViewById(R.id.apps_list_view), null);
+ mAH.get(AdapterHolder.WORK).mRecyclerView = null;
+ }
+ setupHeader();
+
+ mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.MAIN).mRecyclerView);
+ mAllAppsStore.registerIconContainer(mAH.get(AdapterHolder.WORK).mRecyclerView);
+ }
+
+ private void updateSearchResultsVisibility() {
+ if (isSearching()) {
+ getSearchRecyclerView().setVisibility(VISIBLE);
+ getAppsRecyclerViewContainer().setVisibility(GONE);
+ } else {
+ getSearchRecyclerView().setVisibility(GONE);
+ getAppsRecyclerViewContainer().setVisibility(VISIBLE);
+ }
+ if (mHeader.isSetUp()) {
+ mHeader.setActiveRV(getCurrentPage());
+ }
+ }
+
+ private void applyAdapterSideAndBottomPaddings(DeviceProfile grid) {
+ int bottomPadding = Math.max(mInsets.bottom, mNavBarScrimHeight);
+ mAH.forEach(adapterHolder -> {
+ adapterHolder.mPadding.bottom = bottomPadding;
+ adapterHolder.mPadding.left =
+ adapterHolder.mPadding.right = grid.allAppsLeftRightPadding;
+ adapterHolder.applyPadding();
+ });
+ }
+
+ private void setDeviceManagementResources() {
+ if (mActivityContext.getStringCache() != null) {
+ Button personalTab = findViewById(R.id.tab_personal);
+ personalTab.setText(mActivityContext.getStringCache().allAppsPersonalTab);
+
+ Button workTab = findViewById(R.id.tab_work);
+ workTab.setText(mActivityContext.getStringCache().allAppsWorkTab);
+ }
+ }
+
+ protected boolean shouldShowTabs() {
+ return mHasWorkApps;
+ }
+
+ protected boolean isSearching() {
+ return false;
+ }
+
+ protected View replaceAppsRVContainer(boolean showTabs) {
+ for (int i = AdapterHolder.MAIN; i <= AdapterHolder.WORK; i++) {
+ AdapterHolder adapterHolder = mAH.get(i);
+ if (adapterHolder.mRecyclerView != null) {
+ adapterHolder.mRecyclerView.setLayoutManager(null);
+ adapterHolder.mRecyclerView.setAdapter(null);
+ }
+ }
+ View oldView = getAppsRecyclerViewContainer();
+ int index = indexOfChild(oldView);
+ removeView(oldView);
+ int layout = showTabs ? R.layout.all_apps_tabs : R.layout.all_apps_rv_layout;
+ View newView = getLayoutInflater().inflate(layout, this, false);
+ addView(newView, index);
+ if (showTabs) {
+ mViewPager = (AllAppsPagedView) newView;
+ mViewPager.initParentViews(this);
+ mViewPager.getPageIndicator().setOnActivePageChangedListener(this);
+ if (mWorkManager.attachWorkModeSwitch()) {
+ mWorkManager.getWorkModeSwitch().post(
+ () -> mAH.get(AdapterHolder.WORK).applyPadding());
+ }
+ } else {
+ mWorkManager.detachWorkModeSwitch();
+ mViewPager = null;
+ }
+ return newView;
+ }
+
+ @Override
+ public void onActivePageChanged(int currentActivePage) {
+ if (mAH.get(currentActivePage).mRecyclerView != null) {
+ mAH.get(currentActivePage).mRecyclerView.bindFastScrollbar();
+ }
+ reset(true /* animate */);
+
+ mWorkManager.onActivePageChanged(currentActivePage);
+ }
+
+ // Used by tests only
+ private boolean isDescendantViewVisible(int viewId) {
+ final View view = findViewById(viewId);
+ if (view == null) return false;
+
+ if (!view.isShown()) return false;
+
+ return view.getGlobalVisibleRect(new Rect());
+ }
+
+ @VisibleForTesting
+ public boolean isPersonalTabVisible() {
+ return isDescendantViewVisible(R.id.tab_personal);
+ }
+
+ @VisibleForTesting
+ public boolean isWorkTabVisible() {
+ return isDescendantViewVisible(R.id.tab_work);
+ }
+
+ public AlphabeticalAppsList<T> getSearchResultList() {
+ return mAH.get(AdapterHolder.SEARCH).mAppsList;
+ }
+
+ public FloatingHeaderView getFloatingHeaderView() {
+ return mHeader;
+ }
+
+ @VisibleForTesting
+ public View getContentView() {
+ return isSearching() ? getSearchRecyclerView() : getAppsRecyclerViewContainer();
+ }
+
+ /** The current page visible in all apps. */
+ public int getCurrentPage() {
+ return isSearching()
+ ? AdapterHolder.SEARCH
+ : mViewPager == null ? AdapterHolder.MAIN : mViewPager.getNextPage();
+ }
+
+ /** The scroll bar for the active apps recycler view. */
+ public RecyclerViewFastScroller getScrollBar() {
+ AllAppsRecyclerView rv = getActiveAppsRecyclerView();
+ return rv == null ? null : rv.getScrollbar();
+ }
+
+ void setupHeader() {
+ mHeader.setVisibility(View.VISIBLE);
+ boolean tabsHidden = !mUsingTabs;
+ mHeader.setup(
+ mAH.get(AdapterHolder.MAIN).mRecyclerView,
+ mAH.get(AdapterHolder.WORK).mRecyclerView,
+ (SearchRecyclerView) mAH.get(AdapterHolder.SEARCH).mRecyclerView,
+ getCurrentPage(),
+ tabsHidden);
+
+ int padding = mHeader.getMaxTranslation();
+ mAH.forEach(adapterHolder -> {
+ adapterHolder.mPadding.top = padding;
+ adapterHolder.applyPadding();
+ if (adapterHolder.mRecyclerView != null) {
+ adapterHolder.mRecyclerView.scrollToTop();
+ }
+ });
+ }
+
+ public boolean isHeaderVisible() {
+ return mHeader != null && mHeader.getVisibility() == View.VISIBLE;
+ }
+
+ /**
+ * Adds an update listener to animator that adds springs to the animation.
+ */
+ public void addSpringFromFlingUpdateListener(ValueAnimator animator,
+ float velocity /* release velocity */,
+ float progress /* portion of the distance to travel*/) {
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animator) {
+ float distance = (1 - progress) * getHeight(); // px
+ float settleVelocity = Math.min(0, distance
+ / (AllAppsTransitionController.INTERP_COEFF * animator.getDuration())
+ + velocity);
+ absorbSwipeUpVelocity(Math.max(1000, Math.abs(
+ Math.round(settleVelocity * FLING_VELOCITY_MULTIPLIER))));
+ }
+ });
+ }
+
+ /** Invoked when the container is pulled. */
+ public void onPull(float deltaDistance, float displacement) {
+ absorbPullDeltaDistance(PULL_MULTIPLIER * deltaDistance, PULL_MULTIPLIER * displacement);
+ // Current motion spec is to actually push and not pull
+ // on this surface. However, until EdgeEffect.onPush (b/190612804) is
+ // implemented at view level, we will simply pull
+ }
+
+ @Override
+ public void getDrawingRect(Rect outRect) {
+ super.getDrawingRect(outRect);
+ outRect.offset(0, (int) getTranslationY());
+ }
+
+ @Override
+ public void setTranslationY(float translationY) {
+ super.setTranslationY(translationY);
+ invalidateHeader();
+ }
+
+ public void setScrimView(ScrimView scrimView) {
+ mScrimView = scrimView;
+ }
+
+ @Override
+ public void drawOnScrim(Canvas canvas) {
+ if (!mHeader.isHeaderProtectionSupported()) {
+ return;
+ }
+ mHeaderPaint.setColor(mHeaderColor);
+ mHeaderPaint.setAlpha((int) (getAlpha() * Color.alpha(mHeaderColor)));
+ if (mHeaderPaint.getColor() != mScrimColor && mHeaderPaint.getColor() != 0) {
+ int bottom = getHeaderBottom();
+ if (!mUsingTabs) {
+ bottom += getFloatingHeaderView().getPaddingBottom() - mHeaderBottomAdjustment;
+ }
+ canvas.drawRect(0, 0, canvas.getWidth(), bottom, mHeaderPaint);
+ int tabsHeight = getFloatingHeaderView().getPeripheralProtectionHeight();
+ if (mTabsProtectionAlpha > 0 && tabsHeight != 0) {
+ mHeaderPaint.setAlpha((int) (getAlpha() * mTabsProtectionAlpha));
+ canvas.drawRect(0, bottom, canvas.getWidth(), bottom + tabsHeight, mHeaderPaint);
+ }
+ }
+ }
+
+ /**
+ * redraws header protection
+ */
+ public void invalidateHeader() {
+ if (mScrimView != null && mHeader.isHeaderProtectionSupported()) {
+ mScrimView.invalidate();
+ }
+ }
+
+ protected void updateHeaderScroll(int scrolledOffset) {
+ float prog = Utilities.boundToRange((float) scrolledOffset / mHeaderThreshold, 0f, 1f);
+ int headerColor = getHeaderColor(prog);
+ int tabsAlpha = mHeader.getPeripheralProtectionHeight() == 0 ? 0
+ : (int) (Utilities.boundToRange(
+ (scrolledOffset + mHeader.mSnappedScrolledY) / mHeaderThreshold, 0f, 1f)
+ * 255);
+ if (headerColor != mHeaderColor || mTabsProtectionAlpha != tabsAlpha) {
+ mHeaderColor = headerColor;
+ mTabsProtectionAlpha = tabsAlpha;
+ invalidateHeader();
+ }
+ }
+
+ protected int getHeaderColor(float blendRatio) {
+ return ColorUtils.blendARGB(mScrimColor, mHeaderProtectionColor, blendRatio);
+ }
+
+ protected abstract BaseAllAppsAdapter<T> createAdapter(AlphabeticalAppsList<T> mAppsList,
+ BaseAdapterProvider[] adapterProviders);
+
+ public int getHeaderBottom() {
+ return (int) getTranslationY();
+ }
+
+ /**
+ * Returns a view that denotes the visible part of all apps container view.
+ */
+ public View getVisibleContainerView() {
+ return mActivityContext.getDeviceProfile().isTablet ? mBottomSheetBackground : this;
+ }
+
+ /** Holds a {@link BaseAllAppsAdapter} and related fields. */
+ public class AdapterHolder {
+ public static final int MAIN = 0;
+ public static final int WORK = 1;
+ public static final int SEARCH = 2;
+
+ private final int mType;
+ public final BaseAllAppsAdapter<T> mAdapter;
+ final RecyclerView.LayoutManager mLayoutManager;
+ final AlphabeticalAppsList<T> mAppsList;
+ final Rect mPadding = new Rect();
+ AllAppsRecyclerView mRecyclerView;
+
+ AdapterHolder(int type) {
+ mType = type;
+ mAppsList = new AlphabeticalAppsList<>(mActivityContext,
+ isSearch() ? null : mAllAppsStore,
+ isWork() ? mWorkManager.getAdapterProvider() : null);
+
+ BaseAdapterProvider[] adapterProviders =
+ isWork() ? new BaseAdapterProvider[]{mMainAdapterProvider,
+ mWorkManager.getAdapterProvider()}
+ : new BaseAdapterProvider[]{mMainAdapterProvider};
+
+ mAdapter = createAdapter(mAppsList, adapterProviders);
+ mAppsList.setAdapter(mAdapter);
+ mLayoutManager = mAdapter.getLayoutManager();
+ }
+
+ void setup(@NonNull View rv, @Nullable Predicate<ItemInfo> matcher) {
+ mAppsList.updateItemFilter(matcher);
+ mRecyclerView = (AllAppsRecyclerView) rv;
+ mRecyclerView.setEdgeEffectFactory(createEdgeEffectFactory());
+ mRecyclerView.setApps(mAppsList);
+ mRecyclerView.setLayoutManager(mLayoutManager);
+ mRecyclerView.setAdapter(mAdapter);
+ mRecyclerView.setHasFixedSize(true);
+ // No animations will occur when changes occur to the items in this RecyclerView.
+ mRecyclerView.setItemAnimator(null);
+ mRecyclerView.addOnScrollListener(mScrollListener);
+ FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(mRecyclerView);
+ mRecyclerView.addItemDecoration(focusedItemDecorator);
+ mAdapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
+ applyPadding();
+ }
+
+ void applyPadding() {
+ if (mRecyclerView != null) {
+ int bottomOffset = 0;
+ if (isWork() && mWorkManager.getWorkModeSwitch() != null) {
+ bottomOffset = mInsets.bottom + mWorkManager.getWorkModeSwitch().getHeight();
+ }
+ mRecyclerView.setPadding(mPadding.left, mPadding.top, mPadding.right,
+ mPadding.bottom + bottomOffset);
+ }
+ }
+
+ private boolean isWork() {
+ return mType == WORK;
+ }
+
+ private boolean isSearch() {
+ return mType == SEARCH;
+ }
+ }
+}
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderRow.java b/src/com/android/launcher3/allapps/FloatingHeaderRow.java
index 6ff2132..75e527a 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderRow.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderRow.java
@@ -15,11 +15,8 @@
*/
package com.android.launcher3.allapps;
-import android.graphics.Rect;
import android.view.View;
-import com.android.launcher3.DeviceProfile;
-
/**
* A abstract representation of a row in all-apps view
*/
@@ -29,8 +26,6 @@
void setup(FloatingHeaderView parent, FloatingHeaderRow[] allRows, boolean tabsHidden);
- void setInsets(Rect insets, DeviceProfile grid);
-
int getExpectedHeight();
/**
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index 85ee636..d0331c9 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -30,12 +30,12 @@
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
+import com.android.launcher3.allapps.BaseAllAppsContainerView.AdapterHolder;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
+import com.android.launcher3.views.ActivityContext;
import com.android.systemui.plugins.AllAppsRow;
import com.android.systemui.plugins.AllAppsRow.OnHeightUpdatedListener;
import com.android.systemui.plugins.PluginListener;
@@ -54,11 +54,10 @@
private final RecyclerView.OnScrollListener mOnScrollListener =
new RecyclerView.OnScrollListener() {
@Override
- public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
- }
+ public void onScrollStateChanged(@NonNull RecyclerView rv, int newState) {}
@Override
- public void onScrolled(RecyclerView rv, int dx, int dy) {
+ public void onScrolled(@NonNull RecyclerView rv, int dx, int dy) {
if (rv != mCurrentRV) {
return;
}
@@ -72,7 +71,8 @@
moved(current);
applyVerticalMove();
if (headerCollapsed != mHeaderCollapsed) {
- AllAppsContainerView parent = (AllAppsContainerView) getParent();
+ BaseAllAppsContainerView<?> parent =
+ (BaseAllAppsContainerView<?>) getParent();
parent.invalidateHeader();
}
}
@@ -80,14 +80,16 @@
protected final Map<AllAppsRow, PluginHeaderRow> mPluginRows = new ArrayMap<>();
- private final int mHeaderTopPadding;
+ // These two values are necessary to ensure that the header protection is drawn correctly.
+ private final int mHeaderTopAdjustment;
+ private final int mHeaderBottomAdjustment;
private final boolean mHeaderProtectionSupported;
protected ViewGroup mTabLayout;
private AllAppsRecyclerView mMainRV;
private AllAppsRecyclerView mWorkRV;
+ private SearchRecyclerView mSearchRV;
private AllAppsRecyclerView mCurrentRV;
- private ViewGroup mParent;
public boolean mHeaderCollapsed;
protected int mSnappedScrolledY;
private int mTranslationY;
@@ -96,7 +98,6 @@
protected boolean mTabsHidden;
protected int mMaxTranslation;
- private boolean mMainRVActive = true;
private boolean mCollapsed = false;
@@ -115,10 +116,14 @@
public FloatingHeaderView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
- mHeaderTopPadding = context.getResources()
- .getDimensionPixelSize(R.dimen.all_apps_header_top_padding);
+ mHeaderTopAdjustment = context.getResources()
+ .getDimensionPixelSize(R.dimen.all_apps_header_top_adjustment);
+ mHeaderBottomAdjustment = context.getResources()
+ .getDimensionPixelSize(R.dimen.all_apps_header_bottom_adjustment);
mHeaderProtectionSupported = context.getResources().getBoolean(
- R.bool.config_header_protection_supported);
+ R.bool.config_header_protection_supported)
+ // TODO(b/208599118) Support header protection for bottom sheet.
+ && !ActivityContext.lookupContext(context).getDeviceProfile().isTablet;
}
@Override
@@ -152,14 +157,6 @@
PluginManagerWrapper.INSTANCE.get(getContext()).removePluginListener(this);
}
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (mMainRV != null) {
- mTabLayout.getLayoutParams().width = mMainRV.getTabWidth();
- }
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
private void recreateAllRowsArray() {
int pluginCount = mPluginRows.size();
if (pluginCount == 0) {
@@ -192,8 +189,8 @@
int oldMaxHeight = mMaxTranslation;
updateExpectedHeight();
- if (mMaxTranslation != oldMaxHeight) {
- AllAppsContainerView parent = (AllAppsContainerView) getParent();
+ if (mMaxTranslation != oldMaxHeight || mCollapsed) {
+ BaseAllAppsContainerView<?> parent = (BaseAllAppsContainerView<?>) getParent();
if (parent != null) {
parent.setupHeader();
}
@@ -222,7 +219,8 @@
return super.getFocusedChild();
}
- public void setup(AllAppsContainerView.AdapterHolder[] mAH, boolean tabsHidden) {
+ void setup(AllAppsRecyclerView mainRV, AllAppsRecyclerView workRV, SearchRecyclerView searchRV,
+ int activeRV, boolean tabsHidden) {
for (FloatingHeaderRow row : mAllRows) {
row.setup(this, mAllRows, tabsHidden);
}
@@ -230,18 +228,27 @@
mTabsHidden = tabsHidden;
mTabLayout.setVisibility(tabsHidden ? View.GONE : View.VISIBLE);
- mMainRV = setupRV(mMainRV, mAH[AllAppsContainerView.AdapterHolder.MAIN].recyclerView);
- mWorkRV = setupRV(mWorkRV, mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView);
- mParent = (ViewGroup) mMainRV.getParent();
- setMainActive(mMainRVActive || mWorkRV == null);
+ mMainRV = mainRV;
+ mWorkRV = workRV;
+ mSearchRV = searchRV;
+ setActiveRV(activeRV);
reset(false);
}
- private AllAppsRecyclerView setupRV(AllAppsRecyclerView old, AllAppsRecyclerView updated) {
- if (old != updated && updated != null) {
- updated.addOnScrollListener(mOnScrollListener);
+ /** Whether this header has been set up previously. */
+ boolean isSetUp() {
+ return mMainRV != null;
+ }
+
+ /** Set the active AllApps RV which will adjust the alpha of the header when scrolled. */
+ void setActiveRV(int rvType) {
+ if (mCurrentRV != null) {
+ mCurrentRV.removeOnScrollListener(mOnScrollListener);
}
- return updated;
+ mCurrentRV =
+ rvType == AdapterHolder.MAIN ? mMainRV
+ : rvType == AdapterHolder.WORK ? mWorkRV : mSearchRV;
+ mCurrentRV.addOnScrollListener(mOnScrollListener);
}
private void updateExpectedHeight() {
@@ -252,11 +259,9 @@
for (FloatingHeaderRow row : mAllRows) {
mMaxTranslation += row.getExpectedHeight();
}
- }
-
- public void setMainActive(boolean active) {
- mCurrentRV = active ? mMainRV : mWorkRV;
- mMainRVActive = active;
+ if (!mTabsHidden) {
+ mMaxTranslation += mHeaderBottomAdjustment;
+ }
}
public int getMaxTranslation() {
@@ -301,7 +306,7 @@
int uncappedTranslationY = mTranslationY;
mTranslationY = Math.max(mTranslationY, -mMaxTranslation);
- if (mCollapsed || uncappedTranslationY < mTranslationY - mHeaderTopPadding) {
+ if (mCollapsed || uncappedTranslationY < mTranslationY - getPaddingTop()) {
// we hide it completely if already capped (for opening search anim)
for (FloatingHeaderRow row : mAllRows) {
row.setVerticalScroll(0, true /* isScrolledOut */);
@@ -314,15 +319,23 @@
mTabLayout.setTranslationY(mTranslationY);
- int clipHeight = mHeaderTopPadding - getPaddingBottom();
- mRVClip.top = mTabsHidden ? clipHeight : 0;
- mHeaderClip.top = clipHeight;
+ int clipTop = getPaddingTop() - mHeaderTopAdjustment;
+ if (mTabsHidden) {
+ clipTop += getPaddingBottom() - mHeaderBottomAdjustment;
+ }
+ mRVClip.top = mTabsHidden ? clipTop : 0;
+ mHeaderClip.top = clipTop;
// clipping on a draw might cause additional redraw
setClipBounds(mHeaderClip);
- mMainRV.setClipBounds(mRVClip);
+ if (mMainRV != null) {
+ mMainRV.setClipBounds(mRVClip);
+ }
if (mWorkRV != null) {
mWorkRV.setClipBounds(mRVClip);
}
+ if (mSearchRV != null) {
+ mSearchRV.setClipBounds(mRVClip);
+ }
}
/**
@@ -389,17 +402,8 @@
}
private void calcOffset(Point p) {
- p.x = getLeft() - mCurrentRV.getLeft() - mParent.getLeft();
- p.y = getTop() - mCurrentRV.getTop() - mParent.getTop();
- }
-
- public boolean hasVisibleContent() {
- for (FloatingHeaderRow row : mAllRows) {
- if (row.hasVisibleContent()) {
- return true;
- }
- }
- return false;
+ p.x = getLeft() - mCurrentRV.getLeft() - ((ViewGroup) mCurrentRV.getParent()).getLeft();
+ p.y = getTop() - mCurrentRV.getTop() - ((ViewGroup) mCurrentRV.getParent()).getTop();
}
public boolean isHeaderProtectionSupported() {
@@ -413,10 +417,9 @@
@Override
public void setInsets(Rect insets) {
- DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
- for (FloatingHeaderRow row : mAllRows) {
- row.setInsets(insets, grid);
- }
+ int leftRightPadding = ActivityContext.lookupContext(getContext())
+ .getDeviceProfile().allAppsLeftRightPadding;
+ setPadding(leftRightPadding, getPaddingTop(), leftRightPadding, getPaddingBottom());
}
public <T extends FloatingHeaderRow> T findFixedRowByType(Class<T> type) {
@@ -444,5 +447,3 @@
return Math.max(getHeight() - getPaddingTop() + mTranslationY, 0);
}
}
-
-
diff --git a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
index b6dcec6..20f5e74 100644
--- a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
@@ -16,19 +16,18 @@
package com.android.launcher3.allapps;
import android.content.Context;
-import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
+import android.view.WindowInsets;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.Utilities;
/**
* AllAppsContainerView with launcher specific callbacks
*/
-public class LauncherAllAppsContainerView extends AllAppsContainerView {
-
- private final Launcher mLauncher;
+public class LauncherAllAppsContainerView extends ActivityAllAppsContainerView<Launcher> {
public LauncherAllAppsContainerView(Context context) {
this(context, null);
@@ -40,14 +39,13 @@
public LauncherAllAppsContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mLauncher = Launcher.getLauncher(context);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// The AllAppsContainerView houses the QSB and is hence visible from the Workspace
// Overview states. We shouldn't intercept for the scrubber in these cases.
- if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
+ if (!mActivityContext.isInState(LauncherState.ALL_APPS)) {
mTouchHandler = null;
return false;
}
@@ -57,22 +55,18 @@
@Override
public boolean onTouchEvent(MotionEvent ev) {
- if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
+ if (!mActivityContext.isInState(LauncherState.ALL_APPS)) {
return false;
}
return super.onTouchEvent(ev);
}
@Override
- public void setInsets(Rect insets) {
- super.setInsets(insets);
- int allAppsStartingPositionY = mLauncher.getDeviceProfile().availableHeightPx
- - mLauncher.getDeviceProfile().allAppsOpenVerticalTranslate;
- mLauncher.getAllAppsController().setScrollRangeDelta(allAppsStartingPositionY);
- }
-
- @Override
- public void onActivePageChanged(int currentActivePage) {
- super.onActivePageChanged(currentActivePage);
+ protected int getNavBarScrimHeight(WindowInsets insets) {
+ if (Utilities.ATLEAST_Q) {
+ return insets.getTappableElementInsets().bottom;
+ } else {
+ return insets.getStableInsetBottom();
+ }
}
}
diff --git a/src/com/android/launcher3/allapps/PluginHeaderRow.java b/src/com/android/launcher3/allapps/PluginHeaderRow.java
index 5b5fbb7..a9d36d1 100644
--- a/src/com/android/launcher3/allapps/PluginHeaderRow.java
+++ b/src/com/android/launcher3/allapps/PluginHeaderRow.java
@@ -18,10 +18,8 @@
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
-import android.graphics.Rect;
import android.view.View;
-import com.android.launcher3.DeviceProfile;
import com.android.systemui.plugins.AllAppsRow;
/**
@@ -43,9 +41,6 @@
boolean tabsHidden) { }
@Override
- public void setInsets(Rect insets, DeviceProfile grid) { }
-
- @Override
public int getExpectedHeight() {
return mPlugin.getExpectedHeight();
}
diff --git a/src/com/android/launcher3/allapps/SearchRecyclerView.java b/src/com/android/launcher3/allapps/SearchRecyclerView.java
new file mode 100644
index 0000000..482bd29
--- /dev/null
+++ b/src/com/android/launcher3/allapps/SearchRecyclerView.java
@@ -0,0 +1,60 @@
+/*
+ * 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.allapps;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import com.android.launcher3.views.RecyclerViewFastScroller;
+
+/** A RecyclerView for AllApps Search results. */
+public class SearchRecyclerView extends AllAppsRecyclerView {
+ private static final String TAG = "SearchRecyclerView";
+
+ public SearchRecyclerView(Context context) {
+ this(context, null);
+ }
+
+ public SearchRecyclerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public SearchRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public SearchRecyclerView(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ protected void updatePoolSize() {
+ RecycledViewPool pool = getRecycledViewPool();
+ pool.setMaxRecycledViews(AllAppsGridAdapter.VIEW_TYPE_ICON, mNumAppsPerRow);
+ // TODO(b/206905515): Add maxes for other View types.
+ }
+
+ @Override
+ public boolean supportsFastScrolling() {
+ return false;
+ }
+
+ @Override
+ public RecyclerViewFastScroller getScrollbar() {
+ return null;
+ }
+}
diff --git a/src/com/android/launcher3/allapps/SearchUiManager.java b/src/com/android/launcher3/allapps/SearchUiManager.java
index 7478b53..6138bc4 100644
--- a/src/com/android/launcher3/allapps/SearchUiManager.java
+++ b/src/com/android/launcher3/allapps/SearchUiManager.java
@@ -29,7 +29,7 @@
/**
* Initializes the search manager.
*/
- void initializeSearch(AllAppsContainerView containerView);
+ void initializeSearch(ActivityAllAppsContainerView<?> containerView);
/**
* Notifies the search manager to close any active search session.
@@ -65,4 +65,12 @@
* sets highlight result's title
*/
default void setFocusedResultTitle(@Nullable CharSequence title) { }
+
+ /** Refresh the currently displayed list of results. */
+ default void refreshResults() {}
+
+ /** Returns whether search is in zero state. */
+ default boolean inZeroState() {
+ return false;
+ }
}
diff --git a/src/com/android/launcher3/allapps/SecondaryLauncherAllAppsContainerView.java b/src/com/android/launcher3/allapps/SecondaryLauncherAllAppsContainerView.java
new file mode 100644
index 0000000..0719c43
--- /dev/null
+++ b/src/com/android/launcher3/allapps/SecondaryLauncherAllAppsContainerView.java
@@ -0,0 +1,45 @@
+/*
+ * 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.allapps;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.secondarydisplay.SecondaryDisplayLauncher;
+
+/**
+ * AllAppsContainerView for secondary launcher
+ */
+public class SecondaryLauncherAllAppsContainerView extends
+ ActivityAllAppsContainerView<SecondaryDisplayLauncher> {
+
+ public SecondaryLauncherAllAppsContainerView(Context context) {
+ this(context, null);
+ }
+
+ public SecondaryLauncherAllAppsContainerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public SecondaryLauncherAllAppsContainerView(Context context, AttributeSet attrs,
+ int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ protected void updateBackground(DeviceProfile deviceProfile) {}
+}
diff --git a/src/com/android/launcher3/allapps/WorkAdapterProvider.java b/src/com/android/launcher3/allapps/WorkAdapterProvider.java
index 331320d..76d08c8 100644
--- a/src/com/android/launcher3/allapps/WorkAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/WorkAdapterProvider.java
@@ -17,9 +17,14 @@
import android.content.SharedPreferences;
import android.view.LayoutInflater;
+import android.view.View;
import android.view.ViewGroup;
+import android.widget.TextView;
import com.android.launcher3.R;
+import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
+import com.android.launcher3.model.StringCache;
+import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList;
@@ -35,9 +40,11 @@
@WorkProfileManager.WorkProfileState
private int mState;
+ private ActivityContext mActivityContext;
private SharedPreferences mPreferences;
- WorkAdapterProvider(SharedPreferences prefs) {
+ WorkAdapterProvider(ActivityContext activityContext, SharedPreferences prefs) {
+ mActivityContext = activityContext;
mPreferences = prefs;
}
@@ -53,7 +60,38 @@
ViewGroup parent, int viewType) {
int viewId = viewType == VIEW_TYPE_WORK_DISABLED_CARD ? R.layout.work_apps_paused
: R.layout.work_apps_edu;
- return new AllAppsGridAdapter.ViewHolder(layoutInflater.inflate(viewId, parent, false));
+ View view = layoutInflater.inflate(viewId, parent, false);
+ setDeviceManagementResources(view, viewType);
+ return new AllAppsGridAdapter.ViewHolder(view);
+ }
+
+ private void setDeviceManagementResources(View view, int viewType) {
+ StringCache cache = mActivityContext.getStringCache();
+ if (cache == null) {
+ return;
+ }
+ if (viewType == VIEW_TYPE_WORK_DISABLED_CARD) {
+ setWorkProfilePausedResources(view, cache);
+ } else {
+ setWorkProfileEduResources(view, cache);
+ }
+ }
+
+ private void setWorkProfilePausedResources(View view, StringCache cache) {
+ TextView title = view.findViewById(R.id.work_apps_paused_title);
+ title.setText(cache.workProfilePausedTitle);
+
+ TextView body = view.findViewById(R.id.work_apps_paused_content);
+ body.setText(cache.workProfilePausedDescription);
+
+ TextView button = view.findViewById(R.id.enable_work_apps);
+ button.setText(cache.workProfileEnableButton);
+ }
+
+ private void setWorkProfileEduResources(View view, StringCache cache) {
+ TextView title = view.findViewById(R.id.work_apps_paused_title);
+ title.setText(cache.workProfileEdu);
+
}
/**
@@ -69,13 +107,9 @@
public int addWorkItems(ArrayList<AllAppsGridAdapter.AdapterItem> adapterItems) {
if (mState == WorkProfileManager.STATE_DISABLED) {
//add disabled card here.
- AllAppsGridAdapter.AdapterItem disabledCard = new AllAppsGridAdapter.AdapterItem();
- disabledCard.viewType = VIEW_TYPE_WORK_DISABLED_CARD;
- adapterItems.add(disabledCard);
+ adapterItems.add(new AdapterItem(VIEW_TYPE_WORK_DISABLED_CARD));
} else if (mState == WorkProfileManager.STATE_ENABLED && !isEduSeen()) {
- AllAppsGridAdapter.AdapterItem eduCard = new AllAppsGridAdapter.AdapterItem();
- eduCard.viewType = VIEW_TYPE_WORK_EDU_CARD;
- adapterItems.add(eduCard);
+ adapterItems.add(new AdapterItem(VIEW_TYPE_WORK_EDU_CARD));
}
return adapterItems.size();
diff --git a/src/com/android/launcher3/allapps/WorkEduCard.java b/src/com/android/launcher3/allapps/WorkEduCard.java
index 9db7bf0..539cff1 100644
--- a/src/com/android/launcher3/allapps/WorkEduCard.java
+++ b/src/com/android/launcher3/allapps/WorkEduCard.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.allapps;
+import static com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.getTabWidth;
+
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
@@ -23,16 +25,18 @@
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
-import com.android.launcher3.Launcher;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.views.ActivityContext;
/**
* Work profile toggle switch shown at the bottom of AllApps work tab
*/
-public class WorkEduCard extends FrameLayout implements View.OnClickListener,
+public class WorkEduCard extends FrameLayout implements
+ View.OnClickListener,
Animation.AnimationListener {
- private final Launcher mLauncher;
+ private final ActivityContext mActivityContext;
Animation mDismissAnim;
private int mPosition = -1;
@@ -46,7 +50,7 @@
public WorkEduCard(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mLauncher = Launcher.getLauncher(getContext());
+ mActivityContext = ActivityContext.lookupContext(getContext());
mDismissAnim = AnimationUtils.loadAnimation(context, android.R.anim.fade_out);
mDismissAnim.setDuration(500);
mDismissAnim.setAnimationListener(this);
@@ -68,14 +72,13 @@
protected void onFinishInflate() {
super.onFinishInflate();
findViewById(R.id.action_btn).setOnClickListener(this);
- MarginLayoutParams lp = ((MarginLayoutParams) findViewById(R.id.wrapper).getLayoutParams());
- lp.width = mLauncher.getAppsView().getActiveRecyclerView().getTabWidth();
}
@Override
public void onClick(View view) {
startAnimation(mDismissAnim);
- mLauncher.getSharedPrefs().edit().putInt(WorkAdapterProvider.KEY_WORK_EDU_STEP, 1).apply();
+ Utilities.getPrefs(getContext()).edit().putInt(WorkAdapterProvider.KEY_WORK_EDU_STEP,
+ 1).apply();
}
@Override
@@ -84,28 +87,30 @@
}
@Override
- public void onAnimationRepeat(Animation animation) {
-
- }
+ public void onAnimationRepeat(Animation animation) { }
@Override
- public void onAnimationStart(Animation animation) {
-
- }
+ public void onAnimationStart(Animation animation) { }
private void removeCard() {
if (mPosition == -1) {
if (getParent() != null) ((ViewGroup) getParent()).removeView(WorkEduCard.this);
} else {
- AllAppsRecyclerView rv = mLauncher.getAppsView()
- .mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView;
+ AllAppsRecyclerView rv = mActivityContext.getAppsView().mAH.get(
+ ActivityAllAppsContainerView.AdapterHolder.WORK).mRecyclerView;
rv.getApps().getAdapterItems().remove(mPosition);
rv.getAdapter().notifyItemRemoved(mPosition);
}
}
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int size = MeasureSpec.getSize(widthMeasureSpec);
+ findViewById(R.id.wrapper).getLayoutParams().width = getTabWidth(getContext(), size);
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
public void setPosition(int position) {
mPosition = position;
}
-
}
diff --git a/src/com/android/launcher3/allapps/WorkModeSwitch.java b/src/com/android/launcher3/allapps/WorkModeSwitch.java
index be01581..edb0128 100644
--- a/src/com/android/launcher3/allapps/WorkModeSwitch.java
+++ b/src/com/android/launcher3/allapps/WorkModeSwitch.java
@@ -16,22 +16,25 @@
package com.android.launcher3.allapps;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TURN_OFF_WORK_APPS_TAP;
+import static com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.getTabWidth;
import android.content.Context;
import android.graphics.Insets;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
-import android.view.ViewGroup;
+import android.view.ViewGroup.MarginLayoutParams;
import android.view.WindowInsets;
import android.widget.Button;
-import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
-import com.android.launcher3.Launcher;
+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.model.StringCache;
+import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip;
/**
@@ -50,7 +53,6 @@
private boolean mWorkEnabled;
private boolean mOnWorkTab;
-
public WorkModeSwitch(Context context) {
this(context, null, 0);
}
@@ -73,25 +75,56 @@
new KeyboardInsetAnimationCallback(this);
setWindowInsetsAnimationCallback(keyboardInsetAnimationCallback);
}
- DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
+ ActivityContext activityContext = ActivityContext.lookupContext(getContext());
+ DeviceProfile grid = activityContext.getDeviceProfile();
setInsets(grid.getInsets());
+
+ StringCache cache = activityContext.getStringCache();
+ if (cache != null) {
+ setText(cache.workProfilePauseButton);
+ }
}
@Override
public void setInsets(Rect insets) {
- int bottomInset = insets.bottom - mInsets.bottom;
mInsets.set(insets);
- ViewGroup.MarginLayoutParams marginLayoutParams =
- (ViewGroup.MarginLayoutParams) getLayoutParams();
- if (marginLayoutParams != null) {
- marginLayoutParams.bottomMargin = bottomInset + marginLayoutParams.bottomMargin;
+ MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
+ if (lp != null) {
+ int bottomMargin = getResources().getDimensionPixelSize(R.dimen.work_fab_margin_bottom);
+ if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+ bottomMargin <<= 1; // Double margin to add space above search bar.
+ bottomMargin += getResources().getDimensionPixelSize(R.dimen.qsb_widget_height);
+ }
+
+ DeviceProfile dp = ActivityContext.lookupContext(getContext()).getDeviceProfile();
+ lp.rightMargin = lp.leftMargin = dp.allAppsLeftRightPadding;
+ if (!dp.isGestureMode) {
+ if (dp.isTaskbarPresent) {
+ bottomMargin += dp.taskbarSize;
+ } else {
+ bottomMargin += insets.bottom;
+ }
+ }
+
+ lp.bottomMargin = bottomMargin;
}
}
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ DeviceProfile dp = ActivityContext.lookupContext(getContext()).getDeviceProfile();
+ View parent = (View) getParent();
+ int size = parent.getWidth() - parent.getPaddingLeft() - parent.getPaddingRight()
+ - 2 * dp.allAppsLeftRightPadding;
+ int tabWidth = getTabWidth(getContext(), size);
+ int shift = (size - tabWidth) / 2 + dp.allAppsLeftRightPadding;
+ setTranslationX(Utilities.isRtl(getResources()) ? shift : -shift);
+ }
@Override
public void onActivePageChanged(int page) {
- mOnWorkTab = page == AllAppsContainerView.AdapterHolder.WORK;
+ mOnWorkTab = page == ActivityAllAppsContainerView.AdapterHolder.WORK;
updateVisibility();
}
@@ -99,9 +132,9 @@
public void onClick(View view) {
if (Utilities.ATLEAST_P && isEnabled()) {
setFlag(FLAG_PROFILE_TOGGLE_ONGOING);
- Launcher launcher = Launcher.getLauncher(getContext());
- launcher.getStatsLogManager().logger().log(LAUNCHER_TURN_OFF_WORK_APPS_TAP);
- launcher.getAppsView().getWorkManager().setWorkProfileEnabled(false);
+ ActivityContext activityContext = ActivityContext.lookupContext(getContext());
+ activityContext.getStatsLogManager().logger().log(LAUNCHER_TURN_OFF_WORK_APPS_TAP);
+ activityContext.getAppsView().getWorkManager().setWorkProfileEnabled(false);
}
}
@@ -121,7 +154,6 @@
}
}
-
private void updateVisibility() {
clearAnimation();
if (mWorkEnabled && mOnWorkTab) {
diff --git a/src/com/android/launcher3/allapps/WorkPausedCard.java b/src/com/android/launcher3/allapps/WorkPausedCard.java
index 7593ca7..729622f 100644
--- a/src/com/android/launcher3/allapps/WorkPausedCard.java
+++ b/src/com/android/launcher3/allapps/WorkPausedCard.java
@@ -24,16 +24,16 @@
import android.widget.Button;
import android.widget.LinearLayout;
-import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.views.ActivityContext;
/**
* Work profile toggle switch shown at the bottom of AllApps work tab
*/
public class WorkPausedCard extends LinearLayout implements View.OnClickListener {
- private final Launcher mLauncher;
+ private final ActivityContext mActivityContext;
private Button mBtn;
public WorkPausedCard(Context context) {
@@ -46,7 +46,7 @@
public WorkPausedCard(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mLauncher = Launcher.getLauncher(getContext());
+ mActivityContext = ActivityContext.lookupContext(getContext());
}
@@ -61,8 +61,8 @@
public void onClick(View view) {
if (Utilities.ATLEAST_P) {
setEnabled(false);
- mLauncher.getAppsView().getWorkManager().setWorkProfileEnabled(true);
- mLauncher.getStatsLogManager().logger().log(LAUNCHER_TURN_ON_WORK_APPS_TAP);
+ mActivityContext.getAppsView().getWorkManager().setWorkProfileEnabled(true);
+ mActivityContext.getStatsLogManager().logger().log(LAUNCHER_TURN_ON_WORK_APPS_TAP);
}
}
diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java
index e223248..2f5b7a2 100644
--- a/src/com/android/launcher3/allapps/WorkProfileManager.java
+++ b/src/com/android/launcher3/allapps/WorkProfileManager.java
@@ -31,15 +31,18 @@
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
-import com.android.launcher3.util.ItemInfoMatcher;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.function.Predicate;
/**
- * Companion class for {@link AllAppsContainerView} to manage work tab and personal tab related
+ * Companion class for {@link BaseAllAppsContainerView} to manage work tab and personal tab
+ * related
* logic based on {@link WorkProfileState}?
*/
public class WorkProfileManager implements PersonalWorkSlidingTabStrip.OnActivePageChangedListener {
@@ -50,7 +53,6 @@
public static final int STATE_DISABLED = 2;
public static final int STATE_TRANSITION = 3;
-
private final UserManager mUserManager;
/**
@@ -65,21 +67,23 @@
public @interface WorkProfileState {
}
- private final AllAppsContainerView mAllApps;
+ private final BaseAllAppsContainerView<?> mAllApps;
private final WorkAdapterProvider mAdapterProvider;
- private final ItemInfoMatcher mMatcher;
+ private final Predicate<ItemInfo> mMatcher;
private WorkModeSwitch mWorkModeSwitch;
+ private final DeviceProfile mDeviceProfile;
@WorkProfileState
private int mCurrentState;
- public WorkProfileManager(UserManager userManager, AllAppsContainerView allApps,
- SharedPreferences preferences) {
+ public WorkProfileManager(UserManager userManager, BaseAllAppsContainerView<?> allApps,
+ SharedPreferences preferences, DeviceProfile deviceProfile) {
mUserManager = userManager;
mAllApps = allApps;
- mAdapterProvider = new WorkAdapterProvider(preferences);
+ mDeviceProfile = deviceProfile;
+ mAdapterProvider = new WorkAdapterProvider(allApps.mActivityContext, preferences);
mMatcher = mAllApps.mPersonalMatcher.negate();
}
@@ -118,7 +122,7 @@
mCurrentState = currentState;
mAdapterProvider.updateCurrentState(currentState);
if (getAH() != null) {
- getAH().appsList.updateAdapterItems();
+ getAH().mAppsList.updateAdapterItems();
}
if (mWorkModeSwitch != null) {
mWorkModeSwitch.updateCurrentState(currentState == STATE_ENABLED);
@@ -126,7 +130,7 @@
}
/**
- * Creates and attaches for profile toggle button to {@link AllAppsContainerView}
+ * Creates and attaches for profile toggle button to {@link BaseAllAppsContainerView}
*/
public boolean attachWorkModeSwitch() {
if (!mAllApps.getAppsStore().hasModelFlag(
@@ -147,9 +151,8 @@
mWorkModeSwitch.updateCurrentState(mCurrentState == STATE_ENABLED);
return true;
}
-
/**
- * Removes work profile toggle button from {@link AllAppsContainerView}
+ * Removes work profile toggle button from {@link BaseAllAppsContainerView}
*/
public void detachWorkModeSwitch() {
if (mWorkModeSwitch != null && mWorkModeSwitch.getParent() == mAllApps) {
@@ -158,12 +161,11 @@
mWorkModeSwitch = null;
}
-
public WorkAdapterProvider getAdapterProvider() {
return mAdapterProvider;
}
- public ItemInfoMatcher getMatcher() {
+ public Predicate<ItemInfo> getMatcher() {
return mMatcher;
}
@@ -172,8 +174,8 @@
return mWorkModeSwitch;
}
- private AllAppsContainerView.AdapterHolder getAH() {
- return mAllApps.mAH[AllAppsContainerView.AdapterHolder.WORK];
+ private BaseAllAppsContainerView<?>.AdapterHolder getAH() {
+ return mAllApps.mAH.get(BaseAllAppsContainerView.AdapterHolder.WORK);
}
public int getCurrentState() {
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index 0137e2a..886460e 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -16,6 +16,7 @@
package com.android.launcher3.allapps.search;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_FOCUSED_ITEM_SELECTED_WITH_IME;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_QUICK_SEARCH_WITH_IME;
import android.text.Editable;
import android.text.SpannableStringBuilder;
@@ -29,14 +30,13 @@
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
-import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.ExtendedEditText;
-import com.android.launcher3.Launcher;
import com.android.launcher3.Utilities;
-import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
+import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.search.SearchAlgorithm;
import com.android.launcher3.search.SearchCallback;
+import com.android.launcher3.views.ActivityContext;
/**
* An interface to a search box that AllApps can command.
@@ -45,7 +45,7 @@
implements TextWatcher, OnEditorActionListener, ExtendedEditText.OnBackKeyListener,
OnFocusChangeListener {
- protected BaseDraggingActivity mLauncher;
+ protected ActivityContext mLauncher;
protected SearchCallback<AdapterItem> mCallback;
protected ExtendedEditText mInput;
protected String mQuery;
@@ -62,7 +62,7 @@
*/
public final void initialize(
SearchAlgorithm<AdapterItem> searchAlgorithm, ExtendedEditText input,
- BaseDraggingActivity launcher, SearchCallback<AdapterItem> callback) {
+ ActivityContext launcher, SearchCallback<AdapterItem> callback) {
mCallback = callback;
mLauncher = launcher;
@@ -123,9 +123,11 @@
if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_GO) {
mLauncher.getStatsLogManager().logger()
- .log(LAUNCHER_ALLAPPS_FOCUSED_ITEM_SELECTED_WITH_IME);
+ .log(actionId == EditorInfo.IME_ACTION_SEARCH
+ ? LAUNCHER_ALLAPPS_QUICK_SEARCH_WITH_IME
+ : LAUNCHER_ALLAPPS_FOCUSED_ITEM_SELECTED_WITH_IME);
// selectFocusedView should return SearchTargetEvent that is passed onto onClick
- return Launcher.getLauncher(mLauncher).getAppsView().launchHighlightedItem();
+ return mLauncher.getAppsView().getMainAdapterProvider().launchHighlightedItem();
}
return false;
}
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
index 4c5a9e6..6539c05 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -32,17 +32,16 @@
import android.view.View;
import android.view.ViewGroup.MarginLayoutParams;
-import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.ExtendedEditText;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsContainerView;
-import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.allapps.AllAppsStore;
-import com.android.launcher3.allapps.AlphabeticalAppsList;
+import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
import com.android.launcher3.allapps.SearchUiManager;
import com.android.launcher3.search.SearchCallback;
+import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList;
@@ -53,12 +52,11 @@
implements SearchUiManager, SearchCallback<AdapterItem>,
AllAppsStore.OnUpdateListener, Insettable {
- private final BaseDraggingActivity mLauncher;
+ private final ActivityContext mLauncher;
private final AllAppsSearchBarController mSearchBarController;
private final SpannableStringBuilder mSearchQueryBuilder;
- private AlphabeticalAppsList mApps;
- private AllAppsContainerView mAppsView;
+ private ActivityAllAppsContainerView<?> mAppsView;
// The amount of pixels to shift down and overlap with the rest of the content.
private final int mContentOverlap;
@@ -74,7 +72,7 @@
public AppsSearchContainerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mLauncher = BaseDraggingActivity.fromContext(context);
+ mLauncher = ActivityContext.lookupContext(context);
mSearchBarController = new AllAppsSearchBarController();
mSearchQueryBuilder = new SpannableStringBuilder();
@@ -82,7 +80,7 @@
setHint(prefixTextWithIcon(getContext(), R.drawable.ic_allapps_search, getHint()));
mContentOverlap =
- getResources().getDimensionPixelSize(R.dimen.all_apps_search_bar_field_height) / 2;
+ getResources().getDimensionPixelSize(R.dimen.all_apps_search_bar_content_overlap);
}
@Override
@@ -130,11 +128,10 @@
}
@Override
- public void initializeSearch(AllAppsContainerView appsView) {
- mApps = appsView.getApps();
+ public void initializeSearch(ActivityAllAppsContainerView<?> appsView) {
mAppsView = appsView;
mSearchBarController.initialize(
- new DefaultAppSearchAlgorithm(mLauncher),
+ new DefaultAppSearchAlgorithm(getContext()),
this, mLauncher, this);
}
@@ -170,25 +167,14 @@
@Override
public void onSearchResult(String query, ArrayList<AdapterItem> items) {
if (items != null) {
- mApps.setSearchResults(items);
- notifyResultChanged();
+ mAppsView.setSearchResults(items);
mAppsView.setLastSearchQuery(query);
}
}
@Override
- public void onAppendSearchResult(String query, ArrayList<AdapterItem> items) {
- if (items != null) {
- mApps.appendSearchResults(items);
- notifyResultChanged();
- }
- }
-
- @Override
public void clearSearchResult() {
- if (mApps.setSearchResults(null)) {
- notifyResultChanged();
- }
+ mAppsView.setSearchResults(null);
// Clear the search query
mSearchQueryBuilder.clear();
@@ -197,10 +183,6 @@
mAppsView.onClearSearchResult();
}
- private void notifyResultChanged() {
- mAppsView.onSearchResultsChanged();
- }
-
@Override
public void setInsets(Rect insets) {
MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
diff --git a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
index 1f854c6..4eceb71 100644
--- a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
+++ b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
@@ -23,7 +23,7 @@
import androidx.annotation.AnyThread;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
+import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
import com.android.launcher3.model.AllAppsList;
import com.android.launcher3.model.BaseModelUpdateTask;
import com.android.launcher3.model.BgDataModel;
@@ -85,8 +85,7 @@
for (int i = 0; i < total && resultCount < MAX_RESULTS_COUNT; i++) {
AppInfo info = apps.get(i);
if (StringMatcherUtility.matches(queryTextLower, info.title.toString(), matcher)) {
- AdapterItem appItem = AdapterItem.asApp(resultCount, "", info, resultCount);
- result.add(appItem);
+ result.add(AdapterItem.asApp(info));
resultCount++;
}
}
diff --git a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
index 7abd555..a95bd51 100644
--- a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
@@ -23,23 +23,21 @@
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
-import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.BubbleTextView;
-import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.allapps.AllAppsGridAdapter;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.views.AppLauncher;
/**
- * Provides views for local search results
+ * Provides views for local search results.
*/
-public class DefaultSearchAdapterProvider extends SearchAdapterProvider {
+public class DefaultSearchAdapterProvider extends SearchAdapterProvider<AppLauncher> {
private final RecyclerView.ItemDecoration mDecoration;
private View mHighlightedView;
- public DefaultSearchAdapterProvider(BaseDraggingActivity launcher,
- AllAppsContainerView appsContainerView) {
- super(launcher, appsContainerView);
+ public DefaultSearchAdapterProvider(AppLauncher launcher) {
+ super(launcher);
mDecoration = new RecyclerView.ItemDecoration() {
@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent,
diff --git a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
index 7af0406..bc52784 100644
--- a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
@@ -21,18 +21,19 @@
import androidx.recyclerview.widget.RecyclerView;
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.allapps.BaseAdapterProvider;
+import com.android.launcher3.views.ActivityContext;
/**
* A UI expansion wrapper providing for search results
+ *
+ * @param <T> Context for this adapter provider.
*/
-public abstract class SearchAdapterProvider extends BaseAdapterProvider {
+public abstract class SearchAdapterProvider<T extends ActivityContext> extends BaseAdapterProvider {
- protected final BaseDraggingActivity mLauncher;
+ protected final T mLauncher;
- public SearchAdapterProvider(BaseDraggingActivity launcher, AllAppsContainerView appsView) {
+ public SearchAdapterProvider(T launcher) {
mLauncher = launcher;
}
diff --git a/src/com/android/launcher3/anim/AnimatedPropertySetter.java b/src/com/android/launcher3/anim/AnimatedPropertySetter.java
new file mode 100644
index 0000000..e5f5e7c
--- /dev/null
+++ b/src/com/android/launcher3/anim/AnimatedPropertySetter.java
@@ -0,0 +1,144 @@
+/*
+ * 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.anim;
+
+import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.graphics.drawable.ColorDrawable;
+import android.util.FloatProperty;
+import android.util.IntProperty;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+
+import java.util.function.Consumer;
+
+/**
+ * Extension of {@link PropertySetter} which applies the property through an animation
+ */
+public class AnimatedPropertySetter extends PropertySetter {
+
+ protected final AnimatorSet mAnim = new AnimatorSet();
+ protected ValueAnimator mProgressAnimator;
+
+ @Override
+ public Animator setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
+ if (view == null || view.getAlpha() == alpha) {
+ return NO_OP;
+ }
+ ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.ALPHA, alpha);
+ anim.addListener(new AlphaUpdateListener(view));
+ anim.setInterpolator(interpolator);
+ add(anim);
+ return anim;
+ }
+
+ @Override
+ public Animator setViewBackgroundColor(View view, int color, TimeInterpolator interpolator) {
+ if (view == null || (view.getBackground() instanceof ColorDrawable
+ && ((ColorDrawable) view.getBackground()).getColor() == color)) {
+ return NO_OP;
+ }
+ ObjectAnimator anim = ObjectAnimator.ofArgb(view, VIEW_BACKGROUND_COLOR, color);
+ anim.setInterpolator(interpolator);
+ add(anim);
+ return anim;
+ }
+
+ @Override
+ public <T> Animator setFloat(T target, FloatProperty<T> property, float value,
+ TimeInterpolator interpolator) {
+ if (property.get(target) == value) {
+ return NO_OP;
+ }
+ Animator anim = ObjectAnimator.ofFloat(target, property, value);
+ anim.setInterpolator(interpolator);
+ add(anim);
+ return anim;
+ }
+
+ @Override
+ public <T> Animator setInt(T target, IntProperty<T> property, int value,
+ TimeInterpolator interpolator) {
+ if (property.get(target) == value) {
+ return NO_OP;
+ }
+ Animator anim = ObjectAnimator.ofInt(target, property, value);
+ anim.setInterpolator(interpolator);
+ add(anim);
+ return anim;
+ }
+
+
+ /**
+ * Adds a callback to be run on every frame of the animation
+ */
+ public void addOnFrameCallback(Runnable runnable) {
+ addOnFrameListener(anim -> runnable.run());
+ }
+
+ /**
+ * Adds a listener to be run on every frame of the animation
+ */
+ public void addOnFrameListener(ValueAnimator.AnimatorUpdateListener listener) {
+ if (mProgressAnimator == null) {
+ mProgressAnimator = ValueAnimator.ofFloat(0, 1);
+ }
+
+ mProgressAnimator.addUpdateListener(listener);
+ }
+
+ @Override
+ public void addEndListener(Consumer<Boolean> listener) {
+ if (mProgressAnimator == null) {
+ mProgressAnimator = ValueAnimator.ofFloat(0, 1);
+ }
+ mProgressAnimator.addListener(AnimatorListeners.forEndCallback(listener));
+ }
+
+ /**
+ * @see AnimatorSet#addListener(AnimatorListener)
+ */
+ public void addListener(Animator.AnimatorListener listener) {
+ mAnim.addListener(listener);
+ }
+
+ @Override
+ public void add(Animator a) {
+ mAnim.play(a);
+ }
+
+ /**
+ * Creates and returns the underlying AnimatorSet
+ */
+ @NonNull
+ public AnimatorSet buildAnim() {
+ // Add progress animation to the end, so that frame callback is called after all the other
+ // animation update.
+ if (mProgressAnimator != null) {
+ add(mProgressAnimator);
+ mProgressAnimator = null;
+ }
+ return mAnim;
+ }
+}
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index 85ca280..1cc0c21 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -19,7 +19,7 @@
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.DisplayController.getSingleFrameMs;
+import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index 1e7b224..0a77aa7 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -57,6 +57,11 @@
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 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;
@@ -145,8 +150,9 @@
}
/**
- * 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.
+ * 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) {
@@ -155,18 +161,42 @@
String.format("upperBound (%f) must be greater than lowerBound (%f)",
upperBound, lowerBound));
}
- return t -> {
- if (t == lowerBound && t == upperBound) {
- return t == 0f ? 0 : 1;
- }
- if (t < lowerBound) {
- return 0;
- }
- if (t > upperBound) {
- return 1;
- }
- return interpolator.getInterpolation((t - lowerBound) / (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);
}
/**
@@ -178,4 +208,14 @@
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);
+ }
}
diff --git a/src/com/android/launcher3/anim/PendingAnimation.java b/src/com/android/launcher3/anim/PendingAnimation.java
index 3ab893b..7316420 100644
--- a/src/com/android/launcher3/anim/PendingAnimation.java
+++ b/src/com/android/launcher3/anim/PendingAnimation.java
@@ -15,24 +15,18 @@
*/
package com.android.launcher3.anim;
-import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
import static com.android.launcher3.anim.AnimatorPlaybackController.addAnimationHoldersRecur;
import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
-import android.graphics.drawable.ColorDrawable;
import android.util.FloatProperty;
-import android.util.IntProperty;
-import android.view.View;
import com.android.launcher3.anim.AnimatorPlaybackController.Holder;
import java.util.ArrayList;
-import java.util.function.Consumer;
/**
* Utility class to keep track of a running animation.
@@ -43,17 +37,13 @@
*
* TODO: Find a better name
*/
-public class PendingAnimation implements PropertySetter {
+public class PendingAnimation extends AnimatedPropertySetter {
private final ArrayList<Holder> mAnimHolders = new ArrayList<>();
- private final AnimatorSet mAnim;
private final long mDuration;
- private ValueAnimator mProgressAnimator;
-
public PendingAnimation(long duration) {
mDuration = duration;
- mAnim = new AnimatorSet();
}
public long getDuration() {
@@ -68,6 +58,7 @@
add(anim, springProperty);
}
+ @Override
public void add(Animator anim) {
add(anim, SpringProperty.DEFAULT);
}
@@ -77,37 +68,11 @@
addAnimationHoldersRecur(a, mDuration, springProperty, mAnimHolders);
}
- @Override
- public void setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
- if (view == null || view.getAlpha() == alpha) {
- return;
- }
- ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.ALPHA, alpha);
- anim.addListener(new AlphaUpdateListener(view));
- anim.setInterpolator(interpolator);
- add(anim);
- }
-
- @Override
- public void setViewBackgroundColor(View view, int color, TimeInterpolator interpolator) {
- if (view == null || (view.getBackground() instanceof ColorDrawable
- && ((ColorDrawable) view.getBackground()).getColor() == color)) {
- return;
- }
- ObjectAnimator anim = ObjectAnimator.ofArgb(view, VIEW_BACKGROUND_COLOR, color);
- anim.setInterpolator(interpolator);
- add(anim);
- }
-
- @Override
- public <T> void setFloat(T target, FloatProperty<T> property, float value,
- TimeInterpolator interpolator) {
- if (property.get(target) == value) {
- return;
- }
- Animator anim = ObjectAnimator.ofFloat(target, property, value);
- anim.setDuration(mDuration).setInterpolator(interpolator);
- add(anim);
+ /**
+ * Configures interpolator of the underlying AnimatorSet.
+ */
+ public void setInterpolator(TimeInterpolator interpolator) {
+ mAnim.setInterpolator(interpolator);
}
public <T> void addFloat(T target, FloatProperty<T> property, float from, float to,
@@ -117,57 +82,16 @@
add(anim);
}
- @Override
- public <T> void setInt(T target, IntProperty<T> property, int value,
- TimeInterpolator interpolator) {
- if (property.get(target) == value) {
- return;
- }
- Animator anim = ObjectAnimator.ofInt(target, property, value);
- anim.setInterpolator(interpolator);
- add(anim);
- }
-
- /**
- * Adds a callback to be run on every frame of the animation
- */
- public void addOnFrameCallback(Runnable runnable) {
- addOnFrameListener(anim -> runnable.run());
- }
-
- /**
- * Adds a listener to be run on every frame of the animation
- */
- public void addOnFrameListener(ValueAnimator.AnimatorUpdateListener listener) {
- if (mProgressAnimator == null) {
- mProgressAnimator = ValueAnimator.ofFloat(0, 1);
- }
-
- mProgressAnimator.addUpdateListener(listener);
- }
-
- /**
- * @see AnimatorSet#addListener(AnimatorListener)
- */
- public void addListener(Animator.AnimatorListener listener) {
- mAnim.addListener(listener);
- }
-
/**
* Creates and returns the underlying AnimatorSet
*/
+ @Override
public AnimatorSet buildAnim() {
- // Add progress animation to the end, so that frame callback is called after all the other
- // animation update.
- if (mProgressAnimator != null) {
- add(mProgressAnimator);
- mProgressAnimator = null;
- }
if (mAnimHolders.isEmpty()) {
// Add a placeholder animation to that the duration is respected
add(ValueAnimator.ofFloat(0, 1).setDuration(mDuration));
}
- return mAnim;
+ return super.buildAnim();
}
/**
@@ -176,14 +100,4 @@
public AnimatorPlaybackController createPlaybackController() {
return new AnimatorPlaybackController(buildAnim(), mDuration, mAnimHolders);
}
-
- /**
- * Add a listener of receiving the success/failure callback in the end.
- */
- public void addEndListener(Consumer<Boolean> listener) {
- if (mProgressAnimator == null) {
- mProgressAnimator = ValueAnimator.ofFloat(0, 1);
- }
- mProgressAnimator.addListener(AnimatorListeners.forEndCallback(listener));
- }
}
diff --git a/src/com/android/launcher3/anim/PropertySetter.java b/src/com/android/launcher3/anim/PropertySetter.java
index 8d77b4b..d2207f6 100644
--- a/src/com/android/launcher3/anim/PropertySetter.java
+++ b/src/com/android/launcher3/anim/PropertySetter.java
@@ -17,57 +17,94 @@
package com.android.launcher3.anim;
import android.animation.Animator;
+import android.animation.AnimatorSet;
import android.animation.TimeInterpolator;
import android.util.FloatProperty;
import android.util.IntProperty;
import android.view.View;
+import androidx.annotation.NonNull;
+
+import java.util.function.Consumer;
+
/**
* Utility class for setting a property with or without animation
*/
-public interface PropertySetter {
+public abstract class PropertySetter {
- PropertySetter NO_ANIM_PROPERTY_SETTER = new PropertySetter() { };
+ public static final PropertySetter NO_ANIM_PROPERTY_SETTER = new PropertySetter() {
+
+ @Override
+ public void add(Animator animatorSet) {
+ animatorSet.setDuration(0);
+ animatorSet.start();
+ }
+ };
+
+ protected static final AnimatorSet NO_OP = new AnimatorSet();
/**
* Sets the view alpha using the provided interpolator.
* Unlike {@link #setFloat}, this also updates the visibility of the view as alpha changes
* between zero and non-zero.
*/
- default void setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
+ @NonNull
+ public Animator setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
if (view != null) {
view.setAlpha(alpha);
AlphaUpdateListener.updateVisibility(view);
}
+ return NO_OP;
}
/**
* Sets the background color of the provided view using the provided interpolator.
*/
- default void setViewBackgroundColor(View view, int color, TimeInterpolator interpolator) {
+ @NonNull
+ public Animator setViewBackgroundColor(View view, int color, TimeInterpolator interpolator) {
if (view != null) {
view.setBackgroundColor(color);
}
+ return NO_OP;
}
/**
* Updates the float property of the target using the provided interpolator
*/
- default <T> void setFloat(T target, FloatProperty<T> property, float value,
+ @NonNull
+ public <T> Animator setFloat(T target, FloatProperty<T> property, float value,
TimeInterpolator interpolator) {
property.setValue(target, value);
+ return NO_OP;
}
/**
* Updates the int property of the target using the provided interpolator
*/
- default <T> void setInt(T target, IntProperty<T> property, int value,
+ @NonNull
+ public <T> Animator setInt(T target, IntProperty<T> property, int value,
TimeInterpolator interpolator) {
property.setValue(target, value);
+ return NO_OP;
}
- default void add(Animator animatorSet) {
- animatorSet.setDuration(0);
- animatorSet.start();
+ /**
+ * Runs the animation as part of setting the property
+ */
+ public abstract void add(Animator animatorSet);
+
+ /**
+ * Add a listener of receiving the success/failure callback in the end.
+ */
+ public void addEndListener(Consumer<Boolean> listener) {
+ listener.accept(true);
+ }
+
+ /**
+ * Creates and returns the AnimatorSet that can be run to apply the properties
+ */
+ @NonNull
+ public AnimatorSet buildAnim() {
+ return NO_OP;
}
}
diff --git a/src/com/android/launcher3/anim/SpringAnimationBuilder.java b/src/com/android/launcher3/anim/SpringAnimationBuilder.java
index bd52158..40fa0cf 100644
--- a/src/com/android/launcher3/anim/SpringAnimationBuilder.java
+++ b/src/com/android/launcher3/anim/SpringAnimationBuilder.java
@@ -25,7 +25,7 @@
import androidx.annotation.FloatRange;
import androidx.dynamicanimation.animation.SpringForce;
-import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.window.RefreshRateTracker;
/**
* Utility class to build an object animator which follows the same path as a spring animation for
@@ -134,7 +134,7 @@
}
public SpringAnimationBuilder computeParams() {
- int singleFrameMs = DisplayController.getSingleFrameMs(mContext);
+ int singleFrameMs = RefreshRateTracker.getSingleFrameMs(mContext);
double naturalFreq = Math.sqrt(mStiffness);
double dampedFreq = naturalFreq * Math.sqrt(1 - mDampingRatio * mDampingRatio);
diff --git a/src/com/android/launcher3/compat/AlphabeticIndexCompat.java b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
index 46c9006..4f8d53e 100644
--- a/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
+++ b/src/com/android/launcher3/compat/AlphabeticIndexCompat.java
@@ -4,12 +4,12 @@
import android.icu.text.AlphabeticIndex;
import android.os.LocaleList;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.Utilities;
import java.util.Locale;
-import androidx.annotation.NonNull;
-
public class AlphabeticIndexCompat {
private static final String MID_DOT = "\u2219";
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 2d31aa4..33beacd 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -52,7 +52,7 @@
* Enable moving the QSB on the 0th screen of the workspace. This is not a configuration feature
* and should be modified at a project level.
*/
- public static final boolean QSB_ON_FIRST_SCREEN = true;
+ public static final boolean QSB_ON_FIRST_SCREEN = BuildConfig.QSB_ON_FIRST_SCREEN;
/**
* Feature flag to handle define config changes dynamically instead of killing the process.
@@ -79,9 +79,6 @@
public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(
"KEYGUARD_ANIMATION", false, "Enable animation for keyguard going away on wallpaper");
- public static final BooleanFlag ADAPTIVE_ICON_WINDOW_ANIM = getDebugFlag(
- "ADAPTIVE_ICON_WINDOW_ANIM", true, "Use adaptive icons for window animations.");
-
public static final BooleanFlag ENABLE_QUICKSTEP_LIVE_TILE = getDebugFlag(
"ENABLE_QUICKSTEP_LIVE_TILE", true, "Enable live tile in Quickstep overview");
@@ -92,11 +89,21 @@
public static final BooleanFlag ENABLE_DEVICE_SEARCH = new DeviceFlag(
"ENABLE_DEVICE_SEARCH", true, "Allows on device search in all apps");
+ public static final BooleanFlag ENABLE_FLOATING_SEARCH_BAR =
+ getDebugFlag("ENABLE_FLOATING_SEARCH_BAR", false,
+ "Keep All Apps search bar at the bottom (but above keyboard if open)");
+
+ public static final BooleanFlag ENABLE_QUICK_SEARCH = new DeviceFlag("ENABLE_QUICK_SEARCH",
+ true, "Use quick search behavior.");
+
+ public static final BooleanFlag COLLECT_SEARCH_HISTORY = new DeviceFlag(
+ "COLLECT_SEARCH_HISTORY", false, "Allow launcher to collect search history for log");
+
public static final BooleanFlag ENABLE_TWOLINE_ALLAPPS = getDebugFlag(
"ENABLE_TWOLINE_ALLAPPS", false, "Enables two line label inside all apps.");
public static final BooleanFlag ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING = new DeviceFlag(
- "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", true,
+ "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", false,
"Allows on device search in all apps logging");
public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(
@@ -132,12 +139,12 @@
public static final BooleanFlag ENABLE_BULK_WORKSPACE_ICON_LOADING = getDebugFlag(
"ENABLE_BULK_WORKSPACE_ICON_LOADING",
- false,
+ true,
"Enable loading workspace icons in bulk.");
public static final BooleanFlag ENABLE_BULK_ALL_APPS_ICON_LOADING = getDebugFlag(
"ENABLE_BULK_ALL_APPS_ICON_LOADING",
- false,
+ true,
"Enable loading all apps icons in bulk.");
// Keep as DeviceFlag for remote disable in emergency.
@@ -190,20 +197,10 @@
"ENABLE_APP_PREDICTIONS_WHILE_VISIBLE", true, "Allows app "
+ "predictions to be updated while they are visible to the user.");
- public static final BooleanFlag ENABLE_TASKBAR = getDebugFlag(
- "ENABLE_TASKBAR", true, "Allows a system Taskbar to be shown on larger devices.");
-
- public static final BooleanFlag ENABLE_TASKBAR_EDU = getDebugFlag("ENABLE_TASKBAR_EDU", true,
- "Enables showing taskbar education the first time an app is opened.");
-
public static final BooleanFlag ENABLE_TASKBAR_POPUP_MENU = getDebugFlag(
- "ENABLE_TASKBAR_POPUP_MENU", false, "Enables long pressing taskbar icons to show the"
+ "ENABLE_TASKBAR_POPUP_MENU", true, "Enables long pressing taskbar icons to show the"
+ " popup menu.");
- public static final BooleanFlag ENABLE_OVERVIEW_GRID = getDebugFlag(
- "ENABLE_OVERVIEW_GRID", true, "Uses grid overview layout. "
- + "Only applicable on large screen devices.");
-
public static final BooleanFlag ENABLE_TWO_PANEL_HOME = getDebugFlag(
"ENABLE_TWO_PANEL_HOME", true,
"Uses two panel on home screen. Only applicable on large screen devices.");
@@ -245,6 +242,41 @@
"ENABLE_ICON_LABEL_AUTO_SCALING", true,
"Enables scaling/spacing for icon labels to make more characters visible");
+ public static final BooleanFlag ENABLE_ALL_APPS_IN_TASKBAR = getDebugFlag(
+ "ENABLE_ALL_APPS_IN_TASKBAR", true,
+ "Enables accessing All Apps from the system Taskbar.");
+
+ public static final BooleanFlag ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT = getDebugFlag(
+ "ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT", false,
+ "Enables displaying the all apps button in the hotseat.");
+
+ public static final BooleanFlag ENABLE_ALL_APPS_ONE_SEARCH_IN_TASKBAR = getDebugFlag(
+ "ENABLE_ALL_APPS_ONE_SEARCH_IN_TASKBAR", false,
+ "Enables One Search box in Taskbar All Apps.");
+
+ public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE = getDebugFlag(
+ "ENABLE_SPLIT_FROM_WORKSPACE", true,
+ "Enable initiating split screen from workspace.");
+
+ public static final BooleanFlag ENABLE_NEW_MIGRATION_LOGIC = getDebugFlag(
+ "ENABLE_NEW_MIGRATION_LOGIC", true,
+ "Enable the new grid migration logic, keeping pages when src < dest");
+
+ public static final BooleanFlag ENABLE_ONE_SEARCH_MOTION = new DeviceFlag(
+ "ENABLE_ONE_SEARCH_MOTION", true, "Enables animations in OneSearch.");
+
+ public static final BooleanFlag ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS = new DeviceFlag(
+ "ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS", true,
+ "Enable option to show keyboard when going to all-apps");
+
+ public static final BooleanFlag USE_LOCAL_ICON_OVERRIDES = getDebugFlag(
+ "USE_LOCAL_ICON_OVERRIDES", true,
+ "Use inbuilt monochrome icons if app doesn't provide one");
+
+ public static final BooleanFlag ENABLE_DISMISS_PREDICTION_UNDO = getDebugFlag(
+ "ENABLE_DISMISS_PREDICTION_UNDO", false,
+ "Show an 'Undo' snackbar when users dismiss a predicted hotseat item");
+
public static void initialize(Context context) {
synchronized (sDebugFlags) {
for (DebugFlag flag : sDebugFlags) {
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index fdb2799..35cdfef 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.Utilities.ATLEAST_Q;
-import android.content.ComponentName;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -36,12 +35,12 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.testing.TestProtocol;
-import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList;
import java.util.Optional;
+import java.util.function.Predicate;
/**
* Class for initiating a drag within a view or across multiple views.
@@ -275,15 +274,12 @@
protected abstract void exitDrag();
- public void onAppsRemoved(ItemInfoMatcher matcher) {
+ public void onAppsRemoved(Predicate<ItemInfo> matcher) {
// Cancel the current drag if we are removing an app that we are dragging
if (mDragObject != null) {
ItemInfo dragInfo = mDragObject.dragInfo;
- if (dragInfo instanceof WorkspaceItemInfo) {
- ComponentName cn = dragInfo.getTargetComponent();
- if (cn != null && matcher.matches(dragInfo, cn)) {
- cancelDrag();
- }
+ if (dragInfo instanceof WorkspaceItemInfo && matcher.test(dragInfo)) {
+ cancelDrag();
}
}
}
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index 5ee4203..8eeca7d 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -65,9 +65,7 @@
public class DragLayer extends BaseDragLayer<Launcher> {
public static final int ALPHA_INDEX_OVERLAY = 0;
- public static final int ALPHA_INDEX_LAUNCHER_LOAD = 1;
- public static final int ALPHA_INDEX_TRANSITIONS = 2;
- private static final int ALPHA_CHANNEL_COUNT = 3;
+ private static final int ALPHA_CHANNEL_COUNT = 1;
public static final int ANIMATION_END_DISAPPEAR = 0;
public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
@@ -104,7 +102,10 @@
mFocusIndicatorHelper = new ViewGroupFocusHelper(this);
}
- public void setup(DragController dragController, Workspace workspace) {
+ /**
+ * Set up the drag layer with the parameters.
+ */
+ public void setup(DragController dragController, Workspace<?> workspace) {
mDragController = dragController;
recreateControllers();
mWorkspaceDragScrim = new Scrim(this);
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index c37613f..0264ae2 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -21,6 +21,7 @@
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;
import android.animation.Animator;
@@ -31,9 +32,9 @@
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.TargetApi;
import android.content.Context;
-import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.ColorFilter;
import android.graphics.Path;
import android.graphics.Picture;
import android.graphics.Point;
@@ -97,6 +98,7 @@
final ValueAnimator mAnim;
// Whether mAnim has started. Unlike mAnim.isStarted(), this is true even after mAnim ends.
private boolean mAnimStarted;
+ private Runnable mOnAnimEndCallback = null;
private int mLastTouchX;
private int mLastTouchY;
@@ -179,6 +181,14 @@
public void onAnimationStart(Animator animation) {
mAnimStarted = true;
}
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ if (mOnAnimEndCallback != null) {
+ mOnAnimEndCallback.run();
+ }
+ }
});
setDragRegion(new Rect(0, 0, width, height));
@@ -198,6 +208,10 @@
setWillNotDraw(false);
}
+ public void setOnAnimationEndCallback(Runnable callback) {
+ mOnAnimEndCallback = callback;
+ }
+
/**
* Initialize {@code #mIconDrawable} if the item can be represented using
* an {@link AdaptiveIconDrawable} or {@link FolderAdaptiveIcon}.
@@ -215,7 +229,8 @@
Object[] outObj = new Object[1];
int w = mWidth;
int h = mHeight;
- Drawable dr = Utilities.getFullDrawable(mActivity, info, w, h, outObj);
+ Drawable dr = Utilities.getFullDrawable(mActivity, info, w, h,
+ true /* shouldThemeIcon */, outObj);
if (dr instanceof AdaptiveIconDrawable) {
int blurMargin = (int) mActivity.getResources()
@@ -225,9 +240,8 @@
bounds.inset(blurMargin, blurMargin);
// Badge is applied after icon normalization so the bounds for badge should not
// be scaled down due to icon normalization.
- Rect badgeBounds = new Rect(bounds);
mBadge = getBadge(mActivity, info, outObj[0]);
- mBadge.setBounds(badgeBounds);
+ FastBitmapDrawable.setBadgeBounds(mBadge, bounds);
// Do not draw the background in case of folder as its translucent
final boolean shouldDrawBackground = !(dr instanceof FolderAdaptiveIcon);
@@ -280,11 +294,10 @@
removeAllViewsInLayout();
if (info.isDisabled()) {
- FastBitmapDrawable d = new FastBitmapDrawable((Bitmap) null);
- d.setIsDisabled(true);
- mBgSpringDrawable.setColorFilter(d.getColorFilter());
- mFgSpringDrawable.setColorFilter(d.getColorFilter());
- mBadge.setColorFilter(d.getColorFilter());
+ ColorFilter filter = getDisabledColorFilter();
+ mBgSpringDrawable.setColorFilter(filter);
+ mFgSpringDrawable.setColorFilter(filter);
+ mBadge.setColorFilter(filter);
}
invalidate();
}));
diff --git a/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java b/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java
index 74d9a22..6f295e6 100644
--- a/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java
+++ b/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java
@@ -20,9 +20,13 @@
import android.annotation.TargetApi;
import android.graphics.Bitmap;
-import android.graphics.Matrix;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
+import android.graphics.Path.Direction;
+import android.graphics.Picture;
+import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.AdaptiveIconDrawable;
@@ -31,10 +35,11 @@
import android.util.Log;
import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+import com.android.launcher3.Utilities;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.folder.PreviewBackground;
-import com.android.launcher3.graphics.ShiftedBitmapDrawable;
import com.android.launcher3.icons.BitmapRenderer;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.views.ActivityContext;
@@ -69,79 +74,104 @@
return mBadge;
}
+ @TargetApi(Build.VERSION_CODES.P)
public static @Nullable FolderAdaptiveIcon createFolderAdaptiveIcon(
- ActivityContext activity, int folderId, Point dragViewSize) {
+ ActivityContext activity, int folderId, Point size) {
Preconditions.assertNonUiThread();
+ if (!Utilities.ATLEAST_P) {
+ return null;
+ }
- // Create the actual drawable on the UI thread to avoid race conditions with
+ // assume square
+ if (size.x != size.y) {
+ return null;
+ }
+ int requestedSize = size.x;
+
+ // Only use the size actually needed for drawing the folder icon
+ int drawingSize = activity.getDeviceProfile().folderIconSizePx;
+ int foregroundSize = Math.max(requestedSize, drawingSize);
+ float shift = foregroundSize - requestedSize;
+
+ Picture background = new Picture();
+ Picture foreground = new Picture();
+ Picture badge = new Picture();
+
+ Canvas bgCanvas = background.beginRecording(requestedSize, requestedSize);
+ Canvas badgeCanvas = badge.beginRecording(requestedSize, requestedSize);
+
+ Canvas fgCanvas = foreground.beginRecording(foregroundSize, foregroundSize);
+ fgCanvas.translate(shift, shift);
+
+ // Do not clip the folder drawing since the icon previews extend outside the background.
+ Path mask = new Path();
+ mask.addRect(-shift, -shift, requestedSize + shift, requestedSize + shift,
+ Direction.CCW);
+
+ // Initialize the actual draw commands on the UI thread to avoid race conditions with
// FolderIcon draw pass
try {
- return MAIN_EXECUTOR.submit(() -> {
+ MAIN_EXECUTOR.submit(() -> {
FolderIcon icon = activity.findFolderIcon(folderId);
- return icon == null ? null : createDrawableOnUiThread(icon, dragViewSize);
-
+ if (icon == null) {
+ throw new IllegalArgumentException("Folder not found with id: " + folderId);
+ }
+ initLayersOnUiThread(icon, requestedSize, bgCanvas, fgCanvas, badgeCanvas);
}).get();
} catch (Exception e) {
Log.e(TAG, "Unable to create folder icon", e);
return null;
+ } finally {
+ background.endRecording();
+ foreground.endRecording();
+ badge.endRecording();
}
+
+ // Only convert foreground to a bitmap as it can contain multiple draw commands. Other
+ // layers either draw a nothing or a single draw call.
+ Bitmap fgBitmap = Bitmap.createBitmap(foreground);
+ Paint foregroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+
+ // Do not use PictureDrawable as it moves the picture to the canvas bounds, whereas we want
+ // to draw it at (0,0)
+ return new FolderAdaptiveIcon(
+ new BitmapRendererDrawable(c -> c.drawPicture(background)),
+ new BitmapRendererDrawable(
+ c -> c.drawBitmap(fgBitmap, -shift, -shift, foregroundPaint)),
+ new BitmapRendererDrawable(c -> c.drawPicture(badge)),
+ mask);
}
- private static FolderAdaptiveIcon createDrawableOnUiThread(FolderIcon icon,
- Point dragViewSize) {
- Preconditions.assertUIThread();
-
+ @UiThread
+ private static void initLayersOnUiThread(FolderIcon icon, int size,
+ Canvas backgroundCanvas, Canvas foregroundCanvas, Canvas badgeCanvas) {
icon.getPreviewBounds(sTmpRect);
-
- PreviewBackground bg = icon.getFolderBackground();
-
- // assume square
- assert (dragViewSize.x == dragViewSize.y);
final int previewSize = sTmpRect.width();
- final int margin = (dragViewSize.x - previewSize) / 2;
+ PreviewBackground bg = icon.getFolderBackground();
+ final int margin = (size - previewSize) / 2;
final float previewShiftX = -sTmpRect.left + margin;
final float previewShiftY = -sTmpRect.top + margin;
// Initialize badge, which consists of the outline stroke, shadow and dot; these
// must be rendered above the foreground
- Bitmap badgeBmp = BitmapRenderer.createHardwareBitmap(dragViewSize.x, dragViewSize.y,
- (canvas) -> {
- canvas.save();
- canvas.translate(previewShiftX, previewShiftY);
- bg.drawShadow(canvas);
- bg.drawBackgroundStroke(canvas);
- icon.drawDot(canvas);
- canvas.restore();
- });
+ badgeCanvas.save();
+ badgeCanvas.translate(previewShiftX, previewShiftY);
+ icon.drawDot(badgeCanvas);
+ badgeCanvas.restore();
- // Initialize mask
- Path mask = new Path();
- Matrix m = new Matrix();
- m.setTranslate(previewShiftX, previewShiftY);
- bg.getClipPath().transform(m, mask);
+ // Draw foreground
+ foregroundCanvas.save();
+ foregroundCanvas.translate(previewShiftX, previewShiftY);
+ icon.getPreviewItemManager().draw(foregroundCanvas);
+ foregroundCanvas.restore();
- Bitmap previewBitmap = BitmapRenderer.createHardwareBitmap(dragViewSize.x, dragViewSize.y,
- (canvas) -> {
- canvas.save();
- canvas.translate(previewShiftX, previewShiftY);
- icon.getPreviewItemManager().draw(canvas);
- canvas.restore();
- });
-
- Bitmap bgBitmap = BitmapRenderer.createHardwareBitmap(dragViewSize.x, dragViewSize.y,
- (canvas) -> {
- Paint p = new Paint();
- p.setColor(bg.getBgColor());
-
- canvas.drawCircle(dragViewSize.x / 2f, dragViewSize.y / 2f, bg.getRadius(), p);
- });
-
- ShiftedBitmapDrawable badge = new ShiftedBitmapDrawable(badgeBmp, 0, 0);
- ShiftedBitmapDrawable foreground = new ShiftedBitmapDrawable(previewBitmap, 0, 0);
- ShiftedBitmapDrawable background = new ShiftedBitmapDrawable(bgBitmap, 0, 0);
-
- return new FolderAdaptiveIcon(background, foreground, badge, mask);
+ // Draw background
+ Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ backgroundPaint.setColor(bg.getBgColor());
+ bg.drawShadow(backgroundCanvas);
+ backgroundCanvas.drawCircle(size / 2f, size / 2f, bg.getRadius(), backgroundPaint);
+ bg.drawBackgroundStroke(backgroundCanvas);
}
@Override
@@ -174,4 +204,52 @@
& mBadge.getChangingConfigurations();
}
}
+
+ private static class BitmapRendererDrawable extends Drawable {
+
+ private final BitmapRenderer mRenderer;
+
+ BitmapRendererDrawable(BitmapRenderer renderer) {
+ mRenderer = renderer;
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ mRenderer.draw(canvas);
+ }
+
+ @Override
+ public void setAlpha(int i) { }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) { }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public ConstantState getConstantState() {
+ return new MyConstantState(mRenderer);
+ }
+
+ private static class MyConstantState extends ConstantState {
+ private final BitmapRenderer mRenderer;
+
+ MyConstantState(BitmapRenderer renderer) {
+ mRenderer = renderer;
+ }
+
+ @Override
+ public Drawable newDrawable() {
+ return new BitmapRendererDrawable(mRenderer);
+ }
+
+ @Override
+ public int getChangingConfigurations() {
+ return 0;
+ }
+ }
+ }
}
diff --git a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
index 29e7c18..f9916d0 100644
--- a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
+++ b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
@@ -87,7 +87,8 @@
// Total duration for the drop animation to complete.
long duration = mContext.getResources().getInteger(R.integer.config_dropAnimMaxDuration) +
LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY +
- LauncherState.SPRING_LOADED.getTransitionDuration(Launcher.getLauncher(mContext));
+ LauncherState.SPRING_LOADED.getTransitionDuration(Launcher.getLauncher(mContext),
+ true /* isToState */);
// Delay the actual accept() call until the drop animation is complete.
return PinRequestHelper.createWorkspaceItemFromPinItemRequest(
mContext, mRequest, duration);
diff --git a/src/com/android/launcher3/dragndrop/SpringLoadedDragController.java b/src/com/android/launcher3/dragndrop/SpringLoadedDragController.java
index 6325877..fb8a1bc 100644
--- a/src/com/android/launcher3/dragndrop/SpringLoadedDragController.java
+++ b/src/com/android/launcher3/dragndrop/SpringLoadedDragController.java
@@ -55,7 +55,7 @@
public void onAlarm(Alarm alarm) {
if (mScreen != null) {
// Snap to the screen that we are hovering over now
- Workspace w = mLauncher.getWorkspace();
+ Workspace<?> w = mLauncher.getWorkspace();
if (!w.isVisible(mScreen)) {
w.snapToPage(w.indexOfChild(mScreen));
}
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index daef682..e68ebdb 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -24,7 +24,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.util.DisplayController.getSingleFrameMs;
+import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -57,6 +57,7 @@
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
+import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
@@ -71,7 +72,6 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.OnAlarmListener;
-import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.Utilities;
@@ -87,10 +87,10 @@
import com.android.launcher3.logger.LauncherAtom.ToState;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
-import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.FolderInfo.FolderListener;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemFactory;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pageindicators.PageIndicatorDots;
import com.android.launcher3.util.Executors;
@@ -101,6 +101,8 @@
import com.android.launcher3.views.ClipPathView;
import com.android.launcher3.widget.PendingAddShortcutInfo;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -130,16 +132,19 @@
*/
private static final int MIN_CONTENT_DIMEN = 5;
- static final int STATE_NONE = -1;
- static final int STATE_SMALL = 0;
- static final int STATE_ANIMATING = 1;
- static final int STATE_OPEN = 2;
+ public static final int STATE_CLOSED = 0;
+ public static final int STATE_ANIMATING = 1;
+ public static final int STATE_OPEN = 2;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({STATE_CLOSED, STATE_ANIMATING, STATE_OPEN})
+ public @interface FolderState {}
/**
* Time for which the scroll hint is shown before automatically changing page.
*/
public static final int SCROLL_HINT_DURATION = 500;
- public static final int RESCROLL_DELAY = PagedView.PAGE_SNAP_ANIMATION_DURATION + 150;
+ private static final int RESCROLL_EXTRA_DELAY = 150;
public static final int SCROLL_NONE = -1;
public static final int SCROLL_LEFT = 0;
@@ -198,13 +203,12 @@
@ViewDebug.ExportedProperty(category = "launcher",
mapping = {
- @ViewDebug.IntToString(from = STATE_NONE, to = "STATE_NONE"),
- @ViewDebug.IntToString(from = STATE_SMALL, to = "STATE_SMALL"),
+ @ViewDebug.IntToString(from = STATE_CLOSED, to = "STATE_CLOSED"),
@ViewDebug.IntToString(from = STATE_ANIMATING, to = "STATE_ANIMATING"),
@ViewDebug.IntToString(from = STATE_OPEN, to = "STATE_OPEN"),
})
- @Thunk
- int mState = STATE_NONE;
+ private int mState = STATE_CLOSED;
+ private OnFolderStateChangedListener mOnFolderStateChangedListener;
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mRearrangeOnClose = false;
boolean mItemsInvalidated = false;
@@ -277,19 +281,15 @@
mPageIndicator = findViewById(R.id.folder_page_indicator);
mFolderName = findViewById(R.id.folder_name);
mFolderName.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp.folderLabelTextSizePx);
- if (mActivityContext.supportsIme()) {
- mFolderName.setOnBackKeyListener(this);
- mFolderName.setOnFocusChangeListener(this);
- mFolderName.setOnEditorActionListener(this);
- mFolderName.setSelectAllOnFocus(true);
- mFolderName.setInputType(mFolderName.getInputType()
- & ~InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
- | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
- | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
- mFolderName.forceDisableSuggestions(true);
- } else {
- mFolderName.setEnabled(false);
- }
+ mFolderName.setOnBackKeyListener(this);
+ mFolderName.setOnFocusChangeListener(this);
+ mFolderName.setOnEditorActionListener(this);
+ mFolderName.setSelectAllOnFocus(true);
+ mFolderName.setInputType(mFolderName.getInputType()
+ & ~InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
+ | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
+ | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
+ mFolderName.forceDisableSuggestions(true);
mFooter = findViewById(R.id.folder_footer);
mFooterHeight = getResources().getDimensionPixelSize(R.dimen.folder_label_height);
@@ -561,7 +561,7 @@
a.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
- mState = STATE_ANIMATING;
+ setState(STATE_ANIMATING);
mCurrentAnimator = a;
}
@@ -686,7 +686,7 @@
@Override
public void onAnimationEnd(Animator animation) {
- mState = STATE_OPEN;
+ setState(STATE_OPEN);
announceAccessibilityChanges();
AccessibilityManagerCompat.sendFolderOpenedEventToTest(getContext());
@@ -862,7 +862,7 @@
}
mSuppressFolderDeletion = false;
clearDragInfo();
- mState = STATE_SMALL;
+ setState(STATE_CLOSED);
mContent.setCurrentPage(0);
}
@@ -1282,9 +1282,9 @@
final WorkspaceItemInfo si;
if (pasiSi != null) {
si = pasiSi;
- } else if (d.dragInfo instanceof AppInfo) {
+ } else if (d.dragInfo instanceof WorkspaceItemFactory) {
// Came from all apps -- make a copy.
- si = ((AppInfo) d.dragInfo).makeWorkspaceItem();
+ si = ((WorkspaceItemFactory) d.dragInfo).makeWorkspaceItem(launcher);
} else {
// WorkspaceItemInfo
si = (WorkspaceItemInfo) d.dragInfo;
@@ -1522,7 +1522,9 @@
// Pause drag event until the scrolling is finished
mScrollPauseAlarm.setOnAlarmListener(new OnScrollFinishedListener(mDragObject));
- mScrollPauseAlarm.setAlarm(RESCROLL_DELAY);
+ int rescrollDelay = getResources().getInteger(
+ R.integer.config_pageSnapAnimationDuration) + RESCROLL_EXTRA_DELAY;
+ mScrollPauseAlarm.setAlarm(rescrollDelay);
}
}
@@ -1655,4 +1657,21 @@
return windowBottomPx - folderBottomPx;
}
+
+ private void setState(@FolderState int newState) {
+ mState = newState;
+ if (mOnFolderStateChangedListener != null) {
+ mOnFolderStateChangedListener.onFolderStateChanged(mState);
+ }
+ }
+
+ public void setOnFolderStateChangedListener(@Nullable OnFolderStateChangedListener listener) {
+ mOnFolderStateChangedListener = listener;
+ }
+
+ /** Listener that can be registered via {@link Folder#setOnFolderStateChangedListener} */
+ public interface OnFolderStateChangedListener {
+ /** See {@link Folder.FolderState} */
+ void onFolderStateChanged(@FolderState int newState);
+ }
}
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 98be72a..b1e2701 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -55,7 +55,7 @@
import com.android.launcher3.Reorderable;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dot.FolderDotInfo;
@@ -68,11 +68,11 @@
import com.android.launcher3.logger.LauncherAtom.ToState;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.StatsLogManager;
-import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.FolderInfo.FolderListener;
import com.android.launcher3.model.data.FolderInfo.LabelState;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemFactory;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.Executors;
@@ -284,7 +284,7 @@
mBackground.animateToAccept(cl, lp.cellX, lp.cellY);
mOpenAlarm.setOnAlarmListener(mOnOpenListener);
if (SPRING_LOADING_ENABLED &&
- ((dragInfo instanceof AppInfo)
+ ((dragInfo instanceof WorkspaceItemFactory)
|| (dragInfo instanceof WorkspaceItemInfo)
|| (dragInfo instanceof PendingAddShortcutInfo))) {
mOpenAlarm.setAlarm(ON_OPEN_DELAY);
@@ -342,7 +342,7 @@
Rect to = finalRect;
if (to == null) {
to = new Rect();
- Workspace workspace = launcher.getWorkspace();
+ Workspace<?> workspace = launcher.getWorkspace();
// Set cellLayout and this to it's final state to compute final animation locations
workspace.setFinalTransitionTransform();
float scaleX = getScaleX();
@@ -397,7 +397,7 @@
float finalScale = scale * scaleRelativeToDragLayer;
// Account for potentially different icon sizes with non-default grid settings
- if (d.dragSource instanceof AllAppsContainerView) {
+ if (d.dragSource instanceof ActivityAllAppsContainerView) {
DeviceProfile grid = mActivity.getDeviceProfile();
float containerScale = (1f * grid.iconSizePx / grid.allAppsIconSizePx);
finalScale *= containerScale;
@@ -486,9 +486,9 @@
public void onDrop(DragObject d, boolean itemReturnedOnFailedDrop) {
WorkspaceItemInfo item;
- if (d.dragInfo instanceof AppInfo) {
+ if (d.dragInfo instanceof WorkspaceItemFactory) {
// Came from all apps -- make a copy
- item = ((AppInfo) d.dragInfo).makeWorkspaceItem();
+ item = ((WorkspaceItemFactory) d.dragInfo).makeWorkspaceItem(getContext());
} else if (d.dragSource instanceof BaseItemDragListener){
// Came from a different window -- make a copy
item = new WorkspaceItemInfo((WorkspaceItemInfo) d.dragInfo);
@@ -637,7 +637,7 @@
// If we are animating to the accepting state, animate the dot out.
mDotParams.scale = Math.max(0, mDotScale - mBackground.getScaleProgress());
- mDotParams.color = mBackground.getDotColor();
+ mDotParams.dotColor = mBackground.getDotColor();
mDotRenderer.draw(canvas, mDotParams);
}
}
diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java
index 9c1b24d..5021644 100644
--- a/src/com/android/launcher3/folder/FolderNameProvider.java
+++ b/src/com/android/launcher3/folder/FolderNameProvider.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.folder;
+import android.annotation.SuppressLint;
+import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.os.Process;
@@ -22,11 +24,15 @@
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.WorkerThread;
+
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.model.AllAppsList;
import com.android.launcher3.model.BaseModelUpdateTask;
import com.android.launcher3.model.BgDataModel;
+import com.android.launcher3.model.StringCache;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -94,6 +100,7 @@
/**
* Generate and rank the suggested Folder names.
*/
+ @WorkerThread
public void getSuggestedFolderName(Context context,
ArrayList<WorkspaceItemInfo> workspaceItemInfos,
FolderNameInfos nameInfos) {
@@ -101,13 +108,13 @@
if (DEBUG) {
Log.d(TAG, "getSuggestedFolderName:" + nameInfos.toString());
}
+
// If all the icons are from work profile,
// Then, suggest "Work" as the folder name
Set<UserHandle> users = workspaceItemInfos.stream().map(w -> w.user)
.collect(Collectors.toSet());
if (users.size() == 1 && !users.contains(Process.myUserHandle())) {
- setAsLastSuggestion(nameInfos,
- context.getResources().getString(R.string.work_folder_name));
+ setAsLastSuggestion(nameInfos, getWorkFolderName(context));
}
// If all the icons are from same package (e.g., main icon, shortcut, shortcut)
@@ -121,13 +128,25 @@
if (packageNames.size() == 1) {
Optional<AppInfo> info = getAppInfoByPackageName(packageNames.iterator().next());
// Place it as first viable suggestion and shift everything else
- info.ifPresent(i -> setAsFirstSuggestion(nameInfos, i.title.toString()));
+ info.ifPresent(i -> setAsFirstSuggestion(
+ nameInfos, i.title == null ? "" : i.title.toString()));
}
if (DEBUG) {
Log.d(TAG, "getSuggestedFolderName:" + nameInfos.toString());
}
}
+ @WorkerThread
+ @SuppressLint("NewApi")
+ private String getWorkFolderName(Context context) {
+ if (!Utilities.ATLEAST_T) {
+ return context.getString(R.string.work_folder_name);
+ }
+ return context.getSystemService(DevicePolicyManager.class).getResources()
+ .getString(StringCache.WORK_FOLDER_NAME, () ->
+ context.getString(R.string.work_folder_name));
+ }
+
private Optional<AppInfo> getAppInfoByPackageName(String packageName) {
if (mAppInfos == null || mAppInfos.isEmpty()) {
return Optional.empty();
diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java
index 65991e4..3d5aef5 100644
--- a/src/com/android/launcher3/folder/FolderPagedView.java
+++ b/src/com/android/launcher3/folder/FolderPagedView.java
@@ -252,7 +252,7 @@
}
@Override
- protected int getChildGap() {
+ protected int getChildGap(int fromIndex, int toIndex) {
return getPaddingLeft() + getPaddingRight();
}
diff --git a/src/com/android/launcher3/folder/LauncherDelegate.java b/src/com/android/launcher3/folder/LauncherDelegate.java
index c5b3913..1f0a011 100644
--- a/src/com/android/launcher3/folder/LauncherDelegate.java
+++ b/src/com/android/launcher3/folder/LauncherDelegate.java
@@ -100,7 +100,8 @@
}
// Remove the folder
- mLauncher.removeItem(folder.mFolderIcon, info, true /* deleteFromDb */);
+ mLauncher.removeItem(folder.mFolderIcon, info, true /* deleteFromDb */,
+ "folder removed because there's only 1 item in it");
if (folder.mFolderIcon instanceof DropTarget) {
folder.mDragController.removeDropTarget((DropTarget) folder.mFolderIcon);
}
diff --git a/src/com/android/launcher3/folder/PreviewItemManager.java b/src/com/android/launcher3/folder/PreviewItemManager.java
index 8bef6ad..6355b62 100644
--- a/src/com/android/launcher3/folder/PreviewItemManager.java
+++ b/src/com/android/launcher3/folder/PreviewItemManager.java
@@ -21,6 +21,7 @@
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
import static com.android.launcher3.folder.FolderIcon.DROP_IN_ANIMATION_DURATION;
import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
+import static com.android.launcher3.icons.BitmapInfo.FLAG_THEMED;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -429,7 +430,7 @@
drawable.setLevel(item.getProgressLevel());
p.drawable = drawable;
} else {
- p.drawable = item.newIcon(mContext, true);
+ p.drawable = item.newIcon(mContext, FLAG_THEMED);
}
p.drawable.setBounds(0, 0, mIconSize, mIconSize);
p.item = item;
diff --git a/src/com/android/launcher3/graphics/IconPalette.java b/src/com/android/launcher3/graphics/IconPalette.java
index 3d4a100..778b32a 100644
--- a/src/com/android/launcher3/graphics/IconPalette.java
+++ b/src/com/android/launcher3/graphics/IconPalette.java
@@ -16,18 +16,16 @@
package com.android.launcher3.graphics;
-import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
-
import android.app.Notification;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
+import androidx.core.graphics.ColorUtils;
+
import com.android.launcher3.R;
import com.android.launcher3.util.Themes;
-import androidx.core.graphics.ColorUtils;
-
/**
* Contains colors based on the dominant color of an icon.
*/
@@ -147,9 +145,4 @@
}
return ColorUtils.LABToColor(low, a, b);
}
-
- public static int getMutedColor(int color, float whiteScrimAlpha) {
- int whiteScrim = setColorAlphaBound(Color.WHITE, (int) (255 * whiteScrimAlpha));
- return ColorUtils.compositeColors(whiteScrim, color);
- }
}
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 73e18f4..d5bcb0c 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -23,7 +23,6 @@
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems;
import static com.android.launcher3.model.ModelUtils.getMissingHotseatRanks;
-import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially;
import android.annotation.TargetApi;
import android.app.Fragment;
@@ -43,7 +42,6 @@
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
-import android.os.Process;
import android.util.AttributeSet;
import android.util.SparseIntArray;
import android.view.ContextThemeWrapper;
@@ -85,9 +83,11 @@
import com.android.launcher3.uioverrides.PredictedAppIconInflater;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
+import com.android.launcher3.util.window.WindowManagerProxy;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
import com.android.launcher3.widget.BaseLauncherAppWidgetHostView;
@@ -112,7 +112,7 @@
* 3) Place appropriate elements like icons and first-page qsb
* 4) Measure and draw the view on a canvas
*/
-@TargetApi(Build.VERSION_CODES.O)
+@TargetApi(Build.VERSION_CODES.R)
public class LauncherPreviewRenderer extends ContextWrapper
implements ActivityContext, WorkspaceLayoutManager, LayoutInflater.Factory2 {
@@ -129,28 +129,31 @@
public PreviewContext(Context base, InvariantDeviceProfile idp) {
super(base, UserCache.INSTANCE, InstallSessionHelper.INSTANCE,
LauncherAppState.INSTANCE, InvariantDeviceProfile.INSTANCE,
- CustomWidgetManager.INSTANCE, PluginManagerWrapper.INSTANCE);
+ CustomWidgetManager.INSTANCE, PluginManagerWrapper.INSTANCE,
+ WindowManagerProxy.INSTANCE, DisplayController.INSTANCE);
mIdp = idp;
mObjectMap.put(InvariantDeviceProfile.INSTANCE, idp);
mObjectMap.put(LauncherAppState.INSTANCE,
new LauncherAppState(this, null /* iconCacheFileName */));
-
}
- public LauncherIcons newLauncherIcons(Context context, boolean shapeDetection) {
+ /**
+ * Creates a new LauncherIcons for the preview, skipping the global pool
+ */
+ public LauncherIcons newLauncherIcons(Context context) {
LauncherIconsForPreview launcherIconsForPreview = mIconPool.poll();
if (launcherIconsForPreview != null) {
return launcherIconsForPreview;
}
return new LauncherIconsForPreview(context, mIdp.fillResIconDpi, mIdp.iconBitmapSize,
- -1 /* poolId */, shapeDetection);
+ -1 /* poolId */);
}
private final class LauncherIconsForPreview extends LauncherIcons {
private LauncherIconsForPreview(Context context, int fillResIconDpi, int iconBitmapSize,
- int poolId, boolean shapeDetection) {
- super(context, fillResIconDpi, iconBitmapSize, poolId, shapeDetection);
+ int poolId) {
+ super(context, fillResIconDpi, iconBitmapSize, poolId);
}
@Override
@@ -185,27 +188,21 @@
mIdp = idp;
mDp = idp.getDeviceProfile(context).copy(context);
- if (Utilities.ATLEAST_R) {
- WindowInsets currentWindowInsets = context.getSystemService(WindowManager.class)
- .getCurrentWindowMetrics().getWindowInsets();
- mInsets = new Rect(
- currentWindowInsets.getSystemWindowInsetLeft(),
- currentWindowInsets.getSystemWindowInsetTop(),
- currentWindowInsets.getSystemWindowInsetRight(),
- currentWindowInsets.getSystemWindowInsetBottom());
- } else {
- mInsets = new Rect();
- mInsets.left = mInsets.right = (mDp.widthPx - mDp.availableWidthPx) / 2;
- mInsets.top = mInsets.bottom = (mDp.heightPx - mDp.availableHeightPx) / 2;
- }
+ WindowInsets currentWindowInsets = context.getSystemService(WindowManager.class)
+ .getCurrentWindowMetrics().getWindowInsets();
+ mInsets = new Rect(
+ currentWindowInsets.getSystemWindowInsetLeft(),
+ currentWindowInsets.getSystemWindowInsetTop(),
+ currentWindowInsets.getSystemWindowInsetRight(),
+ mDp.isTaskbarPresent ? 0 : currentWindowInsets.getSystemWindowInsetBottom());
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)),
- Process.myUserHandle(),
- Build.VERSION.SDK_INT);
+ BitmapInfo iconInfo = iconFactory.createBadgedIconBitmap(
+ new AdaptiveIconDrawable(
+ new ColorDrawable(Color.WHITE),
+ new ColorDrawable(Color.WHITE)));
mWorkspaceItemInfo = new WorkspaceItemInfo();
mWorkspaceItemInfo.bitmap = iconInfo;
@@ -228,21 +225,21 @@
mHotseat.resetLayout(false);
CellLayout firstScreen = mRootView.findViewById(R.id.workspace);
- firstScreen.setPadding(mDp.workspacePadding.left + mDp.cellLayoutPaddingLeftRightPx,
- mDp.workspacePadding.top,
+ firstScreen.setPadding(mDp.workspacePadding.left + mDp.cellLayoutPaddingPx.left,
+ mDp.workspacePadding.top + mDp.cellLayoutPaddingPx.top,
(mDp.isTwoPanels ? mDp.cellLayoutBorderSpacePx.x / 2
- : mDp.workspacePadding.right) + mDp.cellLayoutPaddingLeftRightPx,
- mDp.workspacePadding.bottom
+ : mDp.workspacePadding.right) + mDp.cellLayoutPaddingPx.right,
+ mDp.workspacePadding.bottom + mDp.cellLayoutPaddingPx.bottom
);
mWorkspaceScreens.put(FIRST_SCREEN_ID, firstScreen);
if (mDp.isTwoPanels) {
CellLayout rightPanel = mRootView.findViewById(R.id.workspace_right);
rightPanel.setPadding(
- mDp.cellLayoutBorderSpacePx.x / 2 + mDp.cellLayoutPaddingLeftRightPx,
- mDp.workspacePadding.top,
- mDp.workspacePadding.right + mDp.cellLayoutPaddingLeftRightPx,
- mDp.workspacePadding.bottom
+ mDp.cellLayoutBorderSpacePx.x / 2 + mDp.cellLayoutPaddingPx.left,
+ mDp.workspacePadding.top + mDp.cellLayoutPaddingPx.top,
+ mDp.workspacePadding.right + mDp.cellLayoutPaddingPx.right,
+ mDp.workspacePadding.bottom + mDp.cellLayoutPaddingPx.bottom
);
mWorkspaceScreens.put(Workspace.SECOND_SCREEN_ID, rightPanel);
}
@@ -423,8 +420,6 @@
currentWorkspaceItems, otherWorkspaceItems);
filterCurrentWorkspaceItems(currentScreenIds, dataModel.appWidgets, currentAppWidgets,
otherAppWidgets);
-
- sortWorkspaceItemsSpatially(mIdp, currentWorkspaceItems);
for (ItemInfo itemInfo : currentWorkspaceItems) {
switch (itemInfo.itemType) {
case Favorites.ITEM_TYPE_APPLICATION:
@@ -457,10 +452,10 @@
}
IntArray ranks = getMissingHotseatRanks(currentWorkspaceItems,
mDp.numShownHotseatIcons);
- FixedContainerItems hotseatpredictions =
+ FixedContainerItems hotseatPredictions =
dataModel.extraItems.get(CONTAINER_HOTSEAT_PREDICTION);
- List<ItemInfo> predictions = hotseatpredictions == null
- ? Collections.emptyList() : hotseatpredictions.items;
+ List<ItemInfo> predictions = hotseatPredictions == null
+ ? Collections.emptyList() : hotseatPredictions.items;
int count = Math.min(ranks.size(), predictions.size());
for (int i = 0; i < count; i++) {
int rank = ranks.get(i);
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index 24d6fe5..d2e4c51 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -345,11 +345,10 @@
}
@Override
- public ConstantState getConstantState() {
+ public FastBitmapConstantState newConstantState() {
return new PreloadIconConstantState(
mBitmap,
mIconColor,
- !mItem.isAppStartable(),
mItem,
mIndicatorColor,
new int[] {mSystemAccentColor, mSystemBackgroundColor},
@@ -367,12 +366,11 @@
public PreloadIconConstantState(
Bitmap bitmap,
int iconColor,
- boolean isDisabled,
ItemInfoWithIcon info,
int indicatorColor,
int[] preloadColors,
boolean isDarkMode) {
- super(bitmap, iconColor, isDisabled);
+ super(bitmap, iconColor);
mInfo = info;
mIndicatorColor = indicatorColor;
mPreloadColors = preloadColors;
@@ -381,17 +379,12 @@
}
@Override
- public PreloadIconDrawable newDrawable() {
+ public PreloadIconDrawable createDrawable() {
return new PreloadIconDrawable(
mInfo,
mIndicatorColor,
mPreloadColors,
mIsDarkMode);
}
-
- @Override
- public int getChangingConfigurations() {
- return 0;
- }
}
}
diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
index 2f3d5d8..fd11b37 100644
--- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
+++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
@@ -47,7 +47,6 @@
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.GridSizeMigrationTaskV2;
import com.android.launcher3.model.LoaderTask;
-import com.android.launcher3.model.ModelDelegate;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.Themes;
@@ -156,9 +155,10 @@
PreviewContext previewContext = new PreviewContext(inflationContext, mIdp);
new LoaderTask(
LauncherAppState.getInstance(previewContext),
- null,
+ /* bgAllAppsList= */ null,
new BgDataModel(),
- new ModelDelegate(), null) {
+ LauncherAppState.getInstance(previewContext).getModel().getModelDelegate(),
+ /* results= */ null) {
@Override
public void run() {
diff --git a/src/com/android/launcher3/graphics/ShiftedBitmapDrawable.java b/src/com/android/launcher3/graphics/ShiftedBitmapDrawable.java
deleted file mode 100644
index f8583b8..0000000
--- a/src/com/android/launcher3/graphics/ShiftedBitmapDrawable.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.graphics;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.Drawable;
-
-/**
- * A simple drawable which draws a bitmap at a fixed position irrespective of the bounds
- */
-public class ShiftedBitmapDrawable extends Drawable {
-
- private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
- private final Bitmap mBitmap;
- private float mShiftX;
- private float mShiftY;
-
- private final ConstantState mConstantState;
-
- public ShiftedBitmapDrawable(Bitmap bitmap, float shiftX, float shiftY) {
- mBitmap = bitmap;
- mShiftX = shiftX;
- mShiftY = shiftY;
-
- mConstantState = new MyConstantState(mBitmap, mShiftX, mShiftY);
- }
-
- public float getShiftX() {
- return mShiftX;
- }
-
- public float getShiftY() {
- return mShiftY;
- }
-
- public void setShiftX(float shiftX) {
- mShiftX = shiftX;
- }
-
- public void setShiftY(float shiftY) {
- mShiftY = shiftY;
- }
-
- @Override
- public void draw(Canvas canvas) {
- canvas.drawBitmap(mBitmap, mShiftX, mShiftY, mPaint);
- }
-
- @Override
- public void setAlpha(int i) { }
-
- @Override
- public void setColorFilter(ColorFilter colorFilter) {
- mPaint.setColorFilter(colorFilter);
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
-
- @Override
- public ConstantState getConstantState() {
- return mConstantState;
- }
-
- private static class MyConstantState extends ConstantState {
- private final Bitmap mBitmap;
- private float mShiftX;
- private float mShiftY;
-
- MyConstantState(Bitmap bitmap, float shiftX, float shiftY) {
- mBitmap = bitmap;
- mShiftX = shiftX;
- mShiftY = shiftY;
- }
-
- @Override
- public Drawable newDrawable() {
- return new ShiftedBitmapDrawable(mBitmap, mShiftX, mShiftY);
- }
-
- @Override
- public int getChangingConfigurations() {
- return 0;
- }
- }
-}
\ No newline at end of file
diff --git a/src/com/android/launcher3/icons/ComponentWithLabelAndIcon.java b/src/com/android/launcher3/icons/ComponentWithLabelAndIcon.java
index 248a57d..c8606b1 100644
--- a/src/com/android/launcher3/icons/ComponentWithLabelAndIcon.java
+++ b/src/com/android/launcher3/icons/ComponentWithLabelAndIcon.java
@@ -21,6 +21,7 @@
import androidx.annotation.NonNull;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.icons.BaseIconFactory.IconOptions;
/**
* Extension of ComponentWithLabel to also support loading icons
@@ -47,7 +48,7 @@
return super.loadIcon(context, object);
}
try (LauncherIcons li = LauncherIcons.obtain(context)) {
- return li.createBadgedIconBitmap(d, object.getUser(), 0);
+ return li.createBadgedIconBitmap(d, new IconOptions().setUser(object.getUser()));
}
}
}
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 936eeb9..fe9b633 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -16,6 +16,7 @@
package com.android.launcher3.icons;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.widget.WidgetSections.NO_CATEGORY;
@@ -41,9 +42,11 @@
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
-import android.util.Pair;
+import android.util.SparseArray;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.util.Pair;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherFiles;
@@ -93,6 +96,8 @@
private final InstantAppResolver mInstantAppResolver;
private final IconProvider mIconProvider;
+ private final SparseArray<BitmapInfo> mWidgetCategoryBitmapInfos;
+
private int mPendingIconRequestCount = 0;
public IconCache(Context context, InvariantDeviceProfile idp) {
@@ -110,6 +115,7 @@
mUserManager = UserCache.INSTANCE.get(mContext);
mInstantAppResolver = InstantAppResolver.newInstance(mContext);
mIconProvider = iconProvider;
+ mWidgetCategoryBitmapInfos = new SparseArray<>();
}
@Override
@@ -216,14 +222,7 @@
* Fill in {@param info} with the icon for {@param si}
*/
public void getShortcutIcon(ItemInfoWithIcon info, ShortcutInfo si) {
- getShortcutIcon(info, si, true, mIsUsingFallbackOrNonDefaultIconCheck);
- }
-
- /**
- * Fill in {@param info} with an unbadged icon for {@param si}
- */
- public void getUnbadgedShortcutIcon(ItemInfoWithIcon info, ShortcutInfo si) {
- getShortcutIcon(info, si, false, mIsUsingFallbackOrNonDefaultIconCheck);
+ getShortcutIcon(info, si, mIsUsingFallbackOrNonDefaultIconCheck);
}
/**
@@ -232,11 +231,6 @@
*/
public <T extends ItemInfoWithIcon> void getShortcutIcon(T info, ShortcutInfo si,
@NonNull Predicate<T> fallbackIconCheck) {
- getShortcutIcon(info, si, true /* use badged */, fallbackIconCheck);
- }
-
- private synchronized <T extends ItemInfoWithIcon> void getShortcutIcon(T info, ShortcutInfo si,
- boolean useBadged, @NonNull Predicate<T> fallbackIconCheck) {
BitmapInfo bitmapInfo;
if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) {
bitmapInfo = cacheLocked(ShortcutKey.fromInfo(si).componentName, si.getUserHandle(),
@@ -252,13 +246,7 @@
if (isDefaultIcon(bitmapInfo, si.getUserHandle()) && fallbackIconCheck.test(info)) {
return;
}
- info.bitmap = bitmapInfo;
- if (useBadged) {
- BitmapInfo badgeInfo = getShortcutInfoBadge(si);
- try (LauncherIcons li = LauncherIcons.obtain(mContext)) {
- info.bitmap = li.badgeBitmap(info.bitmap.icon, badgeInfo);
- }
- }
+ info.bitmap = bitmapInfo.withBadgeInfo(getShortcutInfoBadge(si));
}
/**
@@ -357,6 +345,17 @@
List<IconRequestInfo<T>> iconRequestInfos) {
Map<Pair<UserHandle, Boolean>, List<IconRequestInfo<T>>> iconLoadSubsectionsMap =
iconRequestInfos.stream()
+ .filter(iconRequest -> {
+ if (iconRequest.itemInfo.getTargetComponent() == null) {
+ Log.i(TAG,
+ "Skipping Item info with null component name: "
+ + iconRequest.itemInfo);
+ iconRequest.itemInfo.bitmap = getDefaultIcon(
+ iconRequest.itemInfo.user);
+ return false;
+ }
+ return true;
+ })
.collect(groupingBy(iconRequest ->
Pair.create(iconRequest.itemInfo.user, iconRequest.useLowResIcon)));
@@ -364,45 +363,116 @@
iconLoadSubsectionsMap.forEach((sectionKey, filteredList) -> {
Map<ComponentName, List<IconRequestInfo<T>>> duplicateIconRequestsMap =
filteredList.stream()
+ .filter(iconRequest -> {
+ // Filter out icons that should not share the same bitmap and title
+ if (iconRequest.itemInfo.itemType == ITEM_TYPE_DEEP_SHORTCUT) {
+ Log.e(TAG,
+ "Skipping Item info for deep shortcut: "
+ + iconRequest.itemInfo,
+ new IllegalStateException());
+ return false;
+ }
+ return true;
+ })
.collect(groupingBy(iconRequest ->
iconRequest.itemInfo.getTargetComponent()));
Trace.beginSection("loadIconSubsectionInBulk");
- try (Cursor c = createBulkQueryCursor(
- filteredList,
- /* user = */ sectionKey.first,
- /* useLowResIcons = */ sectionKey.second)) {
- int componentNameColumnIndex = c.getColumnIndexOrThrow(IconDB.COLUMN_COMPONENT);
- while (c.moveToNext()) {
- ComponentName cn = ComponentName.unflattenFromString(
- c.getString(componentNameColumnIndex));
- List<IconRequestInfo<T>> duplicateIconRequests =
- duplicateIconRequestsMap.get(cn);
-
- if (cn != null) {
- CacheEntry entry = cacheLocked(
- cn,
- /* user = */ sectionKey.first,
- () -> duplicateIconRequests.get(0).launcherActivityInfo,
- mLauncherActivityInfoCachingLogic,
- c,
- /* usePackageIcon= */ false,
- /* useLowResIcons = */ sectionKey.second);
-
- for (IconRequestInfo<T> iconRequest : duplicateIconRequests) {
- applyCacheEntry(entry, iconRequest.itemInfo);
- }
- }
- }
- } catch (SQLiteException e) {
- Log.d(TAG, "Error reading icon cache", e);
- } finally {
- Trace.endSection();
- }
+ loadIconSubsection(sectionKey, filteredList, duplicateIconRequestsMap);
+ Trace.endSection();
});
Trace.endSection();
}
+ private <T extends ItemInfoWithIcon> void loadIconSubsection(
+ Pair<UserHandle, Boolean> sectionKey,
+ List<IconRequestInfo<T>> filteredList,
+ Map<ComponentName, List<IconRequestInfo<T>>> duplicateIconRequestsMap) {
+ Trace.beginSection("loadIconSubsectionWithDatabase");
+ try (Cursor c = createBulkQueryCursor(
+ filteredList,
+ /* user = */ sectionKey.first,
+ /* useLowResIcons = */ sectionKey.second)) {
+ // Database title and icon loading
+ int componentNameColumnIndex = c.getColumnIndexOrThrow(IconDB.COLUMN_COMPONENT);
+ while (c.moveToNext()) {
+ ComponentName cn = ComponentName.unflattenFromString(
+ c.getString(componentNameColumnIndex));
+ List<IconRequestInfo<T>> duplicateIconRequests =
+ duplicateIconRequestsMap.get(cn);
+
+ if (cn != null) {
+ CacheEntry entry = cacheLocked(
+ cn,
+ /* user = */ sectionKey.first,
+ () -> duplicateIconRequests.get(0).launcherActivityInfo,
+ mLauncherActivityInfoCachingLogic,
+ c,
+ /* usePackageIcon= */ false,
+ /* useLowResIcons = */ sectionKey.second);
+
+ for (IconRequestInfo<T> iconRequest : duplicateIconRequests) {
+ applyCacheEntry(entry, iconRequest.itemInfo);
+ }
+ }
+ }
+ } catch (SQLiteException e) {
+ Log.d(TAG, "Error reading icon cache", e);
+ } finally {
+ Trace.endSection();
+ }
+
+ Trace.beginSection("loadIconSubsectionWithFallback");
+ // Fallback title and icon loading
+ for (ComponentName cn : duplicateIconRequestsMap.keySet()) {
+ IconRequestInfo<T> iconRequestInfo = duplicateIconRequestsMap.get(cn).get(0);
+ ItemInfoWithIcon itemInfo = iconRequestInfo.itemInfo;
+ BitmapInfo icon = itemInfo.bitmap;
+ boolean loadFallbackTitle = TextUtils.isEmpty(itemInfo.title);
+ boolean loadFallbackIcon = icon == null
+ || isDefaultIcon(icon, itemInfo.user)
+ || icon == BitmapInfo.LOW_RES_INFO;
+
+ if (loadFallbackTitle || loadFallbackIcon) {
+ Log.i(TAG,
+ "Database bulk icon loading failed, using fallback bulk icon loading "
+ + "for: " + cn);
+ CacheEntry entry = new CacheEntry();
+ LauncherActivityInfo lai = iconRequestInfo.launcherActivityInfo;
+
+ // Fill fields that are not updated below so they are not subsequently
+ // deleted.
+ entry.title = itemInfo.title;
+ if (icon != null) {
+ entry.bitmap = icon;
+ }
+ entry.contentDescription = itemInfo.contentDescription;
+
+ if (loadFallbackIcon) {
+ loadFallbackIcon(
+ lai,
+ entry,
+ mLauncherActivityInfoCachingLogic,
+ /* usePackageIcon= */ false,
+ /* usePackageTitle= */ loadFallbackTitle,
+ cn,
+ sectionKey.first);
+ }
+ if (loadFallbackTitle && TextUtils.isEmpty(entry.title) && lai != null) {
+ loadFallbackTitle(
+ lai,
+ entry,
+ mLauncherActivityInfoCachingLogic,
+ sectionKey.first);
+ }
+
+ for (IconRequestInfo<T> iconRequest : duplicateIconRequestsMap.get(cn)) {
+ applyCacheEntry(entry, iconRequest.itemInfo);
+ }
+ }
+ }
+ Trace.endSection();
+ }
/**
* Fill in {@param infoInOut} with the corresponding icon and label.
@@ -412,13 +482,39 @@
CacheEntry entry = getEntryForPackageLocked(
infoInOut.packageName, infoInOut.user, useLowResIcon);
applyCacheEntry(entry, infoInOut);
- if (infoInOut.widgetCategory != NO_CATEGORY) {
- WidgetSection widgetSection = WidgetSections.getWidgetSections(mContext)
- .get(infoInOut.widgetCategory);
- infoInOut.title = mContext.getString(widgetSection.mSectionTitle);
- infoInOut.contentDescription = mPackageManager.getUserBadgedLabel(
- infoInOut.title, infoInOut.user);
+ if (infoInOut.widgetCategory == NO_CATEGORY) {
+ return;
}
+
+ WidgetSection widgetSection = WidgetSections.getWidgetSections(mContext)
+ .get(infoInOut.widgetCategory);
+ infoInOut.title = mContext.getString(widgetSection.mSectionTitle);
+ infoInOut.contentDescription = mPackageManager.getUserBadgedLabel(
+ infoInOut.title, infoInOut.user);
+ final BitmapInfo cachedBitmap = mWidgetCategoryBitmapInfos.get(infoInOut.widgetCategory);
+ if (cachedBitmap != null) {
+ infoInOut.bitmap = getBadgedIcon(cachedBitmap, infoInOut.user);
+ return;
+ }
+
+ try (LauncherIcons li = LauncherIcons.obtain(mContext)) {
+ final BitmapInfo tempBitmap = li.createBadgedIconBitmap(
+ mContext.getDrawable(widgetSection.mSectionDrawable),
+ new BaseIconFactory.IconOptions().setShrinkNonAdaptiveIcons(false));
+ mWidgetCategoryBitmapInfos.put(infoInOut.widgetCategory, tempBitmap);
+ infoInOut.bitmap = getBadgedIcon(tempBitmap, infoInOut.user);
+ } catch (Exception e) {
+ Log.e(TAG, "Error initializing bitmap for icons with widget category", e);
+ }
+
+ }
+
+ private synchronized BitmapInfo getBadgedIcon(@Nullable final BitmapInfo bitmap,
+ @NonNull final UserHandle user) {
+ if (bitmap == null) {
+ return getDefaultIcon(user);
+ }
+ return bitmap.withFlags(getUserFlagOpLocked(user));
}
protected void applyCacheEntry(CacheEntry entry, ItemInfoWithIcon info) {
diff --git a/src/com/android/launcher3/icons/LauncherActivityCachingLogic.java b/src/com/android/launcher3/icons/LauncherActivityCachingLogic.java
index e820ac4..4b8c1ad 100644
--- a/src/com/android/launcher3/icons/LauncherActivityCachingLogic.java
+++ b/src/com/android/launcher3/icons/LauncherActivityCachingLogic.java
@@ -22,6 +22,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
+import com.android.launcher3.icons.BaseIconFactory.IconOptions;
import com.android.launcher3.icons.cache.CachingLogic;
import com.android.launcher3.util.ResourceBasedOverride;
@@ -59,7 +60,7 @@
try (LauncherIcons li = LauncherIcons.obtain(context)) {
return li.createBadgedIconBitmap(LauncherAppState.getInstance(context)
.getIconProvider().getIcon(object, li.mFillResIconDpi),
- object.getUser(), object.getApplicationInfo().targetSdkVersion);
+ new IconOptions().setUser(object.getUser()));
}
}
}
diff --git a/src/com/android/launcher3/icons/LauncherIconProvider.java b/src/com/android/launcher3/icons/LauncherIconProvider.java
new file mode 100644
index 0000000..c4d5f2b
--- /dev/null
+++ b/src/com/android/launcher3/icons/LauncherIconProvider.java
@@ -0,0 +1,104 @@
+/*
+ * 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.icons;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.util.Themes;
+
+import org.xmlpull.v1.XmlPullParser;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Extension of {@link IconProvider} with support for overriding theme icons
+ */
+public class LauncherIconProvider extends IconProvider {
+
+ private static final String TAG_ICON = "icon";
+ private static final String ATTR_PACKAGE = "package";
+ private static final String ATTR_DRAWABLE = "drawable";
+
+ private static final String TAG = "LIconProvider";
+ private static final Map<String, ThemeData> DISABLED_MAP = Collections.emptyMap();
+
+ private Map<String, ThemeData> mThemedIconMap;
+ private boolean mSupportsIconTheme;
+
+ public LauncherIconProvider(Context context) {
+ super(context);
+ setIconThemeSupported(Themes.isThemedIconEnabled(context));
+ }
+
+ /**
+ * Enables or disables icon theme support
+ */
+ public void setIconThemeSupported(boolean isSupported) {
+ mSupportsIconTheme = isSupported;
+ mThemedIconMap = isSupported && FeatureFlags.USE_LOCAL_ICON_OVERRIDES.get()
+ ? null : DISABLED_MAP;
+ }
+
+ @Override
+ protected ThemeData getThemeDataForPackage(String packageName) {
+ return getThemedIconMap().get(packageName);
+ }
+
+ @Override
+ public String getSystemIconState() {
+ return super.getSystemIconState() + (mSupportsIconTheme ? ",with-theme" : ",no-theme");
+ }
+
+ private Map<String, ThemeData> getThemedIconMap() {
+ if (mThemedIconMap != null) {
+ return mThemedIconMap;
+ }
+ ArrayMap<String, ThemeData> map = new ArrayMap<>();
+ Resources res = mContext.getResources();
+ try (XmlResourceParser parser = res.getXml(R.xml.grayscale_icon_map)) {
+ final int depth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT);
+
+ while (((type = parser.next()) != XmlPullParser.END_TAG
+ || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ }
+ if (TAG_ICON.equals(parser.getName())) {
+ String pkg = parser.getAttributeValue(null, ATTR_PACKAGE);
+ int iconId = parser.getAttributeResourceValue(null, ATTR_DRAWABLE, 0);
+ if (iconId != 0 && !TextUtils.isEmpty(pkg)) {
+ map.put(pkg, new ThemeData(res, iconId));
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to parse icon map", e);
+ }
+ mThemedIconMap = map;
+ return mThemedIconMap;
+ }
+}
diff --git a/src/com/android/launcher3/icons/LauncherIcons.java b/src/com/android/launcher3/icons/LauncherIcons.java
index bf7897e..5508c49 100644
--- a/src/com/android/launcher3/icons/LauncherIcons.java
+++ b/src/com/android/launcher3/icons/LauncherIcons.java
@@ -21,6 +21,7 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.graphics.IconShape;
import com.android.launcher3.graphics.LauncherPreviewRenderer;
+import com.android.launcher3.util.Themes;
/**
* Wrapper class to provide access to {@link BaseIconFactory} and also to provide pool of this class
@@ -32,18 +33,13 @@
private static LauncherIcons sPool;
private static int sPoolId = 0;
- public static LauncherIcons obtain(Context context) {
- return obtain(context, IconShape.getShape().enableShapeDetection());
- }
-
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
- public static LauncherIcons obtain(Context context, boolean shapeDetection) {
+ public static LauncherIcons obtain(Context context) {
if (context instanceof LauncherPreviewRenderer.PreviewContext) {
- return ((LauncherPreviewRenderer.PreviewContext) context).newLauncherIcons(context,
- shapeDetection);
+ return ((LauncherPreviewRenderer.PreviewContext) context).newLauncherIcons(context);
}
int poolId;
@@ -58,8 +54,7 @@
}
InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(context);
- return new LauncherIcons(context, idp.fillResIconDpi, idp.iconBitmapSize, poolId,
- shapeDetection);
+ return new LauncherIcons(context, idp.fillResIconDpi, idp.iconBitmapSize, poolId);
}
public static void clearPool() {
@@ -73,9 +68,9 @@
private LauncherIcons next;
- protected LauncherIcons(Context context, int fillResIconDpi, int iconBitmapSize, int poolId,
- boolean shapeDetection) {
- super(context, fillResIconDpi, iconBitmapSize, shapeDetection);
+ protected LauncherIcons(Context context, int fillResIconDpi, int iconBitmapSize, int poolId) {
+ super(context, fillResIconDpi, iconBitmapSize, IconShape.getShape().enableShapeDetection());
+ mMonoIconEnabled = Themes.isThemedIconEnabled(context);
mPoolId = poolId;
}
diff --git a/src/com/android/launcher3/icons/ShortcutCachingLogic.java b/src/com/android/launcher3/icons/ShortcutCachingLogic.java
index d7eed06..6a8f34a 100644
--- a/src/com/android/launcher3/icons/ShortcutCachingLogic.java
+++ b/src/com/android/launcher3/icons/ShortcutCachingLogic.java
@@ -71,8 +71,8 @@
Drawable unbadgedDrawable = ShortcutCachingLogic.getIcon(
context, info, LauncherAppState.getIDP(context).fillResIconDpi);
if (unbadgedDrawable == null) return BitmapInfo.LOW_RES_INFO;
- return new BitmapInfo(li.createScaledBitmapWithoutShadow(
- unbadgedDrawable, 0), Themes.getColorAccent(context));
+ return new BitmapInfo(li.createScaledBitmapWithoutShadow(unbadgedDrawable),
+ Themes.getColorAccent(context));
}
}
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 8b7bebc..c4ec4e3 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -258,6 +258,9 @@
@UiEvent(doc = "User swipes or fling in DOWN direction to close apps drawer.")
LAUNCHER_ALLAPPS_CLOSE_DOWN(569),
+ @UiEvent(doc = "User tap outside apps drawer sheet to close apps drawer.")
+ LAUNCHER_ALLAPPS_CLOSE_TAP_OUTSIDE(941),
+
@UiEvent(doc = "User swipes or fling in UP direction and hold from the bottom bazel area")
LAUNCHER_OVERVIEW_GESTURE(570),
@@ -372,6 +375,9 @@
@UiEvent(doc = "Notification dismissed by swiping right.")
LAUNCHER_NOTIFICATION_DISMISSED(652),
+ @UiEvent(doc = "Current grid size is changed to 6.")
+ LAUNCHER_GRID_SIZE_6(930),
+
@UiEvent(doc = "Current grid size is changed to 5.")
LAUNCHER_GRID_SIZE_5(662),
@@ -521,7 +527,72 @@
LAUNCHER_TASKBAR_LONGPRESS_SHOW(897),
@UiEvent(doc = "User clicks on the search icon on header to launch search in app.")
- LAUNCHER_ALLAPPS_SEARCHINAPP_LAUNCH(913);
+ LAUNCHER_ALLAPPS_SEARCHINAPP_LAUNCH(913),
+
+ @UiEvent(doc = "User is shown the back gesture navigation tutorial step.")
+ LAUNCHER_GESTURE_TUTORIAL_BACK_STEP_SHOWN(959),
+
+ @UiEvent(doc = "User is shown the home gesture navigation tutorial step.")
+ LAUNCHER_GESTURE_TUTORIAL_HOME_STEP_SHOWN(960),
+
+ @UiEvent(doc = "User is shown the overview gesture navigation tutorial step.")
+ LAUNCHER_GESTURE_TUTORIAL_OVERVIEW_STEP_SHOWN(961),
+
+ @UiEvent(doc = "User completed the back gesture navigation tutorial step.")
+ LAUNCHER_GESTURE_TUTORIAL_BACK_STEP_COMPLETED(962),
+
+ @UiEvent(doc = "User completed the home gesture navigation tutorial step.")
+ LAUNCHER_GESTURE_TUTORIAL_HOME_STEP_COMPLETED(963),
+
+ @UiEvent(doc = "User completed the overview gesture navigation tutorial step.")
+ LAUNCHER_GESTURE_TUTORIAL_OVERVIEW_STEP_COMPLETED(964),
+
+ @UiEvent(doc = "User skips the gesture navigation tutorial.")
+ LAUNCHER_GESTURE_TUTORIAL_SKIPPED(965),
+
+ @UiEvent(doc = "User scrolled on one of the all apps surfaces such as A-Z list, search "
+ + "result page etc.")
+ LAUNCHER_ALLAPPS_SCROLLED(985),
+
+ @UiEvent(doc = "User tapped taskbar home button")
+ LAUNCHER_TASKBAR_HOME_BUTTON_TAP(1003),
+
+ @UiEvent(doc = "User tapped taskbar back button")
+ LAUNCHER_TASKBAR_BACK_BUTTON_TAP(1004),
+
+ @UiEvent(doc = "User tapped taskbar overview/recents button")
+ LAUNCHER_TASKBAR_OVERVIEW_BUTTON_TAP(1005),
+
+ @UiEvent(doc = "User tapped taskbar IME switcher button")
+ LAUNCHER_TASKBAR_IME_SWITCHER_BUTTON_TAP(1006),
+
+ @UiEvent(doc = "User tapped taskbar a11y button")
+ LAUNCHER_TASKBAR_A11Y_BUTTON_TAP(1007),
+
+ @UiEvent(doc = "User tapped taskbar home button")
+ LAUNCHER_TASKBAR_HOME_BUTTON_LONGPRESS(1008),
+
+ @UiEvent(doc = "User tapped taskbar back button")
+ LAUNCHER_TASKBAR_BACK_BUTTON_LONGPRESS(1009),
+
+ @UiEvent(doc = "User tapped taskbar overview/recents button")
+ LAUNCHER_TASKBAR_OVERVIEW_BUTTON_LONGPRESS(1010),
+
+ @UiEvent(doc = "User tapped taskbar a11y button")
+ LAUNCHER_TASKBAR_A11Y_BUTTON_LONGPRESS(1011),
+
+ @UiEvent(doc = "Show an 'Undo' snackbar when users dismiss a predicted hotseat item")
+ LAUNCHER_DISMISS_PREDICTION_UNDO(1035),
+
+ @UiEvent(doc = "User clicked on IME quicksearch button.")
+ LAUNCHER_ALLAPPS_QUICK_SEARCH_WITH_IME(1047),
+
+ @UiEvent(doc = "User tapped taskbar All Apps button.")
+ LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP(1057),
+
+ @UiEvent(doc = "User tapped on Share app system shortcut.")
+ LAUNCHER_SYSTEM_SHORTCUT_APP_SHARE_TAP(1075),
+ ;
// ADD MORE
@@ -556,7 +627,7 @@
}
/**
- * Helps to construct and write the log message.
+ * Helps to construct and log launcher event.
*/
public interface StatsLogger {
@@ -656,6 +727,74 @@
}
/**
+ * Helps to construct and log latency event.
+ */
+ public interface StatsLatencyLogger {
+
+ enum LatencyType {
+ UNKNOWN(0),
+ COLD(1),
+ HOT(2),
+ TIMEOUT(3),
+ FAIL(4),
+ COLD_USERWAITING(5);
+
+ private final int mId;
+
+ LatencyType(int id) {
+ this.mId = id;
+ }
+
+ public int getId() {
+ return mId;
+ }
+
+ }
+
+ /**
+ * Sets {@link InstanceId} of log message.
+ */
+ default StatsLatencyLogger withInstanceId(InstanceId instanceId) {
+ return this;
+ }
+
+
+ /**
+ * Sets latency of the event.
+ */
+ default StatsLatencyLogger withLatency(long latencyInMillis) {
+ return this;
+ }
+
+ /**
+ * Sets {@link LatencyType} of log message.
+ */
+ default StatsLatencyLogger withType(LatencyType type) {
+ return this;
+ }
+
+ /**
+ * Sets query length of the event.
+ */
+ default StatsLatencyLogger withQueryLength(int queryLength) {
+ return this;
+ }
+
+ /**
+ * Sets packageId of log message.
+ */
+ default StatsLatencyLogger withPackageId(int packageId) {
+ return this;
+ }
+
+ /**
+ * Builds the final message and logs it as {@link EventEnum}.
+ */
+ default void log(EventEnum event) {
+ }
+ }
+
+ /**
* Returns new logger object.
*/
public StatsLogger logger() {
@@ -666,11 +805,27 @@
return logger;
}
+ /**
+ * Returns new latency logger object.
+ */
+ public StatsLatencyLogger latencyLogger() {
+ StatsLatencyLogger logger = createLatencyLogger();
+ if (mInstanceId != null) {
+ logger.withInstanceId(mInstanceId);
+ }
+ return logger;
+ }
+
protected StatsLogger createLogger() {
return new StatsLogger() {
};
}
+ protected StatsLatencyLogger createLatencyLogger() {
+ return new StatsLatencyLogger() {
+ };
+ }
+
/**
* Sets InstanceId to every new {@link StatsLogger} object returned by {@link #logger()} when
* not-null.
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index a13fa55..31ef2e5 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -15,33 +15,29 @@
*/
package com.android.launcher3.model;
-import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
-
import android.content.Intent;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageInstaller.SessionInfo;
import android.os.UserHandle;
-import android.util.LongSparseArray;
+import android.util.Log;
import android.util.Pair;
-import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel.CallbackTask;
import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.BgDataModel.Callbacks;
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.WorkspaceItemFactory;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.pm.PackageInstallInfo;
-import com.android.launcher3.util.GridOccupancy;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.IntArray;
-import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.PackageManagerHelper;
import java.util.ArrayList;
@@ -56,11 +52,23 @@
private final List<Pair<ItemInfo, Object>> mItemList;
+ private final WorkspaceItemSpaceFinder mItemSpaceFinder;
+
/**
* @param itemList items to add on the workspace
*/
public AddWorkspaceItemsTask(List<Pair<ItemInfo, Object>> itemList) {
+ this(itemList, new WorkspaceItemSpaceFinder());
+ }
+
+ /**
+ * @param itemList items to add on the workspace
+ * @param itemSpaceFinder inject WorkspaceItemSpaceFinder dependency for testing
+ */
+ public AddWorkspaceItemsTask(List<Pair<ItemInfo, Object>> itemList,
+ WorkspaceItemSpaceFinder itemSpaceFinder) {
mItemList = itemList;
+ mItemSpaceFinder = itemSpaceFinder;
}
@Override
@@ -72,7 +80,7 @@
final ArrayList<ItemInfo> addedItemsFinal = new ArrayList<>();
final IntArray addedWorkspaceScreensFinal = new IntArray();
- synchronized(dataModel) {
+ synchronized (dataModel) {
IntArray workspaceScreens = dataModel.collectWorkspaceScreens();
List<ItemInfo> filteredItems = new ArrayList<>();
@@ -82,18 +90,26 @@
item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
// Short-circuit this logic if the icon exists somewhere on the workspace
if (shortcutExists(dataModel, item.getIntent(), item.user)) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON,
+ LOG + " Item already on workspace.");
+ }
continue;
}
// b/139663018 Short-circuit this logic if the icon is a system app
if (PackageManagerHelper.isSystemApp(app.getContext(), item.getIntent())) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON,
+ LOG + " Item is a system app.");
+ }
continue;
}
}
if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
- if (item instanceof AppInfo) {
- item = ((AppInfo) item).makeWorkspaceItem();
+ if (item instanceof WorkspaceItemFactory) {
+ item = ((WorkspaceItemFactory) item).makeWorkspaceItem(app.getContext());
}
}
if (item != null) {
@@ -107,7 +123,7 @@
for (ItemInfo item : filteredItems) {
// Find appropriate space for the item.
- int[] coords = findSpaceForItem(app, dataModel, workspaceScreens,
+ int[] coords = mItemSpaceFinder.findSpaceForItem(app, dataModel, workspaceScreens,
addedWorkspaceScreensFinal, item.spanX, item.spanY);
int screenId = coords[0];
@@ -115,8 +131,8 @@
if (item instanceof WorkspaceItemInfo || item instanceof FolderInfo ||
item instanceof LauncherAppWidgetInfo) {
itemInfo = item;
- } else if (item instanceof AppInfo) {
- itemInfo = ((AppInfo) item).makeWorkspaceItem();
+ } else if (item instanceof WorkspaceItemFactory) {
+ itemInfo = ((WorkspaceItemFactory) item).makeWorkspaceItem(app.getContext());
} else {
throw new RuntimeException("Unexpected info type");
}
@@ -126,6 +142,9 @@
String packageName = item.getTargetComponent() != null
? item.getTargetComponent().getPackageName() : null;
if (packageName == null) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + " Null packageName.");
+ }
continue;
}
SessionInfo sessionInfo = packageInstaller.getActiveSessionInfo(item.user,
@@ -134,6 +153,9 @@
if (!packageInstaller.verifySessionInfo(sessionInfo)) {
FileLog.d(LOG, "Item info failed session info verification. "
+ "Skipping : " + workspaceInfo);
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + "Failed verification.");
+ }
continue;
}
@@ -144,6 +166,9 @@
if (sessionInfo == null) {
if (!hasActivity) {
// Session was cancelled, do not add.
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + "Session cancelled");
+ }
continue;
}
} else {
@@ -156,13 +181,16 @@
// App was installed while launcher was in the background,
// or app was already installed for another user.
itemInfo = new AppInfo(app.getContext(), activities.get(0), item.user)
- .makeWorkspaceItem();
+ .makeWorkspaceItem(app.getContext());
if (shortcutExists(dataModel, itemInfo.getIntent(), itemInfo.user)) {
// We need this additional check here since we treat all auto added
// workspace items as promise icons. At this point we now have the
// correct intent to compare against existing workspace icons.
// Icon already exists on the workspace and should not be auto-added.
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + "shortcutExists");
+ }
continue;
}
@@ -266,82 +294,4 @@
}
return false;
}
-
- /**
- * Find a position on the screen for the given size or adds a new screen.
- * @return screenId and the coordinates for the item in an int array of size 3.
- */
- protected int[] findSpaceForItem( LauncherAppState app, BgDataModel dataModel,
- IntArray workspaceScreens, IntArray addedWorkspaceScreensFinal, int spanX, int spanY) {
- LongSparseArray<ArrayList<ItemInfo>> screenItems = new LongSparseArray<>();
-
- // Use sBgItemsIdMap as all the items are already loaded.
- synchronized (dataModel) {
- for (ItemInfo info : dataModel.itemsIdMap) {
- if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- ArrayList<ItemInfo> items = screenItems.get(info.screenId);
- if (items == null) {
- items = new ArrayList<>();
- screenItems.put(info.screenId, items);
- }
- items.add(info);
- }
- }
- }
-
- // Find appropriate space for the item.
- int screenId = 0;
- int[] coordinates = new int[2];
- boolean found = false;
-
- int screenCount = workspaceScreens.size();
- // First check the preferred screen.
- IntSet screensToExclude = new IntSet();
- if (FeatureFlags.QSB_ON_FIRST_SCREEN) {
- screensToExclude.add(FIRST_SCREEN_ID);
- }
-
- for (int screen = 0; screen < screenCount; screen++) {
- screenId = workspaceScreens.get(screen);
- if (!screensToExclude.contains(screenId) && findNextAvailableIconSpaceInScreen(
- app, screenItems.get(screenId), coordinates, spanX, spanY)) {
- // We found a space for it
- found = true;
- break;
- }
- }
-
- 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);
-
- // Save the screen id for binding in the workspace
- workspaceScreens.add(screenId);
- addedWorkspaceScreensFinal.add(screenId);
-
- // If we still can't find an empty space, then God help us all!!!
- if (!findNextAvailableIconSpaceInScreen(
- app, screenItems.get(screenId), coordinates, spanX, spanY)) {
- throw new RuntimeException("Can't find space to add the item");
- }
- }
- return new int[] {screenId, coordinates[0], coordinates[1]};
- }
-
- private boolean findNextAvailableIconSpaceInScreen(
- LauncherAppState app, ArrayList<ItemInfo> occupiedPos,
- int[] xy, int spanX, int spanY) {
- InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
-
- GridOccupancy occupied = new GridOccupancy(profile.numColumns, profile.numRows);
- if (occupiedPos != null) {
- for (ItemInfo r : occupiedPos) {
- occupied.markCells(r, true);
- }
- }
- return occupied.findVacantCell(xy, spanX, spanY);
- }
-
}
diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java
index dbed9a9..4875d83 100644
--- a/src/com/android/launcher3/model/AllAppsList.java
+++ b/src/com/android/launcher3/model/AllAppsList.java
@@ -36,9 +36,9 @@
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.pm.PackageInstallInfo;
import com.android.launcher3.util.FlagOp;
-import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.SafeCloseable;
@@ -47,6 +47,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.function.Consumer;
+import java.util.function.Predicate;
/**
@@ -143,6 +144,8 @@
if (loadIcon) {
mIconCache.getTitleAndIcon(info, activityInfo, false /* useLowResIcon */);
info.sectionName = mIndex.computeSectionName(info.title);
+ } else {
+ info.title = "";
}
data.add(info);
@@ -167,6 +170,8 @@
if (loadIcon) {
mIconCache.getTitleAndIcon(promiseAppInfo, promiseAppInfo.usingLowResIcon());
promiseAppInfo.sectionName = mIndex.computeSectionName(promiseAppInfo.title);
+ } else {
+ promiseAppInfo.title = "";
}
data.add(promiseAppInfo);
@@ -253,11 +258,11 @@
/**
* Updates the disabled flags of apps matching {@param matcher} based on {@param op}.
*/
- public void updateDisabledFlags(ItemInfoMatcher matcher, FlagOp op) {
+ public void updateDisabledFlags(Predicate<ItemInfo> matcher, FlagOp op) {
final List<AppInfo> data = this.data;
for (int i = data.size() - 1; i >= 0; i--) {
AppInfo info = data.get(i);
- if (matcher.matches(info, info.componentName)) {
+ if (matcher.test(info)) {
info.runtimeStatusFlags = op.apply(info.runtimeStatusFlags);
mDataChanged = true;
}
diff --git a/src/com/android/launcher3/model/BaseLoaderResults.java b/src/com/android/launcher3/model/BaseLoaderResults.java
index d270cc5..b50ab58 100644
--- a/src/com/android/launcher3/model/BaseLoaderResults.java
+++ b/src/com/android/launcher3/model/BaseLoaderResults.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.model.ItemInstallQueue.FLAG_LOADER_RUNNING;
import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems;
-import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.os.Process;
@@ -27,6 +26,8 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel.CallbackTask;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.data.AppInfo;
@@ -42,6 +43,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -110,6 +112,42 @@
public abstract void bindWidgets();
+ /**
+ * Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to right)
+ */
+ protected void sortWorkspaceItemsSpatially(InvariantDeviceProfile profile,
+ ArrayList<ItemInfo> workspaceItems) {
+ final int screenCols = profile.numColumns;
+ final int screenCellCount = profile.numColumns * profile.numRows;
+ Collections.sort(workspaceItems, (lhs, rhs) -> {
+ if (lhs.container == rhs.container) {
+ // Within containers, order by their spatial position in that container
+ switch (lhs.container) {
+ case LauncherSettings.Favorites.CONTAINER_DESKTOP: {
+ int lr = (lhs.screenId * screenCellCount + lhs.cellY * screenCols
+ + lhs.cellX);
+ int rr = (rhs.screenId * screenCellCount + +rhs.cellY * screenCols
+ + rhs.cellX);
+ return Integer.compare(lr, rr);
+ }
+ case LauncherSettings.Favorites.CONTAINER_HOTSEAT: {
+ // We currently use the screen id as the rank
+ return Integer.compare(lhs.screenId, rhs.screenId);
+ }
+ default:
+ if (FeatureFlags.IS_STUDIO_BUILD) {
+ throw new RuntimeException(
+ "Unexpected container type when sorting workspace items.");
+ }
+ return 0;
+ }
+ } else {
+ // Between containers, order by hotseat, desktop
+ return Integer.compare(lhs.container, rhs.container);
+ }
+ });
+ }
+
protected void executeCallbacksTask(CallbackTask task, Executor executor) {
executor.execute(() -> {
if (mMyBindingId != mBgDataModel.lastBindId) {
@@ -131,7 +169,7 @@
return idleLock;
}
- private static class WorkspaceBinder {
+ private class WorkspaceBinder {
private final Executor mUiExecutor;
private final Callbacks mCallbacks;
@@ -166,7 +204,9 @@
}
private void bind() {
- IntSet currentScreenIds = mCallbacks.getPagesToBindSynchronously(mOrderedScreenIds);
+ final IntSet currentScreenIds =
+ mCallbacks.getPagesToBindSynchronously(mOrderedScreenIds);
+ Objects.requireNonNull(currentScreenIds, "Null screen ids provided by " + mCallbacks);
// Separate the items that are on the current screen, and all the other remaining items
ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<>();
@@ -226,6 +266,8 @@
MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
c.onInitialBindComplete(currentScreenIds, pendingTasks);
}, mUiExecutor);
+
+ mCallbacks.bindStringCache(mBgDataModel.stringCache.clone());
}
private void bindWorkspaceItems(
diff --git a/src/com/android/launcher3/model/BaseModelUpdateTask.java b/src/com/android/launcher3/model/BaseModelUpdateTask.java
index a3a4717..2a6a691 100644
--- a/src/com/android/launcher3/model/BaseModelUpdateTask.java
+++ b/src/com/android/launcher3/model/BaseModelUpdateTask.java
@@ -17,6 +17,8 @@
import android.util.Log;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherModel.CallbackTask;
@@ -27,7 +29,6 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import java.util.ArrayList;
@@ -35,6 +36,7 @@
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
@@ -128,8 +130,9 @@
scheduleCallbackTask(c -> c.bindAllWidgets(widgets));
}
- public void deleteAndBindComponentsRemoved(final ItemInfoMatcher matcher) {
- getModelWriter().deleteItemsFromDatabase(matcher);
+ public void deleteAndBindComponentsRemoved(final Predicate<ItemInfo> matcher,
+ @Nullable final String reason) {
+ getModelWriter().deleteItemsFromDatabase(matcher, reason);
// Call the components-removed callback
scheduleCallbackTask(c -> c.bindWorkspaceComponentsRemoved(matcher));
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index d3351dc..de23c4b 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -31,6 +31,7 @@
import android.util.ArraySet;
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherSettings;
@@ -50,7 +51,6 @@
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.IntSparseArrayMap;
-import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
@@ -66,6 +66,7 @@
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -114,6 +115,11 @@
public final WidgetsModel widgetsModel = new WidgetsModel();
/**
+ * Cache for strings used in launcher
+ */
+ public final StringCache stringCache = new StringCache();
+
+ /**
* Id when the model was last bound
*/
public int lastBindId = 0;
@@ -229,7 +235,6 @@
String.format("Adding item to ID map: %s", item.toString()),
/* stackTrace= */ null);
}
-
itemsIdMap.put(item.id, item);
switch (item.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
@@ -465,6 +470,7 @@
* or an empty IntSet
* @param orderedScreenIds All the page ids to be bound
*/
+ @NonNull
default IntSet getPagesToBindSynchronously(IntArray orderedScreenIds) {
return new IntSet();
}
@@ -491,7 +497,7 @@
default void bindWorkspaceItemsChanged(List<WorkspaceItemInfo> updated) { }
default void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets) { }
default void bindRestoreItemsChange(HashSet<ItemInfo> updates) { }
- default void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher) { }
+ default void bindWorkspaceComponentsRemoved(Predicate<ItemInfo> matcher) { }
default void bindAllWidgets(List<WidgetsListBaseEntry> widgets) { }
default void onInitialBindComplete(IntSet boundPages, RunnableList pendingTasks) {
@@ -506,5 +512,10 @@
default void bindExtraContainerItems(FixedContainerItems item) { }
default void bindAllApplications(AppInfo[] apps, int flags) { }
+
+ /**
+ * Binds the cache of string resources
+ */
+ default void bindStringCache(StringCache cache) { }
}
}
diff --git a/src/com/android/launcher3/model/DeviceGridState.java b/src/com/android/launcher3/model/DeviceGridState.java
index fa11d4e..35fcb78 100644
--- a/src/com/android/launcher3/model/DeviceGridState.java
+++ b/src/com/android/launcher3/model/DeviceGridState.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_3;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_4;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_5;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_6;
import android.content.Context;
import android.content.SharedPreferences;
@@ -37,20 +38,23 @@
/**
* Utility class representing persisted grid properties.
*/
-public class DeviceGridState {
+public class DeviceGridState implements Comparable<DeviceGridState> {
public static final String KEY_WORKSPACE_SIZE = "migration_src_workspace_size";
public static final String KEY_HOTSEAT_COUNT = "migration_src_hotseat_count";
public static final String KEY_DEVICE_TYPE = "migration_src_device_type";
+ public static final String KEY_DB_FILE = "migration_src_db_file";
private final String mGridSizeString;
private final int mNumHotseat;
private final @DeviceType int mDeviceType;
+ private final String mDbFile;
public DeviceGridState(InvariantDeviceProfile idp) {
mGridSizeString = String.format(Locale.ENGLISH, "%d,%d", idp.numColumns, idp.numRows);
mNumHotseat = idp.numDatabaseHotseatIcons;
mDeviceType = idp.deviceType;
+ mDbFile = idp.dbFile;
}
public DeviceGridState(Context context) {
@@ -58,6 +62,7 @@
mGridSizeString = prefs.getString(KEY_WORKSPACE_SIZE, "");
mNumHotseat = prefs.getInt(KEY_HOTSEAT_COUNT, -1);
mDeviceType = prefs.getInt(KEY_DEVICE_TYPE, TYPE_PHONE);
+ mDbFile = prefs.getString(KEY_DB_FILE, "");
}
/**
@@ -68,6 +73,20 @@
}
/**
+ * Returns the databaseFile for the grid.
+ */
+ public String getDbFile() {
+ return mDbFile;
+ }
+
+ /**
+ * Returns the number of hotseat icons.
+ */
+ public int getNumHotseat() {
+ return mNumHotseat;
+ }
+
+ /**
* Stores the device state to shared preferences
*/
public void writeToPrefs(Context context) {
@@ -75,6 +94,7 @@
.putString(KEY_WORKSPACE_SIZE, mGridSizeString)
.putInt(KEY_HOTSEAT_COUNT, mNumHotseat)
.putInt(KEY_DEVICE_TYPE, mDeviceType)
+ .putString(KEY_DB_FILE, mDbFile)
.apply();
}
@@ -83,14 +103,16 @@
*/
public LauncherEvent getWorkspaceSizeEvent() {
if (!TextUtils.isEmpty(mGridSizeString)) {
- switch (mGridSizeString.charAt(0)) {
- case '5':
+ switch (getColumns()) {
+ case 6:
+ return LAUNCHER_GRID_SIZE_6;
+ case 5:
return LAUNCHER_GRID_SIZE_5;
- case '4':
+ case 4:
return LAUNCHER_GRID_SIZE_4;
- case '3':
+ case 3:
return LAUNCHER_GRID_SIZE_3;
- case '2':
+ case 2:
return LAUNCHER_GRID_SIZE_2;
}
}
@@ -103,6 +125,7 @@
+ "mGridSizeString='" + mGridSizeString + '\''
+ ", mNumHotseat=" + mNumHotseat
+ ", mDeviceType=" + mDeviceType
+ + ", mDbFile=" + mDbFile
+ '}';
}
@@ -116,4 +139,21 @@
return mNumHotseat == other.mNumHotseat
&& Objects.equals(mGridSizeString, other.mGridSizeString);
}
+
+ public Integer getColumns() {
+ return Integer.parseInt(String.valueOf(mGridSizeString.charAt(0)));
+ }
+
+ public Integer getRows() {
+ return Integer.parseInt(String.valueOf(mGridSizeString.charAt(2)));
+ }
+
+ @Override
+ public int compareTo(DeviceGridState other) {
+ Integer size = getColumns() * getRows();
+ Integer otherSize = other.getColumns() * other.getRows();
+
+ return size.compareTo(otherSize);
+ }
+
}
diff --git a/src/com/android/launcher3/model/FirstScreenBroadcast.java b/src/com/android/launcher3/model/FirstScreenBroadcast.java
index e391d37..9e91b9d 100644
--- a/src/com/android/launcher3/model/FirstScreenBroadcast.java
+++ b/src/com/android/launcher3/model/FirstScreenBroadcast.java
@@ -20,6 +20,7 @@
import static android.os.Process.myUserHandle;
import static com.android.launcher3.pm.InstallSessionHelper.getUserHandle;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
@@ -31,13 +32,18 @@
import android.os.UserHandle;
import android.util.Log;
+import androidx.annotation.AnyThread;
+import androidx.annotation.WorkerThread;
+
import com.android.launcher3.LauncherSettings;
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.util.PackageUserKey;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -78,6 +84,7 @@
* Sends a broadcast to all package installers that have items with active sessions on the users
* first screen.
*/
+ @WorkerThread
public void sendBroadcasts(Context context, List<ItemInfo> firstScreenItems) {
UserHandle myUser = myUserHandle();
mSessionInfoForPackage
@@ -95,6 +102,7 @@
* @param packages List of packages with active sessions for this package installer.
* @param firstScreenItems List of items on the first screen.
*/
+ @WorkerThread
private void sendBroadcastToInstaller(Context context, String installerPackageName,
Set<String> packages, List<ItemInfo> firstScreenItems) {
Set<String> folderItems = new HashSet<>();
@@ -106,7 +114,7 @@
if (info instanceof FolderInfo) {
FolderInfo folderInfo = (FolderInfo) info;
String folderItemInfoPackage;
- for (ItemInfo folderItemInfo : folderInfo.contents) {
+ for (ItemInfo folderItemInfo : cloneOnMainThread(folderInfo.contents)) {
folderItemInfoPackage = getPackageName(folderItemInfo);
if (folderItemInfoPackage != null
&& packages.contains(folderItemInfoPackage)) {
@@ -135,6 +143,13 @@
printList(installerPackageName, "Widget item", widgetItems);
}
+ if (folderItems.isEmpty()
+ && workspaceItems.isEmpty()
+ && hotseatItems.isEmpty()
+ && widgetItems.isEmpty()) {
+ // Avoid sending broadcast if there is nothing to send.
+ return;
+ }
context.sendBroadcast(new Intent(ACTION_FIRST_SCREEN_ACTIVE_INSTALLS)
.setPackage(installerPackageName)
.putStringArrayListExtra(FOLDER_ITEM_EXTRA, new ArrayList<>(folderItems))
@@ -163,4 +178,17 @@
Log.d(TAG, packageInstaller + ":" + label + ":" + pkg);
}
}
+
+ /**
+ * Clone the provided list on UI thread. This is used for {@link FolderInfo#contents} which
+ * is always modified on UI thread.
+ */
+ @AnyThread
+ private static List<WorkspaceItemInfo> cloneOnMainThread(ArrayList<WorkspaceItemInfo> list) {
+ try {
+ return MAIN_EXECUTOR.submit(() -> new ArrayList(list)).get();
+ } catch (Exception e) {
+ return Collections.emptyList();
+ }
+ }
}
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
index ca680b7..ef9250c 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
@@ -22,7 +22,6 @@
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
@@ -38,6 +37,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.Utilities;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.LauncherPreviewRenderer;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.pm.InstallSessionHelper;
@@ -103,13 +103,16 @@
* Check given a new IDP, if migration is necessary.
*/
public static boolean needsToMigrate(Context context, InvariantDeviceProfile idp) {
- DeviceGridState idpGridState = new DeviceGridState(idp);
- DeviceGridState contextGridState = new DeviceGridState(context);
- boolean needsToMigrate = !idpGridState.isCompatible(contextGridState);
+ return needsToMigrate(new DeviceGridState(context), new DeviceGridState(idp));
+ }
+
+ private static boolean needsToMigrate(
+ DeviceGridState srcDeviceState, DeviceGridState destDeviceState) {
+ boolean needsToMigrate = !destDeviceState.isCompatible(srcDeviceState);
// TODO(b/198965093): Revert this change after bug is fixed
if (needsToMigrate) {
- Log.d("b/198965093", "Migration is needed. idpGridState: " + idpGridState
- + ", contextGridState: " + contextGridState);
+ Log.d("b/198965093", "Migration is needed. destDeviceState: " + destDeviceState
+ + ", srcDeviceState: " + srcDeviceState);
}
return needsToMigrate;
}
@@ -142,23 +145,26 @@
idp = LauncherAppState.getIDP(context);
}
- if (!needsToMigrate(context, idp)) {
+ DeviceGridState srcDeviceState = new DeviceGridState(context);
+ DeviceGridState destDeviceState = new DeviceGridState(idp);
+ if (!needsToMigrate(srcDeviceState, destDeviceState)) {
return true;
}
- SharedPreferences prefs = Utilities.getPrefs(context);
HashSet<String> validPackages = getValidPackages(context);
if (migrateForPreview) {
if (!LauncherSettings.Settings.call(
context.getContentResolver(),
- LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW, idp.dbFile).getBoolean(
+ LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW,
+ destDeviceState.getDbFile()).getBoolean(
LauncherSettings.Settings.EXTRA_VALUE)) {
return false;
}
} else if (!LauncherSettings.Settings.call(
context.getContentResolver(),
- LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER).getBoolean(
+ LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER,
+ destDeviceState.getDbFile()).getBoolean(
LauncherSettings.Settings.EXTRA_VALUE)) {
return false;
}
@@ -178,10 +184,10 @@
: LauncherSettings.Favorites.TABLE_NAME,
context, validPackages);
- Point targetSize = new Point(idp.numColumns, idp.numRows);
+ Point targetSize = new Point(destDeviceState.getColumns(), destDeviceState.getRows());
GridSizeMigrationTaskV2 task = new GridSizeMigrationTaskV2(context, t.getDb(),
- srcReader, destReader, idp.numDatabaseHotseatIcons, targetSize);
- task.migrate(idp);
+ srcReader, destReader, destDeviceState.getNumHotseat(), targetSize);
+ task.migrate(srcDeviceState, destDeviceState);
if (!migrateForPreview) {
dropTable(t.getDb(), LauncherSettings.Favorites.TMP_TABLE);
@@ -199,25 +205,26 @@
if (!migrateForPreview) {
// Save current configuration, so that the migration does not run again.
- new DeviceGridState(idp).writeToPrefs(context);
+ destDeviceState.writeToPrefs(context);
}
}
}
@VisibleForTesting
- protected boolean migrate(InvariantDeviceProfile idp) {
+ protected boolean migrate(DeviceGridState srcDeviceState, DeviceGridState destDeviceState) {
if (mHotseatDiff.isEmpty() && mWorkspaceDiff.isEmpty()) {
return false;
}
+ // Sort the items by the reading order.
+ Collections.sort(mHotseatDiff);
+ Collections.sort(mWorkspaceDiff);
+
// Migrate hotseat
HotseatPlacementSolution hotseatSolution = new HotseatPlacementSolution(mDb, mSrcReader,
mDestReader, mContext, mDestHotseatSize, mHotseatItems, mHotseatDiff);
hotseatSolution.find();
- // Sort the items by the reading order.
- Collections.sort(mWorkspaceDiff);
-
// Migrate workspace.
// First we create a collection of the screens
List<Integer> screens = new ArrayList<>();
@@ -225,13 +232,19 @@
screens.add(screenId);
}
+ boolean preservePages = false;
+ if (screens.isEmpty() && FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC.get()) {
+ preservePages = destDeviceState.compareTo(srcDeviceState) >= 0
+ && destDeviceState.getColumns() - srcDeviceState.getColumns() <= 2;
+ }
+
// Then we place the items on the screens
for (int screenId : screens) {
if (DEBUG) {
Log.d(TAG, "Migrating " + screenId);
}
GridPlacementSolution workspaceSolution = new GridPlacementSolution(mDb, mSrcReader,
- mDestReader, mContext, screenId, mTrgX, mTrgY, mWorkspaceDiff);
+ mDestReader, mContext, screenId, mTrgX, mTrgY, mWorkspaceDiff, false);
workspaceSolution.find();
if (mWorkspaceDiff.isEmpty()) {
break;
@@ -243,10 +256,12 @@
int screenId = mDestReader.mLastScreenId + 1;
while (!mWorkspaceDiff.isEmpty()) {
GridPlacementSolution workspaceSolution = new GridPlacementSolution(mDb, mSrcReader,
- mDestReader, mContext, screenId, mTrgX, mTrgY, mWorkspaceDiff);
+ mDestReader, mContext, screenId, mTrgX, mTrgY, mWorkspaceDiff,
+ preservePages);
workspaceSolution.find();
screenId++;
}
+
return true;
}
@@ -363,13 +378,15 @@
private final int mScreenId;
private final int mTrgX;
private final int mTrgY;
- private final List<DbEntry> mItemsToPlace;
+ private final List<DbEntry> mSortedItemsToPlace;
+ private final boolean mMatchingScreenIdOnly;
private int mNextStartX;
private int mNextStartY;
GridPlacementSolution(SQLiteDatabase db, DbReader srcReader, DbReader destReader,
- Context context, int screenId, int trgX, int trgY, List<DbEntry> itemsToPlace) {
+ Context context, int screenId, int trgX, int trgY, List<DbEntry> sortedItemsToPlace,
+ boolean matchingScreenIdOnly) {
mDb = db;
mSrcReader = srcReader;
mDestReader = destReader;
@@ -379,20 +396,24 @@
mTrgX = trgX;
mTrgY = trgY;
mNextStartX = 0;
- mNextStartY = mTrgY - 1;
+ mNextStartY = mScreenId == 0 && FeatureFlags.QSB_ON_FIRST_SCREEN
+ ? 1 /* smartspace */ : 0;
List<DbEntry> existedEntries = mDestReader.mWorkspaceEntriesByScreenId.get(screenId);
if (existedEntries != null) {
for (DbEntry entry : existedEntries) {
mOccupied.markCells(entry, true);
}
}
- mItemsToPlace = itemsToPlace;
+ mSortedItemsToPlace = sortedItemsToPlace;
+ mMatchingScreenIdOnly = matchingScreenIdOnly;
}
public void find() {
- Iterator<DbEntry> iterator = mItemsToPlace.iterator();
+ Iterator<DbEntry> iterator = mSortedItemsToPlace.iterator();
while (iterator.hasNext()) {
final DbEntry entry = iterator.next();
+ if (mMatchingScreenIdOnly && entry.screenId < mScreenId) continue;
+ if (mMatchingScreenIdOnly && entry.screenId > mScreenId) break;
if (entry.minSpanX > mTrgX || entry.minSpanY > mTrgY) {
iterator.remove();
continue;
@@ -411,7 +432,7 @@
* to speed up the search.
*/
private boolean findPlacement(DbEntry entry) {
- for (int y = mNextStartY; y >= (mScreenId == 0 ? 1 /* smartspace */ : 0); y--) {
+ for (int y = mNextStartY; y < mTrgY; y++) {
for (int x = mNextStartX; x < mTrgX; x++) {
boolean fits = mOccupied.isRegionVacant(x, y, entry.spanX, entry.spanY);
boolean minFits = mOccupied.isRegionVacant(x, y, entry.minSpanX,
@@ -494,7 +515,7 @@
private final SQLiteDatabase mDb;
private final String mTableName;
private final Context mContext;
- private final HashSet<String> mValidPackages;
+ private final Set<String> mValidPackages;
private int mLastScreenId = -1;
private final ArrayList<DbEntry> mHotseatEntries = new ArrayList<>();
@@ -503,7 +524,7 @@
new ArrayMap<>();
DbReader(SQLiteDatabase db, String tableName, Context context,
- HashSet<String> validPackages) {
+ Set<String> validPackages) {
mDb = db;
mTableName = tableName;
mContext = context;
@@ -734,7 +755,7 @@
return Integer.compare(screenId, another.screenId);
}
if (cellY != another.cellY) {
- return -Integer.compare(cellY, another.cellY);
+ return Integer.compare(cellY, another.cellY);
}
return Integer.compare(cellX, another.cellX);
}
diff --git a/src/com/android/launcher3/model/ItemInstallQueue.java b/src/com/android/launcher3/model/ItemInstallQueue.java
index 217f523..5a220f7 100644
--- a/src/com/android/launcher3/model/ItemInstallQueue.java
+++ b/src/com/android/launcher3/model/ItemInstallQueue.java
@@ -49,6 +49,7 @@
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.shortcuts.ShortcutRequest;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.PersistedItemArray;
import com.android.launcher3.util.Preconditions;
@@ -118,10 +119,18 @@
Launcher launcher = Launcher.ACTIVITY_TRACKER.getCreatedActivity();
if (launcher == null) {
// Launcher not loaded
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON,
+ LOG + " flushQueueInBackground launcher not loaded");
+ }
return;
}
ensureQueueLoaded();
if (mItems.isEmpty()) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON,
+ LOG + " flushQueueInBackground no items to load");
+ }
return;
}
@@ -131,6 +140,10 @@
// Add the items and clear queue
if (!installQueue.isEmpty()) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON,
+ LOG + " flushQueueInBackground launcher addAndBindAddedWorkspaceItems");
+ }
// add log
launcher.getModel().addAndBindAddedWorkspaceItems(installQueue);
}
@@ -191,6 +204,10 @@
// Queue the item up for adding if launcher has not loaded properly yet
MODEL_EXECUTOR.post(() -> {
Pair<ItemInfo, Object> itemInfo = info.getItemInfo(mContext);
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + " queuePendingShortcutInfo"
+ + ", itemInfo=" + itemInfo);
+ }
if (itemInfo == null) {
FileLog.d(LOG,
"Adding PendingInstallShortcutInfo with no attached info to queue.",
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index 178fbdb..ae5b66a 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -456,11 +456,13 @@
if (!occupied.containsKey(item.screenId)) {
GridOccupancy screen = new GridOccupancy(countX + 1, countY + 1);
- if (item.screenId == Workspace.FIRST_SCREEN_ID) {
- // Mark the first row as occupied (if the feature is enabled)
- // in order to account for the QSB.
+ if (item.screenId == Workspace.FIRST_SCREEN_ID && FeatureFlags.QSB_ON_FIRST_SCREEN) {
+ // Mark the first X columns (X is width of the search container) in the first row as
+ // occupied (if the feature is enabled) in order to account for the search
+ // container.
+ int spanX = mIDP.numSearchContainerColumns;
int spanY = FeatureFlags.EXPANDED_SMARTSPACE.get() ? 2 : 1;
- screen.markCells(0, 0, countX + 1, spanY, FeatureFlags.QSB_ON_FIRST_SCREEN);
+ screen.markCells(0, 0, spanX, spanY, true);
}
occupied.put(item.screenId, screen);
}
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 2a0f9a6..f1c5d59 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -615,7 +615,13 @@
}
if (info != null) {
- iconRequestInfos.add(c.createIconRequestInfo(info, useLowResIcon));
+ if (info.itemType
+ != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+ // Skip deep shortcuts; their title and icons have already been
+ // loaded above.
+ iconRequestInfos.add(
+ c.createIconRequestInfo(info, useLowResIcon));
+ }
c.applyCommonProperties(info);
@@ -857,6 +863,9 @@
// Load delegate items
mModelDelegate.loadItems(mUserManagerState, shortcutKeyToPinnedShortcuts);
+ // Load string cache
+ mModelDelegate.loadStringCache(mBgDataModel.stringCache);
+
// Break early if we've stopped loading
if (mStopped) {
mBgDataModel.clear();
diff --git a/src/com/android/launcher3/model/ModelDelegate.java b/src/com/android/launcher3/model/ModelDelegate.java
index 765141a..3bd9470 100644
--- a/src/com/android/launcher3/model/ModelDelegate.java
+++ b/src/com/android/launcher3/model/ModelDelegate.java
@@ -44,13 +44,11 @@
boolean isPrimaryInstance) {
ModelDelegate delegate = Overrides.getObject(
ModelDelegate.class, context, R.string.model_delegate_class);
- delegate.mApp = app;
- delegate.mAppsList = appsList;
- delegate.mDataModel = dataModel;
- delegate.mIsPrimaryInstance = isPrimaryInstance;
+ delegate.init(context, app, appsList, dataModel, isPrimaryInstance);
return delegate;
}
+ protected Context mContext;
protected LauncherAppState mApp;
protected AllAppsList mAppsList;
protected BgDataModel mDataModel;
@@ -59,6 +57,18 @@
public ModelDelegate() { }
/**
+ * Initializes the object with the given params.
+ */
+ private void init(Context context, LauncherAppState app, AllAppsList appsList,
+ BgDataModel dataModel, boolean isPrimaryInstance) {
+ this.mApp = app;
+ this.mAppsList = appsList;
+ this.mDataModel = dataModel;
+ this.mIsPrimaryInstance = isPrimaryInstance;
+ this.mContext = context;
+ }
+
+ /**
* Called periodically to validate and update any data
*/
@WorkerThread
@@ -76,6 +86,14 @@
public void loadItems(UserManagerState ums, Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
/**
+ * Load String cache
+ */
+ @WorkerThread
+ public void loadStringCache(StringCache cache) {
+ cache.loadStrings(mContext);
+ }
+
+ /**
* Called during loader after workspace loading is complete
*/
@WorkerThread
diff --git a/src/com/android/launcher3/model/ModelUtils.java b/src/com/android/launcher3/model/ModelUtils.java
index ef5eef1..422af43 100644
--- a/src/com/android/launcher3/model/ModelUtils.java
+++ b/src/com/android/launcher3/model/ModelUtils.java
@@ -23,10 +23,8 @@
import android.os.Process;
import android.util.Log;
-import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.Utilities;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.data.ItemInfo;
@@ -53,7 +51,7 @@
* specified screen.
*/
public static <T extends ItemInfo> void filterCurrentWorkspaceItems(
- IntSet currentScreenIds,
+ final IntSet currentScreenIds,
ArrayList<T> allWorkspaceItems,
ArrayList<T> currentScreenItems,
ArrayList<T> otherScreenItems) {
@@ -92,42 +90,6 @@
}
/**
- * Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to right)
- */
- public static void sortWorkspaceItemsSpatially(InvariantDeviceProfile profile,
- ArrayList<ItemInfo> workspaceItems) {
- final int screenCols = profile.numColumns;
- final int screenCellCount = profile.numColumns * profile.numRows;
- Collections.sort(workspaceItems, (lhs, rhs) -> {
- if (lhs.container == rhs.container) {
- // Within containers, order by their spatial position in that container
- switch (lhs.container) {
- case LauncherSettings.Favorites.CONTAINER_DESKTOP: {
- int lr = (lhs.screenId * screenCellCount + lhs.cellY * screenCols
- + lhs.cellX);
- int rr = (rhs.screenId * screenCellCount + +rhs.cellY * screenCols
- + rhs.cellX);
- return Integer.compare(lr, rr);
- }
- case LauncherSettings.Favorites.CONTAINER_HOTSEAT: {
- // We currently use the screen id as the rank
- return Integer.compare(lhs.screenId, rhs.screenId);
- }
- default:
- if (FeatureFlags.IS_STUDIO_BUILD) {
- throw new RuntimeException(
- "Unexpected container type when sorting workspace items.");
- }
- return 0;
- }
- } else {
- // Between containers, order by hotseat, desktop
- return Integer.compare(lhs.container, rhs.container);
- }
- });
- }
-
- /**
* Iterates though current workspace items and returns available hotseat ranks for prediction.
*/
public static IntArray getMissingHotseatRanks(List<ItemInfo> items, int len) {
diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java
index 94e06d1..0a68d4a 100644
--- a/src/com/android/launcher3/model/ModelWriter.java
+++ b/src/com/android/launcher3/model/ModelWriter.java
@@ -23,8 +23,10 @@
import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
+import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherAppState;
@@ -53,6 +55,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
@@ -271,28 +274,30 @@
/**
* Removes the specified item from the database
*/
- public void deleteItemFromDatabase(ItemInfo item) {
- deleteItemsFromDatabase(Arrays.asList(item));
+ public void deleteItemFromDatabase(ItemInfo item, @Nullable final String reason) {
+ deleteItemsFromDatabase(Arrays.asList(item), reason);
}
/**
* Removes all the items from the database matching {@param matcher}.
*/
- public void deleteItemsFromDatabase(ItemInfoMatcher matcher) {
+ public void deleteItemsFromDatabase(@NonNull final Predicate<ItemInfo> matcher,
+ @Nullable final String reason) {
deleteItemsFromDatabase(StreamSupport.stream(mBgDataModel.itemsIdMap.spliterator(), false)
- .filter(matcher::matchesInfo)
- .collect(Collectors.toList()));
+ .filter(matcher).collect(Collectors.toList()), reason);
}
/**
* Removes the specified items from the database
*/
- public void deleteItemsFromDatabase(final Collection<? extends ItemInfo> items) {
+ public void deleteItemsFromDatabase(final Collection<? extends ItemInfo> items,
+ @Nullable final String reason) {
ModelVerifier verifier = new ModelVerifier();
FileLog.d(TAG, "removing items from db " + items.stream().map(
(item) -> item.getTargetComponent() == null ? ""
: item.getTargetComponent().getPackageName()).collect(
- Collectors.joining(",")));
+ Collectors.joining(","))
+ + ". Reason: [" + (TextUtils.isEmpty(reason) ? "unknown" : reason) + "]");
notifyDelete(items);
enqueueDeleteRunnable(() -> {
for (ItemInfo item : items) {
@@ -328,14 +333,15 @@
/**
* Deletes the widget info and the widget id.
*/
- public void deleteWidgetInfo(final LauncherAppWidgetInfo info, LauncherAppWidgetHost host) {
+ public void deleteWidgetInfo(final LauncherAppWidgetInfo info, LauncherAppWidgetHost host,
+ @Nullable final String reason) {
notifyDelete(Collections.singleton(info));
if (host != null && !info.isCustomWidget() && info.isWidgetIdAllocated()) {
// Deleting an app widget ID is a void call but writes to disk before returning
// to the caller...
enqueueDeleteRunnable(() -> host.deleteAppWidgetId(info.appWidgetId));
}
- deleteItemFromDatabase(info);
+ deleteItemFromDatabase(info, reason);
}
private void notifyDelete(Collection<? extends ItemInfo> items) {
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 83fb3d1..489bc38 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -57,6 +57,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.function.Predicate;
/**
* Handles updates due to changes in package manager (app installed/updated/removed)
@@ -95,7 +96,7 @@
final int N = packages.length;
final FlagOp flagOp;
final HashSet<String> packageSet = new HashSet<>(Arrays.asList(packages));
- final ItemInfoMatcher matcher = mOp == OP_USER_AVAILABILITY_CHANGE
+ final Predicate<ItemInfo> matcher = mOp == OP_USER_AVAILABILITY_CHANGE
? ItemInfoMatcher.ofUser(mUser) // We want to update all packages for this user
: ItemInfoMatcher.ofPackages(packageSet, mUser);
final HashSet<ComponentName> removedComponents = new HashSet<>();
@@ -112,7 +113,7 @@
activitiesLists.put(
packages[i], appsList.addPackage(context, packages[i], mUser));
}
- flagOp = FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
+ flagOp = FlagOp.NO_OP.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
break;
}
case OP_UPDATE:
@@ -134,7 +135,7 @@
}
}
// Since package was just updated, the target must be available now.
- flagOp = FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
+ flagOp = FlagOp.NO_OP.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
break;
case OP_REMOVE: {
for (int i = 0; i < N; i++) {
@@ -148,13 +149,12 @@
if (DEBUG) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
appsList.removePackage(packages[i], mUser);
}
- flagOp = FlagOp.addFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
+ flagOp = FlagOp.NO_OP.addFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE);
break;
case OP_SUSPEND:
case OP_UNSUSPEND:
- flagOp = mOp == OP_SUSPEND ?
- FlagOp.addFlag(WorkspaceItemInfo.FLAG_DISABLED_SUSPENDED) :
- FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_SUSPENDED);
+ flagOp = FlagOp.NO_OP.setFlag(
+ WorkspaceItemInfo.FLAG_DISABLED_SUSPENDED, mOp == OP_SUSPEND);
if (DEBUG) Log.d(TAG, "mAllAppsList.(un)suspend " + N);
appsList.updateDisabledFlags(matcher, flagOp);
break;
@@ -162,9 +162,8 @@
UserManagerState ums = new UserManagerState();
ums.init(UserCache.INSTANCE.get(context),
context.getSystemService(UserManager.class));
- flagOp = ums.isUserQuiet(mUser)
- ? FlagOp.addFlag(WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER)
- : FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER);
+ flagOp = FlagOp.NO_OP.setFlag(
+ WorkspaceItemInfo.FLAG_DISABLED_QUIET_USER, ums.isUserQuiet(mUser));
appsList.updateDisabledFlags(matcher, flagOp);
// We are not synchronizing here, as int operations are atomic
@@ -208,7 +207,7 @@
}
ComponentName cn = si.getTargetComponent();
- if (cn != null && matcher.matches(si, cn)) {
+ if (cn != null && matcher.test(si)) {
String packageName = cn.getPackageName();
if (si.hasStatusFlag(WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI)) {
@@ -312,7 +311,9 @@
bindUpdatedWorkspaceItems(updatedWorkspaceItems);
if (!removedShortcuts.isEmpty()) {
- deleteAndBindComponentsRemoved(ItemInfoMatcher.ofItemIds(removedShortcuts));
+ deleteAndBindComponentsRemoved(
+ ItemInfoMatcher.ofItemIds(removedShortcuts),
+ "removed because the target component is invalid");
}
if (!widgets.isEmpty()) {
@@ -338,10 +339,11 @@
}
if (!removedPackages.isEmpty() || !removedComponents.isEmpty()) {
- ItemInfoMatcher removeMatch = ItemInfoMatcher.ofPackages(removedPackages, mUser)
+ Predicate<ItemInfo> removeMatch = ItemInfoMatcher.ofPackages(removedPackages, mUser)
.or(ItemInfoMatcher.ofComponents(removedComponents, mUser))
.and(ItemInfoMatcher.ofItemIds(forceKeepShortcuts).negate());
- deleteAndBindComponentsRemoved(removeMatch);
+ deleteAndBindComponentsRemoved(removeMatch,
+ "removed because the corresponding package or component is removed");
// Remove any queued items from the install queue
ItemInstallQueue.INSTANCE.get(context)
diff --git a/src/com/android/launcher3/model/ReloadStringCacheTask.java b/src/com/android/launcher3/model/ReloadStringCacheTask.java
new file mode 100644
index 0000000..f4d4298
--- /dev/null
+++ b/src/com/android/launcher3/model/ReloadStringCacheTask.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+package com.android.launcher3.model;
+
+import com.android.launcher3.LauncherAppState;
+
+/**
+ * Handles updates due to changes in Device Policy Management resources triggered by
+ * {@link android.app.admin.DevicePolicyManager#ACTION_DEVICE_POLICY_RESOURCE_UPDATED}.
+ */
+public class ReloadStringCacheTask extends BaseModelUpdateTask {
+ private ModelDelegate mModelDelegate;
+
+ public ReloadStringCacheTask(ModelDelegate modelDelegate) {
+ mModelDelegate = modelDelegate;
+ }
+
+ @Override
+ public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList appsList) {
+ synchronized (dataModel) {
+ mModelDelegate.loadStringCache(dataModel.stringCache);
+ StringCache cloneSC = dataModel.stringCache.clone();
+ scheduleCallbackTask(c -> c.bindStringCache(cloneSC));
+ }
+ }
+}
diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java
index 4296d32..1026e0b 100644
--- a/src/com/android/launcher3/model/ShortcutsChangedTask.java
+++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java
@@ -108,7 +108,8 @@
deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(
nonPinnedIds.stream()
.map(id -> new ShortcutKey(mPackageName, mUser, id))
- .collect(Collectors.toSet())));
+ .collect(Collectors.toSet())),
+ "removed because the shortcut is no longer available in shortcut service");
}
}
diff --git a/src/com/android/launcher3/model/StringCache.java b/src/com/android/launcher3/model/StringCache.java
new file mode 100644
index 0000000..9859ddc
--- /dev/null
+++ b/src/com/android/launcher3/model/StringCache.java
@@ -0,0 +1,254 @@
+/*
+ * 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.model;
+
+import android.annotation.SuppressLint;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+
+/**
+ *
+ * Cache for the device policy strings used in Launcher.
+ */
+public class StringCache {
+
+ private static final String PREFIX = "Launcher.";
+
+ /**
+ * Work folder name.
+ */
+ public static final String WORK_FOLDER_NAME = PREFIX + "WORK_FOLDER_NAME";
+
+ /**
+ * User on-boarding title for work profile apps.
+ */
+ private static final String WORK_PROFILE_EDU = PREFIX + "WORK_PROFILE_EDU";
+
+ /**
+ * Action label to finish work profile edu.
+ */
+ private static final String WORK_PROFILE_EDU_ACCEPT = PREFIX + "WORK_PROFILE_EDU_ACCEPT";
+
+ /**
+ * Title shown when user opens work apps tab while work profile is paused.
+ */
+ private static final String WORK_PROFILE_PAUSED_TITLE =
+ PREFIX + "WORK_PROFILE_PAUSED_TITLE";
+
+ /**
+ * Description shown when user opens work apps tab while work profile is paused.
+ */
+ private static final String WORK_PROFILE_PAUSED_DESCRIPTION =
+ PREFIX + "WORK_PROFILE_PAUSED_DESCRIPTION";
+
+ /**
+ * Shown on the button to pause work profile.
+ */
+ private static final String WORK_PROFILE_PAUSE_BUTTON =
+ PREFIX + "WORK_PROFILE_PAUSE_BUTTON";
+
+ /**
+ * Shown on the button to enable work profile.
+ */
+ private static final String WORK_PROFILE_ENABLE_BUTTON =
+ PREFIX + "WORK_PROFILE_ENABLE_BUTTON";
+
+ /**
+ * Label on launcher tab to indicate work apps.
+ */
+ private static final String ALL_APPS_WORK_TAB = PREFIX + "ALL_APPS_WORK_TAB";
+
+ /**
+ * Label on launcher tab to indicate personal apps.
+ */
+ private static final String ALL_APPS_PERSONAL_TAB = PREFIX + "ALL_APPS_PERSONAL_TAB";
+
+ /**
+ * Accessibility description for launcher tab to indicate work apps.
+ */
+ private static final String ALL_APPS_WORK_TAB_ACCESSIBILITY =
+ PREFIX + "ALL_APPS_WORK_TAB_ACCESSIBILITY";
+
+ /**
+ * Accessibility description for launcher tab to indicate personal apps.
+ */
+ private static final String ALL_APPS_PERSONAL_TAB_ACCESSIBILITY =
+ PREFIX + "ALL_APPS_PERSONAL_TAB_ACCESSIBILITY";
+
+ /**
+ * Label on widget tab to indicate work app widgets.
+ */
+ private static final String WIDGETS_WORK_TAB = PREFIX + "WIDGETS_WORK_TAB";
+
+ /**
+ * Label on widget tab to indicate personal app widgets.
+ */
+ private static final String WIDGETS_PERSONAL_TAB = PREFIX + "WIDGETS_PERSONAL_TAB";
+
+ /**
+ * Message shown when a feature is disabled by the admin (e.g. changing wallpaper).
+ */
+ private static final String DISABLED_BY_ADMIN_MESSAGE =
+ PREFIX + "DISABLED_BY_ADMIN_MESSAGE";
+
+ /**
+ * User on-boarding title for work profile apps.
+ */
+ public String workProfileEdu;
+
+ /**
+ * Action label to finish work profile edu.
+ */
+ public String workProfileEduAccept;
+
+ /**
+ * Title shown when user opens work apps tab while work profile is paused.
+ */
+ public String workProfilePausedTitle;
+
+ /**
+ * Description shown when user opens work apps tab while work profile is paused.
+ */
+ public String workProfilePausedDescription;
+
+ /**
+ * Shown on the button to pause work profile.
+ */
+ public String workProfilePauseButton;
+
+ /**
+ * Shown on the button to enable work profile.
+ */
+ public String workProfileEnableButton;
+
+ /**
+ * Label on launcher tab to indicate work apps.
+ */
+ public String allAppsWorkTab;
+
+ /**
+ * Label on launcher tab to indicate personal apps.
+ */
+ public String allAppsPersonalTab;
+
+ /**
+ * Accessibility description for launcher tab to indicate work apps.
+ */
+ public String allAppsWorkTabAccessibility;
+
+ /**
+ * Accessibility description for launcher tab to indicate personal apps.
+ */
+ public String allAppsPersonalTabAccessibility;
+
+ /**
+ * Work folder name.
+ */
+ public String workFolderName;
+
+ /**
+ * Label on widget tab to indicate work app widgets.
+ */
+ public String widgetsWorkTab;
+
+ /**
+ * Label on widget tab to indicate personal app widgets.
+ */
+ public String widgetsPersonalTab;
+
+ /**
+ * Message shown when a feature is disabled by the admin (e.g. changing wallpaper).
+ */
+ public String disabledByAdminMessage;
+
+ /**
+ * Sets the default values for the strings.
+ */
+ public void loadStrings(Context context) {
+ workProfileEdu = getEnterpriseString(
+ context, WORK_PROFILE_EDU, R.string.work_profile_edu_work_apps);
+ workProfileEduAccept = getEnterpriseString(
+ context, WORK_PROFILE_EDU_ACCEPT, R.string.work_profile_edu_accept);
+ workProfilePausedTitle = getEnterpriseString(
+ context, WORK_PROFILE_PAUSED_TITLE, R.string.work_apps_paused_title);
+ workProfilePausedDescription = getEnterpriseString(
+ context, WORK_PROFILE_PAUSED_DESCRIPTION, R.string.work_apps_paused_body);
+ workProfilePauseButton = getEnterpriseString(
+ context, WORK_PROFILE_PAUSE_BUTTON, R.string.work_apps_pause_btn_text);
+ workProfileEnableButton = getEnterpriseString(
+ context, WORK_PROFILE_ENABLE_BUTTON, R.string.work_apps_enable_btn_text);
+ allAppsWorkTab = getEnterpriseString(
+ context, ALL_APPS_WORK_TAB, R.string.all_apps_work_tab);
+ allAppsPersonalTab = getEnterpriseString(
+ context, ALL_APPS_PERSONAL_TAB, R.string.all_apps_personal_tab);
+ allAppsWorkTabAccessibility = getEnterpriseString(
+ context, ALL_APPS_WORK_TAB_ACCESSIBILITY, R.string.all_apps_button_work_label);
+ allAppsPersonalTabAccessibility = getEnterpriseString(
+ context, ALL_APPS_PERSONAL_TAB_ACCESSIBILITY,
+ R.string.all_apps_button_personal_label);
+ workFolderName = getEnterpriseString(
+ context, WORK_FOLDER_NAME, R.string.work_folder_name);
+ widgetsWorkTab = getEnterpriseString(
+ context, WIDGETS_WORK_TAB, R.string.widgets_full_sheet_work_tab);
+ widgetsPersonalTab = getEnterpriseString(
+ context, WIDGETS_PERSONAL_TAB, R.string.widgets_full_sheet_personal_tab);
+ disabledByAdminMessage = getEnterpriseString(
+ context, DISABLED_BY_ADMIN_MESSAGE, R.string.msg_disabled_by_admin);
+ }
+
+ @SuppressLint("NewApi")
+ private String getEnterpriseString(
+ Context context, String updatableStringId, int defaultStringId) {
+ return Utilities.ATLEAST_T
+ ? getUpdatableEnterpriseSting(context, updatableStringId, defaultStringId)
+ : context.getString(defaultStringId);
+ }
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private String getUpdatableEnterpriseSting(
+ Context context, String updatableStringId, int defaultStringId) {
+ DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+ return dpm.getResources().getString(
+ updatableStringId, () -> context.getString(defaultStringId));
+ }
+
+ @Override
+ public StringCache clone() {
+ StringCache clone = new StringCache();
+ clone.workProfileEdu = this.workProfileEdu;
+ clone.workProfileEduAccept = this.workProfileEduAccept;
+ clone.workProfilePausedTitle = this.workProfilePausedTitle;
+ clone.workProfilePausedDescription = this.workProfilePausedDescription;
+ clone.workProfilePauseButton = this.workProfilePauseButton;
+ clone.workProfileEnableButton = this.workProfileEnableButton;
+ clone.allAppsWorkTab = this.allAppsWorkTab;
+ clone.allAppsPersonalTab = this.allAppsPersonalTab;
+ clone.allAppsWorkTabAccessibility = this.allAppsWorkTabAccessibility;
+ clone.allAppsPersonalTabAccessibility = this.allAppsPersonalTabAccessibility;
+ clone.workFolderName = this.workFolderName;
+ clone.widgetsWorkTab = this.widgetsWorkTab;
+ clone.widgetsPersonalTab = this.widgetsPersonalTab;
+ clone.disabledByAdminMessage = this.disabledByAdminMessage;
+ return clone;
+ }
+}
diff --git a/src/com/android/launcher3/model/UserLockStateChangedTask.java b/src/com/android/launcher3/model/UserLockStateChangedTask.java
index 5048e13..1565b19 100644
--- a/src/com/android/launcher3/model/UserLockStateChangedTask.java
+++ b/src/com/android/launcher3/model/UserLockStateChangedTask.java
@@ -96,7 +96,9 @@
}
bindUpdatedWorkspaceItems(updatedWorkspaceItemInfos);
if (!removedKeys.isEmpty()) {
- deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(removedKeys));
+ deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(removedKeys),
+ "removed during unlock because it's no longer available"
+ + " (possibly due to clear data)");
}
// Remove shortcut id map for that user
diff --git a/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java b/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java
new file mode 100644
index 0000000..93fc6a5
--- /dev/null
+++ b/src/com/android/launcher3/model/WorkspaceItemSpaceFinder.java
@@ -0,0 +1,115 @@
+/*
+ * 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.model;
+
+import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
+
+import android.util.LongSparseArray;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.util.GridOccupancy;
+import com.android.launcher3.util.IntArray;
+import com.android.launcher3.util.IntSet;
+
+import java.util.ArrayList;
+
+/**
+ * Utility class to help find space for new workspace items
+ */
+public class WorkspaceItemSpaceFinder {
+
+ /**
+ * Find a position on the screen for the given size or adds a new screen.
+ *
+ * @return screenId and the coordinates for the item in an int array of size 3.
+ */
+ public int[] findSpaceForItem(LauncherAppState app, BgDataModel dataModel,
+ IntArray workspaceScreens, IntArray addedWorkspaceScreensFinal, int spanX, int spanY) {
+ LongSparseArray<ArrayList<ItemInfo>> screenItems = new LongSparseArray<>();
+
+ // Use sBgItemsIdMap as all the items are already loaded.
+ synchronized (dataModel) {
+ for (ItemInfo info : dataModel.itemsIdMap) {
+ if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ ArrayList<ItemInfo> items = screenItems.get(info.screenId);
+ if (items == null) {
+ items = new ArrayList<>();
+ screenItems.put(info.screenId, items);
+ }
+ items.add(info);
+ }
+ }
+ }
+
+ // Find appropriate space for the item.
+ int screenId = 0;
+ int[] coordinates = new int[2];
+ boolean found = false;
+
+ int screenCount = workspaceScreens.size();
+ // First check the preferred screen.
+ IntSet screensToExclude = new IntSet();
+ if (FeatureFlags.QSB_ON_FIRST_SCREEN) {
+ screensToExclude.add(FIRST_SCREEN_ID);
+ }
+
+ for (int screen = 0; screen < screenCount; screen++) {
+ screenId = workspaceScreens.get(screen);
+ if (!screensToExclude.contains(screenId) && findNextAvailableIconSpaceInScreen(
+ app, screenItems.get(screenId), coordinates, spanX, spanY)) {
+ // We found a space for it
+ found = true;
+ break;
+ }
+ }
+
+ 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);
+
+ // Save the screen id for binding in the workspace
+ workspaceScreens.add(screenId);
+ addedWorkspaceScreensFinal.add(screenId);
+
+ // If we still can't find an empty space, then God help us all!!!
+ if (!findNextAvailableIconSpaceInScreen(
+ app, screenItems.get(screenId), coordinates, spanX, spanY)) {
+ throw new RuntimeException("Can't find space to add the item");
+ }
+ }
+ return new int[]{screenId, coordinates[0], coordinates[1]};
+ }
+
+ private boolean findNextAvailableIconSpaceInScreen(
+ LauncherAppState app, ArrayList<ItemInfo> occupiedPos,
+ int[] xy, int spanX, int spanY) {
+ InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
+
+ GridOccupancy occupied = new GridOccupancy(profile.numColumns, profile.numRows);
+ if (occupiedPos != null) {
+ for (ItemInfo r : occupiedPos) {
+ occupied.markCells(r, true);
+ }
+ }
+ return occupied.findVacantCell(xy, spanX, spanY);
+ }
+}
diff --git a/src/com/android/launcher3/model/data/AppInfo.java b/src/com/android/launcher3/model/data/AppInfo.java
index 7f70bad..5b2bcf5 100644
--- a/src/com/android/launcher3/model/data/AppInfo.java
+++ b/src/com/android/launcher3/model/data/AppInfo.java
@@ -35,7 +35,6 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.Utilities;
import com.android.launcher3.pm.PackageInstallInfo;
-import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageManagerHelper;
import java.util.Comparator;
@@ -43,7 +42,7 @@
/**
* Represents an app in AllAppsView.
*/
-public class AppInfo extends ItemInfoWithIcon {
+public class AppInfo extends ItemInfoWithIcon implements WorkspaceItemFactory {
public static final AppInfo[] EMPTY_ARRAY = new AppInfo[0];
public static final Comparator<AppInfo> COMPONENT_KEY_COMPARATOR = (a, b) -> {
@@ -121,7 +120,8 @@
return super.dumpProperties() + " componentName=" + componentName;
}
- public WorkspaceItemInfo makeWorkspaceItem() {
+ @Override
+ public WorkspaceItemInfo makeWorkspaceItem(Context context) {
WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(this);
if ((runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0) {
@@ -139,10 +139,6 @@
return workspaceItemInfo;
}
- public ComponentKey toComponentKey() {
- return new ComponentKey(componentName, user);
- }
-
public static Intent makeLaunchIntent(LauncherActivityInfo info) {
return makeLaunchIntent(info.getComponentName());
}
diff --git a/src/com/android/launcher3/model/data/FolderInfo.java b/src/com/android/launcher3/model/data/FolderInfo.java
index cd2ef35..efebce3 100644
--- a/src/com/android/launcher3/model/data/FolderInfo.java
+++ b/src/com/android/launcher3/model/data/FolderInfo.java
@@ -217,7 +217,7 @@
return getDefaultItemInfoBuilder()
.setFolderIcon(folderIcon)
.setRank(rank)
- .setAttribute(getLabelState().mLogAttribute)
+ .addItemAttributes(getLabelState().mLogAttribute)
.setContainerInfo(getContainerInfo())
.build();
}
diff --git a/src/com/android/launcher3/model/data/IconRequestInfo.java b/src/com/android/launcher3/model/data/IconRequestInfo.java
index 5dc6a3b..fbf01e5 100644
--- a/src/com/android/launcher3/model/data/IconRequestInfo.java
+++ b/src/com/android/launcher3/model/data/IconRequestInfo.java
@@ -75,7 +75,10 @@
this.useLowResIcon = useLowResIcon;
}
- /** Loads */
+ /**
+ * Loads this request's item info's title. This method should only be used on IconRequestInfos
+ * for WorkspaceItemInfos.
+ */
public boolean loadWorkspaceIcon(Context context) {
if (!(itemInfo instanceof WorkspaceItemInfo)) {
throw new IllegalStateException(
diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
index a74c02f..76a0c4d 100644
--- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
@@ -23,6 +23,7 @@
import androidx.annotation.Nullable;
import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.BitmapInfo.DrawableCreationFlags;
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.pm.PackageInstallInfo;
@@ -70,10 +71,6 @@
*/
public static final int FLAG_DISABLED_LOCKED_USER = 1 << 5;
- public static final int FLAG_DISABLED_MASK = FLAG_DISABLED_SAFEMODE
- | FLAG_DISABLED_NOT_AVAILABLE | FLAG_DISABLED_SUSPENDED
- | FLAG_DISABLED_QUIET_USER | FLAG_DISABLED_BY_PUBLISHER | FLAG_DISABLED_LOCKED_USER;
-
/**
* The item points to a system app.
*/
@@ -113,6 +110,16 @@
| FLAG_INCREMENTAL_DOWNLOAD_ACTIVE;
/**
+ * Indicates that the icon is a disabled shortcut and application updates are required.
+ */
+ public static final int FLAG_DISABLED_VERSION_LOWER = 1 << 12;
+
+ public static final int FLAG_DISABLED_MASK = FLAG_DISABLED_SAFEMODE
+ | FLAG_DISABLED_NOT_AVAILABLE | FLAG_DISABLED_SUSPENDED
+ | FLAG_DISABLED_QUIET_USER | FLAG_DISABLED_BY_PUBLISHER | FLAG_DISABLED_LOCKED_USER
+ | FLAG_DISABLED_VERSION_LOWER;
+
+ /**
* 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.
*/
@@ -230,15 +237,14 @@
* Returns a FastBitmapDrawable with the icon.
*/
public FastBitmapDrawable newIcon(Context context) {
- return newIcon(context, false);
+ return newIcon(context, 0);
}
/**
* Returns a FastBitmapDrawable with the icon and context theme applied
*/
- public FastBitmapDrawable newIcon(Context context, boolean applyTheme) {
- FastBitmapDrawable drawable = applyTheme
- ? bitmap.newThemedIcon(context) : bitmap.newIcon(context);
+ public FastBitmapDrawable newIcon(Context context, @DrawableCreationFlags int creationFlags) {
+ FastBitmapDrawable drawable = bitmap.newIcon(context, creationFlags);
drawable.setIsDisabled(isDisabled());
return drawable;
}
diff --git a/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java b/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
index 0283d5f..e57a895 100644
--- a/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
@@ -288,7 +288,7 @@
LauncherAtom.ItemInfo info = super.buildProto(folderInfo);
return info.toBuilder()
.setWidget(info.getWidget().toBuilder().setWidgetFeatures(widgetFeatures))
- .setAttribute(getAttribute(sourceContainer))
+ .addItemAttributes(getAttribute(sourceContainer))
.build();
}
}
diff --git a/src/com/android/launcher3/model/data/SearchActionItemInfo.java b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
index c6e5e8a..e879313 100644
--- a/src/com/android/launcher3/model/data/SearchActionItemInfo.java
+++ b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.LauncherSettings.Favorites.EXTENDED_CONTAINERS;
import android.app.PendingIntent;
+import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.os.Process;
@@ -26,19 +27,14 @@
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.logger.LauncherAtom.ItemInfo;
import com.android.launcher3.logger.LauncherAtom.SearchActionItem;
-import com.android.launcher3.model.AllAppsList;
-import com.android.launcher3.model.BaseModelUpdateTask;
-import com.android.launcher3.model.BgDataModel;
/**
* Represents a SearchAction with in launcher
*/
-public class SearchActionItemInfo extends ItemInfoWithIcon {
+public class SearchActionItemInfo extends ItemInfoWithIcon implements WorkspaceItemFactory {
public static final int FLAG_SHOULD_START = 1 << 1;
public static final int FLAG_SHOULD_START_FOR_RESULT = FLAG_SHOULD_START | 1 << 2;
@@ -159,7 +155,8 @@
/**
* Creates a {@link WorkspaceItemInfo} coorsponding to search action to be stored in launcher db
*/
- public WorkspaceItemInfo createWorkspaceItem(LauncherModel model) {
+ @Override
+ public WorkspaceItemInfo makeWorkspaceItem(Context context) {
WorkspaceItemInfo info = new WorkspaceItemInfo();
info.title = title;
info.bitmap = bitmap;
@@ -168,20 +165,12 @@
if (hasFlags(FLAG_SHOULD_START_FOR_RESULT)) {
info.options |= WorkspaceItemInfo.FLAG_START_FOR_RESULT;
}
-
- model.enqueueModelUpdateTask(new BaseModelUpdateTask() {
- @Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
-
- model.updateAndBindWorkspaceItem(() -> {
- PackageItemInfo pkgInfo = new PackageItemInfo(getIntentPackageName(), user);
- app.getIconCache().getTitleAndIconForApp(pkgInfo, false);
- try (LauncherIcons li = LauncherIcons.obtain(app.getContext())) {
- info.bitmap = li.badgeBitmap(info.bitmap.icon, pkgInfo.bitmap);
- }
- return info;
- });
- }
+ LauncherAppState app = LauncherAppState.getInstance(context);
+ app.getModel().updateAndBindWorkspaceItem(() -> {
+ PackageItemInfo pkgInfo = new PackageItemInfo(getIntentPackageName(), user);
+ app.getIconCache().getTitleAndIconForApp(pkgInfo, false);
+ info.bitmap = info.bitmap.withBadgeInfo(pkgInfo.bitmap);
+ return info;
});
return info;
}
diff --git a/src/com/android/launcher3/allapps/DecorationInfo.java b/src/com/android/launcher3/model/data/WorkspaceItemFactory.java
similarity index 61%
copy from src/com/android/launcher3/allapps/DecorationInfo.java
copy to src/com/android/launcher3/model/data/WorkspaceItemFactory.java
index 50b250c..47b9c6e 100644
--- a/src/com/android/launcher3/allapps/DecorationInfo.java
+++ b/src/com/android/launcher3/model/data/WorkspaceItemFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * 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.
@@ -13,7 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.launcher3.allapps;
+package com.android.launcher3.model.data;
-public class DecorationInfo {
+import android.content.Context;
+
+/**
+ * Interface to objects capable of generating workspace item
+ */
+public interface WorkspaceItemFactory {
+
+ /**
+ * Called to create a pinnable item info
+ */
+ WorkspaceItemInfo makeWorkspaceItem(Context context);
}
diff --git a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
index a195979..2b3da33 100644
--- a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
+++ b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
@@ -180,12 +180,25 @@
runtimeStatusFlags |= FLAG_DISABLED_BY_PUBLISHER;
}
disabledMessage = shortcutInfo.getDisabledMessage();
+ if (Utilities.ATLEAST_P
+ && shortcutInfo.getDisabledReason() == ShortcutInfo.DISABLED_REASON_VERSION_LOWER) {
+ runtimeStatusFlags |= FLAG_DISABLED_VERSION_LOWER;
+ } else {
+ runtimeStatusFlags &= ~FLAG_DISABLED_VERSION_LOWER;
+ }
Person[] persons = ApiWrapper.getPersons(shortcutInfo);
personKeys = persons.length == 0 ? Utilities.EMPTY_STRING_ARRAY
: Arrays.stream(persons).map(Person::getKey).sorted().toArray(String[]::new);
}
+ /**
+ * {@code true} if the shortcut is disabled due to its app being a lower version.
+ */
+ public boolean isDisabledVersionLower() {
+ return (runtimeStatusFlags & FLAG_DISABLED_VERSION_LOWER) != 0;
+ }
+
/** Returns the WorkspaceItemInfo id associated with the deep shortcut. */
public String getDeepShortcutId() {
return itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT
diff --git a/src/com/android/launcher3/notification/NotificationInfo.java b/src/com/android/launcher3/notification/NotificationInfo.java
index d27d8c7..bb2c37f 100644
--- a/src/com/android/launcher3/notification/NotificationInfo.java
+++ b/src/com/android/launcher3/notification/NotificationInfo.java
@@ -16,6 +16,8 @@
package com.android.launcher3.notification;
+import static com.android.launcher3.AbstractFloatingView.TYPE_ACTION_POPUP;
+import static com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_ALL_APPS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NOTIFICATION_LAUNCH_TAP;
import android.app.ActivityOptions;
@@ -29,12 +31,13 @@
import android.view.View;
import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.util.PackageUserKey;
+import com.android.launcher3.views.ActivityContext;
/**
* An object that contains relevant information from a {@link StatusBarNotification}. This should
@@ -99,21 +102,24 @@
if (intent == null) {
return;
}
- final Launcher launcher = Launcher.getLauncher(view.getContext());
+ final ActivityContext context = ActivityContext.lookupContext(view.getContext());
Bundle activityOptions = ActivityOptions.makeClipRevealAnimation(
view, 0, 0, view.getWidth(), view.getHeight()).toBundle();
try {
intent.send(null, 0, null, null, null, null, activityOptions);
- launcher.getStatsLogManager().logger().withItemInfo(mItemInfo)
+ context.getStatsLogManager().logger().withItemInfo(mItemInfo)
.log(LAUNCHER_NOTIFICATION_LAUNCH_TAP);
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
if (autoCancel) {
- launcher.getPopupDataProvider().cancelNotification(notificationKey);
+ PopupDataProvider popupDataProvider = context.getPopupDataProvider();
+ if (popupDataProvider != null) {
+ popupDataProvider.cancelNotification(notificationKey);
+ }
}
- AbstractFloatingView.closeOpenContainer(launcher, AbstractFloatingView
- .TYPE_ACTION_POPUP);
+ AbstractFloatingView.closeOpenViews(
+ context, true, TYPE_ACTION_POPUP | TYPE_TASKBAR_ALL_APPS);
}
public Drawable getIconForBackground(Context context, int background) {
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index e58f5fa..04eb38a 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -30,10 +30,12 @@
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import androidx.annotation.AnyThread;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
@@ -66,7 +68,8 @@
private static final int MSG_RANKING_UPDATE = 5;
private static NotificationListener sNotificationListenerInstance = null;
- private static NotificationsChangedListener sNotificationsChangedListener;
+ private static final ArraySet<NotificationsChangedListener> sNotificationsChangedListeners =
+ new ArraySet<>();
private static boolean sIsConnected;
private final Handler mWorkerHandler;
@@ -94,8 +97,11 @@
return sIsConnected ? sNotificationListenerInstance : null;
}
- public static void setNotificationsChangedListener(NotificationsChangedListener listener) {
- sNotificationsChangedListener = listener;
+ public static void addNotificationsChangedListener(NotificationsChangedListener listener) {
+ if (listener == null) {
+ return;
+ }
+ sNotificationsChangedListeners.add(listener);
NotificationListener notificationListener = getInstanceIfConnected();
if (notificationListener != null) {
@@ -108,8 +114,10 @@
}
}
- public static void removeNotificationsChangedListener() {
- sNotificationsChangedListener = null;
+ public static void removeNotificationsChangedListener(NotificationsChangedListener listener) {
+ if (listener != null) {
+ sNotificationsChangedListeners.remove(listener);
+ }
}
private boolean handleWorkerMessage(Message message) {
@@ -147,14 +155,9 @@
case MSG_NOTIFICATION_FULL_REFRESH:
List<StatusBarNotification> activeNotifications = null;
if (sIsConnected) {
- try {
- activeNotifications = Arrays.stream(getActiveNotifications())
- .filter(this::notificationIsValidForUI)
- .collect(Collectors.toList());
- } catch (SecurityException ex) {
- Log.e(TAG, "SecurityException: failed to fetch notifications");
- activeNotifications = new ArrayList<>();
- }
+ activeNotifications = Arrays.stream(getActiveNotificationsSafely(null))
+ .filter(this::notificationIsValidForUI)
+ .collect(Collectors.toList());
} else {
activeNotifications = new ArrayList<>();
}
@@ -168,7 +171,7 @@
}
case MSG_RANKING_UPDATE: {
String[] keys = ((RankingMap) message.obj).getOrderedKeys();
- for (StatusBarNotification sbn : getActiveNotifications(keys)) {
+ for (StatusBarNotification sbn : getActiveNotificationsSafely(keys)) {
updateGroupKeyIfNecessary(sbn);
}
return true;
@@ -180,29 +183,43 @@
private boolean handleUiMessage(Message message) {
switch (message.what) {
case MSG_NOTIFICATION_POSTED:
- if (sNotificationsChangedListener != null) {
+ if (sNotificationsChangedListeners.size() > 0) {
Pair<PackageUserKey, NotificationKeyData> msg = (Pair) message.obj;
- sNotificationsChangedListener.onNotificationPosted(
- msg.first, msg.second);
+ for (NotificationsChangedListener listener : sNotificationsChangedListeners) {
+ listener.onNotificationPosted(msg.first, msg.second);
+ }
}
break;
case MSG_NOTIFICATION_REMOVED:
- if (sNotificationsChangedListener != null) {
+ if (sNotificationsChangedListeners.size() > 0) {
Pair<PackageUserKey, NotificationKeyData> msg = (Pair) message.obj;
- sNotificationsChangedListener.onNotificationRemoved(
- msg.first, msg.second);
+ for (NotificationsChangedListener listener : sNotificationsChangedListeners) {
+ listener.onNotificationRemoved(msg.first, msg.second);
+ }
}
break;
case MSG_NOTIFICATION_FULL_REFRESH:
- if (sNotificationsChangedListener != null) {
- sNotificationsChangedListener.onNotificationFullRefresh(
- (List<StatusBarNotification>) message.obj);
+ if (sNotificationsChangedListeners.size() > 0) {
+ for (NotificationsChangedListener listener : sNotificationsChangedListeners) {
+ listener.onNotificationFullRefresh(
+ (List<StatusBarNotification>) message.obj);
+ }
}
break;
}
return true;
}
+ private @NonNull StatusBarNotification[] getActiveNotificationsSafely(@Nullable String[] keys) {
+ StatusBarNotification[] result = null;
+ try {
+ result = getActiveNotifications(keys);
+ } catch (SecurityException e) {
+ Log.e(TAG, "SecurityException: failed to fetch notifications");
+ }
+ return result == null ? new StatusBarNotification[0] : result;
+ }
+
@Override
public void onListenerConnected() {
super.onListenerConnected();
@@ -302,9 +319,8 @@
*/
@WorkerThread
public List<StatusBarNotification> getNotificationsForKeys(List<NotificationKeyData> keys) {
- StatusBarNotification[] notifications = getActiveNotifications(
- keys.stream().map(n -> n.notificationKey).toArray(String[]::new));
- return notifications == null ? Collections.emptyList() : Arrays.asList(notifications);
+ return Arrays.asList(getActiveNotificationsSafely(
+ keys.stream().map(n -> n.notificationKey).toArray(String[]::new)));
}
/**
diff --git a/src/com/android/launcher3/notification/NotificationMainView.java b/src/com/android/launcher3/notification/NotificationMainView.java
index f9ff8a6..16a4057 100644
--- a/src/com/android/launcher3/notification/NotificationMainView.java
+++ b/src/com/android/launcher3/notification/NotificationMainView.java
@@ -38,11 +38,12 @@
import androidx.annotation.Nullable;
-import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.util.Themes;
+import com.android.launcher3.views.ActivityContext;
/**
* A {@link android.widget.FrameLayout} that contains a single notification,
@@ -320,9 +321,12 @@
}
public void onChildDismissed() {
- Launcher launcher = Launcher.getLauncher(getContext());
- launcher.getPopupDataProvider().cancelNotification(
- mNotificationInfo.notificationKey);
- launcher.getStatsLogManager().logger().log(LAUNCHER_NOTIFICATION_DISMISSED);
+ ActivityContext activityContext = ActivityContext.lookupContext(getContext());
+ PopupDataProvider popupDataProvider = activityContext.getPopupDataProvider();
+ if (popupDataProvider == null) {
+ return;
+ }
+ popupDataProvider.cancelNotification(mNotificationInfo.notificationKey);
+ activityContext.getStatsLogManager().logger().log(LAUNCHER_NOTIFICATION_DISMISSED);
}
}
diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java
index 8fafb6f..ec69193 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicator.java
@@ -25,4 +25,25 @@
void setActiveMarker(int activePage);
void setMarkersCount(int numMarkers);
+
+ /**
+ * Sets the flag if the Page Indicator should autohide.
+ */
+ default void setShouldAutoHide(boolean shouldAutoHide) {
+ // No-op by default
+ }
+
+ /**
+ * Pauses all currently running animations.
+ */
+ default void pauseAnimations() {
+ // No-op by default
+ }
+
+ /**
+ * Force-ends all currently running or paused animations.
+ */
+ default void skipAnimationsToEnd() {
+ // No-op by default
+ }
}
diff --git a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
index c685891..1681ea5 100644
--- a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
@@ -187,6 +187,7 @@
}
}
+ @Override
public void setShouldAutoHide(boolean shouldAutoHide) {
mShouldAutoHide = shouldAutoHide;
if (shouldAutoHide && mLinePaint.getAlpha() > 0) {
@@ -236,6 +237,7 @@
/**
* Pauses all currently running animations.
*/
+ @Override
public void pauseAnimations() {
for (int i = 0; i < ANIMATOR_COUNT; i++) {
if (mAnimators[i] != null) {
@@ -247,6 +249,7 @@
/**
* Force-ends all currently running or paused animations.
*/
+ @Override
public void skipAnimationsToEnd() {
for (int i = 0; i < ANIMATOR_COUNT; i++) {
if (mAnimators[i] != null) {
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index 4b86f65..618f926 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -27,6 +27,7 @@
import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
@@ -38,6 +39,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.ItemInstallQueue;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.MainThreadInitializedObject;
@@ -142,6 +144,16 @@
if (sessionInfo == null
|| sessionInfo.getInstallerPackageName() == null
|| TextUtils.isEmpty(sessionInfo.getAppPackageName())) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + " verify"
+ + ", info=" + (sessionInfo == null)
+ + ", info install name" + (sessionInfo == null
+ ? null
+ : sessionInfo.getInstallerPackageName())
+ + ", empty pkg name" + TextUtils.isEmpty((sessionInfo == null
+ ? null
+ : sessionInfo.getAppPackageName())));
+ }
return null;
}
String pkg = sessionInfo.getInstallerPackageName();
@@ -211,6 +223,14 @@
*/
@WorkerThread
void tryQueuePromiseAppIcon(PackageInstaller.SessionInfo sessionInfo) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + " tryQueuePromiseAppIcon"
+ + ", FeatureFlags=" + FeatureFlags.PROMISE_APPS_NEW_INSTALLS.get()
+ + ", SessionCommitReceiveEnabled" + SessionCommitReceiver.isEnabled(mAppContext)
+ + ", verifySessionInfo(sessionInfo)=" + verifySessionInfo(sessionInfo)
+ + ", !promiseIconAdded=" + (sessionInfo != null
+ && !promiseIconAddedForId(sessionInfo.getSessionId())));
+ }
if (FeatureFlags.PROMISE_APPS_NEW_INSTALLS.get()
&& SessionCommitReceiver.isEnabled(mAppContext)
&& verifySessionInfo(sessionInfo)
@@ -227,6 +247,20 @@
}
public boolean verifySessionInfo(PackageInstaller.SessionInfo sessionInfo) {
+ if (TestProtocol.sDebugTracing) {
+ boolean appNotInstalled = sessionInfo == null
+ || !new PackageManagerHelper(mAppContext)
+ .isAppInstalled(sessionInfo.getAppPackageName(), getUserHandle(sessionInfo));
+ boolean labelNotEmpty = sessionInfo != null
+ && !TextUtils.isEmpty(sessionInfo.getAppLabel());
+ Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + " verifySessionInfo"
+ + ", verify(sessionInfo)=" + verify(sessionInfo)
+ + ", reason=" + (sessionInfo == null ? null : sessionInfo.getInstallReason())
+ + ", PackageManager.INSTALL_REASON_USER=" + PackageManager.INSTALL_REASON_USER
+ + ", hasIcon=" + (sessionInfo != null && sessionInfo.getAppIcon() != null)
+ + ", label is ! empty=" + labelNotEmpty
+ + " +, app not installed=" + appNotInstalled);
+ }
return verify(sessionInfo) != null
&& sessionInfo.getInstallReason() == PackageManager.INSTALL_REASON_USER
&& sessionInfo.getAppIcon() != null
diff --git a/src/com/android/launcher3/pm/InstallSessionTracker.java b/src/com/android/launcher3/pm/InstallSessionTracker.java
index e1b3c1a..75cf7a8 100644
--- a/src/com/android/launcher3/pm/InstallSessionTracker.java
+++ b/src/com/android/launcher3/pm/InstallSessionTracker.java
@@ -25,10 +25,12 @@
import android.content.pm.PackageInstaller.SessionInfo;
import android.os.Build;
import android.os.UserHandle;
+import android.util.Log;
import android.util.SparseArray;
import androidx.annotation.WorkerThread;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.PackageUserKey;
import java.lang.ref.WeakReference;
@@ -57,10 +59,19 @@
public void onCreated(int sessionId) {
InstallSessionHelper helper = mWeakHelper.get();
Callback callback = mWeakCallback.get();
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON, "Session created sessionId=" + sessionId
+ + ", callback=" + callback
+ + ", helper=" + helper);
+ }
if (callback == null || helper == null) {
return;
}
SessionInfo sessionInfo = pushSessionDisplayToLauncher(sessionId, helper, callback);
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON, "Session created sessionId=" + sessionId
+ + ", sessionInfo=" + sessionInfo);
+ }
if (sessionInfo != null) {
callback.onInstallSessionCreated(PackageInstallInfo.fromInstallingState(sessionInfo));
}
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index b1a4109..196cc56 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -48,7 +48,7 @@
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
-import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.InsettableFrameLayout;
@@ -120,7 +120,7 @@
private final GradientDrawable mRoundedTop;
private final GradientDrawable mRoundedBottom;
- private Runnable mOnCloseCallback = () -> { };
+ @Nullable private Runnable mOnCloseCallback = null;
// The rect string of the view that the arrow is attached to, in screen reference frame.
protected int mArrowColor;
@@ -351,7 +351,7 @@
if (mColorExtractors == null) {
return;
}
- Workspace workspace = launcher.getWorkspace();
+ Workspace<?> workspace = launcher.getWorkspace();
if (workspace == null) {
return;
}
@@ -602,6 +602,7 @@
mIsAboveIcon = y > dragLayer.getTop() + insets.top;
if (!mIsAboveIcon) {
y = mTempRect.top + iconHeight + extraVerticalSpace;
+ height -= extraVerticalSpace;
}
// Insets are added later, so subtract them now.
@@ -609,7 +610,7 @@
y -= insets.top;
mGravity = 0;
- if (y + height > dragLayer.getBottom() - insets.bottom) {
+ if ((insets.top + y + height) > (dragLayer.getBottom() - insets.bottom)) {
// The container is opening off the screen, so just center it in the drag layer instead.
mGravity = Gravity.CENTER_VERTICAL;
// Put the container next to the icon, preferring the right side in ltr (left in rtl).
@@ -766,7 +767,6 @@
}
}
-
protected void animateClose() {
if (!mIsOpen) {
return;
@@ -816,7 +816,9 @@
mDeferContainerRemoval = false;
getPopupContainer().removeView(this);
getPopupContainer().removeView(mArrow);
- mOnCloseCallback.run();
+ if (mOnCloseCallback != null) {
+ mOnCloseCallback.run();
+ }
if (mColorExtractors != null) {
mColorExtractors.forEach(e -> e.setListener(null));
}
@@ -825,7 +827,7 @@
/**
* Callback to be called when the popup is closed
*/
- public void setOnCloseCallback(@NonNull Runnable callback) {
+ public void setOnCloseCallback(@Nullable Runnable callback) {
mOnCloseCallback = callback;
}
diff --git a/src/com/android/launcher3/popup/LauncherPopupLiveUpdateHandler.java b/src/com/android/launcher3/popup/LauncherPopupLiveUpdateHandler.java
new file mode 100644
index 0000000..c0a04b1
--- /dev/null
+++ b/src/com/android/launcher3/popup/LauncherPopupLiveUpdateHandler.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.popup;
+
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.model.data.ItemInfo;
+
+/**
+ * Utility class to handle updates while the popup is visible on the Launcher
+ */
+public class LauncherPopupLiveUpdateHandler extends PopupLiveUpdateHandler<Launcher> {
+
+ public LauncherPopupLiveUpdateHandler(
+ Launcher launcher, PopupContainerWithArrow<Launcher> popupContainerWithArrow) {
+ super(launcher, popupContainerWithArrow);
+ }
+
+ private View getWidgetsView(ViewGroup container) {
+ for (int i = container.getChildCount() - 1; i >= 0; --i) {
+ View systemShortcutView = container.getChildAt(i);
+ if (systemShortcutView.getTag() instanceof SystemShortcut.Widgets) {
+ return systemShortcutView;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void onWidgetsBound() {
+ BubbleTextView originalIcon = mPopupContainerWithArrow.getOriginalIcon();
+ SystemShortcut widgetInfo = SystemShortcut.WIDGETS.getShortcut(mContext,
+ (ItemInfo) originalIcon.getTag(), originalIcon);
+ View widgetsView = getWidgetsView(mPopupContainerWithArrow);
+ if (widgetsView == null && mPopupContainerWithArrow.getWidgetContainer() != null) {
+ widgetsView = getWidgetsView(mPopupContainerWithArrow.getWidgetContainer());
+ }
+
+ if (widgetInfo != null && widgetsView == null) {
+ // We didn't have any widgets cached but now there are some, so enable the shortcut.
+ if (mPopupContainerWithArrow.getSystemShortcutContainer()
+ != mPopupContainerWithArrow) {
+ if (mPopupContainerWithArrow.getWidgetContainer() == null) {
+ mPopupContainerWithArrow.setWidgetContainer(
+ mPopupContainerWithArrow.inflateAndAdd(
+ R.layout.widget_shortcut_container,
+ mPopupContainerWithArrow));
+ }
+ mPopupContainerWithArrow.initializeWidgetShortcut(
+ mPopupContainerWithArrow.getWidgetContainer(),
+ widgetInfo);
+ } else {
+ // If using the expanded system shortcut (as opposed to just the icon), we need
+ // to reopen the container to ensure measurements etc. all work out. While this
+ // could be quite janky, in practice the user would typically see a small
+ // flicker as the animation restarts partway through, and this is a very rare
+ // edge case anyway.
+ mPopupContainerWithArrow.close(false);
+ PopupContainerWithArrow.showForIcon(mPopupContainerWithArrow.getOriginalIcon());
+ }
+ } else if (widgetInfo == null && widgetsView != null) {
+ // No widgets exist, but we previously added the shortcut so remove it.
+ if (mPopupContainerWithArrow.getSystemShortcutContainer()
+ != mPopupContainerWithArrow
+ && mPopupContainerWithArrow.getWidgetContainer() != null) {
+ mPopupContainerWithArrow.getWidgetContainer().removeView(widgetsView);
+ } else {
+ mPopupContainerWithArrow.close(false);
+ PopupContainerWithArrow.showForIcon(mPopupContainerWithArrow.getOriginalIcon());
+ }
+ }
+ }
+
+ @Override
+ protected void showPopupContainerForIcon(BubbleTextView originalIcon) {
+ PopupContainerWithArrow.showForIcon(originalIcon);
+ }
+}
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 6d2b12f..49d97d2 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -60,7 +60,6 @@
import com.android.launcher3.notification.NotificationContainer;
import com.android.launcher3.notification.NotificationInfo;
import com.android.launcher3.notification.NotificationKeyData;
-import com.android.launcher3.popup.PopupDataProvider.PopupDataChangeListener;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
import com.android.launcher3.touch.ItemLongClickListener;
@@ -72,9 +71,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
-import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
@@ -93,6 +90,7 @@
private BubbleTextView mOriginalIcon;
private int mNumNotifications;
private NotificationContainer mNotificationContainer;
+ private int mContainerWidth;
private ViewGroup mWidgetContainer;
@@ -107,6 +105,7 @@
super(context, attrs, defStyleAttr);
mStartDragThreshold = getResources().getDimensionPixelSize(
R.dimen.deep_shortcuts_start_drag_threshold);
+ mContainerWidth = getResources().getDimensionPixelSize(R.dimen.bg_popup_item_width);
}
public PopupContainerWithArrow(Context context, AttributeSet attrs) {
@@ -151,10 +150,13 @@
public OnClickListener getItemClickListener() {
return (view) -> {
mActivityContext.getItemOnClickListener().onClick(view);
- close(true);
};
}
+ public void setPopupItemDragHandler(PopupItemDragHandler popupItemDragHandler) {
+ mPopupItemDragHandler = popupItemDragHandler;
+ }
+
public PopupItemDragHandler getItemDragHandler() {
return mPopupItemDragHandler;
}
@@ -185,7 +187,10 @@
/**
* Returns true if we can show the container.
+ *
+ * @deprecated Left here since some dependent projects are using this method
*/
+ @Deprecated
public static boolean canShow(View icon, ItemInfo item) {
return icon instanceof BubbleTextView && ShortcutUtil.supportsShortcuts(item);
}
@@ -202,7 +207,7 @@
return null;
}
ItemInfo item = (ItemInfo) icon.getTag();
- if (!canShow(icon, item)) {
+ if (!ShortcutUtil.supportsShortcuts(item)) {
return null;
}
@@ -216,7 +221,7 @@
popupDataProvider.getShortcutCountForItem(item),
popupDataProvider.getNotificationKeysForItem(item),
launcher.getSupportedShortcuts()
- .map(s -> s.getShortcut(launcher, item))
+ .map(s -> s.getShortcut(launcher, item, icon))
.filter(Objects::nonNull)
.collect(Collectors.toList()));
launcher.refreshAndBindWidgetsForPackageUser(PackageUserKey.fromItemInfo(item));
@@ -225,7 +230,8 @@
}
private void configureForLauncher(Launcher launcher) {
- addOnAttachStateChangeListener(new LiveUpdateHandler(launcher));
+ addOnAttachStateChangeListener(new LauncherPopupLiveUpdateHandler(
+ launcher, (PopupContainerWithArrow<Launcher>) this));
mPopupItemDragHandler = new LauncherPopupItemDragHandler(launcher, this);
mAccessibilityDelegate = new ShortcutMenuAccessibilityDelegate(launcher);
launcher.getDragController().addDragListener(this);
@@ -245,14 +251,15 @@
mOriginalIcon = originalIcon;
boolean hasDeepShortcuts = shortcutCount > 0;
- int containerWidth = (int) getResources().getDimension(R.dimen.bg_popup_item_width);
+ mContainerWidth = getResources().getDimensionPixelSize(R.dimen.bg_popup_item_width);
// if there are deep shortcuts, we might want to increase the width of shortcuts to fit
// horizontally laid out system shortcuts.
if (hasDeepShortcuts) {
- containerWidth = (int) Math.max(containerWidth,
- systemShortcuts.size() * getResources().getDimension(
- R.dimen.system_shortcut_header_icon_touch_size));
+ mContainerWidth = Math.max(mContainerWidth,
+ systemShortcuts.size() * getResources()
+ .getDimensionPixelSize(R.dimen.system_shortcut_header_icon_touch_size)
+ );
}
// Add views
if (mNumNotifications > 0) {
@@ -276,7 +283,7 @@
for (int i = shortcutCount; i > 0; i--) {
DeepShortcutView v = inflateAndAdd(R.layout.deep_shortcut, mDeepShortcutContainer);
- v.getLayoutParams().width = containerWidth;
+ v.getLayoutParams().width = mContainerWidth;
mShortcuts.add(v);
}
updateHiddenShortcuts();
@@ -288,8 +295,7 @@
mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container,
this);
}
- initializeSystemShortcut(R.layout.system_shortcut, mWidgetContainer,
- shortcut);
+ initializeWidgetShortcut(mWidgetContainer, shortcut);
}
}
mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_icons, this);
@@ -329,6 +335,26 @@
this, mShortcuts, notificationKeys));
}
+ protected NotificationContainer getNotificationContainer() {
+ return mNotificationContainer;
+ }
+
+ protected BubbleTextView getOriginalIcon() {
+ return mOriginalIcon;
+ }
+
+ protected ViewGroup getSystemShortcutContainer() {
+ return mSystemShortcutContainer;
+ }
+
+ protected ViewGroup getWidgetContainer() {
+ return mWidgetContainer;
+ }
+
+ protected void setWidgetContainer(ViewGroup widgetContainer) {
+ mWidgetContainer = widgetContainer;
+ }
+
private String getTitleForAccessibility() {
return getContext().getString(mNumNotifications == 0 ?
R.string.action_deep_shortcut :
@@ -352,7 +378,7 @@
}
}
- private void updateHiddenShortcuts() {
+ protected void updateHiddenShortcuts() {
int allowedCount = mNotificationContainer != null
? MAX_SHORTCUTS_IF_NOTIFICATIONS : MAX_SHORTCUTS;
@@ -363,7 +389,12 @@
}
}
- private void initializeSystemShortcut(int resId, ViewGroup container, SystemShortcut info) {
+ protected void initializeWidgetShortcut(ViewGroup container, SystemShortcut info) {
+ View view = initializeSystemShortcut(R.layout.system_shortcut, container, info);
+ view.getLayoutParams().width = mContainerWidth;
+ }
+
+ protected View initializeSystemShortcut(int resId, ViewGroup container, SystemShortcut info) {
View view = inflateAndAdd(
resId, container, getInsertIndexForSystemShortcut(container, info));
if (view instanceof DeepShortcutView) {
@@ -377,6 +408,7 @@
}
view.setTag(info);
view.setOnClickListener(info);
+ return view;
}
/**
@@ -442,7 +474,7 @@
};
}
- private void updateNotificationHeader() {
+ protected void updateNotificationHeader() {
ItemInfoWithIcon itemInfo = (ItemInfoWithIcon) mOriginalIcon.getTag();
DotInfo dotInfo = mActivityContext.getDotInfoForItem(itemInfo);
if (mNotificationContainer != null && dotInfo != null) {
@@ -504,118 +536,12 @@
}
/**
- * Utility class to handle updates while the popup is visible (like widgets and
- * notification changes)
- */
- private class LiveUpdateHandler implements
- PopupDataChangeListener, View.OnAttachStateChangeListener {
-
- private final Launcher mLauncher;
-
- LiveUpdateHandler(Launcher launcher) {
- mLauncher = launcher;
- }
-
- @Override
- public void onViewAttachedToWindow(View view) {
- mLauncher.getPopupDataProvider().setChangeListener(this);
- }
-
- @Override
- public void onViewDetachedFromWindow(View view) {
- mLauncher.getPopupDataProvider().setChangeListener(null);
- }
-
- private View getWidgetsView(ViewGroup container) {
- for (int i = container.getChildCount() - 1; i >= 0; --i) {
- View systemShortcutView = container.getChildAt(i);
- if (systemShortcutView.getTag() instanceof SystemShortcut.Widgets) {
- return systemShortcutView;
- }
- }
- return null;
- }
-
- @Override
- public void onWidgetsBound() {
- ItemInfo itemInfo = (ItemInfo) mOriginalIcon.getTag();
- SystemShortcut widgetInfo = SystemShortcut.WIDGETS.getShortcut(mLauncher, itemInfo);
- View widgetsView = getWidgetsView(PopupContainerWithArrow.this);
- if (widgetsView == null && mWidgetContainer != null) {
- widgetsView = getWidgetsView(mWidgetContainer);
- }
-
- if (widgetInfo != null && widgetsView == null) {
- // We didn't have any widgets cached but now there are some, so enable the shortcut.
- if (mSystemShortcutContainer != PopupContainerWithArrow.this) {
- if (mWidgetContainer == null) {
- mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container,
- PopupContainerWithArrow.this);
- }
- initializeSystemShortcut(R.layout.system_shortcut, mWidgetContainer,
- widgetInfo);
- } else {
- // If using the expanded system shortcut (as opposed to just the icon), we need
- // to reopen the container to ensure measurements etc. all work out. While this
- // could be quite janky, in practice the user would typically see a small
- // flicker as the animation restarts partway through, and this is a very rare
- // edge case anyway.
- close(false);
- PopupContainerWithArrow.showForIcon(mOriginalIcon);
- }
- } else if (widgetInfo == null && widgetsView != null) {
- // No widgets exist, but we previously added the shortcut so remove it.
- if (mSystemShortcutContainer
- != PopupContainerWithArrow.this
- && mWidgetContainer != null) {
- mWidgetContainer.removeView(widgetsView);
- } else {
- close(false);
- PopupContainerWithArrow.showForIcon(mOriginalIcon);
- }
- }
- }
-
- /**
- * Updates the notification header if the original icon's dot updated.
- */
- @Override
- public void onNotificationDotsUpdated(Predicate<PackageUserKey> updatedDots) {
- ItemInfo itemInfo = (ItemInfo) mOriginalIcon.getTag();
- PackageUserKey packageUser = PackageUserKey.fromItemInfo(itemInfo);
- if (updatedDots.test(packageUser)) {
- updateNotificationHeader();
- }
- }
-
-
- @Override
- public void trimNotifications(Map<PackageUserKey, DotInfo> updatedDots) {
- if (mNotificationContainer == null) {
- return;
- }
- ItemInfo originalInfo = (ItemInfo) mOriginalIcon.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.
- mNotificationContainer.setVisibility(GONE);
- updateHiddenShortcuts();
- assignMarginsAndBackgrounds(PopupContainerWithArrow.this);
- updateArrowColor();
- } else {
- mNotificationContainer.trimNotifications(
- NotificationKeyData.extractKeysOnly(dotInfo.getNotificationKeys()));
- }
- }
- }
-
- /**
* Dismisses the popup if it is no longer valid
*/
public static void dismissInvalidPopup(BaseDraggingActivity activity) {
PopupContainerWithArrow popup = getOpen(activity);
if (popup != null && (!popup.mOriginalIcon.isAttachedToWindow()
- || !canShow(popup.mOriginalIcon, (ItemInfo) popup.mOriginalIcon.getTag()))) {
+ || !ShortcutUtil.supportsShortcuts((ItemInfo) popup.mOriginalIcon.getTag()))) {
popup.animateClose();
}
}
diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java
index 6f9f0d7..80ffecc 100644
--- a/src/com/android/launcher3/popup/PopupDataProvider.java
+++ b/src/com/android/launcher3/popup/PopupDataProvider.java
@@ -264,6 +264,13 @@
writer.println(prefix + "\tmPackageUserToDotInfos:" + mPackageUserToDotInfos);
}
+ /**
+ * Tells the listener that the system shortcuts have been updated, causing them to be redrawn.
+ */
+ public void redrawSystemShortcuts() {
+ mChangeListener.onSystemShortcutsUpdated();
+ }
+
public interface PopupDataChangeListener {
PopupDataChangeListener INSTANCE = new PopupDataChangeListener() { };
@@ -276,5 +283,8 @@
/** A callback to get notified when recommended widgets are bound. */
default void onRecommendedWidgetsBound() { }
+
+ /** A callback to get notified when system shortcuts have been updated. */
+ default void onSystemShortcutsUpdated() { }
}
}
diff --git a/src/com/android/launcher3/popup/PopupLiveUpdateHandler.java b/src/com/android/launcher3/popup/PopupLiveUpdateHandler.java
new file mode 100644
index 0000000..c5d5452
--- /dev/null
+++ b/src/com/android/launcher3/popup/PopupLiveUpdateHandler.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.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)
+ *
+ * @param <T> The activity on which the popup shows
+ */
+public abstract class PopupLiveUpdateHandler<T extends Context & ActivityContext> implements
+ PopupDataProvider.PopupDataChangeListener, View.OnAttachStateChangeListener {
+
+ protected final T mContext;
+ protected final PopupContainerWithArrow<T> mPopupContainerWithArrow;
+
+ public PopupLiveUpdateHandler(
+ T context, PopupContainerWithArrow<T> popupContainerWithArrow) {
+ mContext = context;
+ mPopupContainerWithArrow = popupContainerWithArrow;
+ }
+
+ @Override
+ public void onViewAttachedToWindow(View view) {
+ PopupDataProvider popupDataProvider = mContext.getPopupDataProvider();
+
+ if (popupDataProvider != null) {
+ popupDataProvider.setChangeListener(this);
+ }
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View view) {
+ PopupDataProvider popupDataProvider = mContext.getPopupDataProvider();
+
+ if (popupDataProvider != null) {
+ popupDataProvider.setChangeListener(null);
+ }
+ }
+
+ /**
+ * 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);
+ showPopupContainerForIcon(mPopupContainerWithArrow.getOriginalIcon());
+ }
+
+ protected abstract void showPopupContainerForIcon(BubbleTextView originalIcon);
+}
diff --git a/src/com/android/launcher3/popup/PopupPopulator.java b/src/com/android/launcher3/popup/PopupPopulator.java
index 1dce1f2..8be4e6c 100644
--- a/src/com/android/launcher3/popup/PopupPopulator.java
+++ b/src/com/android/launcher3/popup/PopupPopulator.java
@@ -162,7 +162,7 @@
for (int i = 0; i < shortcuts.size() && i < shortcutViews.size(); i++) {
final ShortcutInfo shortcut = shortcuts.get(i);
final WorkspaceItemInfo si = new WorkspaceItemInfo(shortcut, context);
- cache.getUnbadgedShortcutIcon(si, shortcut);
+ cache.getShortcutIcon(si, shortcut);
si.rank = i;
si.container = CONTAINER_SHORTCUTS;
diff --git a/src/com/android/launcher3/popup/RemoteActionShortcut.java b/src/com/android/launcher3/popup/RemoteActionShortcut.java
index 7c393ad..e5e2c35 100644
--- a/src/com/android/launcher3/popup/RemoteActionShortcut.java
+++ b/src/com/android/launcher3/popup/RemoteActionShortcut.java
@@ -46,8 +46,8 @@
private final RemoteAction mAction;
public RemoteActionShortcut(RemoteAction action,
- BaseDraggingActivity activity, ItemInfo itemInfo) {
- super(0, R.id.action_remote_action_shortcut, activity, itemInfo);
+ BaseDraggingActivity activity, ItemInfo itemInfo, View originalView) {
+ super(0, R.id.action_remote_action_shortcut, activity, itemInfo, originalView);
mAction = action;
}
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index af87275..0e25984c 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -46,18 +46,21 @@
protected final T mTarget;
protected final ItemInfo mItemInfo;
+ protected final View mOriginalView;
/**
* Indicates if it's invokable or not through some disabled UI
*/
private boolean isEnabled = true;
- public SystemShortcut(int iconResId, int labelResId, T target, ItemInfo itemInfo) {
+ public SystemShortcut(int iconResId, int labelResId, T target, ItemInfo itemInfo,
+ View originalView) {
mIconResId = iconResId;
mLabelResId = labelResId;
mAccessibilityActionId = labelResId;
mTarget = target;
mItemInfo = itemInfo;
+ mOriginalView = originalView;
}
public SystemShortcut(SystemShortcut<T> other) {
@@ -66,6 +69,7 @@
mAccessibilityActionId = other.mAccessibilityActionId;
mTarget = other.mTarget;
mItemInfo = other.mItemInfo;
+ mOriginalView = other.mOriginalView;
}
/**
@@ -77,12 +81,15 @@
public void setIconAndLabelFor(View iconView, TextView labelView) {
iconView.setBackgroundResource(mIconResId);
+ iconView.setEnabled(isEnabled);
labelView.setText(mLabelResId);
+ labelView.setEnabled(isEnabled);
}
public void setIconAndContentDescriptionFor(ImageView view) {
view.setImageResource(mIconResId);
view.setContentDescription(view.getContext().getText(mLabelResId));
+ view.setEnabled(isEnabled);
}
public AccessibilityNodeInfo.AccessibilityAction createAccessibilityAction(Context context) {
@@ -104,10 +111,10 @@
public interface Factory<T extends Context & ActivityContext> {
- @Nullable SystemShortcut<T> getShortcut(T activity, ItemInfo itemInfo);
+ @Nullable SystemShortcut<T> getShortcut(T activity, ItemInfo itemInfo, View originalView);
}
- public static final Factory<Launcher> WIDGETS = (launcher, itemInfo) -> {
+ public static final Factory<Launcher> WIDGETS = (launcher, itemInfo, originalView) -> {
if (itemInfo.getTargetComponent() == null) return null;
final List<WidgetItem> widgets =
launcher.getPopupDataProvider().getWidgetsForPackageUser(new PackageUserKey(
@@ -115,12 +122,13 @@
if (widgets.isEmpty()) {
return null;
}
- return new Widgets(launcher, itemInfo);
+ return new Widgets(launcher, itemInfo, originalView);
};
public static class Widgets extends SystemShortcut<Launcher> {
- public Widgets(Launcher target, ItemInfo itemInfo) {
- super(R.drawable.ic_widget, R.string.widget_button_text, target, itemInfo);
+ public Widgets(Launcher target, ItemInfo itemInfo, View originalView) {
+ super(R.drawable.ic_widget, R.string.widget_button_text, target, itemInfo,
+ originalView);
}
@Override
@@ -142,9 +150,9 @@
@Nullable
private SplitAccessibilityInfo mSplitA11yInfo;
- public AppInfo(T target, ItemInfo itemInfo) {
+ public AppInfo(T target, ItemInfo itemInfo, View originalView) {
super(R.drawable.ic_info_no_shadow, R.string.app_info_drop_target_label, target,
- itemInfo);
+ itemInfo, originalView);
}
/**
@@ -157,8 +165,9 @@
* That way it could directly create the correct node info for any shortcut that supports
* split, but then we'll need custom resIDs for each pair of shortcuts.
*/
- public AppInfo(T target, ItemInfo itemInfo, SplitAccessibilityInfo accessibilityInfo) {
- this(target, itemInfo);
+ public AppInfo(T target, ItemInfo itemInfo, View originalView,
+ SplitAccessibilityInfo accessibilityInfo) {
+ this(target, itemInfo, originalView);
mSplitA11yInfo = accessibilityInfo;
mAccessibilityActionId = accessibilityInfo.nodeId;
}
@@ -200,28 +209,29 @@
}
}
- public static final Factory<BaseDraggingActivity> INSTALL = (activity, itemInfo) -> {
- boolean supportsWebUI = (itemInfo instanceof WorkspaceItemInfo)
- && ((WorkspaceItemInfo) itemInfo).hasStatusFlag(
+ public static final Factory<BaseDraggingActivity> INSTALL =
+ (activity, itemInfo, originalView) -> {
+ boolean supportsWebUI = (itemInfo instanceof WorkspaceItemInfo)
+ && ((WorkspaceItemInfo) itemInfo).hasStatusFlag(
WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI);
- boolean isInstantApp = false;
- if (itemInfo instanceof com.android.launcher3.model.data.AppInfo) {
- com.android.launcher3.model.data.AppInfo
- appInfo = (com.android.launcher3.model.data.AppInfo) itemInfo;
- isInstantApp = InstantAppResolver.newInstance(activity).isInstantApp(appInfo);
- }
- boolean enabled = supportsWebUI || isInstantApp;
- if (!enabled) {
- return null;
- }
- return new Install(activity, itemInfo);
+ boolean isInstantApp = false;
+ if (itemInfo instanceof com.android.launcher3.model.data.AppInfo) {
+ com.android.launcher3.model.data.AppInfo
+ appInfo = (com.android.launcher3.model.data.AppInfo) itemInfo;
+ isInstantApp = InstantAppResolver.newInstance(activity).isInstantApp(appInfo);
+ }
+ boolean enabled = supportsWebUI || isInstantApp;
+ if (!enabled) {
+ return null;
+ }
+ return new Install(activity, itemInfo, originalView);
};
public static class Install extends SystemShortcut<BaseDraggingActivity> {
- public Install(BaseDraggingActivity target, ItemInfo itemInfo) {
+ public Install(BaseDraggingActivity target, ItemInfo itemInfo, View originalView) {
super(R.drawable.ic_install_no_shadow, R.string.install_drop_target_label,
- target, itemInfo);
+ target, itemInfo, originalView);
}
@Override
diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java
index d994dbe..48b3acf 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -79,11 +79,15 @@
helper.createEmptyDB(helper.getWritableDatabase());
}
+ // Obtain InvariantDeviceProfile first before setting pending to false, so
+ // InvariantDeviceProfile won't switch to new grid when initializing.
+ InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(context);
+
// Set is pending to false irrespective of the result, so that it doesn't get
// executed again.
Utilities.getPrefs(context).edit().remove(RESTORED_DEVICE_TYPE).commit();
- InvariantDeviceProfile.INSTANCE.get(context).reinitializeAfterRestore(context);
+ idp.reinitializeAfterRestore(context);
}
private static boolean performRestore(Context context, DatabaseHelper helper) {
diff --git a/src/com/android/launcher3/search/SearchCallback.java b/src/com/android/launcher3/search/SearchCallback.java
index 5796116..495a303 100644
--- a/src/com/android/launcher3/search/SearchCallback.java
+++ b/src/com/android/launcher3/search/SearchCallback.java
@@ -32,13 +32,6 @@
void onSearchResult(String query, ArrayList<T> items);
/**
- * Called when the search from secondary source is complete.
- *
- * @param items list of search results
- */
- void onAppendSearchResult(String query, ArrayList<T> items);
-
- /**
* Called when the search results should be cleared.
*/
void clearSearchResult();
diff --git a/src/com/android/launcher3/secondarydisplay/PinnedAppsAdapter.java b/src/com/android/launcher3/secondarydisplay/PinnedAppsAdapter.java
index e9058c3..a0ed77e 100644
--- a/src/com/android/launcher3/secondarydisplay/PinnedAppsAdapter.java
+++ b/src/com/android/launcher3/secondarydisplay/PinnedAppsAdapter.java
@@ -205,8 +205,8 @@
/**
* Returns a system shortcut to pin/unpin a shortcut
*/
- public SystemShortcut getSystemShortcut(ItemInfo info) {
- return new PinUnPinShortcut(mLauncher, info,
+ public SystemShortcut getSystemShortcut(ItemInfo info, View originalView) {
+ return new PinUnPinShortcut(mLauncher, info, originalView,
mPinnedApps.contains(new ComponentKey(info.getTargetComponent(), info.user)));
}
@@ -214,10 +214,11 @@
private final boolean mIsPinned;
- PinUnPinShortcut(SecondaryDisplayLauncher target, ItemInfo info, boolean isPinned) {
+ PinUnPinShortcut(SecondaryDisplayLauncher target, ItemInfo info, View originalView,
+ boolean isPinned) {
super(isPinned ? R.drawable.ic_remove_no_shadow : R.drawable.ic_pin,
isPinned ? R.string.remove_drop_target_label : R.string.action_add_to_workspace,
- target, info);
+ target, info, originalView);
mIsPinned = isPinned;
}
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
index 1a96c23..a2ab7f9 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
@@ -30,8 +30,9 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.model.BgDataModel;
+import com.android.launcher3.model.StringCache;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
@@ -52,13 +53,15 @@
private LauncherModel mModel;
private BaseDragLayer mDragLayer;
- private AllAppsContainerView mAppsView;
+ private ActivityAllAppsContainerView<SecondaryDisplayLauncher> mAppsView;
private View mAppsButton;
private PopupDataProvider mPopupDataProvider;
private boolean mAppDrawerShown = false;
+ private StringCache mStringCache;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -143,7 +146,8 @@
return mAppDrawerShown;
}
- public AllAppsContainerView getAppsView() {
+ @Override
+ public ActivityAllAppsContainerView<SecondaryDisplayLauncher> getAppsView() {
return mAppsView;
}
@@ -225,6 +229,16 @@
PopupContainerWithArrow.dismissInvalidPopup(this);
}
+ @Override
+ public StringCache getStringCache() {
+ return mStringCache;
+ }
+
+ @Override
+ public void bindStringCache(StringCache cache) {
+ mStringCache = cache;
+ }
+
public PopupDataProvider getPopupDataProvider() {
return mPopupDataProvider;
}
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
index 1820933..c79d70d 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
@@ -30,9 +30,10 @@
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.popup.PopupContainerWithArrow;
+import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.util.ShortcutUtil;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
@@ -46,7 +47,7 @@
public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher> {
private View mAllAppsButton;
- private AllAppsContainerView mAppsView;
+ private ActivityAllAppsContainerView<SecondaryDisplayLauncher> mAppsView;
private GridView mWorkspace;
private PinnedAppsAdapter mPinnedAppsAdapter;
@@ -112,26 +113,27 @@
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child == mAppsView) {
- int padding = 2 * (grid.desiredWorkspaceHorizontalMarginPx
- + grid.cellLayoutPaddingLeftRightPx);
+ int horizontalPadding = (2 * grid.desiredWorkspaceHorizontalMarginPx)
+ + grid.cellLayoutPaddingPx.left + grid.cellLayoutPaddingPx.right;
+ int verticalPadding =
+ grid.cellLayoutPaddingPx.top + grid.cellLayoutPaddingPx.bottom;
- int maxWidth = grid.allAppsCellWidthPx * grid.numShownAllAppsColumns + padding;
- int appsWidth = Math.min(width, maxWidth);
+ int maxWidth =
+ grid.allAppsCellWidthPx * grid.numShownAllAppsColumns + horizontalPadding;
+ int appsWidth = Math.min(width - getPaddingLeft() - getPaddingRight(), maxWidth);
- int maxHeight = grid.allAppsCellHeightPx * grid.numShownAllAppsColumns + padding;
- int appsHeight = Math.min(height, maxHeight);
+ int maxHeight =
+ grid.allAppsCellHeightPx * grid.numShownAllAppsColumns + verticalPadding;
+ int appsHeight = Math.min(height - getPaddingTop() - getPaddingBottom(), maxHeight);
mAppsView.measure(
makeMeasureSpec(appsWidth, EXACTLY), makeMeasureSpec(appsHeight, EXACTLY));
-
} else if (child == mAllAppsButton) {
int appsButtonSpec = makeMeasureSpec(grid.iconSizePx, EXACTLY);
mAllAppsButton.measure(appsButtonSpec, appsButtonSpec);
-
} else if (child == mWorkspace) {
measureChildWithMargins(mWorkspace, widthMeasureSpec, 0, heightMeasureSpec,
grid.iconSizePx + grid.edgeMarginPx);
-
} else {
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
}
@@ -177,15 +179,19 @@
if (!ShortcutUtil.supportsShortcuts(item)) {
return false;
}
+ PopupDataProvider popupDataProvider = mActivity.getPopupDataProvider();
+ if (popupDataProvider == null) {
+ return false;
+ }
final PopupContainerWithArrow container =
(PopupContainerWithArrow) mActivity.getLayoutInflater().inflate(
R.layout.popup_container, mActivity.getDragLayer(), false);
container.populateAndShow((BubbleTextView) v,
- mActivity.getPopupDataProvider().getShortcutCountForItem(item),
+ popupDataProvider.getShortcutCountForItem(item),
Collections.emptyList(),
- Arrays.asList(mPinnedAppsAdapter.getSystemShortcut(item),
- APP_INFO.getShortcut(mActivity, item)));
+ Arrays.asList(mPinnedAppsAdapter.getSystemShortcut(item, v),
+ APP_INFO.getShortcut(mActivity, item, v)));
v.getParent().requestDisallowInterceptTouchEvent(true);
return true;
}
diff --git a/src/com/android/launcher3/settings/NotificationDotsPreference.java b/src/com/android/launcher3/settings/NotificationDotsPreference.java
index 0ee2744..1816e7b 100644
--- a/src/com/android/launcher3/settings/NotificationDotsPreference.java
+++ b/src/com/android/launcher3/settings/NotificationDotsPreference.java
@@ -89,6 +89,7 @@
// Update intent
Bundle extras = new Bundle();
extras.putString(EXTRA_FRAGMENT_ARG_KEY, "notification_badging");
+
setIntent(new Intent("android.settings.NOTIFICATION_SETTINGS")
.putExtra(EXTRA_SHOW_FRAGMENT_ARGS, extras));
}
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index 0c39632..49d27b7 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -213,6 +213,14 @@
}
if (getActivity() != null && !TextUtils.isEmpty(getPreferenceScreen().getTitle())) {
+ if (getPreferenceScreen().getTitle().equals(
+ getResources().getString(R.string.search_pref_screen_title))){
+ DeviceProfile mDeviceProfile = InvariantDeviceProfile.INSTANCE.get(
+ getContext()).getDeviceProfile(getContext());
+ getPreferenceScreen().setTitle(mDeviceProfile.isTablet ?
+ R.string.search_pref_screen_title_tablet
+ : R.string.search_pref_screen_title);
+ }
getActivity().setTitle(getPreferenceScreen().getTitle());
}
}
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutView.java b/src/com/android/launcher3/shortcuts/DeepShortcutView.java
index 71d288c..2f17ce0 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutView.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutView.java
@@ -72,6 +72,7 @@
protected void onFinishInflate() {
super.onFinishInflate();
mBubbleText = findViewById(R.id.bubble_text);
+ mBubbleText.setHideBadge(true);
mIconView = findViewById(R.id.icon);
tryUpdateTextBackground();
}
diff --git a/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java b/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java
index cecbb0d..c166bfc 100644
--- a/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java
+++ b/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java
@@ -23,12 +23,12 @@
import android.graphics.drawable.Drawable;
import android.view.View;
-import com.android.launcher3.Launcher;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.DragPreviewProvider;
import com.android.launcher3.icons.BitmapRenderer;
import com.android.launcher3.icons.FastBitmapDrawable;
+import com.android.launcher3.views.ActivityContext;
/**
* Extension of {@link DragPreviewProvider} which generates bitmaps scaled to the default icon size.
@@ -45,7 +45,8 @@
@Override
public Drawable createDrawable() {
if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) {
- int size = Launcher.getLauncher(mView.getContext()).getDeviceProfile().iconSizePx;
+ int size = ActivityContext.lookupContext(mView.getContext())
+ .getDeviceProfile().iconSizePx;
return new FastBitmapDrawable(
BitmapRenderer.createHardwareBitmap(
size + blurSizeOutline,
@@ -59,7 +60,7 @@
private Bitmap createDragBitmapLegacy() {
Drawable d = mView.getBackground();
Rect bounds = getDrawableBounds(d);
- int size = Launcher.getLauncher(mView.getContext()).getDeviceProfile().iconSizePx;
+ int size = ActivityContext.lookupContext(mView.getContext()).getDeviceProfile().iconSizePx;
final Bitmap b = Bitmap.createBitmap(
size + blurSizeOutline,
size + blurSizeOutline,
@@ -84,9 +85,9 @@
@Override
public float getScaleAndPosition(Drawable preview, int[] outPos) {
- Launcher launcher = Launcher.getLauncher(mView.getContext());
+ ActivityContext context = ActivityContext.lookupContext(mView.getContext());
int iconSize = getDrawableBounds(mView.getBackground()).width();
- float scale = launcher.getDragLayer().getLocationInDragLayer(mView, outPos);
+ float scale = context.getDragLayer().getLocationInDragLayer(mView, outPos);
int iconLeft = mView.getPaddingStart();
if (Utilities.isRtl(mView.getResources())) {
@@ -98,7 +99,7 @@
+ mPositionShift.x);
outPos[1] += Math.round((scale * mView.getHeight() - preview.getIntrinsicHeight()) / 2
+ mPositionShift.y);
- float size = launcher.getDeviceProfile().iconSizePx;
+ float size = context.getDeviceProfile().iconSizePx;
return scale * iconSize / size;
}
}
diff --git a/src/com/android/launcher3/shortcuts/ShortcutKey.java b/src/com/android/launcher3/shortcuts/ShortcutKey.java
index 0c6d675..9af68c0 100644
--- a/src/com/android/launcher3/shortcuts/ShortcutKey.java
+++ b/src/com/android/launcher3/shortcuts/ShortcutKey.java
@@ -57,11 +57,17 @@
}
public static Intent makeIntent(ShortcutInfo si) {
+ return makeIntent(si.getId(), si.getPackage()).setComponent(si.getActivity());
+ }
+
+ /**
+ * Creates an intent for shortcut id and package name.
+ */
+ public static Intent makeIntent(String shortcutId, String packageName) {
return new Intent(Intent.ACTION_MAIN)
.addCategory(INTENT_CATEGORY)
- .setComponent(si.getActivity())
- .setPackage(si.getPackage())
+ .setPackage(packageName)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
- .putExtra(EXTRA_SHORTCUT_ID, si.getId());
+ .putExtra(EXTRA_SHORTCUT_ID, shortcutId);
}
}
diff --git a/src/com/android/launcher3/statemanager/BaseState.java b/src/com/android/launcher3/statemanager/BaseState.java
index 122573c..f9a36ad 100644
--- a/src/com/android/launcher3/statemanager/BaseState.java
+++ b/src/com/android/launcher3/statemanager/BaseState.java
@@ -18,6 +18,7 @@
import android.content.Context;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
/**
* Interface representing a state of a StatefulActivity
@@ -36,7 +37,8 @@
/**
* @return How long the animation to this state should take (or from this state to NORMAL).
*/
- int getTransitionDuration(Context context);
+ <DEVICE_PROFILE_CONTEXT extends Context & DeviceProfileListenable>
+ int getTransitionDuration(DEVICE_PROFILE_CONTEXT context, boolean isToState);
/**
* Returns the state to go back to from this state
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index 1767939..2aa9dde 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -253,8 +253,8 @@
// Since state mBaseState can be reached from multiple states, just assume that the
// transition plays in reverse and use the same duration as previous state.
mConfig.duration = state == mBaseState
- ? fromState.getTransitionDuration(mActivity)
- : state.getTransitionDuration(mActivity);
+ ? fromState.getTransitionDuration(mActivity, false /* isToState */)
+ : state.getTransitionDuration(mActivity, true /* isToState */);
prepareForAtomicAnimation(fromState, state, mConfig);
AnimatorSet animation = createAnimationToNewWorkspaceInternal(state).buildAnim();
if (listener != null) {
diff --git a/src/com/android/launcher3/statemanager/StatefulActivity.java b/src/com/android/launcher3/statemanager/StatefulActivity.java
index e036943..c554d06 100644
--- a/src/com/android/launcher3/statemanager/StatefulActivity.java
+++ b/src/com/android/launcher3/statemanager/StatefulActivity.java
@@ -17,15 +17,11 @@
import static com.android.launcher3.LauncherState.FLAG_NON_INTERACTIVE;
-import android.graphics.Insets;
-import android.os.Build;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.WindowInsets;
import androidx.annotation.CallSuper;
-import androidx.annotation.RequiresApi;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.LauncherRootView;
@@ -152,7 +148,7 @@
/**
* Called if the Activity UI changed while the activity was not visible
*/
- protected void onUiChangedWhileSleeping() { }
+ public void onUiChangedWhileSleeping() { }
private void handleDeferredResume() {
if (hasBeenResumed() && !getStateManager().getState().hasFlag(FLAG_NON_INTERACTIVE)) {
@@ -179,14 +175,6 @@
}
/**
- * Gives subclasses a chance to override some window insets (via
- * {@link android.view.WindowInsets.Builder#setInsets(int, Insets)}).
- */
- @RequiresApi(api = Build.VERSION_CODES.R)
- public void updateWindowInsets(WindowInsets.Builder updatedInsetsBuilder,
- WindowInsets oldInsets) { }
-
- /**
* Runs the given {@param r} runnable when this activity binds to the touch interaction service.
*/
public void runOnBindToTouchInteractionService(Runnable r) {
diff --git a/src/com/android/launcher3/states/HintState.java b/src/com/android/launcher3/states/HintState.java
index 8b52016..4cfced8 100644
--- a/src/com/android/launcher3/states/HintState.java
+++ b/src/com/android/launcher3/states/HintState.java
@@ -43,7 +43,7 @@
}
@Override
- public int getTransitionDuration(Context context) {
+ public int getTransitionDuration(Context context, boolean isToState) {
return 80;
}
diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
index 867fd99..38b62d4 100644
--- a/src/com/android/launcher3/states/RotationHelper.java
+++ b/src/com/android/launcher3/states/RotationHelper.java
@@ -21,7 +21,7 @@
import static android.util.DisplayMetrics.DENSITY_DEVICE_STABLE;
import static com.android.launcher3.Utilities.dpiFromPx;
-import static com.android.launcher3.util.WindowManagerCompat.MIN_TABLET_WIDTH;
+import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WIDTH;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
@@ -109,7 +109,7 @@
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
- if (mDestroyed) return;
+ if (mDestroyed || mIgnoreAutoRotateSettings) return;
boolean wasRotationEnabled = mHomeRotationEnabled;
mHomeRotationEnabled = mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY,
getAllowRotationDefaultValue(mActivity.getDeviceProfile()));
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index d52594e..a205ab5 100644
--- a/src/com/android/launcher3/states/SpringLoadedState.java
+++ b/src/com/android/launcher3/states/SpringLoadedState.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import android.content.Context;
-import android.graphics.Rect;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
@@ -40,40 +39,26 @@
}
@Override
- public int getTransitionDuration(Context context) {
+ public int getTransitionDuration(Context context, boolean isToState) {
return 150;
}
@Override
public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
DeviceProfile grid = launcher.getDeviceProfile();
- Workspace ws = launcher.getWorkspace();
+ Workspace<?> ws = launcher.getWorkspace();
if (ws.getChildCount() == 0) {
return super.getWorkspaceScaleAndTranslation(launcher);
}
- if (grid.isVerticalBarLayout()) {
- float scale = grid.workspaceSpringLoadShrinkFactor;
- return new ScaleAndTranslation(scale, 0, 0);
- }
-
- float scale = grid.workspaceSpringLoadShrinkFactor;
- Rect insets = launcher.getDragLayer().getInsets();
-
- float scaledHeight = scale * ws.getNormalChildHeight();
- float shrunkTop = insets.top + grid.dropTargetBarSizePx;
- float shrunkBottom = ws.getMeasuredHeight() - insets.bottom
- - grid.workspacePadding.bottom
- - grid.workspaceSpringLoadedBottomSpace;
- float totalShrunkSpace = shrunkBottom - shrunkTop;
-
- float desiredCellTop = shrunkTop + (totalShrunkSpace - scaledHeight) / 2;
+ float shrunkTop = grid.getCellLayoutSpringLoadShrunkTop();
+ float scale = grid.getWorkspaceSpringLoadScale();
float halfHeight = ws.getHeight() / 2;
float myCenter = ws.getTop() + halfHeight;
float cellTopFromCenter = halfHeight - ws.getChildAt(0).getTop();
float actualCellTop = myCenter - cellTopFromCenter * scale;
- return new ScaleAndTranslation(scale, 0, (desiredCellTop - actualCellTop) / scale);
+ return new ScaleAndTranslation(scale, 0, (shrunkTop - actualCellTop) / scale);
}
@Override
diff --git a/src/com/android/launcher3/states/StateAnimationConfig.java b/src/com/android/launcher3/states/StateAnimationConfig.java
index bd6f7d3..f99519d 100644
--- a/src/com/android/launcher3/states/StateAnimationConfig.java
+++ b/src/com/android/launcher3/states/StateAnimationConfig.java
@@ -53,6 +53,7 @@
ANIM_WORKSPACE_FADE,
ANIM_HOTSEAT_SCALE,
ANIM_HOTSEAT_TRANSLATE,
+ ANIM_HOTSEAT_FADE,
ANIM_OVERVIEW_SCALE,
ANIM_OVERVIEW_TRANSLATE_X,
ANIM_OVERVIEW_TRANSLATE_Y,
@@ -62,6 +63,7 @@
ANIM_OVERVIEW_MODAL,
ANIM_DEPTH,
ANIM_OVERVIEW_ACTIONS_FADE,
+ ANIM_WORKSPACE_PAGE_TRANSLATE_X,
})
@Retention(RetentionPolicy.SOURCE)
public @interface AnimType {}
@@ -71,6 +73,7 @@
public static final int ANIM_WORKSPACE_FADE = 3;
public static final int ANIM_HOTSEAT_SCALE = 4;
public static final int ANIM_HOTSEAT_TRANSLATE = 5;
+ public static final int ANIM_HOTSEAT_FADE = 16;
public static final int ANIM_OVERVIEW_SCALE = 6;
public static final int ANIM_OVERVIEW_TRANSLATE_X = 7;
public static final int ANIM_OVERVIEW_TRANSLATE_Y = 8;
@@ -80,8 +83,9 @@
public static final int ANIM_OVERVIEW_MODAL = 12;
public static final int ANIM_DEPTH = 13;
public static final int ANIM_OVERVIEW_ACTIONS_FADE = 14;
+ public static final int ANIM_WORKSPACE_PAGE_TRANSLATE_X = 15;
- private static final int ANIM_TYPES_COUNT = 15;
+ private static final int ANIM_TYPES_COUNT = 17;
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 8ebfd62..242d2d4 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -23,16 +23,23 @@
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Insets;
+import android.graphics.Point;
+import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.view.WindowInsets;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.CellLayout;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
+import com.android.launcher3.Workspace;
+import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.util.ResourceBasedOverride;
import com.android.launcher3.widget.picker.WidgetsFullSheet;
@@ -62,12 +69,18 @@
mLauncherAppState = LauncherAppState.getInstanceNoCreate();
}
- public Bundle call(String method) {
- return call(method, /*arg=*/ null);
- }
-
- public Bundle call(String method, String arg) {
+ /**
+ * handle a request and return result Bundle.
+ *
+ * @param method request name.
+ * @param arg optional single string argument.
+ * @param extra extra request payload.
+ */
+ public Bundle call(String method, String arg, @Nullable Bundle extra) {
final Bundle response = new Bundle();
+ if (extra != null && extra.getClassLoader() == null) {
+ extra.setClassLoader(getClass().getClassLoader());
+ }
switch (method) {
case TestProtocol.REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT: {
return getLauncherUIProperty(Bundle::putInt, l -> {
@@ -163,11 +176,54 @@
.forceAllowRotationForTesting(Boolean.parseBoolean(arg)));
return null;
+ case TestProtocol.REQUEST_WORKSPACE_CELL_LAYOUT_SIZE:
+ return getLauncherUIProperty(Bundle::putIntArray, launcher -> {
+ final Workspace<?> workspace = launcher.getWorkspace();
+ final int screenId = workspace.getScreenIdForPageIndex(
+ workspace.getCurrentPage());
+ final CellLayout cellLayout = workspace.getScreenWithId(screenId);
+ return new int[]{cellLayout.getCountX(), cellLayout.getCountY()};
+ });
+
+ case TestProtocol.REQUEST_WORKSPACE_CELL_CENTER:
+ final WorkspaceCellCenterRequest request = extra.getParcelable(
+ TestProtocol.TEST_INFO_REQUEST_FIELD);
+ return getLauncherUIProperty(Bundle::putParcelable, launcher -> {
+ final Workspace<?> workspace = launcher.getWorkspace();
+ // TODO(b/216387249): allow caller selecting different pages.
+ CellLayout cellLayout = (CellLayout) workspace.getPageAt(
+ workspace.getCurrentPage());
+ final Rect cellRect = getDescendantRectRelativeToDragLayerForCell(launcher,
+ cellLayout, request.cellX, request.cellY, request.spanX, request.spanY);
+ return new Point(cellRect.centerX(), cellRect.centerY());
+ });
+
+ case TestProtocol.REQUEST_HAS_TIS: {
+ response.putBoolean(
+ TestProtocol.REQUEST_HAS_TIS, false);
+ return response;
+ }
+
default:
return null;
}
}
+ private static Rect getDescendantRectRelativeToDragLayerForCell(Launcher launcher,
+ CellLayout cellLayout, int cellX, int cellY, int spanX, int spanY) {
+ final DragLayer dragLayer = launcher.getDragLayer();
+ final Rect target = new Rect();
+
+ cellLayout.cellToRect(cellX, cellY, spanX, spanY, target);
+ int[] leftTop = {target.left, target.top};
+ int[] rightBottom = {target.right, target.bottom};
+ dragLayer.getDescendantCoordRelativeToSelf(cellLayout, leftTop);
+ dragLayer.getDescendantCoordRelativeToSelf(cellLayout, rightBottom);
+
+ target.set(leftTop[0], leftTop[1], rightBottom[0], rightBottom[1]);
+ return target;
+ }
+
protected boolean isLauncherInitialized() {
return Launcher.ACTIVITY_TRACKER.getCreatedActivity() == null
|| LauncherAppState.getInstance(mContext).getModel().isModelLoaded();
diff --git a/src/com/android/launcher3/testing/TestInformationProvider.java b/src/com/android/launcher3/testing/TestInformationProvider.java
index 4f2619c..bcc7c2d 100644
--- a/src/com/android/launcher3/testing/TestInformationProvider.java
+++ b/src/com/android/launcher3/testing/TestInformationProvider.java
@@ -60,7 +60,7 @@
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
TestInformationHandler handler = TestInformationHandler.newInstance(getContext());
handler.init(getContext());
- return handler.call(method, arg);
+ return handler.call(method, arg, extras);
}
return null;
}
diff --git a/src/com/android/launcher3/allapps/DecorationInfo.java b/src/com/android/launcher3/testing/TestInformationRequest.java
similarity index 64%
rename from src/com/android/launcher3/allapps/DecorationInfo.java
rename to src/com/android/launcher3/testing/TestInformationRequest.java
index 50b250c..272ae56 100644
--- a/src/com/android/launcher3/allapps/DecorationInfo.java
+++ b/src/com/android/launcher3/testing/TestInformationRequest.java
@@ -13,7 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.launcher3.allapps;
-public class DecorationInfo {
+package com.android.launcher3.testing;
+
+import android.os.Parcelable;
+
+/**
+ * A Request sent to TestInformationHandler can implement this interface to carry more information.
+ */
+public interface TestInformationRequest extends Parcelable {
+ /**
+ * The name for handler to dispatch request.
+ */
+ String getRequestName();
}
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 28e7553..3a030a8 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -68,22 +68,24 @@
}
}
+ public static final String TEST_INFO_REQUEST_FIELD = "request";
public static final String TEST_INFO_RESPONSE_FIELD = "response";
public static final String REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT =
"home-to-overview-swipe-height";
public static final String REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT =
"background-to-overview-swipe-height";
- public static final String REQUEST_ALL_APPS_TO_OVERVIEW_SWIPE_HEIGHT =
- "all-apps-to-overview-swipe-height";
public static final String REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT =
"home-to-all-apps-swipe-height";
public static final String REQUEST_ICON_HEIGHT =
"icon-height";
- public static final String REQUEST_HOTSEAT_TOP = "hotseat-top";
public static final String REQUEST_IS_LAUNCHER_INITIALIZED = "is-launcher-initialized";
public static final String REQUEST_FREEZE_APP_LIST = "freeze-app-list";
public static final String REQUEST_UNFREEZE_APP_LIST = "unfreeze-app-list";
+ public static final String REQUEST_ENABLE_MANUAL_TASKBAR_STASHING = "enable-taskbar-stashing";
+ public static final String REQUEST_DISABLE_MANUAL_TASKBAR_STASHING = "disable-taskbar-stashing";
+ public static final String REQUEST_UNSTASH_TASKBAR_IF_STASHED = "unstash-taskbar-if-stashed";
+ public static final String REQUEST_STASHED_TASKBAR_HEIGHT = "stashed-taskbar-height";
public static final String REQUEST_APP_LIST_FREEZE_FLAGS = "app-list-freeze-flags";
public static final String REQUEST_APPS_LIST_SCROLL_Y = "apps-list-scroll-y";
public static final String REQUEST_WIDGETS_SCROLL_Y = "widgets-scroll-y";
@@ -98,16 +100,26 @@
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_CLEAR_DATA = "clear-data";
+ public static final String REQUEST_USE_TEST_WORKSPACE_LAYOUT = "use-test-workspace-layout";
+ public static final String REQUEST_USE_DEFAULT_WORKSPACE_LAYOUT =
+ "use-default-workspace-layout";
+ public static final String REQUEST_HOTSEAT_ICON_NAMES = "get-hotseat-icon-names";
public static final String REQUEST_IS_TABLET = "is-tablet";
public static final String REQUEST_IS_TWO_PANELS = "is-two-panel";
public static final String REQUEST_START_DRAG_THRESHOLD = "start-drag-threshold";
public static final String REQUEST_GET_ACTIVITIES_CREATED_COUNT =
"get-activities-created-count";
public static final String REQUEST_GET_ACTIVITIES = "get-activities";
+ public static final String REQUEST_HAS_TIS = "has-touch-interaction-service";
+
+ public static final String REQUEST_WORKSPACE_CELL_LAYOUT_SIZE = "workspace-cell-layout-size";
+ public static final String REQUEST_WORKSPACE_CELL_CENTER = "workspace-cell-center";
+
public static final String REQUEST_GET_FOCUSED_TASK_HEIGHT_FOR_TABLET =
"get-focused-task-height-for-tablet";
public static final String REQUEST_GET_GRID_TASK_SIZE_RECT_FOR_TABLET =
"get-grid-task-size-rect-for-tablet";
+ public static final String REQUEST_GET_OVERVIEW_PAGE_SPACING = "get-overview-page-spacing";
public static final String REQUEST_ENABLE_ROTATION = "enable_rotation";
public static Long sForcePauseTimeout;
@@ -122,9 +134,9 @@
public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation";
public static final String PERMANENT_DIAG_TAG = "TaplTarget";
- public static final String TASK_VIEW_ID_CRASH = "b/195430732";
public static final String NO_DROP_TARGET = "b/195031154";
public static final String NULL_INT_SET = "b/200572078";
-
+ public static final String MISSING_PROMISE_ICON = "b/202985412";
public static final String BAD_STATE = "b/223498680";
+ public static final String TASKBAR_IN_APP_STATE = "b/227657604";
}
diff --git a/src/com/android/launcher3/testing/WorkspaceCellCenterRequest.java b/src/com/android/launcher3/testing/WorkspaceCellCenterRequest.java
new file mode 100644
index 0000000..71ab09f
--- /dev/null
+++ b/src/com/android/launcher3/testing/WorkspaceCellCenterRequest.java
@@ -0,0 +1,138 @@
+/*
+ * 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.testing;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Request object for querying a workspace cell region in Rect.
+ */
+public class WorkspaceCellCenterRequest implements TestInformationRequest {
+ public final int cellX;
+ public final int cellY;
+ public final int spanX;
+ public final int spanY;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(cellX);
+ dest.writeInt(cellY);
+ dest.writeInt(spanX);
+ dest.writeInt(spanY);
+ }
+
+ public static final Parcelable.Creator<WorkspaceCellCenterRequest> CREATOR =
+ new Parcelable.Creator<WorkspaceCellCenterRequest>() {
+
+ @Override
+ public WorkspaceCellCenterRequest createFromParcel(Parcel source) {
+ return new WorkspaceCellCenterRequest(source);
+ }
+
+ @Override
+ public WorkspaceCellCenterRequest[] newArray(int size) {
+ return new WorkspaceCellCenterRequest[size];
+ }
+ };
+
+ private WorkspaceCellCenterRequest(int cellX, int cellY, int spanX, int spanY) {
+ this.cellX = cellX;
+ this.cellY = cellY;
+ this.spanX = spanX;
+ this.spanY = spanY;
+ }
+
+ private WorkspaceCellCenterRequest(Parcel in) {
+ this(in.readInt(), in.readInt(), in.readInt(), in.readInt());
+ }
+
+ /**
+ * Create a builder for WorkspaceCellRectRequest.
+ *
+ * @return WorkspaceCellRectRequest builder.
+ */
+ public static WorkspaceCellCenterRequest.Builder builder() {
+ return new WorkspaceCellCenterRequest.Builder();
+ }
+
+ @Override
+ public String getRequestName() {
+ return TestProtocol.REQUEST_WORKSPACE_CELL_CENTER;
+ }
+
+ /**
+ * WorkspaceCellRectRequest Builder.
+ */
+ public static final class Builder {
+ private int mCellX;
+ private int mCellY;
+ private int mSpanX;
+ private int mSpanY;
+
+ private Builder() {
+ this.mCellX = 0;
+ this.mCellY = 0;
+ this.mSpanX = 1;
+ this.mSpanY = 1;
+ }
+
+ /**
+ * Set X coordinate of upper left corner expressed as a cell position
+ */
+ public WorkspaceCellCenterRequest.Builder setCellX(int x) {
+ this.mCellX = x;
+ return this;
+ }
+
+ /**
+ * Set Y coordinate of upper left corner expressed as a cell position
+ */
+ public WorkspaceCellCenterRequest.Builder setCellY(int y) {
+ this.mCellY = y;
+ return this;
+ }
+
+ /**
+ * Set span Width in cells
+ */
+ public WorkspaceCellCenterRequest.Builder setSpanX(int x) {
+ this.mSpanX = x;
+ return this;
+ }
+
+ /**
+ * Set span Height in cells
+ */
+ public WorkspaceCellCenterRequest.Builder setSpanY(int y) {
+ this.mCellY = y;
+ return this;
+ }
+
+ /**
+ * build the WorkspaceCellRectRequest.
+ */
+ public WorkspaceCellCenterRequest build() {
+ return new WorkspaceCellCenterRequest(mCellX, mCellY, mSpanX, mSpanY);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 61d488c..09b8228 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -16,17 +16,19 @@
package com.android.launcher3.touch;
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;
import static com.android.launcher3.LauncherState.ALL_APPS;
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;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEDOWN;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEUP;
-import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
+import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
import android.animation.Animator.AnimatorListener;
import android.animation.ValueAnimator;
@@ -285,8 +287,13 @@
? mToState : mFromState;
// snap to top or bottom using the release velocity
} else {
+ float successTransitionProgress =
+ mLauncher.getDeviceProfile().isTablet
+ && (mToState == ALL_APPS || mFromState == ALL_APPS)
+ ? TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS
+ : SUCCESS_TRANSITION_PROGRESS;
targetState =
- (interpolatedProgress > SUCCESS_TRANSITION_PROGRESS) ? mToState : mFromState;
+ (interpolatedProgress > successTransitionProgress) ? mToState : mFromState;
}
final float endProgress;
@@ -324,9 +331,6 @@
Math.min(progress, 1) - endProgress) * durationMultiplier;
}
}
- if (targetState != mStartState) {
- logReachedState(targetState);
- }
mCurrentAnimation.setEndAction(() -> onSwipeInteractionCompleted(targetState));
ValueAnimator anim = mCurrentAnimation.getAnimationPlayer();
anim.setFloatValues(startProgress, endProgress);
@@ -355,6 +359,8 @@
boolean shouldGoToTargetState = mGoingBetweenStates || (mToState != targetState);
if (shouldGoToTargetState) {
goToTargetState(targetState);
+ } else {
+ logReachedState(mToState);
}
}
@@ -362,13 +368,19 @@
if (!mLauncher.isInState(targetState)) {
// If we're already in the target state, don't jump to it at the end of the animation in
// case the user started interacting with it before the animation finished.
- mLauncher.getStateManager().goToState(targetState, false /* animated */);
+ mLauncher.getStateManager().goToState(targetState, false /* animated */,
+ forEndCallback(() -> logReachedState(targetState)));
+ } else {
+ logReachedState(targetState);
}
mLauncher.getRootView().getSysUiScrim().createSysuiMultiplierAnim(
1f).setDuration(0).start();
}
private void logReachedState(LauncherState targetState) {
+ if (mStartState == targetState) {
+ return;
+ }
// Transition complete. log the action
mLauncher.getStatsLogManager().logger()
.withSrcState(mStartState.statsLogOrdinal)
diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java
index 989a9e4..db43baa 100644
--- a/src/com/android/launcher3/touch/AllAppsSwipeController.java
+++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java
@@ -17,9 +17,21 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
+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.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_ALL_APPS_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;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
import android.view.MotionEvent;
import android.view.animation.Interpolator;
@@ -37,11 +49,47 @@
private static final float ALLAPPS_STAGGERED_FADE_THRESHOLD = 0.5f;
+ // Custom timing for NORMAL -> ALL_APPS on phones only.
+ private static final float WORKSPACE_MOTION_START = 0.1667f;
+ private static final float ALL_APPS_STATE_TRANSITION = 0.305f;
+ private static final float ALL_APPS_FADE_END = 0.4717f;
+ private static final float ALL_APPS_FULL_DEPTH_PROGRESS = 0.5f;
+
public static final Interpolator ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER =
Interpolators.clampToProgress(LINEAR, 0, ALLAPPS_STAGGERED_FADE_THRESHOLD);
public static final Interpolator ALLAPPS_STAGGERED_FADE_LATE_RESPONDER =
Interpolators.clampToProgress(LINEAR, ALLAPPS_STAGGERED_FADE_THRESHOLD, 1f);
+ // Custom interpolators for NORMAL -> ALL_APPS on phones only.
+ // The blur to All Apps is set to be complete when the interpolator is at 0.5.
+ public static final Interpolator BLUR =
+ Interpolators.clampToProgress(
+ Interpolators.mapToProgress(
+ LINEAR, 0f, ALL_APPS_FULL_DEPTH_PROGRESS),
+ WORKSPACE_MOTION_START, ALL_APPS_STATE_TRANSITION);
+ public static final Interpolator WORKSPACE_FADE =
+ Interpolators.clampToProgress(FINAL_FRAME, 0f, ALL_APPS_STATE_TRANSITION);
+ public static final Interpolator WORKSPACE_SCALE =
+ Interpolators.clampToProgress(
+ EMPHASIZED_ACCELERATE, WORKSPACE_MOTION_START, ALL_APPS_STATE_TRANSITION);
+ public static final Interpolator HOTSEAT_FADE = WORKSPACE_FADE;
+ public static final Interpolator HOTSEAT_SCALE = HOTSEAT_FADE;
+ public static final Interpolator HOTSEAT_TRANSLATE =
+ Interpolators.clampToProgress(
+ EMPHASIZED_ACCELERATE, WORKSPACE_MOTION_START, ALL_APPS_STATE_TRANSITION);
+ public static final Interpolator SCRIM_FADE =
+ Interpolators.clampToProgress(
+ Interpolators.mapToProgress(LINEAR, 0f, 0.8f),
+ WORKSPACE_MOTION_START, ALL_APPS_STATE_TRANSITION);
+ public static final Interpolator ALL_APPS_FADE =
+ Interpolators.clampToProgress(
+ Interpolators.mapToProgress(DECELERATED_EASE, 0.2f, 1.0f),
+ ALL_APPS_STATE_TRANSITION, ALL_APPS_FADE_END);
+ public static final Interpolator ALL_APPS_VERTICAL_PROGRESS =
+ Interpolators.clampToProgress(
+ Interpolators.mapToProgress(EMPHASIZED_DECELERATE, 0.4f, 1.0f),
+ ALL_APPS_STATE_TRANSITION, 1.0f);
+
public AllAppsSwipeController(Launcher l) {
super(l, SingleAxisSwipeDetector.VERTICAL);
}
@@ -94,9 +142,9 @@
LauncherState toState) {
StateAnimationConfig config = super.getConfigForStates(fromState, toState);
if (fromState == NORMAL && toState == ALL_APPS) {
- applyNormalToAllAppsAnimConfig(config);
+ applyNormalToAllAppsAnimConfig(mLauncher, config);
} else if (fromState == ALL_APPS && toState == NORMAL) {
- applyAllAppsToNormalConfig(config);
+ applyAllAppsToNormalConfig(mLauncher, config);
}
return config;
}
@@ -104,18 +152,34 @@
/**
* Applies Animation config values for transition from all apps to home
*/
- public static void applyAllAppsToNormalConfig(StateAnimationConfig config) {
+ public static void applyAllAppsToNormalConfig(Launcher launcher, StateAnimationConfig config) {
+ boolean isTablet = launcher.getDeviceProfile().isTablet;
config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
- config.setInterpolator(ANIM_ALL_APPS_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
+ config.setInterpolator(ANIM_ALL_APPS_FADE, isTablet
+ ? FINAL_FRAME : ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
+ if (!isTablet) {
+ config.setInterpolator(ANIM_WORKSPACE_FADE, INSTANT);
+ }
}
/**
* Applies Animation config values for transition from home to all apps
*/
- public static void applyNormalToAllAppsAnimConfig(StateAnimationConfig config) {
- config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
- config.setInterpolator(ANIM_ALL_APPS_FADE, ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
+ public static void applyNormalToAllAppsAnimConfig(Launcher launcher,
+ StateAnimationConfig config) {
+ if (launcher.getDeviceProfile().isTablet) {
+ config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
+ config.setInterpolator(ANIM_ALL_APPS_FADE, INSTANT);
+ } else {
+ config.setInterpolator(ANIM_DEPTH, BLUR);
+ config.setInterpolator(ANIM_WORKSPACE_FADE, WORKSPACE_FADE);
+ config.setInterpolator(ANIM_WORKSPACE_SCALE, WORKSPACE_SCALE);
+ config.setInterpolator(ANIM_HOTSEAT_FADE, HOTSEAT_FADE);
+ config.setInterpolator(ANIM_HOTSEAT_SCALE, HOTSEAT_SCALE);
+ config.setInterpolator(ANIM_HOTSEAT_TRANSLATE, HOTSEAT_TRANSLATE);
+ config.setInterpolator(ANIM_SCRIM_FADE, SCRIM_FADE);
+ config.setInterpolator(ANIM_ALL_APPS_FADE, ALL_APPS_FADE);
+ config.setInterpolator(ANIM_VERTICAL_PROGRESS, ALL_APPS_VERTICAL_PROGRESS);
+ }
}
-
-
}
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 8d57d69..e95a787 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -43,6 +43,7 @@
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.folder.Folder;
@@ -58,8 +59,10 @@
import com.android.launcher3.model.data.SearchActionItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.InstallSessionHelper;
+import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.views.FloatingIconView;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
@@ -67,6 +70,8 @@
import com.android.launcher3.widget.WidgetAddFlowHandler;
import com.android.launcher3.widget.WidgetManagerHelper;
+import java.util.Collections;
+
/**
* Class for handling clicks on workspace and all-apps items
*/
@@ -95,8 +100,7 @@
onClickFolderIcon(v);
}
} else if (tag instanceof AppInfo) {
- startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher
- );
+ startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher);
} else if (tag instanceof LauncherAppWidgetInfo) {
if (v instanceof PendingAppWidgetHostView) {
onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
@@ -171,7 +175,9 @@
(d, i) -> startMarketIntentForPackage(v, launcher, packageName))
.setNeutralButton(R.string.abandoned_clean_this,
(d, i) -> launcher.getWorkspace()
- .removeAbandonedPromise(packageName, user))
+ .persistRemoveItemsByMatcher(ItemInfoMatcher.ofPackages(
+ Collections.singleton(packageName), user),
+ "user explicitly removes the promise app icon"))
.create().show();
}
@@ -205,6 +211,12 @@
public static boolean handleDisabledItemClicked(WorkspaceItemInfo shortcut, Context context) {
final int disabledFlags = shortcut.runtimeStatusFlags
& WorkspaceItemInfo.FLAG_DISABLED_MASK;
+ // Handle the case where the disabled reason is DISABLED_REASON_VERSION_LOWER.
+ // Show an AlertDialog for the user to choose either updating the app or cancel the launch.
+ if (maybeCreateAlertDialogForShortcut(shortcut, context)) {
+ return true;
+ }
+
if ((disabledFlags
& ~FLAG_DISABLED_SUSPENDED
& ~FLAG_DISABLED_QUIET_USER) == 0) {
@@ -230,6 +242,38 @@
}
}
+ private static boolean maybeCreateAlertDialogForShortcut(final WorkspaceItemInfo shortcut,
+ Context context) {
+ try {
+ final Launcher launcher = Launcher.getLauncher(context);
+ if (shortcut.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
+ && shortcut.isDisabledVersionLower()) {
+
+ new AlertDialog.Builder(context)
+ .setTitle(R.string.dialog_update_title)
+ .setMessage(R.string.dialog_update_message)
+ .setPositiveButton(R.string.dialog_update, (d, i) -> {
+ // Direct the user to the play store to update the app
+ context.startActivity(shortcut.getMarketIntent(context));
+ })
+ .setNeutralButton(R.string.dialog_remove, (d, i) -> {
+ // Remove the icon if launcher is successfully initialized
+ launcher.getWorkspace().persistRemoveItemsByMatcher(ItemInfoMatcher
+ .ofShortcutKeys(Collections.singleton(ShortcutKey
+ .fromItemInfo(shortcut))),
+ "user explicitly removes disabled shortcut");
+ })
+ .create()
+ .show();
+ return true;
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Error creating alert dialog", e);
+ }
+
+ return false;
+ }
+
/**
* Event handler for an app shortcut click.
*
diff --git a/src/com/android/launcher3/touch/ItemLongClickListener.java b/src/com/android/launcher3/touch/ItemLongClickListener.java
index f876dd9..6bae745 100644
--- a/src/com/android/launcher3/touch/ItemLongClickListener.java
+++ b/src/com/android/launcher3/touch/ItemLongClickListener.java
@@ -37,6 +37,7 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.views.BubbleTextHolder;
/**
* Class to handle long-clicks on workspace items and start drag as a result.
@@ -79,9 +80,12 @@
launcher.getWorkspace().startDrag(longClickCellInfo, dragOptions);
}
- private static boolean onAllAppsItemLongClick(View v) {
+ private static boolean onAllAppsItemLongClick(View view) {
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onAllAppsItemLongClick");
- v.cancelLongPress();
+ view.cancelLongPress();
+ View v = (view instanceof BubbleTextHolder)
+ ? ((BubbleTextHolder) view).getBubbleText()
+ : view;
Launcher launcher = Launcher.getLauncher(v.getContext());
if (!canStartDrag(launcher)) return false;
// When we have exited all apps or are in transition, disregard long clicks
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index a94ad7c..b477905 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -16,6 +16,7 @@
package com.android.launcher3.touch;
+import static android.view.Gravity.BOTTOM;
import static android.view.Gravity.CENTER_VERTICAL;
import static android.view.Gravity.END;
import static android.view.Gravity.START;
@@ -102,6 +103,17 @@
}
@Override
+ public void fixBoundsForHomeAnimStartRect(RectF outStartRect, DeviceProfile deviceProfile) {
+ // We don't need to check the "top" value here because the startRect is in the orientation
+ // of the app, not of the fixed portrait launcher.
+ if (outStartRect.left > deviceProfile.heightPx) {
+ outStartRect.offsetTo(0, outStartRect.top);
+ } else if (outStartRect.left < -deviceProfile.heightPx) {
+ outStartRect.offsetTo(0, outStartRect.top);
+ }
+ }
+
+ @Override
public <T> void setPrimary(T target, Int2DAction<T> action, int param) {
action.call(target, 0, param);
}
@@ -178,18 +190,6 @@
}
@Override
- public int getSplitTaskViewDismissDirection(@StagePosition int stagePosition,
- DeviceProfile dp) {
- // Don't use device profile here because we know we're in fake landscape, only split option
- // available is top/left
- if (stagePosition == STAGE_POSITION_TOP_OR_LEFT) {
- // Top (visually left) side
- return SPLIT_TRANSLATE_PRIMARY_NEGATIVE;
- }
- throw new IllegalStateException("Invalid split stage position: " + stagePosition);
- }
-
- @Override
public int getPrimaryScroll(View view) {
return view.getScrollY();
}
@@ -310,9 +310,10 @@
}
@Override
- public Pair<Float, Float> setDwbLayoutParamsAndGetTranslations(int taskViewWidth,
+ public Pair<Float, Float> getDwbLayoutTranslations(int taskViewWidth,
int taskViewHeight, StagedSplitBounds splitBounds, DeviceProfile deviceProfile,
View[] thumbnailViews, int desiredTaskId, View banner) {
+ boolean isRtl = banner.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
float translationX = 0;
float translationY = 0;
FrameLayout.LayoutParams bannerParams = (FrameLayout.LayoutParams) banner.getLayoutParams();
@@ -323,7 +324,7 @@
FrameLayout.LayoutParams snapshotParams =
(FrameLayout.LayoutParams) thumbnailViews[0]
.getLayoutParams();
- bannerParams.gravity = TOP | START;
+ bannerParams.gravity = TOP | (isRtl ? END : START);
if (splitBounds == null) {
// Single, fullscreen case
bannerParams.width = taskViewHeight - snapshotParams.topMargin;
@@ -339,9 +340,11 @@
// Set translations
if (desiredTaskId == splitBounds.rightBottomTaskId) {
- translationY = (snapshotParams.topMargin + taskViewHeight)
- * (splitBounds.leftTaskPercent) +
- (taskViewHeight * splitBounds.dividerWidthPercent);
+ float topLeftTaskPlusDividerPercent = splitBounds.appsStackedVertically
+ ? (splitBounds.topTaskPercent + splitBounds.dividerHeightPercent)
+ : (splitBounds.leftTaskPercent + splitBounds.dividerWidthPercent);
+ translationY = snapshotParams.topMargin
+ + ((taskViewHeight - snapshotParams.topMargin) * topLeftTaskPlusDividerPercent);
}
if (desiredTaskId == splitBounds.leftTopTaskId) {
translationY = snapshotParams.topMargin;
@@ -402,12 +405,34 @@
}
@Override
- public void getInitialSplitPlaceholderBounds(int placeholderHeight, DeviceProfile dp,
- @StagePosition int stagePosition, Rect out) {
+ public void getInitialSplitPlaceholderBounds(int placeholderHeight, int placeholderInset,
+ DeviceProfile dp, @StagePosition int stagePosition, Rect out) {
// In fake land/seascape, the placeholder always needs to go to the "top" of the device,
// which is the same bounds as 0 rotation.
int width = dp.widthPx;
- out.set(0, 0, width, placeholderHeight);
+ int insetThickness = dp.getInsets().top;
+ out.set(0, 0, width, placeholderHeight + insetThickness);
+ out.inset(placeholderInset, 0);
+
+ // Adjust the top to account for content off screen. This will help to animate the view in
+ // with rounded corners.
+ int screenWidth = dp.widthPx;
+ int screenHeight = dp.heightPx;
+ int totalHeight = (int) (1.0f * screenHeight / 2 * (screenWidth - 2 * placeholderInset)
+ / screenWidth);
+ out.top -= (totalHeight - placeholderHeight);
+ }
+
+ @Override
+ public void updateStagedSplitIconParams(View out, float onScreenRectCenterX,
+ float onScreenRectCenterY, float fullscreenScaleX, float fullscreenScaleY,
+ int drawableWidth, int drawableHeight, DeviceProfile dp,
+ @StagePosition int stagePosition) {
+ float inset = dp.getInsets().top;
+ out.setX(Math.round(onScreenRectCenterX / fullscreenScaleX
+ - 1.0f * drawableWidth / 2));
+ out.setY(Math.round((onScreenRectCenterY + (inset / 2f)) / fullscreenScaleY
+ - 1.0f * drawableHeight / 2));
}
@Override
@@ -423,24 +448,29 @@
@Override
public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
StagedSplitBounds splitInfo, int desiredStagePosition) {
- float diff;
- float horizontalDividerDiff = splitInfo.visualDividerBounds.width() / 2f;
+ float topLeftTaskPercent = splitInfo.appsStackedVertically
+ ? splitInfo.topTaskPercent
+ : splitInfo.leftTaskPercent;
+ float dividerBarPercent = splitInfo.appsStackedVertically
+ ? splitInfo.dividerHeightPercent
+ : splitInfo.dividerWidthPercent;
+
if (desiredStagePosition == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) {
- diff = outRect.height() * (1f - splitInfo.leftTaskPercent) + horizontalDividerDiff;
- outRect.bottom -= diff;
+ outRect.bottom = outRect.top + (int) (outRect.height() * topLeftTaskPercent);
} else {
- diff = outRect.height() * splitInfo.leftTaskPercent + horizontalDividerDiff;
- outRect.top += diff;
+ outRect.top += (int) (outRect.height() * (topLeftTaskPercent + dividerBarPercent));
}
}
@Override
public void measureGroupedTaskViewThumbnailBounds(View primarySnapshot, View secondarySnapshot,
- int parentWidth, int parentHeight,
- StagedSplitBounds splitBoundsConfig, DeviceProfile dp) {
+ int parentWidth, int parentHeight, StagedSplitBounds splitBoundsConfig,
+ DeviceProfile dp, boolean isRtl) {
int spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx;
int totalThumbnailHeight = parentHeight - spaceAboveSnapshot;
- int dividerBar = splitBoundsConfig.visualDividerBounds.width();
+ int dividerBar = splitBoundsConfig.appsStackedVertically
+ ? splitBoundsConfig.visualDividerBounds.height()
+ : splitBoundsConfig.visualDividerBounds.width();
int primarySnapshotHeight;
int primarySnapshotWidth;
int secondarySnapshotHeight;
@@ -464,35 +494,54 @@
}
@Override
- public void setIconAndSnapshotParams(View iconView, int taskIconMargin, int taskIconHeight,
- FrameLayout.LayoutParams snapshotParams, boolean isRtl) {
- FrameLayout.LayoutParams iconParams =
- (FrameLayout.LayoutParams) iconView.getLayoutParams();
+ public void setTaskIconParams(FrameLayout.LayoutParams iconParams, int taskIconMargin,
+ int taskIconHeight, int thumbnailTopMargin, boolean isRtl) {
iconParams.gravity = (isRtl ? START : END) | CENTER_VERTICAL;
iconParams.rightMargin = -taskIconHeight - taskIconMargin / 2;
iconParams.leftMargin = 0;
- iconParams.topMargin = snapshotParams.topMargin / 2;
+ iconParams.topMargin = thumbnailTopMargin / 2;
}
@Override
public void setSplitIconParams(View primaryIconView, View secondaryIconView,
int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
- boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
+ int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
+ DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
FrameLayout.LayoutParams primaryIconParams =
(FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
FrameLayout.LayoutParams secondaryIconParams =
new FrameLayout.LayoutParams(primaryIconParams);
- int dividerBar = (splitConfig.appsStackedVertically ?
- splitConfig.visualDividerBounds.height() :
- splitConfig.visualDividerBounds.width());
- primaryIconParams.gravity = (isRtl ? START : END) | TOP;
- primaryIconView.setTranslationY(primarySnapshotHeight - primaryIconView.getHeight() / 2f);
+ // We calculate the "midpoint" of the thumbnail area, and place the icons there.
+ // This is the place where the thumbnail area splits by default, in a near-50/50 split.
+ // It is usually not exactly 50/50, due to insets/screen cutouts.
+ int fullscreenInsetThickness = deviceProfile.getInsets().top;
+ int fullscreenMidpointFromBottom = ((deviceProfile.heightPx - fullscreenInsetThickness)
+ / 2);
+ float midpointFromBottomPct = (float) fullscreenMidpointFromBottom / deviceProfile.heightPx;
+ float insetPct = (float) fullscreenInsetThickness / deviceProfile.heightPx;
+ int spaceAboveSnapshots = deviceProfile.overviewTaskThumbnailTopMarginPx;
+ int overviewThumbnailAreaThickness = groupedTaskViewHeight - spaceAboveSnapshots;
+ int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness * midpointFromBottomPct);
+ int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct);
+
+ primaryIconParams.gravity = BOTTOM | (isRtl ? START : END);
+ secondaryIconParams.gravity = BOTTOM | (isRtl ? START : END);
primaryIconView.setTranslationX(0);
-
- secondaryIconParams.gravity = (isRtl ? START : END) | TOP;
- secondaryIconView.setTranslationY(primarySnapshotHeight + taskIconHeight + dividerBar);
secondaryIconView.setTranslationX(0);
+ if (splitConfig.initiatedFromSeascape) {
+ // if the split was initiated from seascape,
+ // the task on the right (secondary) is slightly larger
+ primaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset);
+ secondaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset
+ + taskIconHeight);
+ } else {
+ // if not,
+ // the task on the left (primary) is slightly larger
+ primaryIconView.setTranslationY(-bottomToMidpointOffset);
+ secondaryIconView.setTranslationY(-bottomToMidpointOffset + taskIconHeight);
+ }
+
primaryIconView.setLayoutParams(primaryIconParams);
secondaryIconView.setLayoutParams(secondaryIconParams);
}
diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java
index 19c4639..ca46aa8 100644
--- a/src/com/android/launcher3/touch/PagedOrientationHandler.java
+++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java
@@ -47,10 +47,6 @@
*/
public interface PagedOrientationHandler {
- int SPLIT_TRANSLATE_PRIMARY_POSITIVE = 0;
- int SPLIT_TRANSLATE_PRIMARY_NEGATIVE = 1;
- int SPLIT_TRANSLATE_SECONDARY_NEGATIVE = 2;
-
PagedOrientationHandler PORTRAIT = new PortraitPagedViewHandler();
PagedOrientationHandler LANDSCAPE = new LandscapePagedViewHandler();
PagedOrientationHandler SEASCAPE = new SeascapePagedViewHandler();
@@ -82,12 +78,6 @@
FloatProperty<View> getPrimaryViewTranslate();
FloatProperty<View> getSecondaryViewTranslate();
- /**
- * @param stagePosition The position where the view to be split will go
- * @return {@link #SPLIT_TRANSLATE_*} constants to indicate which direction the
- * dismissal should happen
- */
- int getSplitTaskViewDismissDirection(@StagePosition int stagePosition, DeviceProfile dp);
int getPrimaryScroll(View view);
float getPrimaryScale(View view);
int getChildStart(View view);
@@ -120,10 +110,29 @@
int getDistanceToBottomOfRect(DeviceProfile dp, Rect rect);
List<SplitPositionOption> getSplitPositionOptions(DeviceProfile dp);
/**
- * @param splitholderSize height of placeholder view in portrait, width in landscape
+ * @param placeholderHeight height of placeholder view in portrait, width in landscape
*/
- void getInitialSplitPlaceholderBounds(int splitholderSize, DeviceProfile dp,
- @StagePosition int stagePosition, Rect out);
+ void getInitialSplitPlaceholderBounds(int placeholderHeight, int placeholderInset,
+ DeviceProfile dp, @StagePosition int stagePosition, Rect out);
+
+ /**
+ * Centers an icon in the split staging area, accounting for insets.
+ * @param out The icon that needs to be centered.
+ * @param onScreenRectCenterX The x-center of the on-screen staging area (most of the Rect is
+ * offscreen).
+ * @param onScreenRectCenterY The y-center of the on-screen staging area (most of the Rect is
+ * offscreen).
+ * @param fullscreenScaleX A x-scaling factor used to convert coordinates back into pixels.
+ * @param fullscreenScaleY A y-scaling factor used to convert coordinates back into pixels.
+ * @param drawableWidth The icon's drawable (final) width.
+ * @param drawableHeight The icon's drawable (final) height.
+ * @param dp The device profile, used to report rotation and hardware insets.
+ * @param stagePosition 0 if the staging area is pinned to top/left, 1 for bottom/right.
+ */
+ void updateStagedSplitIconParams(View out, float onScreenRectCenterX,
+ float onScreenRectCenterY, float fullscreenScaleX, float fullscreenScaleY,
+ int drawableWidth, int drawableHeight, DeviceProfile dp,
+ @StagePosition int stagePosition);
/**
* @param splitDividerSize height of split screen drag handle in portrait, width in landscape
@@ -149,14 +158,15 @@
void measureGroupedTaskViewThumbnailBounds(View primarySnapshot, View secondarySnapshot,
int parentWidth, int parentHeight,
- StagedSplitBounds splitBoundsConfig, DeviceProfile dp);
+ StagedSplitBounds splitBoundsConfig, DeviceProfile dp, boolean isRtl);
// Overview TaskMenuView methods
- void setIconAndSnapshotParams(View iconView, int taskIconMargin, int taskIconHeight,
- FrameLayout.LayoutParams snapshotParams, boolean isRtl);
+ void setTaskIconParams(FrameLayout.LayoutParams iconParams,
+ int taskIconMargin, int taskIconHeight, int thumbnailTopMargin, boolean isRtl);
void setSplitIconParams(View primaryIconView, View secondaryIconView,
int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
- boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig);
+ int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
+ DeviceProfile deviceProfile, StagedSplitBounds splitConfig);
/*
* The following two methods try to center the TaskMenuView in landscape by finding the center
@@ -191,7 +201,12 @@
*/
PointF getAdditionalInsetForTaskMenu(float margin);
- Pair<Float, Float> setDwbLayoutParamsAndGetTranslations(int taskViewWidth,
+ /**
+ * Calculates the position where a Digital Wellbeing Banner should be placed on its parent
+ * TaskView.
+ * @return A Pair of Floats representing the proper x and y translations.
+ */
+ Pair<Float, Float> getDwbLayoutTranslations(int taskViewWidth,
int taskViewHeight, StagedSplitBounds splitBounds, DeviceProfile deviceProfile,
View[] thumbnailViews, int desiredTaskId, View banner);
@@ -211,6 +226,12 @@
*/
void adjustFloatingIconStartVelocity(PointF velocity);
+ /**
+ * Ensures that outStartRect left bound is within the DeviceProfile's visual boundaries
+ * @param outStartRect The start rect that will directly be modified
+ */
+ void fixBoundsForHomeAnimStartRect(RectF outStartRect, DeviceProfile deviceProfile);
+
class ChildBounds {
public final int primaryDimension;
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index ad9f95c..508823c 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -18,6 +18,7 @@
import static android.view.Gravity.BOTTOM;
import static android.view.Gravity.CENTER_HORIZONTAL;
+import static android.view.Gravity.END;
import static android.view.Gravity.START;
import static android.view.Gravity.TOP;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
@@ -28,7 +29,6 @@
import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL;
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.content.res.Resources;
import android.graphics.Matrix;
@@ -47,7 +47,6 @@
import android.widget.LinearLayout;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
@@ -55,7 +54,6 @@
import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
import com.android.launcher3.views.BaseDragLayer;
-import java.util.ArrayList;
import java.util.List;
public class PortraitPagedViewHandler implements PagedOrientationHandler {
@@ -104,6 +102,15 @@
}
@Override
+ public void fixBoundsForHomeAnimStartRect(RectF outStartRect, DeviceProfile deviceProfile) {
+ if (outStartRect.left > deviceProfile.widthPx) {
+ outStartRect.offsetTo(0, outStartRect.top);
+ } else if (outStartRect.left < -deviceProfile.widthPx) {
+ outStartRect.offsetTo(0, outStartRect.top);
+ }
+ }
+
+ @Override
public <T> void setPrimary(T target, Int2DAction<T> action, int param) {
action.call(target, param, 0);
}
@@ -180,24 +187,6 @@
}
@Override
- public int getSplitTaskViewDismissDirection(@StagePosition int stagePosition,
- DeviceProfile dp) {
- if (stagePosition == STAGE_POSITION_TOP_OR_LEFT) {
- if (dp.isLandscape) {
- // Left side
- return SPLIT_TRANSLATE_PRIMARY_NEGATIVE;
- } else {
- // Top side
- return SPLIT_TRANSLATE_SECONDARY_NEGATIVE;
- }
- } else if (stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) {
- // We don't have a bottom option, so should be right
- return SPLIT_TRANSLATE_PRIMARY_POSITIVE;
- }
- throw new IllegalStateException("Invalid split stage position: " + stagePosition);
- }
-
- @Override
public int getPrimaryScroll(View view) {
return view.getScrollX();
}
@@ -289,9 +278,9 @@
@Override
public int getTaskMenuWidth(View view, DeviceProfile deviceProfile) {
- return deviceProfile.isLandscape && !deviceProfile.overviewShowAsGrid ?
- view.getMeasuredHeight() :
- view.getMeasuredWidth();
+ return deviceProfile.isLandscape && !deviceProfile.isTablet
+ ? view.getMeasuredHeight()
+ : view.getMeasuredWidth();
}
@Override
@@ -324,7 +313,7 @@
}
@Override
- public Pair<Float, Float> setDwbLayoutParamsAndGetTranslations(int taskViewWidth,
+ public Pair<Float, Float> getDwbLayoutTranslations(int taskViewWidth,
int taskViewHeight, StagedSplitBounds splitBounds, DeviceProfile deviceProfile,
View[] thumbnailViews, int desiredTaskId, View banner) {
float translationX = 0;
@@ -352,16 +341,25 @@
// Set translations
if (deviceProfile.isLandscape) {
if (desiredTaskId == splitBounds.rightBottomTaskId) {
- translationX = ((taskViewWidth * splitBounds.leftTaskPercent)
- + (taskViewWidth * splitBounds.dividerWidthPercent));
+ float leftTopTaskPercent = splitBounds.appsStackedVertically
+ ? splitBounds.topTaskPercent
+ : splitBounds.leftTaskPercent;
+ float dividerThicknessPercent = splitBounds.appsStackedVertically
+ ? splitBounds.dividerHeightPercent
+ : splitBounds.dividerWidthPercent;
+ translationX = ((taskViewWidth * leftTopTaskPercent)
+ + (taskViewWidth * dividerThicknessPercent));
}
} else {
if (desiredTaskId == splitBounds.leftTopTaskId) {
FrameLayout.LayoutParams snapshotParams =
(FrameLayout.LayoutParams) thumbnailViews[0]
.getLayoutParams();
+ float bottomRightTaskPlusDividerPercent = splitBounds.appsStackedVertically
+ ? (1f - splitBounds.topTaskPercent)
+ : (1f - splitBounds.leftTaskPercent);
translationY = -((taskViewHeight - snapshotParams.topMargin)
- * (1f - splitBounds.topTaskPercent));
+ * bottomRightTaskPlusDividerPercent);
}
}
return new Pair<>(translationX, translationY);
@@ -414,59 +412,85 @@
@Override
public List<SplitPositionOption> getSplitPositionOptions(DeviceProfile dp) {
- List<SplitPositionOption> options = new ArrayList<>(1);
- // Add both left and right options if we're in tablet mode
- if (dp.isTablet && dp.isLandscape) {
- options.add(new SplitPositionOption(
- R.drawable.ic_split_right, R.string.split_screen_position_right,
- STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_MAIN));
- options.add(new SplitPositionOption(
- R.drawable.ic_split_left, R.string.split_screen_position_left,
- STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
- } else {
- if (dp.isSeascape()) {
- // Add left/right options
- options.add(new SplitPositionOption(
- R.drawable.ic_split_right, R.string.split_screen_position_right,
- STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_MAIN));
- } else if (dp.isLandscape) {
- options.add(new SplitPositionOption(
- R.drawable.ic_split_left, R.string.split_screen_position_left,
- STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
- } else {
- // Only add top option
- options.add(new SplitPositionOption(
- R.drawable.ic_split_top, R.string.split_screen_position_top,
- STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
- }
- }
- return options;
+ return Utilities.getSplitPositionOptions(dp);
}
@Override
- public void getInitialSplitPlaceholderBounds(int placeholderHeight, DeviceProfile dp,
- @StagePosition int stagePosition, Rect out) {
- int width = dp.widthPx;
- out.set(0, 0, width, placeholderHeight);
+ public void getInitialSplitPlaceholderBounds(int placeholderHeight, int placeholderInset,
+ DeviceProfile dp, @StagePosition int stagePosition, Rect out) {
+ int screenWidth = dp.widthPx;
+ int screenHeight = dp.heightPx;
+ boolean pinToRight = stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT;
+ int insetThickness;
+ if (!dp.isLandscape) {
+ insetThickness = dp.getInsets().top;
+ } else {
+ insetThickness = pinToRight ? dp.getInsets().right : dp.getInsets().left;
+ }
+ out.set(0, 0, screenWidth, placeholderHeight + insetThickness);
if (!dp.isLandscape) {
// portrait, phone or tablet - spans width of screen, nothing else to do
+ out.inset(placeholderInset, 0);
+
+ // Adjust the top to account for content off screen. This will help to animate the view
+ // in with rounded corners.
+ int totalHeight = (int) (1.0f * screenHeight / 2 * (screenWidth - 2 * placeholderInset)
+ / screenWidth);
+ out.top -= (totalHeight - placeholderHeight);
return;
}
// Now we rotate the portrait rect depending on what side we want pinned
- boolean pinToRight = stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT;
- int screenHeight = dp.heightPx;
- float postRotateScale = (float) screenHeight / width;
+ float postRotateScale = (float) screenHeight / screenWidth;
mTmpMatrix.reset();
mTmpMatrix.postRotate(pinToRight ? 90 : 270);
- mTmpMatrix.postTranslate(pinToRight ? width : 0, pinToRight ? 0 : width);
+ mTmpMatrix.postTranslate(pinToRight ? screenWidth : 0, pinToRight ? 0 : screenWidth);
// The placeholder height stays constant after rotation, so we don't change width scale
mTmpMatrix.postScale(1, postRotateScale);
mTmpRectF.set(out);
mTmpMatrix.mapRect(mTmpRectF);
+ mTmpRectF.inset(0, placeholderInset);
mTmpRectF.roundOut(out);
+
+ // Adjust the top to account for content off screen. This will help to animate the view in
+ // with rounded corners.
+ int totalWidth = (int) (1.0f * screenWidth / 2 * (screenHeight - 2 * placeholderInset)
+ / screenHeight);
+ int width = out.width();
+ if (pinToRight) {
+ out.right += totalWidth - width;
+ } else {
+ out.left -= totalWidth - width;
+ }
+ }
+
+ @Override
+ public void updateStagedSplitIconParams(View out, float onScreenRectCenterX,
+ float onScreenRectCenterY, float fullscreenScaleX, float fullscreenScaleY,
+ int drawableWidth, int drawableHeight, DeviceProfile dp,
+ @StagePosition int stagePosition) {
+ boolean pinToRight = stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT;
+ if (!dp.isLandscape) {
+ float inset = dp.getInsets().top;
+ out.setX(Math.round(onScreenRectCenterX / fullscreenScaleX
+ - 1.0f * drawableWidth / 2));
+ out.setY(Math.round((onScreenRectCenterY + (inset / 2f)) / fullscreenScaleY
+ - 1.0f * drawableHeight / 2));
+ } else {
+ if (pinToRight) {
+ float inset = dp.getInsets().right;
+ out.setX(Math.round((onScreenRectCenterX - (inset / 2f)) / fullscreenScaleX
+ - 1.0f * drawableWidth / 2));
+ } else {
+ float inset = dp.getInsets().left;
+ out.setX(Math.round((onScreenRectCenterX + (inset / 2f)) / fullscreenScaleX
+ - 1.0f * drawableWidth / 2));
+ }
+ out.setY(Math.round(onScreenRectCenterY / fullscreenScaleY
+ - 1.0f * drawableHeight / 2));
+ }
}
@Override
@@ -503,27 +527,32 @@
public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
StagedSplitBounds splitInfo, int desiredStagePosition) {
boolean isLandscape = dp.isLandscape;
+ float topLeftTaskPercent = splitInfo.appsStackedVertically
+ ? splitInfo.topTaskPercent
+ : splitInfo.leftTaskPercent;
+ float dividerBarPercent = splitInfo.appsStackedVertically
+ ? splitInfo.dividerHeightPercent
+ : splitInfo.dividerWidthPercent;
+
if (desiredStagePosition == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) {
if (isLandscape) {
- outRect.right = outRect.left + (int) (outRect.width() * splitInfo.leftTaskPercent);
+ outRect.right = outRect.left + (int) (outRect.width() * topLeftTaskPercent);
} else {
- outRect.bottom = outRect.top + (int) (outRect.height() * splitInfo.topTaskPercent);
+ outRect.bottom = outRect.top + (int) (outRect.height() * topLeftTaskPercent);
}
} else {
if (isLandscape) {
- outRect.left += (int) (outRect.width() *
- (splitInfo.leftTaskPercent + splitInfo.dividerWidthPercent));
+ outRect.left += (int) (outRect.width() * (topLeftTaskPercent + dividerBarPercent));
} else {
- outRect.top += (int) (outRect.height() *
- (splitInfo.topTaskPercent + splitInfo.dividerHeightPercent));
+ outRect.top += (int) (outRect.height() * (topLeftTaskPercent + dividerBarPercent));
}
}
}
@Override
public void measureGroupedTaskViewThumbnailBounds(View primarySnapshot, View secondarySnapshot,
- int parentWidth, int parentHeight,
- StagedSplitBounds splitBoundsConfig, DeviceProfile dp) {
+ int parentWidth, int parentHeight, StagedSplitBounds splitBoundsConfig,
+ DeviceProfile dp, boolean isRtl) {
int spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx;
int totalThumbnailHeight = parentHeight - spaceAboveSnapshot;
int dividerBar = splitBoundsConfig.appsStackedVertically
@@ -542,7 +571,13 @@
secondarySnapshotHeight = totalThumbnailHeight;
secondarySnapshotWidth = parentWidth - primarySnapshotWidth - dividerBar;
int translationX = primarySnapshotWidth + dividerBar;
- secondarySnapshot.setTranslationX(translationX);
+ if (isRtl) {
+ primarySnapshot.setTranslationX(-translationX);
+ secondarySnapshot.setTranslationX(0);
+ } else {
+ secondarySnapshot.setTranslationX(translationX);
+ primarySnapshot.setTranslationX(0);
+ }
secondarySnapshot.setTranslationY(spaceAboveSnapshot);
} else {
primarySnapshotWidth = parentWidth;
@@ -553,6 +588,7 @@
int translationY = primarySnapshotHeight + spaceAboveSnapshot + dividerBar;
secondarySnapshot.setTranslationY(translationY);
secondarySnapshot.setTranslationX(0);
+ primarySnapshot.setTranslationX(0);
}
primarySnapshot.measure(
View.MeasureSpec.makeMeasureSpec(primarySnapshotWidth, View.MeasureSpec.EXACTLY),
@@ -564,10 +600,8 @@
}
@Override
- public void setIconAndSnapshotParams(View iconView, int taskIconMargin, int taskIconHeight,
- FrameLayout.LayoutParams snapshotParams, boolean isRtl) {
- FrameLayout.LayoutParams iconParams =
- (FrameLayout.LayoutParams) iconView.getLayoutParams();
+ public void setTaskIconParams(FrameLayout.LayoutParams iconParams, int taskIconMargin,
+ int taskIconHeight, int thumbnailTopMargin, boolean isRtl) {
iconParams.gravity = TOP | CENTER_HORIZONTAL;
iconParams.leftMargin = iconParams.rightMargin = 0;
iconParams.topMargin = taskIconMargin;
@@ -576,31 +610,72 @@
@Override
public void setSplitIconParams(View primaryIconView, View secondaryIconView,
int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
- boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
+ int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
+ DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
FrameLayout.LayoutParams primaryIconParams =
(FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
FrameLayout.LayoutParams secondaryIconParams =
new FrameLayout.LayoutParams(primaryIconParams);
- int dividerBar = (splitConfig.appsStackedVertically ?
- splitConfig.visualDividerBounds.height() :
- splitConfig.visualDividerBounds.width());
if (deviceProfile.isLandscape) {
- primaryIconParams.gravity = TOP | START;
- primaryIconView.setTranslationX(
- primarySnapshotWidth - primaryIconView.getMeasuredWidth());
- primaryIconView.setTranslationY(0);
- secondaryIconParams.gravity = TOP | START;
- secondaryIconView.setTranslationX(primarySnapshotWidth + dividerBar);
+ // We calculate the "midpoint" of the thumbnail area, and place the icons there.
+ // This is the place where the thumbnail area splits by default, in a near-50/50 split.
+ // It is usually not exactly 50/50, due to insets/screen cutouts.
+ int fullscreenInsetThickness = deviceProfile.isSeascape()
+ ? deviceProfile.getInsets().right
+ : deviceProfile.getInsets().left;
+ int fullscreenMidpointFromBottom = ((deviceProfile.widthPx
+ - fullscreenInsetThickness) / 2);
+ float midpointFromBottomPct = (float) fullscreenMidpointFromBottom
+ / deviceProfile.widthPx;
+ float insetPct = (float) fullscreenInsetThickness / deviceProfile.widthPx;
+ int spaceAboveSnapshots = 0;
+ int overviewThumbnailAreaThickness = groupedTaskViewWidth - spaceAboveSnapshots;
+ int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness
+ * midpointFromBottomPct);
+ int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct);
+
+ if (deviceProfile.isSeascape()) {
+ primaryIconParams.gravity = TOP | (isRtl ? END : START);
+ secondaryIconParams.gravity = TOP | (isRtl ? END : START);
+ if (splitConfig.initiatedFromSeascape) {
+ // if the split was initiated from seascape,
+ // the task on the right (secondary) is slightly larger
+ primaryIconView.setTranslationX(bottomToMidpointOffset - taskIconHeight);
+ secondaryIconView.setTranslationX(bottomToMidpointOffset);
+ } else {
+ // if not,
+ // the task on the left (primary) is slightly larger
+ primaryIconView.setTranslationX(bottomToMidpointOffset + insetOffset
+ - taskIconHeight);
+ secondaryIconView.setTranslationX(bottomToMidpointOffset + insetOffset);
+ }
+ } else {
+ primaryIconParams.gravity = TOP | (isRtl ? START : END);
+ secondaryIconParams.gravity = TOP | (isRtl ? START : END);
+ if (!splitConfig.initiatedFromSeascape) {
+ // if the split was initiated from landscape,
+ // the task on the left (primary) is slightly larger
+ primaryIconView.setTranslationX(-bottomToMidpointOffset);
+ secondaryIconView.setTranslationX(-bottomToMidpointOffset + taskIconHeight);
+ } else {
+ // if not,
+ // the task on the right (secondary) is slightly larger
+ primaryIconView.setTranslationX(-bottomToMidpointOffset - insetOffset);
+ secondaryIconView.setTranslationX(-bottomToMidpointOffset - insetOffset
+ + taskIconHeight);
+ }
+ }
} else {
primaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
- primaryIconView.setTranslationX(-(primaryIconView.getMeasuredWidth()) / 2f);
- primaryIconView.setTranslationY(0);
-
+ // shifts icon half a width left (height is used here since icons are square)
+ primaryIconView.setTranslationX(-(taskIconHeight / 2f));
secondaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
- secondaryIconView.setTranslationX(secondaryIconView.getMeasuredWidth() / 2f);
+ secondaryIconView.setTranslationX(taskIconHeight / 2f);
}
+ primaryIconView.setTranslationY(0);
secondaryIconView.setTranslationY(0);
+
primaryIconView.setLayoutParams(primaryIconParams);
secondaryIconView.setLayoutParams(secondaryIconParams);
}
diff --git a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
index de5f99c..74b6a5b 100644
--- a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
@@ -20,11 +20,9 @@
import static android.view.Gravity.CENTER_VERTICAL;
import static android.view.Gravity.END;
import static android.view.Gravity.START;
-import static android.view.Gravity.TOP;
import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL;
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.content.res.Resources;
@@ -107,21 +105,25 @@
return new PointF(-margin, margin);
}
+
+
@Override
- public Pair<Float, Float> setDwbLayoutParamsAndGetTranslations(int taskViewWidth,
+ public Pair<Float, Float> getDwbLayoutTranslations(int taskViewWidth,
int taskViewHeight, StagedSplitBounds splitBounds, DeviceProfile deviceProfile,
View[] thumbnailViews, int desiredTaskId, View banner) {
+ boolean isRtl = banner.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
float translationX = 0;
float translationY = 0;
FrameLayout.LayoutParams bannerParams = (FrameLayout.LayoutParams) banner.getLayoutParams();
banner.setPivotX(0);
banner.setPivotY(0);
banner.setRotation(getDegreesRotated());
+ translationX = taskViewWidth - banner.getHeight();
FrameLayout.LayoutParams snapshotParams =
(FrameLayout.LayoutParams) thumbnailViews[0]
.getLayoutParams();
- bannerParams.gravity = BOTTOM | END;
- translationX = taskViewWidth - banner.getHeight();
+ bannerParams.gravity = BOTTOM | (isRtl ? END : START);
+
if (splitBounds == null) {
// Single, fullscreen case
bannerParams.width = taskViewHeight - snapshotParams.topMargin;
@@ -131,19 +133,22 @@
// Set correct width
if (desiredTaskId == splitBounds.leftTopTaskId) {
- bannerParams.width = thumbnailViews[1].getMeasuredHeight();
- } else {
bannerParams.width = thumbnailViews[0].getMeasuredHeight();
+ } else {
+ bannerParams.width = thumbnailViews[1].getMeasuredHeight();
}
// Set translations
if (desiredTaskId == splitBounds.rightBottomTaskId) {
- translationY = -(taskViewHeight - snapshotParams.topMargin)
- * (1f - splitBounds.leftTaskPercent)
- + banner.getHeight();
+ translationY = banner.getHeight();
}
if (desiredTaskId == splitBounds.leftTopTaskId) {
- translationY = banner.getHeight();
+ float bottomRightTaskPlusDividerPercent = splitBounds.appsStackedVertically
+ ? (1f - splitBounds.topTaskPercent)
+ : (1f - splitBounds.leftTaskPercent);
+ translationY = banner.getHeight()
+ - ((taskViewHeight - snapshotParams.topMargin)
+ * bottomRightTaskPlusDividerPercent);
}
return new Pair<>(translationX, translationY);
}
@@ -158,33 +163,61 @@
// Add "right" option which is actually the top
return Collections.singletonList(new SplitPositionOption(
R.drawable.ic_split_right, R.string.split_screen_position_right,
- STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
+ STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_MAIN));
}
@Override
- public void setIconAndSnapshotParams(View mIconView, int taskIconMargin, int taskIconHeight,
- FrameLayout.LayoutParams snapshotParams, boolean isRtl) {
- FrameLayout.LayoutParams iconParams =
- (FrameLayout.LayoutParams) mIconView.getLayoutParams();
+ public void setTaskIconParams(FrameLayout.LayoutParams iconParams,
+ int taskIconMargin, int taskIconHeight, int thumbnailTopMargin, boolean isRtl) {
iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL;
iconParams.leftMargin = -taskIconHeight - taskIconMargin / 2;
iconParams.rightMargin = 0;
- iconParams.topMargin = snapshotParams.topMargin / 2;
+ iconParams.topMargin = thumbnailTopMargin / 2;
}
@Override
public void setSplitIconParams(View primaryIconView, View secondaryIconView,
int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
- boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
+ int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
+ DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
super.setSplitIconParams(primaryIconView, secondaryIconView, taskIconHeight,
- primarySnapshotWidth, primarySnapshotHeight, isRtl, deviceProfile, splitConfig);
+ primarySnapshotWidth, primarySnapshotHeight, groupedTaskViewHeight,
+ groupedTaskViewWidth, isRtl, deviceProfile, splitConfig);
FrameLayout.LayoutParams primaryIconParams =
(FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
FrameLayout.LayoutParams secondaryIconParams =
(FrameLayout.LayoutParams) secondaryIconView.getLayoutParams();
- primaryIconParams.gravity = (isRtl ? END : START) | TOP;
- secondaryIconParams.gravity = (isRtl ? END : START) | TOP;
+ // We calculate the "midpoint" of the thumbnail area, and place the icons there.
+ // This is the place where the thumbnail area splits by default, in a near-50/50 split.
+ // It is usually not exactly 50/50, due to insets/screen cutouts.
+ int fullscreenInsetThickness = deviceProfile.getInsets().top;
+ int fullscreenMidpointFromBottom = ((deviceProfile.heightPx
+ - fullscreenInsetThickness) / 2);
+ float midpointFromBottomPct = (float) fullscreenMidpointFromBottom / deviceProfile.heightPx;
+ float insetPct = (float) fullscreenInsetThickness / deviceProfile.heightPx;
+ int spaceAboveSnapshots = deviceProfile.overviewTaskThumbnailTopMarginPx;
+ int overviewThumbnailAreaThickness = groupedTaskViewHeight - spaceAboveSnapshots;
+ int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness * midpointFromBottomPct);
+ int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct);
+
+ primaryIconParams.gravity = BOTTOM | (isRtl ? END : START);
+ secondaryIconParams.gravity = BOTTOM | (isRtl ? END : START);
+ primaryIconView.setTranslationX(0);
+ secondaryIconView.setTranslationX(0);
+ if (splitConfig.initiatedFromSeascape) {
+ // if the split was initiated from seascape,
+ // the task on the right (secondary) is slightly larger
+ primaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset);
+ secondaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset
+ + taskIconHeight);
+ } else {
+ // if not,
+ // the task on the left (primary) is slightly larger
+ primaryIconView.setTranslationY(-bottomToMidpointOffset);
+ secondaryIconView.setTranslationY(-bottomToMidpointOffset + taskIconHeight);
+ }
+
primaryIconView.setLayoutParams(primaryIconParams);
secondaryIconView.setLayoutParams(secondaryIconParams);
}
diff --git a/src/com/android/launcher3/touch/WorkspaceTouchListener.java b/src/com/android/launcher3/touch/WorkspaceTouchListener.java
index 20d2ad3..17bbdf1 100644
--- a/src/com/android/launcher3/touch/WorkspaceTouchListener.java
+++ b/src/com/android/launcher3/touch/WorkspaceTouchListener.java
@@ -21,7 +21,9 @@
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
+import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_CLOSE_TAP_OUTSIDE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WORKSPACE_LONGPRESS;
import android.graphics.PointF;
@@ -39,6 +41,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.Workspace;
import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
@@ -61,7 +64,7 @@
private final Rect mTempRect = new Rect();
private final Launcher mLauncher;
- private final Workspace mWorkspace;
+ private final Workspace<?> mWorkspace;
private final PointF mTouchDownPoint = new PointF();
private final float mTouchSlop;
@@ -69,7 +72,7 @@
private final GestureDetector mGestureDetector;
- public WorkspaceTouchListener(Launcher launcher, Workspace workspace) {
+ public WorkspaceTouchListener(Launcher launcher, Workspace<?> workspace) {
mLauncher = launcher;
mWorkspace = workspace;
// Use twice the touch slop as we are looking for long press which is more
@@ -118,6 +121,9 @@
mLongPressState = STATE_COMPLETED;
}
+ boolean isInAllAppsBottomSheet = mLauncher.isInState(ALL_APPS)
+ && mLauncher.getDeviceProfile().isTablet;
+
final boolean result;
if (mLongPressState == STATE_COMPLETED) {
// We have handled the touch, so workspace does not need to know anything anymore.
@@ -133,8 +139,9 @@
result = true;
} else {
- // We don't want to handle touch, let workspace handle it as usual.
- result = false;
+ // We don't want to handle touch unless we're in AllApps bottom sheet, let workspace
+ // handle it as usual.
+ result = isInAllAppsBottomSheet;
}
if (action == ACTION_UP || action == ACTION_POINTER_UP) {
@@ -150,6 +157,19 @@
if (action == ACTION_UP || action == ACTION_CANCEL) {
cancelLongPress();
}
+ if (action == ACTION_UP && isInAllAppsBottomSheet) {
+ mLauncher.getStateManager().goToState(NORMAL);
+ mLauncher.getStatsLogManager().logger()
+ .withSrcState(ALL_APPS.statsLogOrdinal)
+ .withDstState(NORMAL.statsLogOrdinal)
+ .withContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
+ .setWorkspace(
+ LauncherAtom.WorkspaceContainer.newBuilder()
+ .setPageIndex(
+ mLauncher.getWorkspace().getCurrentPage()))
+ .build())
+ .log(LAUNCHER_ALLAPPS_CLOSE_TAP_OUTSIDE);
+ }
return result;
}
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index c050c6c..7c73be5 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -15,42 +15,47 @@
*/
package com.android.launcher3.util;
+import static android.content.Intent.ACTION_CONFIGURATION_CHANGED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static com.android.launcher3.ResourceUtils.INVALID_RESOURCE_HANDLE;
import static com.android.launcher3.Utilities.dpiFromPx;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_2_BUTTON;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_3_BUTTON;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON;
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.WindowManagerCompat.MIN_TABLET_WIDTH;
-
-import static java.util.Collections.emptyMap;
+import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter;
+import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WIDTH;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.res.Configuration;
import android.graphics.Point;
+import android.graphics.Rect;
import android.hardware.display.DisplayManager;
-import android.hardware.display.DisplayManager.DisplayListener;
import android.os.Build;
-import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
+import android.util.Pair;
import android.view.Display;
import androidx.annotation.AnyThread;
import androidx.annotation.UiThread;
-import androidx.annotation.WorkerThread;
+import com.android.launcher3.ResourceUtils;
import com.android.launcher3.Utilities;
-import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
+import com.android.launcher3.util.window.CachedDisplayInfo;
+import com.android.launcher3.util.window.WindowManagerProxy;
+import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Map;
+import java.util.Collections;
import java.util.Objects;
import java.util.Set;
@@ -58,7 +63,7 @@
* Utility class to cache properties of default display to avoid a system RPC on every call.
*/
@SuppressLint("NewApi")
-public class DisplayController implements DisplayListener, ComponentCallbacks, SafeCloseable {
+public class DisplayController implements ComponentCallbacks, SafeCloseable {
private static final String TAG = "DisplayController";
@@ -67,22 +72,29 @@
public static final int CHANGE_ACTIVE_SCREEN = 1 << 0;
public static final int CHANGE_ROTATION = 1 << 1;
- public static final int CHANGE_FRAME_DELAY = 1 << 2;
- public static final int CHANGE_DENSITY = 1 << 3;
- public static final int CHANGE_SUPPORTED_BOUNDS = 1 << 4;
+ public static final int CHANGE_DENSITY = 1 << 2;
+ public static final int CHANGE_SUPPORTED_BOUNDS = 1 << 3;
+ public static final int CHANGE_NAVIGATION_MODE = 1 << 4;
public static final int CHANGE_ALL = CHANGE_ACTIVE_SCREEN | CHANGE_ROTATION
- | CHANGE_FRAME_DELAY | CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS;
+ | CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS | CHANGE_NAVIGATION_MODE;
+
+ private static final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
+ private static final String NAV_BAR_INTERACTION_MODE_RES_NAME = "config_navBarInteractionMode";
+ private static final String TARGET_OVERLAY_PACKAGE = "android";
private final Context mContext;
private final DisplayManager mDM;
// Null for SDK < S
private final Context mWindowContext;
+
// The callback in this listener updates DeviceProfile, which other listeners might depend on
private DisplayInfoChangeListener mPriorityListener;
private final ArrayList<DisplayInfoChangeListener> mListeners = new ArrayList<>();
+ private final SimpleBroadcastReceiver mReceiver = new SimpleBroadcastReceiver(this::onIntent);
+
private Info mInfo;
private boolean mDestroyed = false;
@@ -96,29 +108,23 @@
mWindowContext.registerComponentCallbacks(this);
} else {
mWindowContext = null;
- SimpleBroadcastReceiver configChangeReceiver =
- new SimpleBroadcastReceiver(this::onConfigChanged);
- mContext.registerReceiver(configChangeReceiver,
- new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
+ mReceiver.register(mContext, ACTION_CONFIGURATION_CHANGED);
}
+
+ // Initialize navigation mode change listener
+ mContext.registerReceiver(mReceiver,
+ getPackageFilter(TARGET_OVERLAY_PACKAGE, ACTION_OVERLAY_CHANGED));
+
+ WindowManagerProxy wmProxy = WindowManagerProxy.INSTANCE.get(context);
mInfo = new Info(getDisplayInfoContext(display), display,
- getInternalDisplays(mDM), emptyMap());
- mDM.registerDisplayListener(this, UI_HELPER_EXECUTOR.getHandler());
+ wmProxy, wmProxy.estimateInternalDisplayBounds(context));
}
- private static ArrayMap<String, PortraitSize> getInternalDisplays(
- DisplayManager displayManager) {
- Display[] displays = displayManager.getDisplays();
- ArrayMap<String, PortraitSize> internalDisplays = new ArrayMap<>();
- for (Display display : displays) {
- if (ApiWrapper.isInternalDisplay(display)) {
- Point size = new Point();
- display.getRealSize(size);
- internalDisplays.put(ApiWrapper.getUniqueId(display),
- new PortraitSize(size.x, size.y));
- }
- }
- return internalDisplays;
+ /**
+ * Returns the current navigation mode
+ */
+ public static NavigationMode getNavigationMode(Context context) {
+ return INSTANCE.get(context).getInfo().navigationMode;
}
@Override
@@ -129,36 +135,6 @@
} else {
// TODO: unregister broadcast receiver
}
- mDM.unregisterDisplayListener(this);
- }
-
- @Override
- public final void onDisplayAdded(int displayId) { }
-
- @Override
- public final void onDisplayRemoved(int displayId) { }
-
- @WorkerThread
- @Override
- public final void onDisplayChanged(int displayId) {
- if (displayId != DEFAULT_DISPLAY) {
- return;
- }
- Display display = mDM.getDisplay(DEFAULT_DISPLAY);
- if (display == null) {
- return;
- }
- if (Utilities.ATLEAST_S) {
- // Only check for refresh rate. Everything else comes from component callbacks
- if (getSingleFrameMs(display) == mInfo.singleFrameMs) {
- return;
- }
- }
- handleInfoChange(display);
- }
-
- public static int getSingleFrameMs(Context context) {
- return INSTANCE.get(context).getInfo().singleFrameMs;
}
/**
@@ -175,15 +151,20 @@
void onDisplayInfoChanged(Context context, Info info, int flags);
}
- /**
- * Only used for pre-S
- */
- private void onConfigChanged(Intent intent) {
+ private void onIntent(Intent intent) {
if (mDestroyed) {
return;
}
- Configuration config = mContext.getResources().getConfiguration();
- if (mInfo.fontScale != config.fontScale || mInfo.densityDpi != config.densityDpi) {
+ boolean reconfigure = false;
+ if (ACTION_OVERLAY_CHANGED.equals(intent.getAction())) {
+ reconfigure = true;
+ } else if (ACTION_CONFIGURATION_CHANGED.equals(intent.getAction())) {
+ Configuration config = mContext.getResources().getConfiguration();
+ reconfigure = mInfo.fontScale != config.fontScale
+ || mInfo.densityDpi != config.densityDpi;
+ }
+
+ if (reconfigure) {
Log.d(TAG, "Configuration changed, notifying listeners");
Display display = mDM.getDisplay(DEFAULT_DISPLAY);
if (display != null) {
@@ -231,15 +212,17 @@
@AnyThread
private void handleInfoChange(Display display) {
+ WindowManagerProxy wmProxy = WindowManagerProxy.INSTANCE.get(mContext);
Info oldInfo = mInfo;
Context displayContext = getDisplayInfoContext(display);
- Info newInfo = new Info(displayContext, display,
- oldInfo.mInternalDisplays, oldInfo.mPerDisplayBounds);
+ Info newInfo = new Info(displayContext, display, wmProxy, oldInfo.mPerDisplayBounds);
- if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale) {
+ if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale
+ || newInfo.navigationMode != oldInfo.navigationMode) {
// Cache may not be valid anymore, recreate without cache
- newInfo = new Info(displayContext, display, getInternalDisplays(mDM), emptyMap());
+ newInfo = new Info(displayContext, display, wmProxy,
+ wmProxy.estimateInternalDisplayBounds(displayContext));
}
int change = 0;
@@ -249,18 +232,19 @@
if (newInfo.rotation != oldInfo.rotation) {
change |= CHANGE_ROTATION;
}
- if (newInfo.singleFrameMs != oldInfo.singleFrameMs) {
- change |= CHANGE_FRAME_DELAY;
- }
if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale) {
change |= CHANGE_DENSITY;
}
+ if (newInfo.navigationMode != oldInfo.navigationMode) {
+ change |= CHANGE_NAVIGATION_MODE;
+ }
if (!newInfo.supportedBounds.equals(oldInfo.supportedBounds)) {
change |= CHANGE_SUPPORTED_BOUNDS;
- PortraitSize realSize = new PortraitSize(newInfo.currentSize.x, newInfo.currentSize.y);
- PortraitSize expectedSize = oldInfo.mInternalDisplays.get(
- ApiWrapper.getUniqueId(display));
+ Point currentS = newInfo.currentSize;
+ Pair<CachedDisplayInfo, WindowBounds[]> cachedBounds =
+ oldInfo.mPerDisplayBounds.get(newInfo.displayId);
+ Point expectedS = cachedBounds == null ? null : cachedBounds.first.size;
if (newInfo.supportedBounds.size() != oldInfo.supportedBounds.size()) {
Log.e("b/198965093",
"Inconsistent number of displays"
@@ -268,8 +252,12 @@
+ "\noldInfo.supportedBounds: " + oldInfo.supportedBounds
+ "\nnewInfo.supportedBounds: " + newInfo.supportedBounds);
}
- if (!realSize.equals(expectedSize) && display.getState() == Display.STATE_OFF) {
- Log.e("b/198965093", "Display size changed while display is off, ignoring change");
+ if (expectedS != null
+ && (Math.min(currentS.x, currentS.y) != Math.min(expectedS.x, expectedS.y)
+ || Math.max(currentS.x, currentS.y) != Math.max(expectedS.x, expectedS.y))
+ && display.getState() == Display.STATE_OFF) {
+ Log.e("b/198965093",
+ "Display size changed while display is off, ignoring change");
return;
}
}
@@ -285,98 +273,109 @@
if (mPriorityListener != null) {
mPriorityListener.onDisplayInfoChanged(context, mInfo, flags);
}
- for (int i = mListeners.size() - 1; i >= 0; i--) {
+
+ int count = mListeners.size();
+ for (int i = 0; i < count; i++) {
mListeners.get(i).onDisplayInfoChanged(context, mInfo, flags);
}
}
public static class Info {
- public final int singleFrameMs;
-
- // Configuration properties
+ // Cached property
public final int rotation;
+ public final String displayId;
+ public final Point currentSize;
+ public final Rect cutout;
+
+ // Configuration property
public final float fontScale;
- public final int densityDpi;
+ private final int densityDpi;
+ public final NavigationMode navigationMode;
private final PortraitSize mScreenSizeDp;
- public final Point currentSize;
-
- public String displayId;
public final Set<WindowBounds> supportedBounds = new ArraySet<>();
- private final Map<String, Set<WindowBounds>> mPerDisplayBounds = new ArrayMap<>();
- private final ArrayMap<String, PortraitSize> mInternalDisplays;
+
+ private final ArrayMap<String, Pair<CachedDisplayInfo, WindowBounds[]>> mPerDisplayBounds =
+ new ArrayMap<>();
public Info(Context context, Display display) {
- this(context, display, new ArrayMap<>(), emptyMap());
+ /* don't need system overrides for external displays */
+ this(context, display, new WindowManagerProxy(), new ArrayMap<>());
}
- private Info(Context context, Display display,
- ArrayMap<String, PortraitSize> internalDisplays,
- Map<String, Set<WindowBounds>> perDisplayBoundsCache) {
- mInternalDisplays = internalDisplays;
- rotation = display.getRotation();
+ // Used for testing
+ public Info(Context context, Display display,
+ WindowManagerProxy wmProxy,
+ ArrayMap<String, Pair<CachedDisplayInfo, WindowBounds[]>> perDisplayBoundsCache) {
+ CachedDisplayInfo displayInfo = wmProxy.getDisplayInfo(context, display);
+ rotation = displayInfo.rotation;
+ currentSize = displayInfo.size;
+ displayId = displayInfo.id;
+ cutout = displayInfo.cutout;
Configuration config = context.getResources().getConfiguration();
fontScale = config.fontScale;
densityDpi = config.densityDpi;
mScreenSizeDp = new PortraitSize(config.screenHeightDp, config.screenWidthDp);
+ navigationMode = parseNavigationMode(context);
- singleFrameMs = getSingleFrameMs(display);
- currentSize = new Point();
- display.getRealSize(currentSize);
+ mPerDisplayBounds.putAll(perDisplayBoundsCache);
+ Pair<CachedDisplayInfo, WindowBounds[]> cachedValue = mPerDisplayBounds.get(displayId);
- displayId = ApiWrapper.getUniqueId(display);
- Set<WindowBounds> currentSupportedBounds =
- getSupportedBoundsForDisplay(display, currentSize);
- mPerDisplayBounds.put(displayId, currentSupportedBounds);
- supportedBounds.addAll(currentSupportedBounds);
-
- if (ApiWrapper.isInternalDisplay(display) && internalDisplays.size() > 1) {
- int displayCount = internalDisplays.size();
- for (int i = 0; i < displayCount; i++) {
- String displayKey = internalDisplays.keyAt(i);
- if (TextUtils.equals(displayId, displayKey)) {
- continue;
- }
-
- Set<WindowBounds> displayBounds = perDisplayBoundsCache.get(displayKey);
- if (displayBounds == null) {
- // We assume densityDpi is the same across all internal displays
- displayBounds = WindowManagerCompat.estimateDisplayProfiles(
- context, internalDisplays.valueAt(i), densityDpi,
- ApiWrapper.TASKBAR_DRAWN_IN_PROCESS);
- }
-
- supportedBounds.addAll(displayBounds);
- mPerDisplayBounds.put(displayKey, displayBounds);
+ WindowBounds realBounds = wmProxy.getRealBounds(context, display, displayInfo);
+ if (cachedValue == null) {
+ supportedBounds.add(realBounds);
+ } else {
+ // Verify that the real bounds are a match
+ WindowBounds expectedBounds = cachedValue.second[displayInfo.rotation];
+ if (!realBounds.equals(expectedBounds)) {
+ WindowBounds[] clone = new WindowBounds[4];
+ System.arraycopy(cachedValue.second, 0, clone, 0, 4);
+ clone[displayInfo.rotation] = realBounds;
+ cachedValue = Pair.create(displayInfo.normalize(), clone);
+ mPerDisplayBounds.put(displayId, cachedValue);
}
}
- }
-
- private static Set<WindowBounds> getSupportedBoundsForDisplay(Display display, Point size) {
- Point smallestSize = new Point();
- Point largestSize = new Point();
- display.getCurrentSizeRange(smallestSize, largestSize);
-
- int portraitWidth = Math.min(size.x, size.y);
- int portraitHeight = Math.max(size.x, size.y);
- Set<WindowBounds> result = new ArraySet<>();
- result.add(new WindowBounds(portraitWidth, portraitHeight,
- smallestSize.x, largestSize.y));
- result.add(new WindowBounds(portraitHeight, portraitWidth,
- largestSize.x, smallestSize.y));
- return result;
+ mPerDisplayBounds.values().forEach(
+ pair -> Collections.addAll(supportedBounds, pair.second));
+ Log.d("b/211775278", "displayId: " + displayId + ", currentSize: " + currentSize);
+ Log.d("b/211775278", "perDisplayBounds: " + mPerDisplayBounds);
}
/**
- * Returns true if the bounds represent a tablet
+ * Returns {@code true} if the bounds represent a tablet.
*/
public boolean isTablet(WindowBounds bounds) {
- return dpiFromPx(Math.min(bounds.bounds.width(), bounds.bounds.height()),
- densityDpi) >= MIN_TABLET_WIDTH;
+ return smallestSizeDp(bounds) >= MIN_TABLET_WIDTH;
}
+
+ /**
+ * Returns smallest size in dp for given bounds.
+ */
+ public float smallestSizeDp(WindowBounds bounds) {
+ return dpiFromPx(Math.min(bounds.bounds.width(), bounds.bounds.height()), densityDpi);
+ }
+
+ public int getDensityDpi() {
+ return densityDpi;
+ }
+ }
+
+ /**
+ * Dumps the current state information
+ */
+ public void dump(PrintWriter pw) {
+ Info info = mInfo;
+ pw.println("DisplayController.Info:");
+ pw.println(" id=" + info.displayId);
+ pw.println(" rotation=" + info.rotation);
+ pw.println(" fontScale=" + info.fontScale);
+ pw.println(" densityDpi=" + info.densityDpi);
+ pw.println(" navigationMode=" + info.navigationMode.name());
+ pw.println(" currentSize=" + info.currentSize);
+ pw.println(" supportedBounds=" + info.supportedBounds);
}
/**
@@ -404,8 +403,35 @@
}
}
- private static int getSingleFrameMs(Display display) {
- float refreshRate = display.getRefreshRate();
- return refreshRate > 0 ? (int) (1000 / refreshRate) : 16;
+ public enum NavigationMode {
+ THREE_BUTTONS(false, 0, LAUNCHER_NAVIGATION_MODE_3_BUTTON),
+ TWO_BUTTONS(true, 1, LAUNCHER_NAVIGATION_MODE_2_BUTTON),
+ NO_BUTTON(true, 2, LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON);
+
+ public final boolean hasGestures;
+ public final int resValue;
+ public final LauncherEvent launcherEvent;
+
+ NavigationMode(boolean hasGestures, int resValue, LauncherEvent launcherEvent) {
+ this.hasGestures = hasGestures;
+ this.resValue = resValue;
+ this.launcherEvent = launcherEvent;
+ }
+ }
+
+ private static NavigationMode parseNavigationMode(Context context) {
+ int modeInt = ResourceUtils.getIntegerByName(NAV_BAR_INTERACTION_MODE_RES_NAME,
+ context.getResources(), INVALID_RESOURCE_HANDLE);
+
+ if (modeInt == INVALID_RESOURCE_HANDLE) {
+ Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
+ } else {
+ for (NavigationMode m : NavigationMode.values()) {
+ if (m.resValue == modeInt) {
+ return m;
+ }
+ }
+ }
+ return Utilities.ATLEAST_S ? NavigationMode.NO_BUTTON : NavigationMode.THREE_BUTTONS;
}
}
diff --git a/src/com/android/launcher3/util/Executors.java b/src/com/android/launcher3/util/Executors.java
index 6329540..6978e0c 100644
--- a/src/com/android/launcher3/util/Executors.java
+++ b/src/com/android/launcher3/util/Executors.java
@@ -19,6 +19,8 @@
import android.os.Looper;
import android.os.Process;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
@@ -34,6 +36,9 @@
Math.max(Runtime.getRuntime().availableProcessors(), 2);
private static final int KEEP_ALIVE = 1;
+ /** Dedicated executor instances for work depending on other packages. */
+ private static final Map<String, LooperExecutor> PACKAGE_EXECUTORS = new ConcurrentHashMap<>();
+
/**
* An {@link ThreadPoolExecutor} to be used with async task with no limit on the queue size.
*/
@@ -76,6 +81,17 @@
new LooperExecutor(createAndStartNewLooper("launcher-loader"));
/**
+ * Returns and caches a single thread executor for a given package.
+ *
+ * @param packageName Package associated with the executor.
+ */
+ public static LooperExecutor getPackageExecutor(String packageName) {
+ return PACKAGE_EXECUTORS.computeIfAbsent(
+ packageName, p -> new LooperExecutor(
+ createAndStartNewLooper(p, Process.THREAD_PRIORITY_DEFAULT)));
+ }
+
+ /**
* A simple ThreadFactory to set the thread name and priority when used with executors.
*/
public static class SimpleThreadFactory implements ThreadFactory {
diff --git a/src/com/android/launcher3/util/FlagOp.java b/src/com/android/launcher3/util/FlagOp.java
deleted file mode 100644
index bd40eb9..0000000
--- a/src/com/android/launcher3/util/FlagOp.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.android.launcher3.util;
-
-public interface FlagOp {
-
- FlagOp NO_OP = i -> i;
-
- int apply(int flags);
-
- static FlagOp addFlag(int flag) {
- return i -> i | flag;
- }
-
- static FlagOp removeFlag(int flag) {
- return i -> i & ~flag;
- }
-}
diff --git a/src/com/android/launcher3/util/GridOccupancy.java b/src/com/android/launcher3/util/GridOccupancy.java
index 9c752a7..1301460 100644
--- a/src/com/android/launcher3/util/GridOccupancy.java
+++ b/src/com/android/launcher3/util/GridOccupancy.java
@@ -7,7 +7,7 @@
/**
* Utility object to manage the occupancy in a grid.
*/
-public class GridOccupancy {
+public class GridOccupancy extends AbsGridOccupancy {
private final int mCountX;
private final int mCountY;
@@ -30,24 +30,7 @@
* @return true if a vacant cell was found
*/
public boolean findVacantCell(int[] vacantOut, int spanX, int spanY) {
- for (int y = 0; (y + spanY) <= mCountY; y++) {
- for (int x = 0; (x + spanX) <= mCountX; x++) {
- boolean available = !cells[x][y];
- out:
- for (int i = x; i < x + spanX; i++) {
- for (int j = y; j < y + spanY; j++) {
- available = available && !cells[i][j];
- if (!available) break out;
- }
- }
- if (available) {
- vacantOut[0] = x;
- vacantOut[1] = y;
- return true;
- }
- }
- }
- return false;
+ return super.findVacantCell(vacantOut, cells, mCountX, mCountY, spanX, spanY);
}
public void copyTo(GridOccupancy dest) {
diff --git a/src/com/android/launcher3/util/ItemInfoMatcher.java b/src/com/android/launcher3/util/ItemInfoMatcher.java
index 7917410..b6af314 100644
--- a/src/com/android/launcher3/util/ItemInfoMatcher.java
+++ b/src/com/android/launcher3/util/ItemInfoMatcher.java
@@ -19,6 +19,8 @@
import android.content.ComponentName;
import android.os.UserHandle;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
@@ -27,90 +29,64 @@
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
+import java.util.function.Predicate;
/**
* A utility class to check for {@link ItemInfo}
*/
-public interface ItemInfoMatcher {
+public abstract class ItemInfoMatcher {
/**
* Empty component used for match testing
*/
- ComponentName EMPTY_COMPONENT = new ComponentName("", "");
+ private static final ComponentName EMPTY_COMPONENT = new ComponentName("", "");
- boolean matches(ItemInfo info, ComponentName cn);
-
- /**
- * Returns true if the itemInfo matches this check
- */
- default boolean matchesInfo(ItemInfo info) {
- if (info != null) {
- ComponentName cn = info.getTargetComponent();
- return matches(info, cn != null ? cn : EMPTY_COMPONENT);
- } else {
- return false;
- }
+ public static Predicate<ItemInfo> ofUser(UserHandle user) {
+ return info -> info != null && info.user.equals(user);
}
- /**
- * Returns a new matcher with returns true if either this or {@param matcher} returns true.
- */
- default ItemInfoMatcher or(ItemInfoMatcher matcher) {
- return (info, cn) -> matches(info, cn) || matcher.matches(info, cn);
+ public static Predicate<ItemInfo> ofComponents(
+ HashSet<ComponentName> components, UserHandle user) {
+ return info -> info != null && info.user.equals(user)
+ && components.contains(getNonNullComponent(info));
}
- /**
- * Returns a new matcher with returns true if both this and {@param matcher} returns true.
- */
- default ItemInfoMatcher and(ItemInfoMatcher matcher) {
- return (info, cn) -> matches(info, cn) && matcher.matches(info, cn);
+ public static Predicate<ItemInfo> ofPackages(Set<String> packageNames, UserHandle user) {
+ return info -> info != null && info.user.equals(user)
+ && packageNames.contains(getNonNullComponent(info).getPackageName());
}
- /**
- * Returns a new matcher with returns the opposite value of this.
- */
- default ItemInfoMatcher negate() {
- return (info, cn) -> !matches(info, cn);
- }
-
- static ItemInfoMatcher ofUser(UserHandle user) {
- return (info, cn) -> info.user.equals(user);
- }
-
- static ItemInfoMatcher ofComponents(HashSet<ComponentName> components, UserHandle user) {
- return (info, cn) -> components.contains(cn) && info.user.equals(user);
- }
-
- static ItemInfoMatcher ofPackages(Set<String> packageNames, UserHandle user) {
- return (info, cn) -> packageNames.contains(cn.getPackageName()) && info.user.equals(user);
- }
-
- static ItemInfoMatcher ofShortcutKeys(Set<ShortcutKey> keys) {
- return (info, cn) -> info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT
+ public static Predicate<ItemInfo> ofShortcutKeys(Set<ShortcutKey> keys) {
+ return info -> info != null && info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT
&& keys.contains(ShortcutKey.fromItemInfo(info));
}
/**
* Returns a matcher for items within folders.
*/
- static ItemInfoMatcher forFolderMatch(ItemInfoMatcher childOperator) {
- return (info, cn) -> info instanceof FolderInfo && ((FolderInfo) info).contents.stream()
- .anyMatch(childOperator::matchesInfo);
+ public static Predicate<ItemInfo> forFolderMatch(Predicate<ItemInfo> childOperator) {
+ return info -> info instanceof FolderInfo && ((FolderInfo) info).contents.stream()
+ .anyMatch(childOperator);
}
/**
* Returns a matcher for items with provided ids
*/
- static ItemInfoMatcher ofItemIds(IntSet ids) {
- return (info, cn) -> ids.contains(info.id);
+ public static Predicate<ItemInfo> ofItemIds(IntSet ids) {
+ return info -> info != null && ids.contains(info.id);
}
/**
* Returns a matcher for items with provided items
*/
- static ItemInfoMatcher ofItems(Collection<? extends ItemInfo> items) {
+ public static Predicate<ItemInfo> ofItems(Collection<? extends ItemInfo> items) {
IntSet ids = new IntSet();
items.forEach(item -> ids.add(item.id));
return ofItemIds(ids);
}
+
+ private static ComponentName getNonNullComponent(@NonNull ItemInfo info) {
+ ComponentName cn = info.getTargetComponent();
+ return cn != null ? cn : EMPTY_COMPONENT;
+ }
}
diff --git a/src/com/android/launcher3/util/MultiAdditivePropertyFactory.java b/src/com/android/launcher3/util/MultiAdditivePropertyFactory.java
new file mode 100644
index 0000000..50f7027
--- /dev/null
+++ b/src/com/android/launcher3/util/MultiAdditivePropertyFactory.java
@@ -0,0 +1,115 @@
+/*
+ * 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;
+
+import android.util.ArrayMap;
+import android.util.FloatProperty;
+import android.util.Log;
+import android.util.Property;
+import android.view.View;
+
+/**
+ * Allows to combine multiple values set by several sources.
+ *
+ * The various sources are meant to use [set], providing different `setterIndex` params. When it is
+ * not set, 0 is used. This is meant to cover the case multiple animations are going on at the same
+ * time.
+ *
+ * This class behaves similarly to [MultiValueAlpha], but is meant to be more abstract and reusable.
+ * It sets the addition of all values.
+ *
+ * @param <T> Type where to apply the property.
+ */
+public class MultiAdditivePropertyFactory<T extends View> {
+
+ private static final boolean DEBUG = false;
+ private static final String TAG = "MultiAdditivePropertyFactory";
+ private final String mName;
+ private final ArrayMap<Integer, MultiAdditiveProperty> mProperties =
+ new ArrayMap<>();
+
+ // This is an optimization for cases when set is called repeatedly with the same setterIndex.
+ private float mAggregationOfOthers = 0f;
+ private Integer mLastIndexSet = -1;
+ private final Property<View, Float> mProperty;
+
+ public MultiAdditivePropertyFactory(String name, Property<View, Float> property) {
+ mName = name;
+ mProperty = property;
+ }
+
+ /** Returns the [MultiFloatProperty] associated with [inx], creating it if not present. */
+ public MultiAdditiveProperty get(Integer index) {
+ return mProperties.computeIfAbsent(index,
+ (k) -> new MultiAdditiveProperty(index, mName + "_" + index));
+ }
+
+ /**
+ * Each [setValue] will be aggregated with the other properties values created by the
+ * corresponding factory.
+ */
+ class MultiAdditiveProperty extends FloatProperty<T> {
+ private final int mInx;
+ private float mValue = 0f;
+
+ MultiAdditiveProperty(int inx, String name) {
+ super(name);
+ mInx = inx;
+ }
+
+ @Override
+ public void setValue(T obj, float newValue) {
+ if (mLastIndexSet != mInx) {
+ mAggregationOfOthers = 0f;
+ mProperties.forEach((key, property) -> {
+ if (key != mInx) {
+ mAggregationOfOthers += property.mValue;
+ }
+ });
+ mLastIndexSet = mInx;
+ }
+ float lastAggregatedValue = mAggregationOfOthers + newValue;
+ mValue = newValue;
+ apply(obj, lastAggregatedValue);
+
+ if (DEBUG) {
+ Log.d(TAG, "name=" + mName
+ + " newValue=" + newValue + " mInx=" + mInx
+ + " aggregated=" + lastAggregatedValue + " others= " + mProperties);
+ }
+ }
+
+ @Override
+ public Float get(T view) {
+ // The scale of the view should match mLastAggregatedValue. Still, if it has been
+ // changed without using this property, it can differ. As this get method is usually
+ // used to set the starting point on an animation, this would result in some jumps
+ // when the view scale is different than the last aggregated value. To stay on the
+ // safe side, let's return the real view scale.
+ return mProperty.get(view);
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(mValue);
+ }
+ }
+
+ protected void apply(View view, float value) {
+ mProperty.set(view, value);
+ }
+}
diff --git a/src/com/android/launcher3/util/MultiScalePropertyFactory.java b/src/com/android/launcher3/util/MultiScalePropertyFactory.java
new file mode 100644
index 0000000..a7e6cc8
--- /dev/null
+++ b/src/com/android/launcher3/util/MultiScalePropertyFactory.java
@@ -0,0 +1,125 @@
+/*
+ * 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;
+
+import android.util.ArrayMap;
+import android.util.FloatProperty;
+import android.util.Log;
+import android.view.View;
+
+import com.android.launcher3.Utilities;
+
+/**
+ * Allows to combine multiple values set by several sources.
+ *
+ * The various sources are meant to use [set], providing different `setterIndex` params. When it is
+ * not set, 0 is used. This is meant to cover the case multiple animations are going on at the same
+ * time.
+ *
+ * This class behaves similarly to [MultiValueAlpha], but is meant to be more abstract and reusable.
+ * It sets the multiplication of all values, bounded to the max and the min values.
+ *
+ * @param <T> Type where to apply the property.
+ */
+public class MultiScalePropertyFactory<T extends View> {
+
+ 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>();
+
+ // This is an optimization for cases when set is called repeatedly with the same setterIndex.
+ private float mMinOfOthers = 0;
+ private float mMaxOfOthers = 0;
+ private float mMultiplicationOfOthers = 0;
+ private Integer mLastIndexSet = -1;
+ private float mLastAggregatedValue = 1.0f;
+
+ public MultiScalePropertyFactory(String name) {
+ mName = name;
+ }
+
+ /** Returns the [MultiFloatProperty] associated with [inx], creating it if not present. */
+ public MultiScaleProperty get(Integer index) {
+ return mProperties.computeIfAbsent(index,
+ (k) -> new MultiScaleProperty(index, mName + "_" + index));
+ }
+
+ /**
+ * Each [setValue] will be aggregated with the other properties values created by the
+ * corresponding factory.
+ */
+ class MultiScaleProperty extends FloatProperty<T> {
+ private final int mInx;
+ private float mValue = 1.0f;
+
+ MultiScaleProperty(int inx, String name) {
+ super(name);
+ mInx = inx;
+ }
+
+ @Override
+ public void setValue(T obj, float newValue) {
+ if (mLastIndexSet != mInx) {
+ mMinOfOthers = Float.MAX_VALUE;
+ mMaxOfOthers = Float.MIN_VALUE;
+ mMultiplicationOfOthers = 1.0f;
+ mProperties.forEach((key, property) -> {
+ if (key != mInx) {
+ mMinOfOthers = Math.min(mMinOfOthers, property.mValue);
+ mMaxOfOthers = Math.max(mMaxOfOthers, property.mValue);
+ mMultiplicationOfOthers *= property.mValue;
+ }
+ });
+ mLastIndexSet = mInx;
+ }
+ float minValue = Math.min(mMinOfOthers, newValue);
+ float maxValue = Math.max(mMaxOfOthers, newValue);
+ float multValue = mMultiplicationOfOthers * newValue;
+ mLastAggregatedValue = Utilities.boundToRange(multValue, minValue, maxValue);
+ mValue = newValue;
+ apply(obj, mLastAggregatedValue);
+
+ if (DEBUG) {
+ Log.d(TAG, "name=" + mName
+ + " newValue=" + newValue + " mInx=" + mInx
+ + " aggregated=" + mLastAggregatedValue + " others= " + mProperties);
+ }
+ }
+
+ @Override
+ public Float get(T view) {
+ // The scale of the view should match mLastAggregatedValue. Still, if it has been
+ // changed without using this property, it can differ. As this get method is usually
+ // used to set the starting point on an animation, this would result in some jumps
+ // when the view scale is different than the last aggregated value. To stay on the
+ // safe side, let's return the real view scale.
+ return view.getScaleX();
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(mValue);
+ }
+ }
+
+ protected void apply(View view, float value) {
+ view.setScaleX(value);
+ view.setScaleY(value);
+ }
+}
diff --git a/src/com/android/launcher3/util/OnboardingPrefs.java b/src/com/android/launcher3/util/OnboardingPrefs.java
index 5ba0d30..f4cf21e 100644
--- a/src/com/android/launcher3/util/OnboardingPrefs.java
+++ b/src/com/android/launcher3/util/OnboardingPrefs.java
@@ -20,7 +20,7 @@
import androidx.annotation.StringDef;
-import com.android.launcher3.Launcher;
+import com.android.launcher3.views.ActivityContext;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -29,23 +29,29 @@
/**
* Stores and retrieves onboarding-related data via SharedPreferences.
+ *
+ * @param <T> Context which owns these preferences.
*/
-public class OnboardingPrefs<T extends Launcher> {
+public class OnboardingPrefs<T extends ActivityContext> {
public static final String HOME_BOUNCE_SEEN = "launcher.apps_view_shown";
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_EDU_SEEN = "launcher.search_edu_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 TASKBAR_EDU_SEEN = "launcher.taskbar_edu_seen";
+ public static final String ALL_APPS_VISITED_COUNT = "launcher.all_apps_visited_count";
// 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_EDU_SEEN, SEARCH_SNACKBAR_COUNT },
- "Taskbar Education", new String[] { TASKBAR_EDU_SEEN }
+ "Search Education", new String[] { SEARCH_KEYBOARD_EDU_SEEN, SEARCH_SNACKBAR_COUNT,
+ SEARCH_ONBOARDING_COUNT},
+ "Taskbar Education", new String[] { TASKBAR_EDU_SEEN },
+ "All Apps Visited Count", new String[] {ALL_APPS_VISITED_COUNT}
);
/**
@@ -54,12 +60,11 @@
@StringDef(value = {
HOME_BOUNCE_SEEN,
HOTSEAT_LONGPRESS_TIP_SEEN,
- SEARCH_EDU_SEEN,
+ SEARCH_KEYBOARD_EDU_SEEN,
TASKBAR_EDU_SEEN
})
@Retention(RetentionPolicy.SOURCE)
- public @interface EventBoolKey {
- }
+ public @interface EventBoolKey {}
/**
* Events that occur multiple times, which we count up to a max defined in {@link #MAX_COUNTS}.
@@ -67,19 +72,23 @@
@StringDef(value = {
HOME_BOUNCE_COUNT,
HOTSEAT_DISCOVERY_TIP_COUNT,
- SEARCH_SNACKBAR_COUNT
+ SEARCH_SNACKBAR_COUNT,
+ SEARCH_ONBOARDING_COUNT,
+ ALL_APPS_VISITED_COUNT
})
@Retention(RetentionPolicy.SOURCE)
- public @interface EventCountKey {
- }
+ public @interface EventCountKey {}
private static final Map<String, Integer> MAX_COUNTS;
static {
- Map<String, Integer> maxCounts = new ArrayMap<>(4);
+ 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);
MAX_COUNTS = Collections.unmodifiableMap(maxCounts);
}
@@ -131,4 +140,14 @@
mSharedPrefs.edit().putInt(eventKey, count).apply();
return hasReachedMaxCount(count, eventKey);
}
+
+ /**
+ * Sets the event count to the given value.
+ *
+ * @return Whether we have now reached the max count.
+ */
+ public boolean setEventCount(int count, @EventCountKey String eventKey) {
+ mSharedPrefs.edit().putInt(eventKey, count).apply();
+ return hasReachedMaxCount(count, eventKey);
+ }
}
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index 08ec591..f42d304 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -202,7 +202,8 @@
public static Intent getStyleWallpapersIntent(Context context) {
return new Intent(Intent.ACTION_SET_WALLPAPER).setComponent(
new ComponentName(context.getString(R.string.wallpaper_picker_package),
- "com.android.customization.picker.CustomizationPickerActivity"));
+ context.getString(R.string.custom_activity_picker)
+ ));
}
/**
diff --git a/src/com/android/launcher3/util/RotationUtils.java b/src/com/android/launcher3/util/RotationUtils.java
new file mode 100644
index 0000000..3414a3d
--- /dev/null
+++ b/src/com/android/launcher3/util/RotationUtils.java
@@ -0,0 +1,75 @@
+/*
+ * 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;
+
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+
+/**
+ * Utility methods based on {@code frameworks/base/core/java/android/util/RotationUtils.java}
+ */
+public class RotationUtils {
+
+ /**
+ * Rotates an Rect according to the given rotation.
+ */
+ public static void rotateRect(Rect rect, int rotation) {
+ switch (rotation) {
+ case ROTATION_0:
+ return;
+ case ROTATION_90:
+ rect.set(rect.top, rect.right, rect.bottom, rect.left);
+ return;
+ case ROTATION_180:
+ rect.set(rect.right, rect.bottom, rect.left, rect.top);
+ return;
+ case ROTATION_270:
+ rect.set(rect.bottom, rect.left, rect.top, rect.right);
+ return;
+ default:
+ throw new IllegalArgumentException("unknown rotation: " + rotation);
+ }
+ }
+
+ /**
+ * Rotates an size according to the given rotation.
+ */
+ public static void rotateSize(Point size, int rotation) {
+ switch (rotation) {
+ case ROTATION_0:
+ case ROTATION_180:
+ return;
+ case ROTATION_90:
+ case ROTATION_270:
+ size.set(size.y, size.x);
+ return;
+ default:
+ throw new IllegalArgumentException("unknown rotation: " + rotation);
+ }
+ }
+
+ /** @return the rotation needed to rotate from oldRotation to newRotation. */
+ public static int deltaRotation(int oldRotation, int newRotation) {
+ int delta = newRotation - oldRotation;
+ if (delta < 0) delta += 4;
+ return delta;
+ }
+}
diff --git a/src/com/android/launcher3/util/SimpleBroadcastReceiver.java b/src/com/android/launcher3/util/SimpleBroadcastReceiver.java
index 465a0e8..4dfa5cc 100644
--- a/src/com/android/launcher3/util/SimpleBroadcastReceiver.java
+++ b/src/com/android/launcher3/util/SimpleBroadcastReceiver.java
@@ -39,10 +39,17 @@
* Helper method to register multiple actions
*/
public void register(Context context, String... actions) {
+ register(context, 0, actions);
+ }
+
+ /**
+ * Helper method to register multiple actions with one or more {@code flags}.
+ */
+ public void register(Context context, int flags, String... actions) {
IntentFilter filter = new IntentFilter();
for (String action : actions) {
filter.addAction(action);
}
- context.registerReceiver(this, filter);
+ context.registerReceiver(this, filter, flags);
}
}
diff --git a/src/com/android/launcher3/util/SplitConfigurationOptions.java b/src/com/android/launcher3/util/SplitConfigurationOptions.java
index cb714b2..6a336cc 100644
--- a/src/com/android/launcher3/util/SplitConfigurationOptions.java
+++ b/src/com/android/launcher3/util/SplitConfigurationOptions.java
@@ -113,6 +113,14 @@
* the bounds were originally in
*/
public final boolean appsStackedVertically;
+ /**
+ * If {@code true}, that means at the time of creation of this object, the phone was in
+ * seascape orientation. This is important on devices with insets, because they do not split
+ * evenly -- one of the insets must be slightly larger to account for the inset.
+ * From landscape, it is the leftTop task that expands slightly.
+ * From seascape, it is the rightBottom task that expands slightly.
+ */
+ public final boolean initiatedFromSeascape;
public final int leftTopTaskId;
public final int rightBottomTaskId;
@@ -128,17 +136,30 @@
this.visualDividerBounds = new Rect(leftTopBounds.left, leftTopBounds.bottom,
leftTopBounds.right, rightBottomBounds.top);
appsStackedVertically = true;
+ initiatedFromSeascape = false;
} else {
// horizontal apps, vertical divider
this.visualDividerBounds = new Rect(leftTopBounds.right, leftTopBounds.top,
rightBottomBounds.left, leftTopBounds.bottom);
appsStackedVertically = false;
+ // The following check is unreliable on devices without insets
+ // (initiatedFromSeascape will always be set to false.) This happens to be OK for
+ // all our current uses, but should be refactored.
+ // TODO: Create a more reliable check, or refactor how splitting works on devices
+ // with insets.
+ if (rightBottomBounds.width() > leftTopBounds.width()) {
+ initiatedFromSeascape = true;
+ } else {
+ initiatedFromSeascape = false;
+ }
}
- leftTaskPercent = this.leftTopBounds.width() / (float) rightBottomBounds.right;
- topTaskPercent = this.leftTopBounds.height() / (float) rightBottomBounds.bottom;
- dividerWidthPercent = visualDividerBounds.width() / (float) rightBottomBounds.right;
- dividerHeightPercent = visualDividerBounds.height() / (float) rightBottomBounds.bottom;
+ float totalWidth = rightBottomBounds.right - leftTopBounds.left;
+ float totalHeight = rightBottomBounds.bottom - leftTopBounds.top;
+ leftTaskPercent = leftTopBounds.width() / totalWidth;
+ topTaskPercent = leftTopBounds.height() / totalHeight;
+ dividerWidthPercent = visualDividerBounds.width() / totalWidth;
+ dividerHeightPercent = visualDividerBounds.height() / totalHeight;
}
}
diff --git a/src/com/android/launcher3/util/UiThreadHelper.java b/src/com/android/launcher3/util/UiThreadHelper.java
index ac5368c..7e6711f 100644
--- a/src/com/android/launcher3/util/UiThreadHelper.java
+++ b/src/com/android/launcher3/util/UiThreadHelper.java
@@ -25,10 +25,13 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.util.Log;
import android.view.View;
+import android.view.WindowInsets;
+import android.view.WindowInsetsController;
import android.view.inputmethod.InputMethodManager;
-import com.android.launcher3.BaseActivity;
+import com.android.launcher3.Utilities;
import com.android.launcher3.views.ActivityContext;
/**
@@ -49,6 +52,25 @@
public static void hideKeyboardAsync(ActivityContext activityContext, IBinder token) {
View root = activityContext.getDragLayer();
+ if (Utilities.ATLEAST_R) {
+ Preconditions.assertUIThread();
+ // Hide keyboard with WindowInsetsController if could. In case
+ // hideSoftInputFromWindow may get ignored by input connection being finished
+ // when the screen is off.
+ //
+ // In addition, inside IMF, the keyboards are closed asynchronously that launcher no
+ // longer need to post to the message queue.
+ final WindowInsetsController wic = root.getWindowInsetsController();
+ WindowInsets insets = root.getRootWindowInsets();
+ boolean isImeShown = insets != null && insets.isVisible(WindowInsets.Type.ime());
+ if (wic != null && isImeShown) {
+ // this method cannot be called cross threads
+ wic.hide(WindowInsets.Type.ime());
+ activityContext.getStatsLogManager().logger()
+ .log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED);
+ return;
+ }
+ }
// Since the launcher context cannot be accessed directly from callback, adding secondary
// message to log keyboard close event asynchronously.
Bundle mHideKeyboardLoggerMsg = new Bundle();
@@ -56,7 +78,7 @@
STATS_LOGGER_KEY,
Message.obtain(
HANDLER.get(root.getContext()),
- () -> BaseActivity.fromContext(root.getContext())
+ () -> activityContext
.getStatsLogManager()
.logger()
.log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED)
diff --git a/src/com/android/launcher3/util/ViewCache.java b/src/com/android/launcher3/util/ViewCache.java
index 08b8744..98e6822 100644
--- a/src/com/android/launcher3/util/ViewCache.java
+++ b/src/com/android/launcher3/util/ViewCache.java
@@ -21,6 +21,8 @@
import android.view.View;
import android.view.ViewGroup;
+import com.android.launcher3.R;
+
/**
* Utility class to cache views at an activity level
*/
@@ -39,18 +41,26 @@
mCache.put(layoutId, entry);
}
+ T result;
if (entry.mCurrentSize > 0) {
entry.mCurrentSize --;
- T result = (T) entry.mViews[entry.mCurrentSize];
+ result = (T) entry.mViews[entry.mCurrentSize];
entry.mViews[entry.mCurrentSize] = null;
- return result;
+ } else {
+ result = (T) LayoutInflater.from(context).inflate(layoutId, parent, false);
+ result.setTag(R.id.cache_entry_tag_id, entry);
}
-
- return (T) LayoutInflater.from(context).inflate(layoutId, parent, false);
+ return result;
}
public void recycleView(int layoutId, View view) {
CacheEntry entry = mCache.get(layoutId);
+ if (entry != view.getTag(R.id.cache_entry_tag_id)) {
+ // Since this view was created, the cache has been reset. The view should not be
+ // recycled since this means the environment could also have changed, requiring new
+ // view setup.
+ return;
+ }
if (entry != null && entry.mCurrentSize < entry.mMaxSize) {
entry.mViews[entry.mCurrentSize] = view;
entry.mCurrentSize++;
diff --git a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
index 8a7cae9..43e9820 100644
--- a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
+++ b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
@@ -14,6 +14,8 @@
import android.util.Log;
import android.view.animation.Interpolator;
+import androidx.annotation.AnyThread;
+
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.anim.Interpolators;
@@ -30,7 +32,7 @@
// Don't use all the wallpaper for parallax until you have at least this many pages
private static final int MIN_PARALLAX_PAGE_SPAN = 4;
- private final Workspace mWorkspace;
+ private final Workspace<?> mWorkspace;
private final boolean mIsRtl;
private final Handler mHandler;
@@ -41,7 +43,7 @@
private boolean mLockedToDefaultPage;
private int mNumScreens;
- public WallpaperOffsetInterpolator(Workspace workspace) {
+ public WallpaperOffsetInterpolator(Workspace<?> workspace) {
mWorkspace = workspace;
mIsRtl = Utilities.isRtl(workspace.getResources());
mHandler = new OffsetHandler(workspace.getContext());
@@ -182,6 +184,7 @@
}
}
+ @AnyThread
private void updateOffset() {
Message.obtain(mHandler, MSG_SET_NUM_PARALLAX, getNumPagesForWallpaperParallax(), 0,
mWindowToken).sendToTarget();
@@ -206,9 +209,12 @@
@Override
public void onReceive(Context context, Intent intent) {
- mWallpaperIsLiveWallpaper =
- WallpaperManager.getInstance(mWorkspace.getContext()).getWallpaperInfo() != null;
- updateOffset();
+ UI_HELPER_EXECUTOR.execute(() -> {
+ // Updating the boolean on a background thread is fine as the assignments are atomic
+ mWallpaperIsLiveWallpaper =
+ WallpaperManager.getInstance(context).getWallpaperInfo() != null;
+ updateOffset();
+ });
}
private static final int MSG_START_ANIMATION = 1;
diff --git a/src/com/android/launcher3/util/WindowBounds.java b/src/com/android/launcher3/util/WindowBounds.java
index c92770e..a15679a 100644
--- a/src/com/android/launcher3/util/WindowBounds.java
+++ b/src/com/android/launcher3/util/WindowBounds.java
@@ -33,19 +33,27 @@
public final Rect bounds;
public final Rect insets;
public final Point availableSize;
+ public final int rotationHint;
public WindowBounds(Rect bounds, Rect insets) {
+ this(bounds, insets, -1);
+ }
+
+ public WindowBounds(Rect bounds, Rect insets, int rotationHint) {
this.bounds = bounds;
this.insets = insets;
+ this.rotationHint = rotationHint;
availableSize = new Point(bounds.width() - insets.left - insets.right,
bounds.height() - insets.top - insets.bottom);
}
- public WindowBounds(int width, int height, int availableWidth, int availableHeight) {
+ public WindowBounds(int width, int height, int availableWidth, int availableHeight,
+ int rotationHint) {
this.bounds = new Rect(0, 0, width, height);
this.availableSize = new Point(availableWidth, availableHeight);
// We don't care about insets in this case
this.insets = new Rect(0, 0, width - availableWidth, height - availableHeight);
+ this.rotationHint = rotationHint;
}
@Override
diff --git a/src/com/android/launcher3/util/WindowManagerCompat.java b/src/com/android/launcher3/util/WindowManagerCompat.java
deleted file mode 100644
index e1b9478..0000000
--- a/src/com/android/launcher3/util/WindowManagerCompat.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.util;
-
-import static com.android.launcher3.ResourceUtils.INVALID_RESOURCE_HANDLE;
-import static com.android.launcher3.Utilities.dpiFromPx;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Insets;
-import android.graphics.Rect;
-import android.os.Build;
-import android.util.ArraySet;
-import android.view.WindowInsets;
-import android.view.WindowInsets.Type;
-import android.view.WindowManager;
-import android.view.WindowMetrics;
-
-import com.android.launcher3.R;
-import com.android.launcher3.ResourceUtils;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.util.DisplayController.PortraitSize;
-
-import java.util.Collections;
-import java.util.Set;
-
-/**
- * Utility class to estimate window manager values
- */
-@TargetApi(Build.VERSION_CODES.S)
-public class WindowManagerCompat {
-
- public static final int MIN_TABLET_WIDTH = 600;
-
- /**
- * Returns a set of supported render sizes for a internal display.
- * This is a temporary workaround which assumes only nav-bar insets change across displays, and
- * is only used until we eventually get the real values
- * @param consumeTaskBar if true, it assumes that task bar is part of the app window
- * and ignores any insets because of task bar.
- */
- public static Set<WindowBounds> estimateDisplayProfiles(
- Context windowContext, PortraitSize size, int densityDpi, boolean consumeTaskBar) {
- if (!Utilities.ATLEAST_S) {
- return Collections.emptySet();
- }
- WindowInsets defaultInsets = windowContext.getSystemService(WindowManager.class)
- .getMaximumWindowMetrics().getWindowInsets();
- boolean isGesturalMode = ResourceUtils.getIntegerByName(
- "config_navBarInteractionMode",
- windowContext.getResources(),
- INVALID_RESOURCE_HANDLE) == 2;
-
- WindowInsets.Builder insetsBuilder = new WindowInsets.Builder(defaultInsets);
- Set<WindowBounds> result = new ArraySet<>();
- int swDP = (int) dpiFromPx(size.width, densityDpi);
- boolean isTablet = swDP >= MIN_TABLET_WIDTH;
-
- final Insets portraitNav, landscapeNav;
- if (isTablet && !consumeTaskBar) {
- portraitNav = landscapeNav = Insets.of(0, 0, 0, windowContext.getResources()
- .getDimensionPixelSize(R.dimen.taskbar_size));
- } else if (!isGesturalMode) {
- portraitNav = Insets.of(0, 0, 0,
- getSystemResource(windowContext, "navigation_bar_height", swDP));
- landscapeNav = isTablet
- ? Insets.of(0, 0, 0, getSystemResource(windowContext,
- "navigation_bar_height_landscape", swDP))
- : Insets.of(0, 0, getSystemResource(windowContext,
- "navigation_bar_width", swDP), 0);
- } else {
- portraitNav = landscapeNav = Insets.of(0, 0, 0, 0);
- }
-
- result.add(WindowBounds.fromWindowMetrics(new WindowMetrics(
- new Rect(0, 0, size.width, size.height),
- insetsBuilder.setInsets(Type.navigationBars(), portraitNav).build())));
- result.add(WindowBounds.fromWindowMetrics(new WindowMetrics(
- new Rect(0, 0, size.height, size.width),
- insetsBuilder.setInsets(Type.navigationBars(), landscapeNav).build())));
- return result;
- }
-
- private static int getSystemResource(Context context, String key, int swDp) {
- int resourceId = context.getResources().getIdentifier(key, "dimen", "android");
- if (resourceId > 0) {
- Configuration conf = new Configuration();
- conf.smallestScreenWidthDp = swDp;
- return context.createConfigurationContext(conf)
- .getResources().getDimensionPixelSize(resourceId);
- }
- return 0;
- }
-}
diff --git a/src/com/android/launcher3/util/window/CachedDisplayInfo.java b/src/com/android/launcher3/util/window/CachedDisplayInfo.java
new file mode 100644
index 0000000..06b9829
--- /dev/null
+++ b/src/com/android/launcher3/util/window/CachedDisplayInfo.java
@@ -0,0 +1,92 @@
+/*
+ * 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.window;
+
+import static com.android.launcher3.util.RotationUtils.deltaRotation;
+import static com.android.launcher3.util.RotationUtils.rotateRect;
+import static com.android.launcher3.util.RotationUtils.rotateSize;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.view.Surface;
+
+import java.util.Objects;
+
+/**
+ * Properties on a display
+ */
+public class CachedDisplayInfo {
+
+ public final String id;
+ public final Point size;
+ public final int rotation;
+ public final Rect cutout;
+
+ public CachedDisplayInfo() {
+ this(new Point(0, 0), 0);
+ }
+
+ public CachedDisplayInfo(Point size, int rotation) {
+ this("", size, rotation, new Rect());
+ }
+
+ public CachedDisplayInfo(String id, Point size, int rotation, Rect cutout) {
+ this.id = id;
+ this.size = size;
+ this.rotation = rotation;
+ this.cutout = cutout;
+ }
+
+ /**
+ * Returns a CachedDisplayInfo where the properties are normalized to {@link Surface#ROTATION_0}
+ */
+ public CachedDisplayInfo normalize() {
+ if (rotation == Surface.ROTATION_0) {
+ return this;
+ }
+ Point newSize = new Point(size);
+ rotateSize(newSize, deltaRotation(rotation, Surface.ROTATION_0));
+
+ Rect newCutout = new Rect(cutout);
+ rotateRect(newCutout, deltaRotation(rotation, Surface.ROTATION_0));
+ return new CachedDisplayInfo(id, newSize, Surface.ROTATION_0, newCutout);
+ }
+
+ @Override
+ public String toString() {
+ return "CachedDisplayInfo{"
+ + "id='" + id + '\''
+ + ", size=" + size
+ + ", rotation=" + rotation
+ + ", cutout=" + cutout
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof CachedDisplayInfo)) return false;
+ CachedDisplayInfo that = (CachedDisplayInfo) o;
+ return rotation == that.rotation && Objects.equals(id, that.id)
+ && Objects.equals(size, that.size) && Objects.equals(cutout,
+ that.cutout);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, size, rotation, cutout);
+ }
+}
diff --git a/src/com/android/launcher3/util/window/RefreshRateTracker.java b/src/com/android/launcher3/util/window/RefreshRateTracker.java
new file mode 100644
index 0000000..7814617
--- /dev/null
+++ b/src/com/android/launcher3/util/window/RefreshRateTracker.java
@@ -0,0 +1,83 @@
+/*
+ * 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.window;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
+import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
+import android.view.Display;
+
+import androidx.annotation.WorkerThread;
+
+import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.SafeCloseable;
+
+/**
+ * Utility class to track refresh rate of the current device
+ */
+public class RefreshRateTracker implements DisplayListener, SafeCloseable {
+
+ private static final MainThreadInitializedObject<RefreshRateTracker> INSTANCE =
+ new MainThreadInitializedObject<>(RefreshRateTracker::new);
+
+ private int mSingleFrameMs = 1;
+
+ private final DisplayManager mDM;
+
+ private RefreshRateTracker(Context context) {
+ mDM = context.getSystemService(DisplayManager.class);
+ updateSingleFrameMs();
+ mDM.registerDisplayListener(this, UI_HELPER_EXECUTOR.getHandler());
+ }
+
+ /**
+ * Returns the single frame time in ms
+ */
+ public static int getSingleFrameMs(Context context) {
+ return INSTANCE.get(context).mSingleFrameMs;
+ }
+
+ @Override
+ public final void onDisplayAdded(int displayId) { }
+
+ @Override
+ public final void onDisplayRemoved(int displayId) { }
+
+ @WorkerThread
+ @Override
+ public final void onDisplayChanged(int displayId) {
+ if (displayId == DEFAULT_DISPLAY) {
+ updateSingleFrameMs();
+ }
+ }
+
+ private void updateSingleFrameMs() {
+ Display display = mDM.getDisplay(DEFAULT_DISPLAY);
+ if (display != null) {
+ float refreshRate = display.getRefreshRate();
+ mSingleFrameMs = refreshRate > 0 ? (int) (1000 / refreshRate) : 16;
+ }
+ }
+
+ @Override
+ public void close() {
+ mDM.unregisterDisplayListener(this);
+ }
+}
diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java
new file mode 100644
index 0000000..9665bf9
--- /dev/null
+++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java
@@ -0,0 +1,365 @@
+/*
+ * 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.window;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+
+import static com.android.launcher3.ResourceUtils.INVALID_RESOURCE_HANDLE;
+import static com.android.launcher3.ResourceUtils.NAVBAR_HEIGHT;
+import static com.android.launcher3.ResourceUtils.NAVBAR_HEIGHT_LANDSCAPE;
+import static com.android.launcher3.ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE;
+import static com.android.launcher3.ResourceUtils.STATUS_BAR_HEIGHT;
+import static com.android.launcher3.ResourceUtils.STATUS_BAR_HEIGHT_LANDSCAPE;
+import static com.android.launcher3.ResourceUtils.STATUS_BAR_HEIGHT_PORTRAIT;
+import static com.android.launcher3.Utilities.dpiFromPx;
+import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
+import static com.android.launcher3.util.RotationUtils.deltaRotation;
+import static com.android.launcher3.util.RotationUtils.rotateRect;
+import static com.android.launcher3.util.RotationUtils.rotateSize;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Insets;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
+import android.os.Build;
+import android.util.ArrayMap;
+import android.util.Pair;
+import android.view.Display;
+import android.view.DisplayCutout;
+import android.view.Surface;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import com.android.launcher3.R;
+import com.android.launcher3.ResourceUtils;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.ResourceBasedOverride;
+import com.android.launcher3.util.WindowBounds;
+
+/**
+ * Utility class for mocking some window manager behaviours
+ */
+public class WindowManagerProxy implements ResourceBasedOverride {
+
+ public static final int MIN_TABLET_WIDTH = 600;
+
+ public static final MainThreadInitializedObject<WindowManagerProxy> INSTANCE =
+ forOverride(WindowManagerProxy.class, R.string.window_manager_proxy_class);
+
+ protected final boolean mTaskbarDrawnInProcess;
+
+ /**
+ * Creates a new instance of proxy, applying any overrides
+ */
+ public static WindowManagerProxy newInstance(Context context) {
+ return Overrides.getObject(WindowManagerProxy.class, context,
+ R.string.window_manager_proxy_class);
+ }
+
+ public WindowManagerProxy() {
+ this(false);
+ }
+
+ protected WindowManagerProxy(boolean taskbarDrawnInProcess) {
+ mTaskbarDrawnInProcess = taskbarDrawnInProcess;
+ }
+
+ /**
+ * Returns a map of normalized info of internal displays to estimated window bounds
+ * for that display
+ */
+ public ArrayMap<String, Pair<CachedDisplayInfo, WindowBounds[]>> estimateInternalDisplayBounds(
+ Context context) {
+ Display[] displays = getDisplays(context);
+ ArrayMap<String, Pair<CachedDisplayInfo, WindowBounds[]>> result = new ArrayMap<>();
+ for (Display display : displays) {
+ if (isInternalDisplay(display)) {
+ Context displayContext = Utilities.ATLEAST_S
+ ? context.createWindowContext(display, TYPE_APPLICATION, null)
+ : context.createDisplayContext(display);
+ CachedDisplayInfo info = getDisplayInfo(displayContext, display).normalize();
+ WindowBounds[] bounds = estimateWindowBounds(context, info);
+ result.put(info.id, Pair.create(info, bounds));
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns the real bounds for the provided display after applying any insets normalization
+ */
+ @TargetApi(Build.VERSION_CODES.R)
+ public WindowBounds getRealBounds(Context windowContext,
+ Display display, CachedDisplayInfo info) {
+ if (!Utilities.ATLEAST_R) {
+ Point smallestSize = new Point();
+ Point largestSize = new Point();
+ display.getCurrentSizeRange(smallestSize, largestSize);
+
+ if (info.size.y > info.size.x) {
+ // Portrait
+ return new WindowBounds(info.size.x, info.size.y, smallestSize.x, largestSize.y,
+ info.rotation);
+ } else {
+ // Landscape
+ new WindowBounds(info.size.x, info.size.y, largestSize.x, smallestSize.y,
+ info.rotation);
+ }
+ }
+
+ WindowMetrics wm = windowContext.getSystemService(WindowManager.class)
+ .getMaximumWindowMetrics();
+
+ Rect insets = new Rect();
+ normalizeWindowInsets(windowContext, wm.getWindowInsets(), insets);
+ return new WindowBounds(wm.getBounds(), insets, info.rotation);
+ }
+
+ /**
+ * Returns an updated insets, accounting for various Launcher UI specific overrides like taskbar
+ */
+ @TargetApi(Build.VERSION_CODES.R)
+ public WindowInsets normalizeWindowInsets(Context context, WindowInsets oldInsets,
+ Rect outInsets) {
+ if (!Utilities.ATLEAST_R || !mTaskbarDrawnInProcess) {
+ outInsets.set(oldInsets.getSystemWindowInsetLeft(), oldInsets.getSystemWindowInsetTop(),
+ oldInsets.getSystemWindowInsetRight(), oldInsets.getSystemWindowInsetBottom());
+ return oldInsets;
+ }
+
+ WindowInsets.Builder insetsBuilder = new WindowInsets.Builder(oldInsets);
+ Insets navInsets = oldInsets.getInsets(WindowInsets.Type.navigationBars());
+
+ Resources systemRes = context.getResources();
+ Configuration config = systemRes.getConfiguration();
+
+ boolean isTablet = config.smallestScreenWidthDp > MIN_TABLET_WIDTH;
+ boolean isGesture = isGestureNav(context);
+ boolean isPortrait = config.screenHeightDp > config.screenWidthDp;
+
+ int bottomNav = isTablet
+ ? 0
+ : (isPortrait
+ ? getDimenByName(systemRes, NAVBAR_HEIGHT)
+ : (isGesture
+ ? getDimenByName(systemRes, NAVBAR_HEIGHT_LANDSCAPE)
+ : 0));
+ Insets newNavInsets = Insets.of(navInsets.left, navInsets.top, navInsets.right, bottomNav);
+ insetsBuilder.setInsets(WindowInsets.Type.navigationBars(), newNavInsets);
+ insetsBuilder.setInsetsIgnoringVisibility(WindowInsets.Type.navigationBars(), newNavInsets);
+
+ Insets statusBarInsets = oldInsets.getInsets(WindowInsets.Type.statusBars());
+
+
+ int statusBarHeight = getDimenByName(systemRes,
+ (isPortrait) ? STATUS_BAR_HEIGHT_PORTRAIT : STATUS_BAR_HEIGHT_LANDSCAPE,
+ STATUS_BAR_HEIGHT);
+
+ Insets newStatusBarInsets = Insets.of(
+ statusBarInsets.left,
+ Math.max(statusBarInsets.top, statusBarHeight),
+ statusBarInsets.right,
+ statusBarInsets.bottom);
+ insetsBuilder.setInsets(WindowInsets.Type.statusBars(), newStatusBarInsets);
+ insetsBuilder.setInsetsIgnoringVisibility(
+ WindowInsets.Type.statusBars(), newStatusBarInsets);
+
+ // Override the tappable insets to be 0 on the bottom for gesture nav (otherwise taskbar
+ // would count towards it). This is used for the bottom protection in All Apps for example.
+ if (isGesture) {
+ Insets oldTappableInsets = oldInsets.getInsets(WindowInsets.Type.tappableElement());
+ Insets newTappableInsets = Insets.of(oldTappableInsets.left, oldTappableInsets.top,
+ oldTappableInsets.right, 0);
+ insetsBuilder.setInsets(WindowInsets.Type.tappableElement(), newTappableInsets);
+ }
+
+ WindowInsets result = insetsBuilder.build();
+ Insets systemWindowInsets = result.getInsetsIgnoringVisibility(
+ WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
+ outInsets.set(systemWindowInsets.left, systemWindowInsets.top, systemWindowInsets.right,
+ systemWindowInsets.bottom);
+ return result;
+ }
+
+ /**
+ * Returns true if the display is an internal displays
+ */
+ protected boolean isInternalDisplay(Display display) {
+ return display.getDisplayId() == Display.DEFAULT_DISPLAY;
+ }
+
+ /**
+ * Returns a list of possible WindowBounds for the display keyed on the 4 surface rotations
+ */
+ public WindowBounds[] estimateWindowBounds(Context context, CachedDisplayInfo display) {
+ int densityDpi = context.getResources().getConfiguration().densityDpi;
+ int rotation = display.rotation;
+ Rect safeCutout = display.cutout;
+
+ int minSize = Math.min(display.size.x, display.size.y);
+ int swDp = (int) dpiFromPx(minSize, densityDpi);
+
+ Resources systemRes;
+ {
+ Configuration conf = new Configuration();
+ conf.smallestScreenWidthDp = swDp;
+ systemRes = context.createConfigurationContext(conf).getResources();
+ }
+
+ boolean isTablet = swDp >= MIN_TABLET_WIDTH;
+ boolean isTabletOrGesture = isTablet
+ || (Utilities.ATLEAST_R && isGestureNav(context));
+
+ int statusBarHeightPortrait = getDimenByName(systemRes,
+ STATUS_BAR_HEIGHT_PORTRAIT, STATUS_BAR_HEIGHT);
+ int statusBarHeightLandscape = getDimenByName(systemRes,
+ STATUS_BAR_HEIGHT_LANDSCAPE, STATUS_BAR_HEIGHT);
+
+ int navBarHeightPortrait, navBarHeightLandscape, navbarWidthLandscape;
+
+ navBarHeightPortrait = isTablet
+ ? (mTaskbarDrawnInProcess
+ ? 0 : systemRes.getDimensionPixelSize(R.dimen.taskbar_size))
+ : getDimenByName(systemRes, NAVBAR_HEIGHT);
+
+ navBarHeightLandscape = isTablet
+ ? (mTaskbarDrawnInProcess
+ ? 0 : systemRes.getDimensionPixelSize(R.dimen.taskbar_size))
+ : (isTabletOrGesture
+ ? getDimenByName(systemRes, NAVBAR_HEIGHT_LANDSCAPE) : 0);
+ navbarWidthLandscape = isTabletOrGesture
+ ? 0
+ : getDimenByName(systemRes, NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE);
+
+ WindowBounds[] result = new WindowBounds[4];
+ Point tempSize = new Point();
+ for (int i = 0; i < 4; i++) {
+ int rotationChange = deltaRotation(rotation, i);
+ tempSize.set(display.size.x, display.size.y);
+ rotateSize(tempSize, rotationChange);
+ Rect bounds = new Rect(0, 0, tempSize.x, tempSize.y);
+
+ int navBarHeight, navbarWidth, statusBarHeight;
+ if (tempSize.y > tempSize.x) {
+ navBarHeight = navBarHeightPortrait;
+ navbarWidth = 0;
+ statusBarHeight = statusBarHeightPortrait;
+ } else {
+ navBarHeight = navBarHeightLandscape;
+ navbarWidth = navbarWidthLandscape;
+ statusBarHeight = statusBarHeightLandscape;
+ }
+
+ Rect insets = new Rect(safeCutout);
+ rotateRect(insets, rotationChange);
+ insets.top = Math.max(insets.top, statusBarHeight);
+ insets.bottom = Math.max(insets.bottom, navBarHeight);
+
+ if (i == Surface.ROTATION_270 || i == Surface.ROTATION_180) {
+ // On reverse landscape (and in rare-case when the natural orientation of the
+ // device is landscape), navigation bar is on the right.
+ insets.left = Math.max(insets.left, navbarWidth);
+ } else {
+ insets.right = Math.max(insets.right, navbarWidth);
+ }
+ result[i] = new WindowBounds(bounds, insets, i);
+ }
+ return result;
+ }
+
+ /**
+ * Wrapper around the utility method for easier emulation
+ */
+ protected int getDimenByName(Resources res, String resName) {
+ return ResourceUtils.getDimenByName(resName, res, 0);
+ }
+
+ /**
+ * Wrapper around the utility method for easier emulation
+ */
+ protected int getDimenByName(Resources res, String resName, String fallback) {
+ int dimen = ResourceUtils.getDimenByName(resName, res, -1);
+ return dimen > -1 ? dimen : getDimenByName(res, fallback);
+ }
+
+ protected boolean isGestureNav(Context context) {
+ return ResourceUtils.getIntegerByName("config_navBarInteractionMode",
+ context.getResources(), INVALID_RESOURCE_HANDLE) == 2;
+ }
+
+ /**
+ * Returns a CachedDisplayInfo initialized for the current display
+ */
+ @TargetApi(Build.VERSION_CODES.S)
+ public CachedDisplayInfo getDisplayInfo(Context displayContext, Display display) {
+ int rotation = getRotation(displayContext);
+ Rect cutoutRect = new Rect();
+ Point size = new Point();
+ if (Utilities.ATLEAST_S) {
+ WindowMetrics wm = displayContext.getSystemService(WindowManager.class)
+ .getMaximumWindowMetrics();
+ DisplayCutout cutout = wm.getWindowInsets().getDisplayCutout();
+ if (cutout != null) {
+ cutoutRect.set(cutout.getSafeInsetLeft(), cutout.getSafeInsetTop(),
+ cutout.getSafeInsetRight(), cutout.getSafeInsetBottom());
+ }
+
+ size.set(wm.getBounds().right, wm.getBounds().bottom);
+ } else {
+ display.getRealSize(size);
+ }
+ return new CachedDisplayInfo(getDisplayId(display), size, rotation, cutoutRect);
+ }
+
+ /**
+ * Returns a unique ID representing the display
+ */
+ protected String getDisplayId(Display display) {
+ return Integer.toString(display.getDisplayId());
+ }
+
+ /**
+ * Returns rotation of the display associated with the context.
+ */
+ public int getRotation(Context context) {
+ Display d = null;
+ if (Utilities.ATLEAST_R) {
+ try {
+ d = context.getDisplay();
+ } catch (UnsupportedOperationException e) {
+ // Ignore
+ }
+ }
+ if (d == null) {
+ d = context.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
+ }
+ return d.getRotation();
+ }
+
+ /**
+ * Returns all currently valid logical displays.
+ */
+ protected Display[] getDisplays(Context context) {
+ return context.getSystemService(DisplayManager.class).getDisplays();
+ }
+}
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index 8ac40b8..47503b1 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -17,6 +17,8 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+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.anim.Interpolators.scrollInterpolatorForVelocity;
import android.animation.Animator;
@@ -113,9 +115,16 @@
return -1;
}
+ /**
+ * Returns the range in height that the slide in view can be dragged.
+ */
+ protected float getShiftRange() {
+ return mContent.getHeight();
+ }
+
protected void setTranslationShift(float translationShift) {
mTranslationShift = translationShift;
- mContent.setTranslationY(mTranslationShift * mContent.getHeight());
+ mContent.setTranslationY(mTranslationShift * getShiftRange());
if (mColorScrim != null) {
mColorScrim.setAlpha(1 - mTranslationShift);
}
@@ -132,8 +141,7 @@
mSwipeDetector.setDetectableScrollConditions(
directionsToDetectScroll, false);
mSwipeDetector.onTouchEvent(ev);
- return mSwipeDetector.isDraggingOrSettling()
- || !getPopupContainer().isEventOverView(mContent, ev);
+ return mSwipeDetector.isDraggingOrSettling() || !isEventOverContent(ev);
}
@Override
@@ -142,13 +150,23 @@
if (ev.getAction() == MotionEvent.ACTION_UP && mSwipeDetector.isIdleState()
&& !isOpeningAnimationRunning()) {
// If we got ACTION_UP without ever starting swipe, close the panel.
- if (!getPopupContainer().isEventOverView(mContent, ev)) {
+ if (!isEventOverContent(ev)) {
close(true);
}
}
return true;
}
+ /**
+ * Returns {@code true} if the touch event is over the visible area of the bottom sheet.
+ *
+ * By default will check if the touch event is over {@code mContent}, subclasses should override
+ * this method if the visible area of the bottom sheet is different from {@code mContent}.
+ */
+ protected boolean isEventOverContent(MotionEvent ev) {
+ return getPopupContainer().isEventOverView(mContent, ev);
+ }
+
private boolean isOpeningAnimationRunning() {
return mIsOpen && mOpenCloseAnimator.isRunning();
}
@@ -160,7 +178,7 @@
@Override
public boolean onDrag(float displacement) {
- float range = mContent.getHeight();
+ float range = getShiftRange();
displacement = Utilities.boundToRange(displacement, 0, range);
setTranslationShift(displacement / range);
return true;
@@ -168,7 +186,10 @@
@Override
public void onDragEnd(float velocity) {
- if ((mSwipeDetector.isFling(velocity) && velocity > 0) || mTranslationShift > 0.5f) {
+ float successfulShiftThreshold = mActivityContext.getDeviceProfile().isTablet
+ ? TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS : SUCCESS_TRANSITION_PROGRESS;
+ if ((mSwipeDetector.isFling(velocity) && velocity > 0)
+ || mTranslationShift > successfulShiftThreshold) {
mScrollInterpolator = scrollInterpolatorForVelocity(velocity);
mOpenCloseAnimator.setDuration(BaseSwipeDetector.calculateDuration(
velocity, TRANSLATION_SHIFT_CLOSED - mTranslationShift));
@@ -203,19 +224,24 @@
mOpenCloseAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
+ mOpenCloseAnimator.removeListener(this);
onCloseComplete();
}
});
if (mSwipeDetector.isIdleState()) {
mOpenCloseAnimator
.setDuration(defaultDuration)
- .setInterpolator(Interpolators.ACCEL);
+ .setInterpolator(getIdleInterpolator());
} else {
mOpenCloseAnimator.setInterpolator(mScrollInterpolator);
}
mOpenCloseAnimator.start();
}
+ protected Interpolator getIdleInterpolator() {
+ return Interpolators.ACCEL;
+ }
+
protected void onCloseComplete() {
mIsOpen = false;
getPopupContainer().removeView(this);
diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java
index a2e4ad6..93078e4 100644
--- a/src/com/android/launcher3/views/ActivityContext.java
+++ b/src/com/android/launcher3/views/ActivityContext.java
@@ -25,12 +25,17 @@
import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
+import com.android.launcher3.allapps.search.SearchAdapterProvider;
import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logging.StatsLogManager;
+import com.android.launcher3.model.StringCache;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.popup.PopupDataProvider;
+import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.util.ViewCache;
/**
@@ -92,6 +97,13 @@
*/
BaseDragLayer getDragLayer();
+ /**
+ * The all apps container, if it exists in this context.
+ */
+ default ActivityAllAppsContainerView<?> getAppsView() {
+ return null;
+ }
+
DeviceProfile getDeviceProfile();
default ViewCache getViewCache() {
@@ -124,17 +136,20 @@
}
/**
- * Returns whether we can show the IME for elements hosted by this ActivityContext.
- */
- default boolean supportsIme() {
- return true;
- }
-
- /**
* Called just before logging the given item.
*/
default void applyOverwritesToLogItem(LauncherAtom.ItemInfo.Builder itemInfoBuilder) { }
+ /** Onboarding preferences for any onboarding data within this context. */
+ default OnboardingPrefs<?> getOnboardingPrefs() {
+ return null;
+ }
+
+ /** Returns {@code true} if items are currently being bound within this context. */
+ default boolean isBindingItems() {
+ return false;
+ }
+
/**
* Returns the ActivityContext associated with the given Context, or throws an exception if
* the Context is not associated with any ActivityContext.
@@ -166,4 +181,24 @@
// No op.
};
}
+
+ @Nullable
+ default PopupDataProvider getPopupDataProvider() {
+ return null;
+ }
+
+ @Nullable
+ default StringCache getStringCache() {
+ return null;
+ }
+
+ /**
+ * Creates and returns {@link SearchAdapterProvider} for build variant specific search result
+ * views.
+ */
+ @Nullable
+ default SearchAdapterProvider<?> createSearchAdapterProvider(
+ ActivityAllAppsContainerView<?> appsView) {
+ return null;
+ }
}
diff --git a/src/com/android/launcher3/views/AllAppsButton.java b/src/com/android/launcher3/views/AllAppsButton.java
new file mode 100644
index 0000000..b1e69c7
--- /dev/null
+++ b/src/com/android/launcher3/views/AllAppsButton.java
@@ -0,0 +1,49 @@
+/*
+ * 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.views;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.util.AttributeSet;
+import android.view.ContextThemeWrapper;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.R;
+import com.android.launcher3.icons.FastBitmapDrawable;
+
+/**
+ * Button in Taskbar that opens All Apps.
+ */
+public class AllAppsButton extends BubbleTextView {
+
+ public AllAppsButton(Context context) {
+ this(context, null);
+ }
+
+ public AllAppsButton(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AllAppsButton(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ Context theme = new ContextThemeWrapper(context, R.style.AllAppsButtonTheme);
+ Bitmap bitmap = LauncherAppState.getInstance(context).getIconCache().getIconFactory()
+ .createScaledBitmapWithShadow(theme.getDrawable(R.drawable.ic_all_apps_button));
+ setIcon(new FastBitmapDrawable(bitmap));
+ }
+}
diff --git a/src/com/android/launcher3/views/AppLauncher.java b/src/com/android/launcher3/views/AppLauncher.java
new file mode 100644
index 0000000..19e66ab
--- /dev/null
+++ b/src/com/android/launcher3/views/AppLauncher.java
@@ -0,0 +1,213 @@
+/*
+ * 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.views;
+
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
+import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS;
+
+import android.app.ActivityOptions;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.LauncherApps;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.StrictMode;
+import android.os.UserHandle;
+import android.util.Log;
+import android.view.Display;
+import android.view.View;
+import android.widget.Toast;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.logging.InstanceId;
+import com.android.launcher3.logging.InstanceIdSequence;
+import com.android.launcher3.logging.StatsLogManager;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.util.ActivityOptionsWrapper;
+import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.util.RunnableList;
+
+/** An {@link ActivityContext} that can also launch app activities and shortcuts safely. */
+public interface AppLauncher extends ActivityContext {
+
+ String TAG = "AppLauncher";
+
+ /**
+ * Safely starts an activity.
+ *
+ * @param v View starting the activity.
+ * @param intent Base intent being launched.
+ * @param item Item associated with the view.
+ * @return {@code true} if the activity starts successfully.
+ */
+ default boolean startActivitySafely(
+ View v, Intent intent, @Nullable ItemInfo item) {
+
+ Context context = (Context) this;
+ if (isAppBlockedForSafeMode() && !PackageManagerHelper.isSystemApp(context, intent)) {
+ Toast.makeText(context, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
+ return false;
+ }
+
+ Bundle optsBundle = (v != null) ? getActivityLaunchOptions(v, item).toBundle() : null;
+ UserHandle user = item == null ? null : item.user;
+
+ // Prepare intent
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ if (v != null) {
+ 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);
+ } else if (user == null || user.equals(Process.myUserHandle())) {
+ // Could be launching some bookkeeping activity
+ context.startActivity(intent, optsBundle);
+ } else {
+ context.getSystemService(LauncherApps.class).startMainActivity(
+ intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
+ }
+ if (item != null) {
+ InstanceId instanceId = new InstanceIdSequence().newInstanceId();
+ logAppLaunch(getStatsLogManager(), item, instanceId);
+ }
+ return true;
+ } catch (NullPointerException | ActivityNotFoundException | SecurityException e) {
+ Toast.makeText(context, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
+ Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
+ }
+ return false;
+ }
+
+ /** Returns {@code true} if an app launch is blocked due to safe mode. */
+ default boolean isAppBlockedForSafeMode() {
+ return false;
+ }
+
+ /**
+ * Creates and logs a new app launch event.
+ */
+ default void logAppLaunch(StatsLogManager statsLogManager, ItemInfo info,
+ InstanceId instanceId) {
+ statsLogManager.logger().withItemInfo(info).withInstanceId(instanceId)
+ .log(LAUNCHER_APP_LAUNCH_TAP);
+ }
+
+ /**
+ * Returns launch options for an Activity.
+ *
+ * @param v View initiating a launch.
+ * @param item Item associated with the view.
+ */
+ default ActivityOptionsWrapper getActivityLaunchOptions(View v, @Nullable ItemInfo item) {
+ int left = 0, top = 0;
+ int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();
+ if (v instanceof BubbleTextView) {
+ // Launch from center of icon, not entire view
+ Drawable icon = ((BubbleTextView) v).getIcon();
+ if (icon != null) {
+ Rect bounds = icon.getBounds();
+ left = (width - bounds.width()) / 2;
+ top = v.getPaddingTop();
+ width = bounds.width();
+ height = bounds.height();
+ }
+ }
+ ActivityOptions options =
+ ActivityOptions.makeClipRevealAnimation(v, left, top, width, height);
+
+ options.setLaunchDisplayId(
+ (v != null && v.getDisplay() != null) ? v.getDisplay().getDisplayId()
+ : Display.DEFAULT_DISPLAY);
+ RunnableList callback = new RunnableList();
+ return new ActivityOptionsWrapper(options, callback);
+ }
+
+ /**
+ * 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) {
+ if (!onErrorStartingShortcut(intent, info)) {
+ 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);
+ }
+ }
+
+ /**
+ * Invoked when a shortcut fails to launch.
+ * @param intent Shortcut intent that failed to start.
+ * @param info Shortcut information.
+ * @return {@code true} if the error is handled by this callback.
+ */
+ default boolean onErrorStartingShortcut(Intent intent, ItemInfo info) {
+ return false;
+ }
+}
diff --git a/src/com/android/launcher3/views/ArrowTipView.java b/src/com/android/launcher3/views/ArrowTipView.java
index ce26a66..8d16a8d 100644
--- a/src/com/android/launcher3/views/ArrowTipView.java
+++ b/src/com/android/launcher3/views/ArrowTipView.java
@@ -137,6 +137,21 @@
* @return The tooltip.
*/
public ArrowTipView show(String text, int gravity, int arrowMarginStart, int top) {
+ return show(text, gravity, arrowMarginStart, top, true);
+ }
+
+ /**
+ * Show the ArrowTipView (tooltip) center, start, or end aligned.
+ *
+ * @param text The text to be shown in the tooltip.
+ * @param gravity The gravity aligns the tooltip center, start, or end.
+ * @param arrowMarginStart The margin from start to place arrow (ignored if center)
+ * @param top The Y coordinate of the bottom of tooltip.
+ * @param shouldAutoClose If Tooltip should be auto close.
+ * @return The tooltip.
+ */
+ public ArrowTipView show(
+ String text, int gravity, int arrowMarginStart, int top, boolean shouldAutoClose) {
((TextView) findViewById(R.id.text)).setText(text);
ViewGroup parent = mActivity.getDragLayer();
parent.addView(this);
@@ -166,7 +181,9 @@
post(() -> setY(top - (mIsPointingUp ? 0 : getHeight())));
mIsOpen = true;
- mHandler.postDelayed(() -> handleClose(true), AUTO_CLOSE_TIMEOUT_MILLIS);
+ if (shouldAutoClose) {
+ mHandler.postDelayed(() -> handleClose(true), AUTO_CLOSE_TIMEOUT_MILLIS);
+ }
setAlpha(0);
animate()
.alpha(1f)
@@ -190,10 +207,32 @@
*/
@Nullable public ArrowTipView showAtLocation(String text, @Px int arrowXCoord, @Px int yCoord) {
return showAtLocation(
+ text,
+ arrowXCoord,
+ /* yCoordDownPointingTip= */ yCoord,
+ /* yCoordUpPointingTip= */ yCoord,
+ /* shouldAutoClose= */ true);
+ }
+
+ /**
+ * Show the ArrowTipView (tooltip) custom aligned. The tooltip is vertically flipped if it
+ * cannot fit on screen in the requested orientation.
+ *
+ * @param text The text to be shown in the tooltip.
+ * @param arrowXCoord The X coordinate for the arrow on the tooltip. The arrow is usually in the
+ * center of tooltip unless the tooltip goes beyond screen margin.
+ * @param yCoord The Y coordinate of the pointed tip end of the tooltip.
+ * @param shouldAutoClose If Tooltip should be auto close.
+ * @return The tool tip view. {@code null} if the tip can not be shown.
+ */
+ @Nullable public ArrowTipView showAtLocation(
+ String text, @Px int arrowXCoord, @Px int yCoord, boolean shouldAutoClose) {
+ return showAtLocation(
text,
arrowXCoord,
/* yCoordDownPointingTip= */ yCoord,
- /* yCoordUpPointingTip= */ yCoord);
+ /* yCoordUpPointingTip= */ yCoord,
+ /* shouldAutoClose= */ shouldAutoClose);
}
/**
@@ -213,7 +252,8 @@
text,
arrowXCoord,
/* yCoordDownPointingTip= */ rect.top - margin,
- /* yCoordUpPointingTip= */ rect.bottom + margin);
+ /* yCoordUpPointingTip= */ rect.bottom + margin,
+ /* shouldAutoClose= */ true);
}
/**
@@ -227,10 +267,11 @@
* tooltip is placed pointing downwards.
* @param yCoordUpPointingTip The Y coordinate of the pointed tip end of the tooltip when the
* tooltip is placed pointing upwards.
+ * @param shouldAutoClose If Tooltip should be auto close.
* @return The tool tip view. {@code null} if the tip can not be shown.
*/
@Nullable private ArrowTipView showAtLocation(String text, @Px int arrowXCoord,
- @Px int yCoordDownPointingTip, @Px int yCoordUpPointingTip) {
+ @Px int yCoordDownPointingTip, @Px int yCoordUpPointingTip, boolean shouldAutoClose) {
ViewGroup parent = mActivity.getDragLayer();
@Px int parentViewWidth = parent.getWidth();
@Px int parentViewHeight = parent.getHeight();
@@ -288,7 +329,9 @@
});
mIsOpen = true;
- mHandler.postDelayed(() -> handleClose(true), AUTO_CLOSE_TIMEOUT_MILLIS);
+ if (shouldAutoClose) {
+ mHandler.postDelayed(() -> handleClose(true), AUTO_CLOSE_TIMEOUT_MILLIS);
+ }
setAlpha(0);
animate()
.alpha(1f)
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index 6e44a43..f553fb4 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -20,7 +20,7 @@
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_UP;
-import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
+import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
import android.annotation.TargetApi;
import android.app.WallpaperManager;
@@ -414,6 +414,14 @@
}
/**
+ * Similar to {@link #mapCoordInSelfToDescendant(View descendant, float[] coord)}
+ * but accepts a Rect instead of float[].
+ */
+ public void mapRectInSelfToDescendant(View descendant, Rect rect) {
+ Utilities.mapRectInSelfToDescendant(descendant, this, rect);
+ }
+
+ /**
* Inverse of {@link #getDescendantCoordRelativeToSelf(View, float[])}.
*/
public void mapCoordInSelfToDescendant(View descendant, float[] coord) {
diff --git a/src/com/android/launcher3/views/BubbleTextHolder.java b/src/com/android/launcher3/views/BubbleTextHolder.java
index 1cb27e1..84f8049 100644
--- a/src/com/android/launcher3/views/BubbleTextHolder.java
+++ b/src/com/android/launcher3/views/BubbleTextHolder.java
@@ -16,20 +16,20 @@
package com.android.launcher3.views;
import com.android.launcher3.BubbleTextView;
-import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.ItemInfoWithIcon;
/**
* Views that contain {@link BubbleTextView} should implement this interface.
*/
-public interface BubbleTextHolder {
+public interface BubbleTextHolder extends IconLabelDotView {
BubbleTextView getBubbleText();
- /**
- * Called when new {@link ItemInfo} is set to {@link BubbleTextView}
- *
- * @param itemInfo the new itemInfo
- */
- default void onItemInfoUpdated(ItemInfoWithIcon itemInfo) {
+ @Override
+ default void setIconVisible(boolean visible) {
+ getBubbleText().setIconVisible(visible);
+ }
+
+ @Override
+ default void setForceHideDot(boolean hide) {
+ getBubbleText().setForceHideDot(hide);
}
}
diff --git a/src/com/android/launcher3/views/ClipIconView.java b/src/com/android/launcher3/views/ClipIconView.java
index a66b3f9..d1f90e9 100644
--- a/src/com/android/launcher3/views/ClipIconView.java
+++ b/src/com/android/launcher3/views/ClipIconView.java
@@ -147,8 +147,7 @@
* Update the icon UI to match the provided parameters during an animation frame
*/
public void update(RectF rect, float progress, float shapeProgressStart, float cornerRadius,
- int fgIconAlpha, boolean isOpening, View container, DeviceProfile dp,
- boolean isVerticalBarLayout) {
+ int fgIconAlpha, boolean isOpening, View container, DeviceProfile dp) {
MarginLayoutParams lp = (MarginLayoutParams) container.getLayoutParams();
float dX = mIsRtl
@@ -169,7 +168,7 @@
}
update(rect, progress, shapeProgressStart, cornerRadius, fgIconAlpha, isOpening, scale,
- minSize, lp, isVerticalBarLayout, dp);
+ minSize, lp, dp);
container.setPivotX(0);
container.setPivotY(0);
@@ -181,7 +180,7 @@
private void update(RectF rect, float progress, float shapeProgressStart, float cornerRadius,
int fgIconAlpha, boolean isOpening, float scale, float minSize,
- MarginLayoutParams parentLp, boolean isVerticalBarLayout, DeviceProfile dp) {
+ MarginLayoutParams parentLp, DeviceProfile dp) {
float dX = mIsRtl
? rect.left - (dp.widthPx - parentLp.getMarginStart() - parentLp.width)
: rect.left - parentLp.getMarginStart();
@@ -193,7 +192,7 @@
float shapeRevealProgress = boundToRange(mapToRange(max(shapeProgressStart, progress),
shapeProgressStart, 1f, 0, toMax, LINEAR), 0, 1);
- if (isVerticalBarLayout) {
+ if (dp.isLandscape) {
mOutline.right = (int) (rect.width() / scale);
} else {
mOutline.bottom = (int) (rect.height() / scale);
@@ -218,16 +217,16 @@
mRevealAnimator.setCurrentFraction(shapeRevealProgress);
}
- float drawableScale = (isVerticalBarLayout ? mOutline.width() : mOutline.height())
+ float drawableScale = (dp.isLandscape ? mOutline.width() : mOutline.height())
/ minSize;
- setBackgroundDrawableBounds(drawableScale, isVerticalBarLayout);
+ setBackgroundDrawableBounds(drawableScale, dp.isLandscape);
if (isOpening) {
// Center align foreground
int height = mFinalDrawableBounds.height();
int width = mFinalDrawableBounds.width();
- int diffY = isVerticalBarLayout ? 0
+ int diffY = dp.isLandscape ? 0
: (int) (((height * drawableScale) - height) / 2);
- int diffX = isVerticalBarLayout ? (int) (((width * drawableScale) - width) / 2)
+ int diffX = dp.isLandscape ? (int) (((width * drawableScale) - width) / 2)
: 0;
sTmpRect.set(mFinalDrawableBounds);
sTmpRect.offset(diffX, diffY);
@@ -247,11 +246,11 @@
invalidateOutline();
}
- private void setBackgroundDrawableBounds(float scale, boolean isVerticalBarLayout) {
+ private void setBackgroundDrawableBounds(float scale, boolean isLandscape) {
sTmpRect.set(mFinalDrawableBounds);
Utilities.scaleRectAboutCenter(sTmpRect, scale);
// Since the drawable is at the top of the view, we need to offset to keep it centered.
- if (isVerticalBarLayout) {
+ if (isLandscape) {
sTmpRect.offsetTo((int) (mFinalDrawableBounds.left * scale), sTmpRect.top);
} else {
sTmpRect.offsetTo(sTmpRect.left, (int) (mFinalDrawableBounds.top * scale));
@@ -269,7 +268,7 @@
* Sets the icon for this view as part of initial setup
*/
public void setIcon(@Nullable Drawable drawable, int iconOffset, MarginLayoutParams lp,
- boolean isOpening, boolean isVerticalBarLayout, DeviceProfile dp) {
+ boolean isOpening, DeviceProfile dp) {
mIsAdaptiveIcon = drawable instanceof AdaptiveIconDrawable;
if (mIsAdaptiveIcon) {
boolean isFolderIcon = drawable instanceof FolderAdaptiveIcon;
@@ -304,7 +303,7 @@
Utilities.scaleRectAboutCenter(mStartRevealRect, IconShape.getNormalizationScale());
}
- if (isVerticalBarLayout) {
+ if (dp.isLandscape) {
lp.width = (int) Math.max(lp.width, lp.height * dp.aspectRatio);
} else {
lp.height = (int) Math.max(lp.height, lp.width * dp.aspectRatio);
@@ -325,7 +324,7 @@
bgDrawableStartScale = scale;
mOutline.set(0, 0, lp.width, lp.height);
}
- setBackgroundDrawableBounds(bgDrawableStartScale, isVerticalBarLayout);
+ setBackgroundDrawableBounds(bgDrawableStartScale, dp.isLandscape);
mEndRevealRect.set(0, 0, lp.width, lp.height);
setOutlineProvider(new ViewOutlineProvider() {
@Override
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 0a800c3..efc83eb 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -17,7 +17,6 @@
import static com.android.launcher3.Utilities.getBadge;
import static com.android.launcher3.Utilities.getFullDrawable;
-import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.views.IconLabelDotView.setIconAndDotVisible;
@@ -44,12 +43,12 @@
import androidx.annotation.WorkerThread;
import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.DragLayer;
-import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.graphics.PreloadIconDrawable;
import com.android.launcher3.icons.FastBitmapDrawable;
@@ -59,6 +58,8 @@
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.shortcuts.DeepShortcutView;
+import java.util.function.Supplier;
+
/**
* A view that is created to look like another view with the purpose of creating fluid animations.
*/
@@ -83,7 +84,6 @@
private final Launcher mLauncher;
private final boolean mIsRtl;
- private boolean mIsVerticalBarLayout = false;
private boolean mIsOpening;
private IconLoadResult mIconLoadResult;
@@ -151,7 +151,7 @@
float shapeProgressStart, float cornerRadius, boolean isOpening) {
setAlpha(alpha);
mClipIconView.update(rect, progress, shapeProgressStart, cornerRadius, fgIconAlpha,
- isOpening, this, mLauncher.getDeviceProfile(), mIsVerticalBarLayout);
+ isOpening, this, mLauncher.getDeviceProfile());
}
@Override
@@ -248,14 +248,15 @@
* @param originalView The View that the FloatingIconView will replace.
* @param info ItemInfo of the originalView
* @param pos The position of the view.
+ * @param btvIcon The drawable of the BubbleTextView. May be null if original view is not a BTV
+ * @param outIconLoadResult We store the icon results into this object.
*/
@WorkerThread
@SuppressWarnings("WrongThread")
private static void getIconResult(Launcher l, View originalView, ItemInfo info, RectF pos,
- Drawable btvIcon, IconLoadResult iconLoadResult) {
+ @Nullable Drawable btvIcon, IconLoadResult outIconLoadResult) {
Drawable drawable;
- boolean supportsAdaptiveIcons = ADAPTIVE_ICON_WINDOW_ANIM.get()
- && !info.isDisabled(); // Use original icon for disabled icons.
+ boolean supportsAdaptiveIcons = !info.isDisabled(); // Use original icon for disabled icons.
Drawable badge = null;
if (info instanceof SystemShortcut) {
@@ -273,7 +274,9 @@
int width = (int) pos.width();
int height = (int) pos.height();
if (supportsAdaptiveIcons) {
- drawable = getFullDrawable(l, info, width, height, sTmpObjArray);
+ boolean shouldThemeIcon = btvIcon instanceof FastBitmapDrawable
+ && ((FastBitmapDrawable) btvIcon).isThemed();
+ drawable = getFullDrawable(l, info, width, height, shouldThemeIcon, sTmpObjArray);
if (drawable instanceof AdaptiveIconDrawable) {
badge = getBadge(l, info, sTmpObjArray[0]);
} else {
@@ -286,24 +289,27 @@
// Similar to DragView, we simply use the BubbleTextView icon here.
drawable = btvIcon;
} else {
- drawable = getFullDrawable(l, info, width, height, sTmpObjArray);
+ drawable = getFullDrawable(l, info, width, height, true /* shouldThemeIcon */,
+ sTmpObjArray);
}
}
}
drawable = drawable == null ? null : drawable.getConstantState().newDrawable();
int iconOffset = getOffsetForIconBounds(l, drawable, pos);
- synchronized (iconLoadResult) {
- iconLoadResult.btvDrawable = btvIcon == null || drawable == btvIcon
- ? null : btvIcon.getConstantState().newDrawable();
- iconLoadResult.drawable = drawable;
- iconLoadResult.badge = badge;
- iconLoadResult.iconOffset = iconOffset;
- if (iconLoadResult.onIconLoaded != null) {
- l.getMainExecutor().execute(iconLoadResult.onIconLoaded);
- iconLoadResult.onIconLoaded = null;
+ // Clone right away as we are on the background thread instead of blocking the
+ // main thread later
+ Drawable btvClone = btvIcon == null ? null : btvIcon.getConstantState().newDrawable();
+ synchronized (outIconLoadResult) {
+ outIconLoadResult.btvDrawable = () -> btvClone;
+ outIconLoadResult.drawable = drawable;
+ outIconLoadResult.badge = badge;
+ outIconLoadResult.iconOffset = iconOffset;
+ if (outIconLoadResult.onIconLoaded != null) {
+ l.getMainExecutor().execute(outIconLoadResult.onIconLoaded);
+ outIconLoadResult.onIconLoaded = null;
}
- iconLoadResult.isIconLoaded = true;
+ outIconLoadResult.isIconLoaded = true;
}
}
@@ -316,12 +322,12 @@
*/
@UiThread
private void setIcon(@Nullable Drawable drawable, @Nullable Drawable badge,
- @Nullable Drawable btvIcon, int iconOffset) {
+ @Nullable Supplier<Drawable> btvIcon, int iconOffset) {
+ final DeviceProfile dp = mLauncher.getDeviceProfile();
final InsettableFrameLayout.LayoutParams lp =
(InsettableFrameLayout.LayoutParams) getLayoutParams();
mBadge = badge;
- mClipIconView.setIcon(drawable, iconOffset, lp, mIsOpening, mIsVerticalBarLayout,
- mLauncher.getDeviceProfile());
+ mClipIconView.setIcon(drawable, iconOffset, lp, mIsOpening, dp);
if (drawable instanceof AdaptiveIconDrawable) {
final int originalHeight = lp.height;
final int originalWidth = lp.width;
@@ -329,7 +335,7 @@
mFinalDrawableBounds.set(0, 0, originalWidth, originalHeight);
float aspectRatio = mLauncher.getDeviceProfile().aspectRatio;
- if (mIsVerticalBarLayout) {
+ if (dp.isLandscape) {
lp.width = (int) Math.max(lp.width, lp.height * aspectRatio);
} else {
lp.height = (int) Math.max(lp.height, lp.width * aspectRatio);
@@ -337,15 +343,13 @@
setLayoutParams(lp);
final LayoutParams clipViewLp = (LayoutParams) mClipIconView.getLayoutParams();
- final int clipViewOgHeight = clipViewLp.height;
- final int clipViewOgWidth = clipViewLp.width;
+ if (mBadge != null) {
+ Rect badgeBounds = new Rect(0, 0, clipViewLp.width, clipViewLp.height);
+ FastBitmapDrawable.setBadgeBounds(mBadge, badgeBounds);
+ }
clipViewLp.width = lp.width;
clipViewLp.height = lp.height;
mClipIconView.setLayoutParams(clipViewLp);
-
- if (mBadge != null) {
- mBadge.setBounds(0, 0, clipViewOgWidth, clipViewOgHeight);
- }
}
setOriginalDrawableBackground(btvIcon);
@@ -361,9 +365,9 @@
*
* Allows nullable as this may be cleared when drawing is deferred to ClipIconView.
*/
- private void setOriginalDrawableBackground(@Nullable Drawable btvIcon) {
+ private void setOriginalDrawableBackground(@Nullable Supplier<Drawable> btvIcon) {
if (!mIsOpening) {
- mBtvDrawable.setBackground(btvIcon);
+ mBtvDrawable.setBackground(btvIcon == null ? null : btvIcon.get());
}
}
@@ -412,8 +416,7 @@
@WorkerThread
@SuppressWarnings("WrongThread")
private static int getOffsetForIconBounds(Launcher l, Drawable drawable, RectF position) {
- if (!(drawable instanceof AdaptiveIconDrawable)
- || (drawable instanceof FolderAdaptiveIcon)) {
+ if (!(drawable instanceof AdaptiveIconDrawable)) {
return 0;
}
int blurSizeOutline =
@@ -519,22 +522,26 @@
getLocationBoundsForView(l, v, isOpening, position);
final FastBitmapDrawable btvIcon;
+ final Supplier<Drawable> btvDrawableSupplier;
if (v instanceof BubbleTextView) {
BubbleTextView btv = (BubbleTextView) v;
if (info instanceof ItemInfoWithIcon
&& (((ItemInfoWithIcon) info).runtimeStatusFlags
& ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK) != 0) {
btvIcon = btv.makePreloadIcon();
+ btvDrawableSupplier = () -> btvIcon;
} else {
btvIcon = btv.getIcon();
+ // Clone when needed
+ btvDrawableSupplier = () -> btvIcon.getConstantState().newDrawable();
}
} else {
btvIcon = null;
+ btvDrawableSupplier = null;
}
- IconLoadResult result = new IconLoadResult(info,
- btvIcon == null ? false : btvIcon.isThemed());
- result.btvDrawable = btvIcon;
+ IconLoadResult result = new IconLoadResult(info, btvIcon != null && btvIcon.isThemed());
+ result.btvDrawable = btvDrawableSupplier;
final long fetchIconId = sFetchIconId++;
MODEL_EXECUTOR.getHandler().postAtFrontOfQueue(() -> {
@@ -565,7 +572,6 @@
view.recycle();
// Init properties before getting the drawable.
- view.mIsVerticalBarLayout = launcher.getDeviceProfile().isVerticalBarLayout();
view.mIsOpening = isOpening;
view.mOriginalIcon = originalView;
view.mPositionOut = positionOut;
@@ -587,7 +593,7 @@
view.matchPositionOf(launcher, originalView, isOpening, positionOut);
// We need to add it to the overlay, but keep it invisible until animation starts..
- view.setVisibility(INVISIBLE);
+ setIconAndDotVisible(view, false);
parent.addView(view);
dragLayer.addView(view.mListenerView);
view.mListenerView.setListener(view::fastFinish);
@@ -596,16 +602,8 @@
view.mEndRunnable = null;
if (hideOriginal) {
- if (isOpening) {
- setIconAndDotVisible(originalView, true);
- view.finish(dragLayer);
- } else {
- originalView.setVisibility(VISIBLE);
- if (originalView instanceof IconLabelDotView) {
- setIconAndDotVisible(originalView, true);
- }
- view.finish(dragLayer);
- }
+ setIconAndDotVisible(originalView, true);
+ view.finish(dragLayer);
} else {
view.finish(dragLayer);
}
@@ -658,7 +656,7 @@
private static class IconLoadResult {
final ItemInfo itemInfo;
final boolean isThemed;
- Drawable btvDrawable;
+ Supplier<Drawable> btvDrawable;
Drawable drawable;
Drawable badge;
int iconOffset;
diff --git a/src/com/android/launcher3/views/FloatingSurfaceView.java b/src/com/android/launcher3/views/FloatingSurfaceView.java
index 09c8c64..bfb75f0 100644
--- a/src/com/android/launcher3/views/FloatingSurfaceView.java
+++ b/src/com/android/launcher3/views/FloatingSurfaceView.java
@@ -40,8 +40,8 @@
import com.android.launcher3.Insettable;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
-import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.window.RefreshRateTracker;
/**
* Similar to {@link FloatingIconView} but displays a surface with the targetIcon. It then passes
@@ -62,7 +62,6 @@
private final SurfaceView mSurfaceView;
-
private View mIcon;
private GestureNavContract mContract;
@@ -97,13 +96,19 @@
// Remove after some time, to avoid flickering
Executors.MAIN_EXECUTOR.getHandler().postDelayed(mRemoveViewRunnable,
- DisplayController.INSTANCE.get(mLauncher).getInfo().singleFrameMs);
+ RefreshRateTracker.getSingleFrameMs(mLauncher));
}
private void removeViewFromParent() {
mPicture.beginRecording(1, 1);
mPicture.endRecording();
- mLauncher.getDragLayer().removeView(this);
+ mLauncher.getDragLayer().removeViewInLayout(this);
+ }
+
+ private void removeViewImmediate() {
+ // Cancel any pending remove
+ Executors.MAIN_EXECUTOR.getHandler().removeCallbacks(mRemoveViewRunnable);
+ removeViewFromParent();
}
/**
@@ -115,9 +120,7 @@
view.mContract = contract;
view.mIsOpen = true;
- // Cancel any pending remove
- Executors.MAIN_EXECUTOR.getHandler().removeCallbacks(view.mRemoveViewRunnable);
- view.removeViewFromParent();
+ view.removeViewImmediate();
launcher.getDragLayer().addView(view);
}
@@ -129,6 +132,7 @@
@Override
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
close(false);
+ removeViewImmediate();
return false;
}
@@ -197,7 +201,7 @@
private void sendIconInfo() {
if (mContract != null && !mIconPosition.isEmpty()) {
- mContract.sendEndPosition(mIconPosition, mSurfaceView.getSurfaceControl());
+ mContract.sendEndPosition(mIconPosition, mLauncher, mSurfaceView.getSurfaceControl());
}
}
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index fc8b4b7..2a9a8a5 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -180,18 +180,6 @@
*/
public static ArrayList<OptionItem> getOptions(Launcher launcher) {
ArrayList<OptionItem> options = new ArrayList<>();
- options.add(new OptionItem(launcher,
- R.string.settings_button_text,
- R.drawable.ic_setting,
- LAUNCHER_SETTINGS_BUTTON_TAP_OR_LONGPRESS,
- OptionsPopupView::startSettings));
- if (!WidgetsModel.GO_DISABLE_WIDGETS) {
- options.add(new OptionItem(launcher,
- R.string.widget_button_text,
- R.drawable.ic_widget,
- LAUNCHER_WIDGETSTRAY_BUTTON_TAP_OR_LONGPRESS,
- OptionsPopupView::onWidgetsClicked));
- }
int resString = Utilities.existsStyleWallpapers(launcher) ?
R.string.styles_wallpaper_button_text : R.string.wallpaper_button_text;
int resDrawable = Utilities.existsStyleWallpapers(launcher) ?
@@ -201,6 +189,18 @@
resDrawable,
IGNORE,
OptionsPopupView::startWallpaperPicker));
+ if (!WidgetsModel.GO_DISABLE_WIDGETS) {
+ options.add(new OptionItem(launcher,
+ R.string.widget_button_text,
+ R.drawable.ic_widget,
+ LAUNCHER_WIDGETSTRAY_BUTTON_TAP_OR_LONGPRESS,
+ OptionsPopupView::onWidgetsClicked));
+ }
+ options.add(new OptionItem(launcher,
+ R.string.settings_button_text,
+ R.drawable.ic_setting,
+ LAUNCHER_SETTINGS_BUTTON_TAP_OR_LONGPRESS,
+ OptionsPopupView::startSettings));
return options;
}
@@ -229,7 +229,7 @@
Launcher launcher = Launcher.getLauncher(view.getContext());
launcher.startActivity(new Intent(Intent.ACTION_APPLICATION_PREFERENCES)
.setPackage(launcher.getPackageName())
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
return true;
}
@@ -240,7 +240,10 @@
private static boolean startWallpaperPicker(View v) {
Launcher launcher = Launcher.getLauncher(v.getContext());
if (!Utilities.isWallpaperAllowed(launcher)) {
- Toast.makeText(launcher, R.string.msg_disabled_by_admin, Toast.LENGTH_SHORT).show();
+ String message = launcher.getStringCache() != null
+ ? launcher.getStringCache().disabledByAdminMessage
+ : launcher.getString(R.string.msg_disabled_by_admin);
+ Toast.makeText(launcher, message, Toast.LENGTH_SHORT).show();
return false;
}
Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER)
diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
index a982786..11ca130 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -20,6 +20,8 @@
import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE;
+import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync;
+
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
@@ -43,7 +45,7 @@
import androidx.annotation.RequiresApi;
import androidx.recyclerview.widget.RecyclerView;
-import com.android.launcher3.BaseRecyclerView;
+import com.android.launcher3.FastScrollRecyclerView;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.graphics.FastScrollThumbDrawable;
@@ -127,7 +129,7 @@
private String mPopupSectionName;
private Insets mSystemGestureInsets;
- protected BaseRecyclerView mRv;
+ protected FastScrollRecyclerView mRv;
private RecyclerView.OnScrollListener mOnScrollListener;
private int mDownX;
@@ -172,7 +174,7 @@
ta.recycle();
}
- public void setRecyclerView(BaseRecyclerView rv, TextView popupView) {
+ public void setRecyclerView(FastScrollRecyclerView rv, TextView popupView) {
if (mRv != null && mOnScrollListener != null) {
mRv.removeOnScrollListener(mOnScrollListener);
}
@@ -306,6 +308,7 @@
}
private void calcTouchOffsetAndPrepToFastScroll(int downY, int lastY) {
+ hideKeyboardAsync(ActivityContext.lookupContext(getContext()), getWindowToken());
mIsDragging = true;
if (mCanThumbDetach) {
mIsThumbDetached = true;
diff --git a/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java b/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java
index d2d569f..9442734 100644
--- a/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.Utilities.ATLEAST_R;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.launcher3.widget.BaseWidgetSheet.MAX_WIDTH_SCALE_FOR_LARGER_SCREEN;
import android.animation.PropertyValuesHolder;
import android.annotation.SuppressLint;
@@ -106,7 +105,10 @@
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
int widthUsed;
- if (mInsets.bottom > 0) {
+ if (deviceProfile.isTablet) {
+ int margin = deviceProfile.allAppsLeftRightMargin;
+ widthUsed = Math.max(2 * margin, 2 * (mInsets.left + mInsets.right));
+ } else if (mInsets.bottom > 0) {
widthUsed = mInsets.left + mInsets.right;
} else {
Rect padding = deviceProfile.workspacePadding;
@@ -114,18 +116,8 @@
2 * (mInsets.left + mInsets.right));
}
- if (deviceProfile.isTablet || deviceProfile.isTwoPanels) {
- // In large screen devices, we restrict the width of the widgets picker to show part of
- // the home screen. Let's ensure the minimum width used is at least the minimum width
- // that isn't taken by the widgets picker.
- int minUsedWidth = (int) (deviceProfile.availableWidthPx
- * (1 - MAX_WIDTH_SCALE_FOR_LARGER_SCREEN));
- widthUsed = Math.max(widthUsed, minUsedWidth);
- }
-
- int heightUsed = mInsets.top + deviceProfile.edgeMarginPx;
measureChildWithMargins(mContent, widthMeasureSpec,
- widthUsed, heightMeasureSpec, heightUsed);
+ widthUsed, heightMeasureSpec, deviceProfile.bottomSheetTopPadding);
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
}
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 00a0050..8962c4f 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -16,6 +16,8 @@
package com.android.launcher3.widget;
import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
@@ -23,6 +25,7 @@
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
+import android.view.WindowInsets;
import android.widget.Toast;
import androidx.annotation.GuardedBy;
@@ -43,7 +46,9 @@
import com.android.launcher3.touch.ItemLongClickListener;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
+import com.android.launcher3.util.window.WindowManagerProxy;
import com.android.launcher3.views.AbstractSlideInView;
+import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.ArrowTipView;
/**
@@ -54,11 +59,6 @@
PopupDataProvider.PopupDataChangeListener, Insettable {
/** The default number of cells that can fit horizontally in a widget sheet. */
protected static final int DEFAULT_MAX_HORIZONTAL_SPANS = 4;
- /**
- * The maximum scale, [0, 1], of the device screen width that the widgets picker can consume
- * on large screen devices.
- */
- protected static final float MAX_WIDTH_SCALE_FOR_LARGER_SCREEN = 0.89f;
protected static final String KEY_WIDGETS_EDUCATION_TIP_SEEN =
"launcher.widgets_education_tip_seen";
@@ -69,10 +69,15 @@
private int mContentHorizontalMarginInPx;
+ protected int mNavBarScrimHeight;
+ private final Paint mNavBarScrimPaint;
+
public BaseWidgetSheet(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContentHorizontalMarginInPx = getResources().getDimensionPixelSize(
R.dimen.widget_list_horizontal_margin);
+ mNavBarScrimPaint = new Paint();
+ mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
}
protected int getScrimColor(Context context) {
@@ -82,6 +87,9 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+ WindowInsets windowInsets = WindowManagerProxy.INSTANCE.get(getContext())
+ .normalizeWindowInsets(getContext(), getRootWindowInsets(), new Rect());
+ mNavBarScrimHeight = getNavBarScrimHeight(windowInsets);
mActivityContext.getPopupDataProvider().setChangeListener(this);
}
@@ -135,6 +143,30 @@
}
}
+ private int getNavBarScrimHeight(WindowInsets insets) {
+ if (Utilities.ATLEAST_Q) {
+ return insets.getTappableElementInsets().bottom;
+ } else {
+ return insets.getStableInsetBottom();
+ }
+ }
+
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ mNavBarScrimHeight = getNavBarScrimHeight(insets);
+ return super.onApplyWindowInsets(insets);
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+
+ if (mNavBarScrimHeight > 0) {
+ canvas.drawRect(0, getHeight() - mNavBarScrimHeight, getWidth(), getHeight(),
+ mNavBarScrimPaint);
+ }
+ }
+
/** Called when the horizontal margin of the content view has changed. */
protected abstract void onContentHorizontalMarginChanged(int contentHorizontalMarginInPx);
@@ -146,7 +178,10 @@
protected void doMeasure(int widthMeasureSpec, int heightMeasureSpec) {
DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
int widthUsed;
- if (mInsets.bottom > 0) {
+ if (deviceProfile.isTablet) {
+ int margin = deviceProfile.allAppsLeftRightMargin;
+ widthUsed = Math.max(2 * margin, 2 * (mInsets.left + mInsets.right));
+ } else if (mInsets.bottom > 0) {
widthUsed = mInsets.left + mInsets.right;
} else {
Rect padding = deviceProfile.workspacePadding;
@@ -154,18 +189,8 @@
2 * (mInsets.left + mInsets.right));
}
- if (deviceProfile.isTablet || deviceProfile.isTwoPanels) {
- // In large screen devices, we restrict the width of the widgets picker to show part of
- // the home screen. Let's ensure the minimum width used is at least the minimum width
- // that isn't taken by the widgets picker.
- int minUsedWidth = (int) (deviceProfile.availableWidthPx
- * (1 - MAX_WIDTH_SCALE_FOR_LARGER_SCREEN));
- widthUsed = Math.max(widthUsed, minUsedWidth);
- }
-
- int heightUsed = mInsets.top + deviceProfile.edgeMarginPx;
measureChildWithMargins(mContent, widthMeasureSpec,
- widthUsed, heightMeasureSpec, heightUsed);
+ widthUsed, heightMeasureSpec, deviceProfile.bottomSheetTopPadding);
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
}
@@ -173,7 +198,9 @@
/** Returns the number of cells that can fit horizontally in a given {@code content}. */
protected int computeMaxHorizontalSpans(View content, int contentHorizontalPaddingPx) {
DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
- int availableWidth = content.getMeasuredWidth() - contentHorizontalPaddingPx;
+ int availableWidth = content.getMeasuredWidth()
+ - contentHorizontalPaddingPx
+ - (2 * mContentHorizontalMarginInPx);
Point cellSize = deviceProfile.getCellSize();
if (cellSize.x > 0) {
return availableWidth / cellSize.x;
@@ -307,4 +334,11 @@
return mActivityContext.getSharedPrefs().getBoolean(KEY_WIDGETS_EDUCATION_TIP_SEEN, false)
|| Utilities.IS_RUNNING_IN_TEST_HARNESS;
}
+
+ @Override
+ protected void setTranslationShift(float translationShift) {
+ super.setTranslationShift(translationShift);
+ Launcher launcher = ActivityContext.lookupContext(getContext());
+ launcher.onWidgetsTransition(1 - translationShift);
+ }
}
diff --git a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
index 784f4f0..7030f6d 100644
--- a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
+++ b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
@@ -25,15 +25,10 @@
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
import android.graphics.RectF;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Handler;
-import android.os.Process;
-import android.os.UserHandle;
-import android.util.ArrayMap;
import android.util.Log;
import android.util.Size;
@@ -44,7 +39,6 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.BitmapRenderer;
-import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.icons.ShadowGenerator;
import com.android.launcher3.icons.cache.HandlerRunnable;
@@ -65,9 +59,6 @@
private final Context mContext;
private final float mPreviewBoxCornerRadius;
- private final UserHandle mMyUser = Process.myUserHandle();
- private final ArrayMap<UserHandle, Bitmap> mUserBadges = new ArrayMap<>();
-
public DatabaseWidgetPreviewLoader(Context context) {
mContext = context;
float previewCornerRadius = RoundedCornerEnforcement.computeEnforcedRadius(context);
@@ -109,52 +100,6 @@
}
/**
- * Returns a drawable that can be used as a badge for the user or null.
- */
- // @UiThread
- public Drawable getBadgeForUser(UserHandle user, int badgeSize) {
- if (mMyUser.equals(user)) {
- return null;
- }
-
- Bitmap badgeBitmap = getUserBadge(user, badgeSize);
- FastBitmapDrawable d = new FastBitmapDrawable(badgeBitmap);
- d.setFilterBitmap(true);
- d.setBounds(0, 0, badgeBitmap.getWidth(), badgeBitmap.getHeight());
- return d;
- }
-
- private Bitmap getUserBadge(UserHandle user, int badgeSize) {
- synchronized (mUserBadges) {
- Bitmap badgeBitmap = mUserBadges.get(user);
- if (badgeBitmap != null) {
- return badgeBitmap;
- }
-
- final Resources res = mContext.getResources();
- badgeBitmap = Bitmap.createBitmap(badgeSize, badgeSize, Bitmap.Config.ARGB_8888);
-
- Drawable drawable = mContext.getPackageManager().getUserBadgedDrawableForDensity(
- new BitmapDrawable(res, badgeBitmap), user,
- new Rect(0, 0, badgeSize, badgeSize),
- 0);
- if (drawable instanceof BitmapDrawable) {
- badgeBitmap = ((BitmapDrawable) drawable).getBitmap();
- } else {
- badgeBitmap.eraseColor(Color.TRANSPARENT);
- Canvas c = new Canvas(badgeBitmap);
- drawable.setBounds(0, 0, badgeSize, badgeSize);
- drawable.draw(c);
- c.setBitmap(null);
- }
-
- mUserBadges.put(user, badgeBitmap);
- return badgeBitmap;
- }
- }
-
-
- /**
* Generates the widget preview from either the {@link WidgetManagerHelper} or cache
* and add badge at the bottom right corner.
*
@@ -318,8 +263,8 @@
LauncherIcons li = LauncherIcons.obtain(mContext);
Drawable icon = li.createBadgedIconBitmap(
mutateOnMainThread(info.getFullResIcon(
- LauncherAppState.getInstance(mContext).getIconCache())),
- Process.myUserHandle(), 0).newIcon(mContext);
+ LauncherAppState.getInstance(mContext).getIconCache())))
+ .newIcon(mContext);
li.recycle();
icon.setBounds(padding, padding, padding + iconSize, padding + iconSize);
diff --git a/src/com/android/launcher3/widget/DeferredAppWidgetHostView.java b/src/com/android/launcher3/widget/DeferredAppWidgetHostView.java
index 57f8bc7..f42142e 100644
--- a/src/com/android/launcher3/widget/DeferredAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/DeferredAppWidgetHostView.java
@@ -16,7 +16,6 @@
package com.android.launcher3.widget;
-import android.annotation.SuppressLint;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.graphics.Canvas;
@@ -31,9 +30,6 @@
import com.android.launcher3.R;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
/**
* A widget host views created while the host has not bind to the system service.
*/
@@ -73,34 +69,23 @@
return;
}
- // Use double padding so that there is extra space between background and text
+ // Use double padding so that there is extra space between background and text if possible.
int availableWidth = getMeasuredWidth() - 2 * (getPaddingLeft() + getPaddingRight());
+ if (availableWidth <= 0) {
+ availableWidth = getMeasuredWidth() - (getPaddingLeft() + getPaddingRight());
+ }
if (mSetupTextLayout != null && mSetupTextLayout.getText().equals(info.label)
&& mSetupTextLayout.getWidth() == availableWidth) {
return;
}
- try {
- mSetupTextLayout = new StaticLayout(info.label, mPaint, availableWidth,
- Layout.Alignment.ALIGN_CENTER, 1, 0, true);
- } catch (IllegalArgumentException e) {
- @SuppressLint("DrawAllocation") StringWriter stringWriter = new StringWriter();
- @SuppressLint("DrawAllocation") PrintWriter printWriter = new PrintWriter(stringWriter);
- mActivity.getDeviceProfile().dump(/*prefix=*/"", printWriter);
- printWriter.flush();
- String message = "b/203530620 "
- + "- availableWidth: " + availableWidth
- + ", getMeasuredWidth: " + getMeasuredWidth()
- + ", getPaddingLeft: " + getPaddingLeft()
- + ", getPaddingRight: " + getPaddingRight()
- + ", deviceProfile: " + stringWriter.toString();
- throw new IllegalArgumentException(message, e);
- }
+ mSetupTextLayout = new StaticLayout(info.label, mPaint, availableWidth,
+ Layout.Alignment.ALIGN_CENTER, 1, 0, true);
}
@Override
protected void onDraw(Canvas canvas) {
if (mSetupTextLayout != null) {
- canvas.translate(getPaddingLeft() * 2,
+ canvas.translate((getWidth() - mSetupTextLayout.getWidth()) / 2,
(getHeight() - mSetupTextLayout.getHeight()) / 2);
mSetupTextLayout.draw(canvas);
}
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index f0b4ba0..0865152 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -16,12 +16,16 @@
package com.android.launcher3.widget;
+import android.annotation.TargetApi;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.Build;
import android.os.Handler;
import android.os.SystemClock;
+import android.os.Trace;
+import android.util.Log;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.view.MotionEvent;
@@ -52,6 +56,8 @@
implements TouchCompleteListener, View.OnLongClickListener,
LocalColorExtractor.Listener {
+ private static final String TAG = "LauncherAppWidgetHostView";
+
// Related to the auto-advancing of widgets
private static final long ADVANCE_INTERVAL = 20000;
private static final long ADVANCE_STAGGER = 250;
@@ -61,6 +67,8 @@
// Maximum duration for which updates can be deferred.
private static final long UPDATE_LOCK_TIMEOUT_MILLIS = 1000;
+ private static final String TRACE_METHOD_NAME = "appwidget load-widget ";
+
private final Rect mTempRect = new Rect();
private final CheckLongPressHelper mLongPressHelper;
protected final Launcher mLauncher;
@@ -88,6 +96,8 @@
/** The drag content height which is only set when the drag content scale is not 1f. */
private int mDragContentHeight = 0;
+ private boolean mTrackingWidgetUpdate = false;
+
public LauncherAppWidgetHostView(Context context) {
super(context);
mLauncher = Launcher.getLauncher(context);
@@ -121,7 +131,25 @@
}
@Override
+ @TargetApi(Build.VERSION_CODES.Q)
+ public void setAppWidget(int appWidgetId, AppWidgetProviderInfo info) {
+ super.setAppWidget(appWidgetId, info);
+ if (!mTrackingWidgetUpdate && Utilities.ATLEAST_Q) {
+ mTrackingWidgetUpdate = true;
+ Trace.beginAsyncSection(TRACE_METHOD_NAME + info.provider, appWidgetId);
+ Log.i(TAG, "App widget created with id: " + appWidgetId);
+ }
+ }
+
+ @Override
+ @TargetApi(Build.VERSION_CODES.Q)
public void updateAppWidget(RemoteViews remoteViews) {
+ if (mTrackingWidgetUpdate && remoteViews != null && Utilities.ATLEAST_Q) {
+ Log.i(TAG, "App widget with id: " + getAppWidgetId() + " loaded");
+ Trace.endAsyncSection(
+ TRACE_METHOD_NAME + getAppWidgetInfo().provider, getAppWidgetId());
+ mTrackingWidgetUpdate = false;
+ }
if (isDeferringUpdates()) {
mDeferredRemoteViews = remoteViews;
return;
@@ -429,7 +457,8 @@
}
// Remove and rebind the current widget (which was inflated in the wrong
// orientation), but don't delete it from the database
- mLauncher.removeItem(this, info, false /* deleteFromDb */);
+ mLauncher.removeItem(this, info, false /* deleteFromDb */,
+ "widget removed because of configuration change");
mLauncher.bindAppWidget(info);
}
diff --git a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
index cbec642..470a800 100644
--- a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
+++ b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
@@ -70,7 +70,7 @@
public LauncherAtom.ItemInfo buildProto(FolderInfo folderInfo) {
LauncherAtom.ItemInfo info = super.buildProto(folderInfo);
return info.toBuilder()
- .setAttribute(LauncherAppWidgetInfo.getAttribute(sourceContainer))
+ .addItemAttributes(LauncherAppWidgetInfo.getAttribute(sourceContainer))
.build();
}
}
diff --git a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
index 553ba13..130ee3a 100644
--- a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
@@ -17,7 +17,7 @@
package com.android.launcher3.widget;
import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
-import static com.android.launcher3.widget.WidgetSections.getWidgetSections;
+import static com.android.launcher3.icons.FastBitmapDrawable.getDisabledColorFilter;
import android.content.Context;
import android.graphics.Canvas;
@@ -159,8 +159,7 @@
disabledIcon.setIsDisabled(true);
mCenterDrawable = disabledIcon;
} else {
- widgetCategoryIcon.setColorFilter(
- FastBitmapDrawable.getDisabledFColorFilter(/* disabledAlpha= */ 1f));
+ widgetCategoryIcon.setColorFilter(getDisabledColorFilter());
mCenterDrawable = widgetCategoryIcon;
}
mSettingIconDrawable = null;
@@ -341,8 +340,6 @@
if (mInfo.pendingItemInfo.widgetCategory == WidgetSections.NO_CATEGORY) {
return null;
}
- Context context = getContext();
- return context.getDrawable(getWidgetSections(context).get(
- mInfo.pendingItemInfo.widgetCategory).mSectionDrawable);
+ return mInfo.pendingItemInfo.newIcon(getContext());
}
}
diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java
index 463f4ac..46c0b99 100644
--- a/src/com/android/launcher3/widget/PendingItemDragHelper.java
+++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java
@@ -181,8 +181,7 @@
PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) mAddInfo;
Drawable icon = createShortcutInfo.activityInfo.getFullResIcon(app.getIconCache());
LauncherIcons li = LauncherIcons.obtain(launcher);
- preview = new FastBitmapDrawable(
- li.createScaledBitmapWithoutShadow(icon, 0));
+ preview = new FastBitmapDrawable(li.createScaledBitmapWithoutShadow(icon));
previewWidth = preview.getIntrinsicWidth();
previewHeight = preview.getIntrinsicHeight();
li.recycle();
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index c92fe5a..2796721 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
+import android.os.Process;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Size;
@@ -48,7 +49,6 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
-import com.android.launcher3.icons.BaseIconFactory;
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.icons.RoundDrawableWrapper;
import com.android.launcher3.icons.cache.HandlerRunnable;
@@ -372,14 +372,11 @@
/** Used to show the badge when the widget is in the recommended section
*/
public void showBadge() {
- Drawable badge = mWidgetPreviewLoader.getBadgeForUser(mItem.user,
- BaseIconFactory.getBadgeSizeForIconSize(
- mActivity.getDeviceProfile().allAppsIconSizePx));
- if (badge == null) {
+ if (Process.myUserHandle().equals(mItem.user)) {
mWidgetBadge.setVisibility(View.GONE);
} else {
mWidgetBadge.setVisibility(View.VISIBLE);
- mWidgetBadge.setImageDrawable(badge);
+ mWidgetBadge.setImageResource(R.drawable.ic_work_app_badge);
}
}
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index b152ddc..bf521cc 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -247,10 +247,12 @@
@Override
public void setInsets(Rect insets) {
super.setInsets(insets);
+ int bottomPadding = Math.max(insets.bottom, mNavBarScrimHeight);
mContent.setPadding(mContent.getPaddingStart(),
- mContent.getPaddingTop(), mContent.getPaddingEnd(), insets.bottom);
- if (insets.bottom > 0) {
+ mContent.getPaddingTop(), mContent.getPaddingEnd(),
+ bottomPadding);
+ if (bottomPadding > 0) {
setupNavBarColor();
} else {
clearNavBarColor();
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 894c4c9..a49cdc0 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -31,6 +31,7 @@
import android.graphics.Rect;
import android.os.Process;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.AttributeSet;
import android.util.Pair;
import android.util.SparseArray;
@@ -41,6 +42,7 @@
import android.view.WindowInsets;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
+import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.Nullable;
@@ -54,7 +56,9 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
+import com.android.launcher3.model.UserManagerState;
import com.android.launcher3.model.WidgetItem;
+import com.android.launcher3.pm.UserCache;
import com.android.launcher3.views.ArrowTipView;
import com.android.launcher3.views.RecyclerViewFastScroller;
import com.android.launcher3.views.SpringRelativeLayout;
@@ -92,14 +96,16 @@
private static final String KEY_WIDGETS_EDUCATION_DIALOG_SEEN =
"launcher.widgets_education_dialog_seen";
- private final Rect mInsets = new Rect();
+ private final UserManagerState mUserManagerState = new UserManagerState();
+
private final boolean mHasWorkProfile;
private final SparseArray<AdapterHolder> mAdapters = new SparseArray();
private final UserHandle mCurrentUser = Process.myUserHandle();
private final Predicate<WidgetsListBaseEntry> mPrimaryWidgetsFilter =
entry -> mCurrentUser.equals(entry.mPkgItem.user);
private final Predicate<WidgetsListBaseEntry> mWorkWidgetsFilter =
- mPrimaryWidgetsFilter.negate();
+ entry -> !mCurrentUser.equals(entry.mPkgItem.user)
+ && !mUserManagerState.isUserQuiet(entry.mPkgItem.user);
@Nullable private ArrowTipView mLatestEducationalTip;
private final OnLayoutChangeListener mLayoutChangeListenerToShowTips =
new OnLayoutChangeListener() {
@@ -170,6 +176,9 @@
: 0;
mWidgetSheetContentHorizontalPadding = 2 * resources.getDimensionPixelSize(
R.dimen.widget_cell_horizontal_padding);
+
+ mUserManagerState.init(UserCache.INSTANCE.get(context),
+ context.getSystemService(UserManager.class));
}
public WidgetsFullSheet(Context context, AttributeSet attrs) {
@@ -199,6 +208,7 @@
findViewById(R.id.tab_work)
.setOnClickListener((View view) -> mViewPager.snapToPage(1));
mAdapters.get(AdapterHolder.WORK).setup(findViewById(R.id.work_widgets_list_view));
+ setDeviceManagementResources();
} else {
mViewPager = null;
}
@@ -220,6 +230,16 @@
setUpEducationViewsIfNeeded();
}
+ private void setDeviceManagementResources() {
+ if (mActivityContext.getStringCache() != null) {
+ Button personalTab = findViewById(R.id.tab_personal);
+ personalTab.setText(mActivityContext.getStringCache().widgetsPersonalTab);
+
+ Button workTab = findViewById(R.id.tab_work);
+ workTab.setText(mActivityContext.getStringCache().widgetsWorkTab);
+ }
+ }
+
@Override
public void onActivePageChanged(int currentActivePage) {
AdapterHolder currentAdapterHolder = mAdapters.get(currentActivePage);
@@ -247,10 +267,15 @@
boolean isWidgetAvailable = adapterHolder.mWidgetsListAdapter.hasVisibleEntries();
adapterHolder.mWidgetsRecyclerView.setVisibility(isWidgetAvailable ? VISIBLE : GONE);
- mNoWidgetsView.setText(
- adapterHolder.mAdapterType == AdapterHolder.SEARCH
- ? R.string.no_search_results
- : R.string.no_widgets_available);
+ if (adapterHolder.mAdapterType == AdapterHolder.SEARCH) {
+ mNoWidgetsView.setText(R.string.no_search_results);
+ } else if (adapterHolder.mAdapterType == AdapterHolder.WORK
+ && mUserManagerState.isAnyProfileQuietModeEnabled()
+ && mActivityContext.getStringCache() != null) {
+ mNoWidgetsView.setText(mActivityContext.getStringCache().workProfilePausedTitle);
+ } else {
+ mNoWidgetsView.setText(R.string.no_widgets_available);
+ }
mNoWidgetsView.setVisibility(isWidgetAvailable ? GONE : VISIBLE);
}
@@ -303,15 +328,15 @@
@Override
public void setInsets(Rect insets) {
super.setInsets(insets);
-
- setBottomPadding(mAdapters.get(AdapterHolder.PRIMARY).mWidgetsRecyclerView, insets.bottom);
- setBottomPadding(mAdapters.get(AdapterHolder.SEARCH).mWidgetsRecyclerView, insets.bottom);
+ int bottomPadding = Math.max(insets.bottom, mNavBarScrimHeight);
+ setBottomPadding(mAdapters.get(AdapterHolder.PRIMARY).mWidgetsRecyclerView, bottomPadding);
+ setBottomPadding(mAdapters.get(AdapterHolder.SEARCH).mWidgetsRecyclerView, bottomPadding);
if (mHasWorkProfile) {
- setBottomPadding(mAdapters.get(AdapterHolder.WORK).mWidgetsRecyclerView, insets.bottom);
+ setBottomPadding(mAdapters.get(AdapterHolder.WORK).mWidgetsRecyclerView, bottomPadding);
}
- ((MarginLayoutParams) mNoWidgetsView.getLayoutParams()).bottomMargin = insets.bottom;
+ ((MarginLayoutParams) mNoWidgetsView.getLayoutParams()).bottomMargin = bottomPadding;
- if (insets.bottom > 0) {
+ if (bottomPadding > 0) {
setupNavBarColor();
} else {
clearNavBarColor();
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListHeader.java b/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
index 932e06d..48df04f 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.widget.picker;
-import static com.android.launcher3.widget.WidgetSections.NO_CATEGORY;
import android.content.Context;
import android.content.res.Resources;
@@ -43,8 +42,6 @@
import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.util.PluralMessageFormat;
import com.android.launcher3.views.ActivityContext;
-import com.android.launcher3.widget.WidgetSections;
-import com.android.launcher3.widget.WidgetSections.WidgetSection;
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry;
@@ -98,7 +95,7 @@
mTitle = findViewById(R.id.app_title);
mSubtitle = findViewById(R.id.app_subtitle);
mExpandToggle = findViewById(R.id.toggle);
- findViewById(R.id.app_container).setAccessibilityDelegate(new AccessibilityDelegate() {
+ setAccessibilityDelegate(new AccessibilityDelegate() {
@Override
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
@@ -177,13 +174,7 @@
private void setIcon(PackageItemInfo info) {
Drawable icon;
- if (info.widgetCategory == NO_CATEGORY) {
- icon = info.newIcon(getContext());
- } else {
- WidgetSection widgetSection = WidgetSections.getWidgetSections(getContext())
- .get(info.widgetCategory);
- icon = getContext().getDrawable(widgetSection.mSectionDrawable);
- }
+ icon = info.newIcon(getContext());
applyDrawables(icon);
mIconDrawable = icon;
if (mIconDrawable != null) {
diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
index f780f03..bdf646b 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
@@ -27,8 +27,8 @@
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener;
-import com.android.launcher3.BaseRecyclerView;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.FastScrollRecyclerView;
import com.android.launcher3.R;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.widget.model.WidgetListSpaceEntry;
@@ -41,7 +41,7 @@
/**
* The widgets recycler view.
*/
-public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouchListener {
+public class WidgetsRecyclerView extends FastScrollRecyclerView implements OnItemTouchListener {
private WidgetsListAdapter mAdapter;
@@ -239,21 +239,6 @@
mHeaderViewDimensionsProvider = headerViewDimensionsProvider;
}
- @Override
- public void scrollToTop() {
- if (mScrollbar != null) {
- mScrollbar.reattachThumbToScroll();
- }
-
- if (getLayoutManager() instanceof LinearLayoutManager) {
- if (getCurrentScrollY() == 0) {
- // We are at the top, so don't scrollToPosition (would cause unnecessary relayout).
- return;
- }
- }
- scrollToPosition(0);
- }
-
/**
* Returns the sum of the height, in pixels, of this list adapter's items from index 0 until
* {@code untilIndex}.
diff --git a/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarController.java b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarController.java
index 2751a52..a15508a 100644
--- a/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarController.java
+++ b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarController.java
@@ -95,11 +95,6 @@
}
@Override
- public void onAppendSearchResult(String query, ArrayList<WidgetsListBaseEntry> items) {
- // Not needed.
- }
-
- @Override
public void clearSearchResult() {
// Any existing search session will be cancelled by setting text to empty.
mInput.setText("");
diff --git a/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java b/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java
index 11185fb..49db2a0 100644
--- a/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java
+++ b/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java
@@ -23,7 +23,9 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.pageindicators.PageIndicator;
+import com.android.launcher3.views.ActivityContext;
/**
* Supports two indicator colors, dedicated for personal and work tabs.
@@ -72,6 +74,26 @@
return false;
}
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ if (getPaddingLeft() == 0 && getPaddingRight() == 0) {
+ // If any padding is not specified, restrict the width to emulate padding
+ int size = MeasureSpec.getSize(widthMeasureSpec);
+ size = getTabWidth(getContext(), size);
+ widthMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
+ }
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ /**
+ * Returns distance between left and right app icons
+ */
+ public static int getTabWidth(Context context, int totalWidth) {
+ DeviceProfile grid = ActivityContext.lookupContext(context).getDeviceProfile();
+ int iconPadding = totalWidth / grid.numShownAllAppsColumns - grid.allAppsIconSizePx;
+ return totalWidth - iconPadding;
+ }
+
/**
* Interface definition for a callback to be invoked when an active page has been changed.
*/
diff --git a/src_build_config/com/android/launcher3/BuildConfig.java b/src_build_config/com/android/launcher3/BuildConfig.java
index 49aadf6..9a81d3f 100644
--- a/src_build_config/com/android/launcher3/BuildConfig.java
+++ b/src_build_config/com/android/launcher3/BuildConfig.java
@@ -17,6 +17,11 @@
package com.android.launcher3;
public final class BuildConfig {
- public static final String APPLICATION_ID = "com.android.launcher3";
- public static final boolean DEBUG = false;
+ public static final String APPLICATION_ID = "com.android.launcher3";
+ public static final boolean DEBUG = false;
+ /**
+ * Flag to state if the QSB is on the first screen and placed on the top,
+ * this can be overwritten in other launchers with a different value, if needed.
+ */
+ public static final boolean QSB_ON_FIRST_SCREEN = true;
}
diff --git a/src_plugins/com/android/systemui/plugins/OverlayPlugin.java b/src_plugins/com/android/systemui/plugins/LauncherOverlayPlugin.java
similarity index 88%
rename from src_plugins/com/android/systemui/plugins/OverlayPlugin.java
rename to src_plugins/com/android/systemui/plugins/LauncherOverlayPlugin.java
index 1edb692..9e22355 100644
--- a/src_plugins/com/android/systemui/plugins/OverlayPlugin.java
+++ b/src_plugins/com/android/systemui/plugins/LauncherOverlayPlugin.java
@@ -24,8 +24,8 @@
/**
* Implement this interface to add a -1 content on the home screen.
*/
-@ProvidesInterface(action = OverlayPlugin.ACTION, version = OverlayPlugin.VERSION)
-public interface OverlayPlugin extends Plugin {
+@ProvidesInterface(action = LauncherOverlayPlugin.ACTION, version = LauncherOverlayPlugin.VERSION)
+public interface LauncherOverlayPlugin extends Plugin {
String ACTION = "com.android.systemui.action.PLUGIN_LAUNCHER_OVERLAY";
int VERSION = 1;
diff --git a/src_plugins/com/android/systemui/plugins/OneSearch.java b/src_plugins/com/android/systemui/plugins/OneSearch.java
index 13a956b..534bc87 100644
--- a/src_plugins/com/android/systemui/plugins/OneSearch.java
+++ b/src_plugins/com/android/systemui/plugins/OneSearch.java
@@ -28,7 +28,7 @@
@ProvidesInterface(action = OneSearch.ACTION, version = OneSearch.VERSION)
public interface OneSearch extends Plugin {
String ACTION = "com.android.systemui.action.PLUGIN_ONE_SEARCH";
- int VERSION = 5;
+ int VERSION = 6;
/**
* Get the content provider warmed up.
@@ -45,6 +45,8 @@
/** Get image bitmap with the URL. */
Parcelable getImageBitmap(String imageUrl);
+ void setSuggestOnChrome(boolean enable);
+
/**
* Notifies search events to plugin
*
diff --git a/src_shortcuts_overrides/com/android/launcher3/util/AbsGridOccupancy.java b/src_shortcuts_overrides/com/android/launcher3/util/AbsGridOccupancy.java
new file mode 100644
index 0000000..968b281
--- /dev/null
+++ b/src_shortcuts_overrides/com/android/launcher3/util/AbsGridOccupancy.java
@@ -0,0 +1,55 @@
+/*
+ * 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;
+
+/**
+ * Defines method to find the next vacant cell on a grid.
+ * This uses the default top-down, left-right approach and can be over-written through
+ * code swaps in different launchers.
+ */
+public abstract class AbsGridOccupancy {
+ /**
+ * Find the first vacant cell, if there is one.
+ *
+ * @param vacantOut Holds the x and y coordinate of the vacant cell
+ * @param spanX Horizontal cell span.
+ * @param spanY Vertical cell span.
+ *
+ * @return true if a vacant cell was found
+ */
+ protected boolean findVacantCell(int[] vacantOut, boolean[][] cells, int countX, int countY,
+ int spanX, int spanY) {
+ for (int y = 0; (y + spanY) <= countY; y++) {
+ for (int x = 0; (x + spanX) <= countX; x++) {
+ boolean available = !cells[x][y];
+ out:
+ for (int i = x; i < x + spanX; i++) {
+ for (int j = y; j < y + spanY; j++) {
+ available = available && !cells[i][j];
+ if (!available) break out;
+ }
+ }
+ if (available) {
+ vacantOut[0] = x;
+ vacantOut[1] = y;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java b/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
index 81e3f98..6715749 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
@@ -19,7 +19,6 @@
import android.app.Person;
import android.content.Context;
import android.content.pm.ShortcutInfo;
-import android.view.Display;
import com.android.launcher3.Utilities;
@@ -32,20 +31,6 @@
}
/**
- * Returns true if the display is an internal displays
- */
- public static boolean isInternalDisplay(Display display) {
- return display.getDisplayId() == Display.DEFAULT_DISPLAY;
- }
-
- /**
- * Returns a unique ID representing the display
- */
- public static String getUniqueId(Display display) {
- return Integer.toString(display.getDisplayId());
- }
-
- /**
* Returns the minimum space that should be left empty at the end of hotseat
*/
public static int getHotseatEndOffset(Context context) {
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 978c321..bf35dd8 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -20,6 +20,7 @@
import android.content.Context;
+import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
@@ -31,23 +32,20 @@
public class AllAppsState extends LauncherState {
private static final float PARALLAX_COEFFICIENT = .125f;
+ private static final float WORKSPACE_SCALE_FACTOR = 0.97f;
private static final int STATE_FLAGS = FLAG_WORKSPACE_INACCESSIBLE;
- private static final PageAlphaProvider PAGE_ALPHA_PROVIDER = new PageAlphaProvider(DEACCEL_2) {
- @Override
- public float getPageAlpha(int pageIndex) {
- return 0;
- }
- };
-
public AllAppsState(int id) {
super(id, LAUNCHER_STATE_ALLAPPS, STATE_FLAGS);
}
@Override
- public int getTransitionDuration(Context context) {
- return 320;
+ public <DEVICE_PROFILE_CONTEXT extends Context & DeviceProfileListenable>
+ int getTransitionDuration(DEVICE_PROFILE_CONTEXT context, boolean isToState) {
+ return !context.getDeviceProfile().isTablet && isToState
+ ? 600
+ : isToState ? 500 : 300;
}
@Override
@@ -62,13 +60,34 @@
@Override
public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
- return new ScaleAndTranslation(1f, 0,
- -launcher.getAllAppsController().getShiftRange() * PARALLAX_COEFFICIENT);
+ return new ScaleAndTranslation(WORKSPACE_SCALE_FACTOR, NO_OFFSET, NO_OFFSET);
+ }
+
+ @Override
+ public ScaleAndTranslation getHotseatScaleAndTranslation(Launcher launcher) {
+ if (launcher.getDeviceProfile().isTablet) {
+ return getWorkspaceScaleAndTranslation(launcher);
+ } else {
+ ScaleAndTranslation overviewScaleAndTranslation = LauncherState.OVERVIEW
+ .getWorkspaceScaleAndTranslation(launcher);
+ return new ScaleAndTranslation(
+ WORKSPACE_SCALE_FACTOR,
+ overviewScaleAndTranslation.translationX,
+ overviewScaleAndTranslation.translationY);
+ }
}
@Override
public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
- return PAGE_ALPHA_PROVIDER;
+ PageAlphaProvider superPageAlphaProvider = super.getWorkspacePageAlphaProvider(launcher);
+ return new PageAlphaProvider(DEACCEL_2) {
+ @Override
+ public float getPageAlpha(int pageIndex) {
+ return launcher.getDeviceProfile().isTablet
+ ? superPageAlphaProvider.getPageAlpha(pageIndex)
+ : 0;
+ }
+ };
}
@Override
@@ -78,6 +97,8 @@
@Override
public int getWorkspaceScrimColor(Launcher launcher) {
- return Themes.getAttrColor(launcher, R.attr.allAppsScrimColor);
+ return launcher.getDeviceProfile().isTablet
+ ? launcher.getResources().getColor(R.color.widgets_picker_scrim)
+ : Themes.getAttrColor(launcher, R.attr.allAppsScrimColor);
}
}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java
index d154317..7a228c4 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -34,7 +34,7 @@
}
@Override
- public int getTransitionDuration(Context context) {
+ public int getTransitionDuration(Context context, boolean isToState) {
return 250;
}
diff --git a/tests/Android.bp b/tests/Android.bp
index 3670c37..54cded0 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -11,19 +11,19 @@
// 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
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "packages_apps_Launcher3_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["packages_apps_Launcher3_license"],
+ default_applicable_licenses: ["Android-Apache-2.0"],
}
// Source code used for test
filegroup {
name: "launcher-tests-src",
- srcs: ["src/**/*.java"],
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt"
+ ],
}
// Source code used for oop test helpers
@@ -32,16 +32,19 @@
srcs: [
"src/com/android/launcher3/ui/AbstractLauncherUiTest.java",
"src/com/android/launcher3/ui/PortraitLandscapeRunner.java",
+ "src/com/android/launcher3/util/TestUtil.java",
"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/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/TestStabilityRule.java",
"src/com/android/launcher3/ui/TaplTestsLauncher3.java",
"src/com/android/launcher3/testcomponent/BaseTestingActivity.java",
+ "src/com/android/launcher3/testcomponent/OtherBaseTestingActivity.java",
"src/com/android/launcher3/testcomponent/CustomShortcutConfigActivity.java",
"src/com/android/launcher3/testcomponent/TestCommandReceiver.java",
"src/com/android/launcher3/testcomponent/TestLauncherActivity.java",
@@ -65,12 +68,18 @@
"androidx.test.uiautomator_uiautomator",
"mockito-target-inline-minus-junit4",
"launcher_log_protos_lite",
- "truth-prebuilt"
+ "truth-prebuilt",
+ "platform-test-rules",
],
manifest: "AndroidManifest-common.xml",
platform_apis: true,
}
+android_library {
+ name: "Launcher3TestResources",
+ resource_dirs: ["res"],
+}
+
android_test {
name: "Launcher3Tests",
srcs: [
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index 618ab41..9cc3aed 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -16,6 +16,7 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
package="com.android.launcher3.tests">
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
@@ -93,7 +94,6 @@
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
- <category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
@@ -137,6 +137,7 @@
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
+ <category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<intent-filter>
<action android:name="com.android.launcher3.intent.action.test_shortcut"/>
@@ -266,5 +267,20 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
+ <activity-alias android:name="Activity15" android:exported="true"
+ android:label="ThemeIconTestActivity"
+ android:icon="@drawable/test_theme_icon"
+ 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>
+ </activity-alias>
+
+ <!-- [b/197780098] Disable eager initialization of Jetpack libraries. -->
+ <provider
+ android:name="androidx.startup.InitializationProvider"
+ android:authorities="${applicationId}.androidx-startup"
+ tools:node="remove" />
</application>
</manifest>
diff --git a/tests/dummy_app/Android.bp b/tests/dummy_app/Android.bp
new file mode 100644
index 0000000..08ce2f7
--- /dev/null
+++ b/tests/dummy_app/Android.bp
@@ -0,0 +1,29 @@
+//
+// 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 {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_app {
+ name: "Aardwolf",
+ srcs: ["src/**/*.java"],
+ sdk_version: "current",
+ dex_preopt: {
+ enabled: false,
+ },
+}
diff --git a/tests/dummy_app/Android.mk b/tests/dummy_app/Android.mk
deleted file mode 100644
index 3472079..0000000
--- a/tests/dummy_app/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := samples
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := Aardwolf
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/res/drawable/test_theme_icon.xml b/tests/res/drawable/test_theme_icon.xml
new file mode 100644
index 0000000..be5c4d9
--- /dev/null
+++ b/tests/res/drawable/test_theme_icon.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@android:color/white"/>
+ <foreground>
+ <color android:color="#FFFF0000" />
+ </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/devices.json b/tests/res/raw/devices.json
new file mode 100644
index 0000000..a78dd86
--- /dev/null
+++ b/tests/res/raw/devices.json
@@ -0,0 +1,45 @@
+{
+ "pixel6pro": {
+ "width": 1440,
+ "height": 3120,
+ "density": 560,
+ "name": "pixel6pro",
+ "cutout": "0, 130, 0, 0",
+ "grids": [
+ "normal",
+ "reasonable",
+ "practical",
+ "big",
+ "crazy_big"
+ ],
+ "resourceOverrides": {
+ "status_bar_height": 98,
+ "navigation_bar_height_landscape": 56,
+ "navigation_bar_height": 56,
+ "navigation_bar_width": 56
+ }
+ },
+ "test": {
+ "data needs updating": 0
+ },
+ "pixel5": {
+ "width": 1080,
+ "height": 2340,
+ "density": 440,
+ "name": "pixel5",
+ "cutout": "0, 136, 0, 0",
+ "grids": [
+ "normal",
+ "reasonable",
+ "practical",
+ "big",
+ "crazy_big"
+ ],
+ "resourceOverrides": {
+ "status_bar_height": 66,
+ "navigation_bar_height_landscape": 44,
+ "navigation_bar_height": 44,
+ "navigation_bar_width": 44
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
new file mode 100644
index 0000000..6d0fcb6
--- /dev/null
+++ b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3
+
+import android.content.Context
+import android.graphics.PointF
+import androidx.test.core.app.ApplicationProvider
+import com.android.launcher3.util.DisplayController.Info
+import com.android.launcher3.util.WindowBounds
+import org.junit.Before
+import org.mockito.ArgumentMatchers.any
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.`when` as whenever
+
+abstract class DeviceProfileBaseTest {
+
+ protected var context: Context? = null
+ protected var inv: InvariantDeviceProfile? = null
+ protected var info: Info = mock(Info::class.java)
+ protected var windowBounds: WindowBounds? = null
+ protected var isMultiWindowMode: Boolean = false
+ protected var transposeLayoutWithOrientation: Boolean = false
+ protected var useTwoPanels: Boolean = false
+ protected var isGestureMode: Boolean = true
+
+ @Before
+ fun setUp() {
+ context = ApplicationProvider.getApplicationContext()
+ // make sure to reset values
+ useTwoPanels = false
+ isGestureMode = true
+ }
+
+ protected fun newDP(): DeviceProfile = DeviceProfile(
+ context,
+ inv,
+ info,
+ windowBounds,
+ isMultiWindowMode,
+ transposeLayoutWithOrientation,
+ useTwoPanels,
+ isGestureMode
+ )
+
+ protected fun initializeVarsForPhone(isLandscape: Boolean = false) {
+ val (x, y) = if (isLandscape)
+ Pair(3120, 1440)
+ else
+ Pair(1440, 3120)
+
+ windowBounds = WindowBounds(x, y, x, y - 100, 0)
+
+ whenever(info.isTablet(any())).thenReturn(false)
+ whenever(info.getDensityDpi()).thenReturn(560)
+
+ inv = newScalableInvariantDeviceProfile()
+ }
+
+ protected fun initializeVarsForTablet(isLandscape: Boolean = false) {
+ val (x, y) = if (isLandscape)
+ Pair(2560, 1600)
+ else
+ Pair(1600, 2560)
+
+ windowBounds = WindowBounds(x, y, x, y - 100, 0)
+
+ whenever(info.isTablet(any())).thenReturn(true)
+ whenever(info.getDensityDpi()).thenReturn(320)
+
+ inv = newScalableInvariantDeviceProfile()
+ }
+
+ /**
+ * A very generic grid, just to make qsb tests work. For real calculations, make sure to use
+ * values that better represent a real grid.
+ */
+ protected fun newScalableInvariantDeviceProfile(): InvariantDeviceProfile =
+ InvariantDeviceProfile().apply {
+ isScalable = true
+ numColumns = 4
+ numRows = 4
+ numShownHotseatIcons = 4
+ numDatabaseHotseatIcons = 6
+ numShrunkenHotseatIcons = 5
+ horizontalMargin = FloatArray(4) { 22f }
+ borderSpaces = listOf(
+ PointF(16f, 16f),
+ PointF(16f, 16f),
+ PointF(16f, 16f),
+ PointF(16f, 16f)
+ ).toTypedArray()
+ allAppsBorderSpaces = listOf(
+ PointF(16f, 16f),
+ PointF(16f, 16f),
+ PointF(16f, 16f),
+ PointF(16f, 16f)
+ ).toTypedArray()
+ hotseatBorderSpaces = FloatArray(4) { 16f }
+ hotseatColumnSpan = IntArray(4) { 4 }
+ iconSize = FloatArray(4) { 56f }
+ allAppsIconSize = FloatArray(4) { 56f }
+ iconTextSize = FloatArray(4) { 14f }
+ allAppsIconTextSize = FloatArray(4) { 14f }
+ minCellSize = listOf(
+ PointF(64f, 83f),
+ PointF(64f, 83f),
+ PointF(64f, 83f),
+ PointF(64f, 83f)
+ ).toTypedArray()
+ allAppsCellSize = listOf(
+ PointF(64f, 83f),
+ PointF(64f, 83f),
+ PointF(64f, 83f),
+ PointF(64f, 83f)
+ ).toTypedArray()
+ inlineQsb = booleanArrayOf(
+ false,
+ false,
+ false,
+ false
+ )
+ }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/DeviceProfileGridDimensionsTest.kt b/tests/src/com/android/launcher3/DeviceProfileGridDimensionsTest.kt
new file mode 100644
index 0000000..80259a5
--- /dev/null
+++ b/tests/src/com/android/launcher3/DeviceProfileGridDimensionsTest.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3
+
+import android.graphics.PointF
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.util.WindowBounds
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers
+import org.mockito.Mockito.`when` as whenever
+
+/**
+ * Test for [DeviceProfile] grid dimensions.
+ *
+ * This includes workspace, cell layout, shortcut and widget container, cell sizes, etc.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DeviceProfileGridDimensionsTest : DeviceProfileBaseTest() {
+
+ @Test
+ fun getCellLayoutWidth_twoPanelLandscapeScalable4By4GridTablet_equalsSinglePanelWidth() {
+ val tabletWidth = 2560
+ val tabletHeight = 1600
+ val availableWidth = 2560
+ val availableHeight = 1500
+ windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
+ useTwoPanels = true
+ whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
+ whenever(info.densityDpi).thenReturn(320)
+ inv = newScalableInvariantDeviceProfile()
+
+ val dp = newDP()
+
+ val expectedWorkspaceWidth = availableWidth
+ val expectedCellLayoutWidth =
+ (expectedWorkspaceWidth - (dp.workspacePadding.right + dp.workspacePadding.left)) /
+ dp.panelCount
+ assertThat(dp.cellLayoutWidth).isEqualTo(expectedCellLayoutWidth)
+ }
+
+ @Test
+ fun getCellLayoutHeight_twoPanelLandscapeScalable4By4GridTablet_equalsSinglePanelHeight() {
+ val tabletWidth = 2560
+ val tabletHeight = 1600
+ val availableWidth = 2560
+ val availableHeight = 1500
+ windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
+ useTwoPanels = true
+ whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
+ whenever(info.densityDpi).thenReturn(320)
+ inv = newScalableInvariantDeviceProfile()
+
+ val dp = newDP()
+
+ val expectedWorkspaceHeight = availableHeight
+ val expectedCellLayoutHeight =
+ expectedWorkspaceHeight - (dp.workspacePadding.top + dp.workspacePadding.bottom)
+ assertThat(dp.cellLayoutHeight).isEqualTo(expectedCellLayoutHeight)
+ }
+
+ @Test
+ fun getCellSize_twoPanelLandscapeScalable4By4GridTablet_equalsSinglePanelWidth() {
+ val tabletWidth = 2560
+ val tabletHeight = 1600
+ val availableWidth = 2560
+ val availableHeight = 1500
+ windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
+ useTwoPanels = true
+ whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
+ whenever(info.densityDpi).thenReturn(320)
+ inv = newScalableInvariantDeviceProfile()
+
+ val dp = newDP()
+
+ val expectedWorkspaceWidth = availableWidth
+ val expectedCellLayoutWidth =
+ (expectedWorkspaceWidth - (dp.workspacePadding.right + dp.workspacePadding.left)) /
+ dp.panelCount
+ val expectedShortcutAndWidgetContainerWidth =
+ expectedCellLayoutWidth -
+ (dp.cellLayoutPaddingPx.left + dp.cellLayoutPaddingPx.right)
+ assertThat(dp.getCellSize().x).isEqualTo(
+ (expectedShortcutAndWidgetContainerWidth -
+ ((inv!!.numColumns - 1) * dp.cellLayoutBorderSpacePx.x)) / inv!!.numColumns)
+ val expectedWorkspaceHeight = availableHeight
+ val expectedCellLayoutHeight =
+ expectedWorkspaceHeight - (dp.workspacePadding.top + dp.workspacePadding.bottom)
+ val expectedShortcutAndWidgetContainerHeight = expectedCellLayoutHeight -
+ (dp.cellLayoutPaddingPx.top + dp.cellLayoutPaddingPx.bottom)
+ assertThat(dp.getCellSize().y).isEqualTo(
+ (expectedShortcutAndWidgetContainerHeight -
+ ((inv!!.numRows - 1) * dp.cellLayoutBorderSpacePx.y)) / inv!!.numRows)
+ }
+
+ @Test
+ fun getPanelCount_twoPanelLandscapeScalable4By4GridTablet_equalsTwoPanels() {
+ val tabletWidth = 2560
+ val tabletHeight = 1600
+ val availableWidth = 2560
+ val availableHeight = 1500
+ windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
+ useTwoPanels = true
+ whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
+ whenever(info.densityDpi).thenReturn(320)
+ inv = newScalableInvariantDeviceProfile()
+
+ val dp = newDP()
+
+ assertThat(dp.panelCount).isEqualTo(2)
+ }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/HotseatShownIconsTest.kt b/tests/src/com/android/launcher3/HotseatShownIconsTest.kt
new file mode 100644
index 0000000..593239d
--- /dev/null
+++ b/tests/src/com/android/launcher3/HotseatShownIconsTest.kt
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.InvariantDeviceProfile.TYPE_MULTI_DISPLAY
+import com.android.launcher3.InvariantDeviceProfile.TYPE_PHONE
+import com.android.launcher3.InvariantDeviceProfile.TYPE_TABLET
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Test for [DeviceProfile]
+ */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class HotseatShownIconsTest : DeviceProfileBaseTest() {
+
+ @Test
+ fun hotseat_size_is_normal_for_handhelds() {
+ initializeVarsForPhone()
+ inv = newScalableInvariantDeviceProfile().apply {
+ deviceType = TYPE_PHONE
+ }
+
+ val dp = newDP()
+
+ assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.numShownHotseatIcons).isEqualTo(4)
+ }
+
+ @Test
+ fun hotseat_size_is_max_when_large_screen() {
+ initializeVarsForTablet(isLandscape = true)
+ inv = newScalableInvariantDeviceProfile().apply {
+ deviceType = TYPE_MULTI_DISPLAY
+ }
+ useTwoPanels = true
+
+ val dp = newDP()
+
+ assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.numShownHotseatIcons).isEqualTo(6)
+ }
+
+ @Test
+ fun hotseat_size_is_shrunk_if_needed_when_large_screen() {
+ initializeVarsForTablet(isLandscape = true)
+ inv = newScalableInvariantDeviceProfile().apply {
+ deviceType = TYPE_MULTI_DISPLAY
+ inlineQsb = booleanArrayOf(
+ false,
+ false,
+ false,
+ true // two panels landscape
+ )
+ }
+ useTwoPanels = true
+
+ isGestureMode = false
+ val dp = newDP()
+
+ if (dp.hotseatQsbHeight > 0) {
+ assertThat(dp.isQsbInline).isTrue()
+ assertThat(dp.numShownHotseatIcons).isEqualTo(5)
+ } else { // Launcher3 doesn't have QSB height
+ assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.numShownHotseatIcons).isEqualTo(6)
+ }
+ }
+
+ /**
+ * For consistency, the hotseat should shrink if any orientation on the device type has an
+ * inline qsb
+ */
+ @Test
+ fun hotseat_size_is_shrunk_even_in_portrait_when_large_screen() {
+ initializeVarsForTablet()
+ inv = newScalableInvariantDeviceProfile().apply {
+ deviceType = TYPE_MULTI_DISPLAY
+ inlineQsb = booleanArrayOf(
+ false,
+ false,
+ false,
+ true // two panels landscape
+ )
+ }
+ useTwoPanels = true
+
+ isGestureMode = false
+ val dp = newDP()
+
+ if (dp.hotseatQsbHeight > 0) {
+ assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.numShownHotseatIcons).isEqualTo(5)
+ } else { // Launcher3 doesn't have QSB height
+ assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.numShownHotseatIcons).isEqualTo(6)
+ }
+ }
+
+ @Test
+ fun hotseat_size_is_default_when_small_screen() {
+ initializeVarsForPhone()
+ inv = newScalableInvariantDeviceProfile().apply {
+ deviceType = TYPE_MULTI_DISPLAY
+ }
+ useTwoPanels = true
+
+ val dp = newDP()
+
+ assertThat(dp.numShownHotseatIcons).isEqualTo(4)
+ }
+
+ @Test
+ fun hotseat_size_is_not_shrunk_on_gesture_tablet() {
+ initializeVarsForTablet(isLandscape = true)
+ inv = newScalableInvariantDeviceProfile().apply {
+ deviceType = TYPE_TABLET
+ inlineQsb = booleanArrayOf(
+ false,
+ true, // landscape
+ false,
+ false
+ )
+ numShownHotseatIcons = 6
+ }
+
+ isGestureMode = true
+ val dp = newDP()
+
+ if (dp.hotseatQsbHeight > 0) {
+ assertThat(dp.isQsbInline).isTrue()
+ assertThat(dp.numShownHotseatIcons).isEqualTo(6)
+ } else { // Launcher3 doesn't have QSB height
+ assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.numShownHotseatIcons).isEqualTo(6)
+ }
+ }
+
+ @Test
+ fun hotseat_size_is_shrunk_if_needed_on_tablet() {
+ initializeVarsForTablet(isLandscape = true)
+ inv = newScalableInvariantDeviceProfile().apply {
+ deviceType = TYPE_TABLET
+ inlineQsb = booleanArrayOf(
+ false,
+ true, // landscape
+ false,
+ false
+ )
+ numShownHotseatIcons = 6
+ }
+
+ isGestureMode = false
+ val dp = newDP()
+
+ if (dp.hotseatQsbHeight > 0) {
+ assertThat(dp.isQsbInline).isTrue()
+ assertThat(dp.numShownHotseatIcons).isEqualTo(5)
+ } else { // Launcher3 doesn't have QSB height
+ assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.numShownHotseatIcons).isEqualTo(6)
+ }
+ }
+
+ /**
+ * For consistency, the hotseat should shrink if any orientation on the device type has an
+ * inline qsb
+ */
+ @Test
+ fun hotseat_size_is_shrunk_even_in_portrait_on_tablet() {
+ initializeVarsForTablet()
+ inv = newScalableInvariantDeviceProfile().apply {
+ deviceType = TYPE_TABLET
+ inlineQsb = booleanArrayOf(
+ false,
+ true, // landscape
+ false,
+ false
+ )
+ numShownHotseatIcons = 6
+ }
+
+ isGestureMode = false
+ val dp = newDP()
+
+ if (dp.hotseatQsbHeight > 0) {
+ assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.numShownHotseatIcons).isEqualTo(5)
+ } else { // Launcher3 doesn't have QSB height
+ assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.numShownHotseatIcons).isEqualTo(6)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/InlineQsbTest.kt b/tests/src/com/android/launcher3/InlineQsbTest.kt
new file mode 100644
index 0000000..905c1e1
--- /dev/null
+++ b/tests/src/com/android/launcher3/InlineQsbTest.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Test for [DeviceProfile]
+ */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class InlineQsbTest : DeviceProfileBaseTest() {
+
+ @Test
+ fun qsb_is_not_inline_for_phones() {
+ initializeVarsForPhone()
+
+ val dp = newDP()
+
+ assertThat(dp.isQsbInline).isFalse()
+ }
+
+ @Test
+ fun qsb_is_inline_for_tablet_portrait() {
+ initializeVarsForTablet()
+ inv = newScalableInvariantDeviceProfile().apply {
+ inlineQsb = booleanArrayOf(
+ false,
+ true, // landscape
+ false,
+ false
+ )
+ }
+
+ val dp = DeviceProfile(
+ context,
+ inv,
+ info,
+ windowBounds,
+ isMultiWindowMode,
+ transposeLayoutWithOrientation,
+ useTwoPanels,
+ isGestureMode
+ )
+
+ assertThat(dp.isQsbInline).isFalse()
+ }
+
+ @Test
+ fun qsb_is_inline_for_tablet_landscape() {
+ initializeVarsForTablet(isLandscape = true)
+ inv = newScalableInvariantDeviceProfile().apply {
+ inlineQsb = booleanArrayOf(
+ false,
+ true, // landscape
+ false,
+ false
+ )
+ numColumns = 6
+ numRows = 5
+ numShownHotseatIcons = 6
+ }
+
+ val dp = newDP()
+
+ if (dp.hotseatQsbHeight > 0) {
+ assertThat(dp.isQsbInline).isTrue()
+ } else { // Launcher3 doesn't have QSB height
+ assertThat(dp.isQsbInline).isFalse()
+ }
+ }
+
+ /**
+ * This test is to make sure that a tablet doesn't inline the QSB if the layout doesn't support
+ */
+ @Test
+ fun qsb_is_not_inline_for_tablet_landscape_without_inline() {
+ initializeVarsForTablet(isLandscape = true)
+ useTwoPanels = true
+
+ val dp = newDP()
+
+ assertThat(dp.isQsbInline).isFalse()
+ }
+
+}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java b/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java
index 032a7b4..92e3e64 100644
--- a/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java
+++ b/tests/src/com/android/launcher3/compat/PromiseIconUiTest.java
@@ -27,12 +27,14 @@
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;
import org.junit.runner.RunWith;
import java.util.UUID;
+import java.util.concurrent.TimeUnit;
/**
@@ -43,6 +45,8 @@
public class PromiseIconUiTest extends AbstractLauncherUiTest {
private int mSessionId = -1;
+ // TODO(b/202985412): Revert to default timeout when PackageManager bug is fixed.
+ private static final long PROMISE_ICON_TIMEOUT = TimeUnit.SECONDS.toMillis(60);
@Override
public void setUp() throws Exception {
@@ -73,6 +77,7 @@
}
@Test
+ @ScreenRecord // b/202985412
public void testPromiseIcon_addedFromEligibleSession() throws Throwable {
final String appLabel = "Test Promise App " + UUID.randomUUID().toString();
final ItemOperator findPromiseApp = (info, view) ->
@@ -83,7 +88,8 @@
// Verify promise icon is added
waitForLauncherCondition("Test Promise App not found on workspace", launcher ->
- launcher.getWorkspace().getFirstMatch(findPromiseApp) != null);
+ launcher.getWorkspace().getFirstMatch(findPromiseApp) != null,
+ PROMISE_ICON_TIMEOUT);
// Remove session
mTargetContext.getPackageManager().getPackageInstaller().abandonSession(mSessionId);
@@ -91,10 +97,12 @@
// Verify promise icon is removed
waitForLauncherCondition("Test Promise App not removed from workspace", launcher ->
- launcher.getWorkspace().getFirstMatch(findPromiseApp) == null);
+ launcher.getWorkspace().getFirstMatch(findPromiseApp) == null,
+ PROMISE_ICON_TIMEOUT);
}
@Test
+ @ScreenRecord // b/202985412
public void testPromiseIcon_notAddedFromIneligibleSession() throws Throwable {
final String appLabel = "Test Promise App " + UUID.randomUUID().toString();
final ItemOperator findPromiseApp = (info, view) ->
@@ -108,6 +116,7 @@
// Verify promise icon is not added
waitForLauncherCondition("Test Promise App not found on workspace", launcher ->
- launcher.getWorkspace().getFirstMatch(findPromiseApp) == null);
+ launcher.getWorkspace().getFirstMatch(findPromiseApp) == null,
+ PROMISE_ICON_TIMEOUT);
}
}
diff --git a/tests/src/com/android/launcher3/deviceemulator/DisplayEmulator.java b/tests/src/com/android/launcher3/deviceemulator/DisplayEmulator.java
new file mode 100644
index 0000000..31468c5
--- /dev/null
+++ b/tests/src/com/android/launcher3/deviceemulator/DisplayEmulator.java
@@ -0,0 +1,95 @@
+/*
+ * 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.deviceemulator;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.net.Uri;
+import android.os.UserHandle;
+import android.view.Display;
+import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
+
+import androidx.test.uiautomator.UiDevice;
+
+import com.android.launcher3.deviceemulator.models.DeviceEmulationData;
+import com.android.launcher3.tapl.LauncherInstrumentation;
+import com.android.launcher3.util.window.WindowManagerProxy;
+
+import java.util.concurrent.Callable;
+
+
+public class DisplayEmulator {
+ Context mContext;
+ LauncherInstrumentation mLauncher;
+ DisplayEmulator(Context context, LauncherInstrumentation launcher) {
+ mContext = context;
+ mLauncher = launcher;
+ }
+
+ /**
+ * By changing the WindowManagerProxy we can override the window insets information
+ **/
+ private IWindowManager changeWindowManagerInstance(DeviceEmulationData deviceData) {
+ WindowManagerProxy.INSTANCE.initializeForTesting(
+ new TestWindowManagerProxy(mContext, deviceData));
+ return WindowManagerGlobal.getWindowManagerService();
+ }
+
+ public <T> T emulate(DeviceEmulationData device, String grid, Callable<T> runInEmulation)
+ throws Exception {
+ WindowManagerProxy original = WindowManagerProxy.INSTANCE.get(mContext);
+ // Set up emulation
+ final int userId = UserHandle.myUserId();
+ WindowManagerProxy.INSTANCE.initializeForTesting(
+ new TestWindowManagerProxy(mContext, device));
+ IWindowManager wm = changeWindowManagerInstance(device);
+ // Change density twice to force display controller to reset its state
+ wm.setForcedDisplayDensityForUser(Display.DEFAULT_DISPLAY, device.density / 2, userId);
+ wm.setForcedDisplayDensityForUser(Display.DEFAULT_DISPLAY, device.density, userId);
+ wm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, device.width, device.height);
+ wm.setForcedDisplayScalingMode(Display.DEFAULT_DISPLAY, 1);
+
+ // Set up grid
+ setGrid(grid);
+ try {
+ return runInEmulation.call();
+ } finally {
+ // Clear emulation
+ WindowManagerProxy.INSTANCE.initializeForTesting(original);
+ UiDevice.getInstance(getInstrumentation()).executeShellCommand("cmd window reset");
+ }
+ }
+
+ private void setGrid(String gridType) {
+ // When the grid changes, the desktop arrangement get stored in SQL and we need to wait to
+ // make sure there is no SQL operations running and get SQL_BUSY error, that's why we need
+ // to call mLauncher.waitForLauncherInitialized();
+ mLauncher.waitForLauncherInitialized();
+ String testProviderAuthority = mContext.getPackageName() + ".grid_control";
+ Uri gridUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(testProviderAuthority)
+ .appendPath("default_grid")
+ .build();
+ ContentValues values = new ContentValues();
+ values.put("name", gridType);
+ mContext.getContentResolver().update(gridUri, values, null, null);
+ }
+}
diff --git a/tests/src/com/android/launcher3/deviceemulator/TestWindowManagerProxy.java b/tests/src/com/android/launcher3/deviceemulator/TestWindowManagerProxy.java
new file mode 100644
index 0000000..cbea688
--- /dev/null
+++ b/tests/src/com/android/launcher3/deviceemulator/TestWindowManagerProxy.java
@@ -0,0 +1,80 @@
+/*
+ * 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.deviceemulator;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.view.Display;
+import android.view.WindowInsets;
+
+import com.android.launcher3.deviceemulator.models.DeviceEmulationData;
+import com.android.launcher3.util.RotationUtils;
+import com.android.launcher3.util.WindowBounds;
+import com.android.launcher3.util.window.CachedDisplayInfo;
+import com.android.launcher3.util.window.WindowManagerProxy;
+
+public class TestWindowManagerProxy extends WindowManagerProxy {
+
+ private final DeviceEmulationData mDevice;
+
+ public TestWindowManagerProxy(Context context, DeviceEmulationData device) {
+ super(true);
+ mDevice = device;
+ }
+
+ @Override
+ public boolean isInternalDisplay(Display display) {
+ return display.getDisplayId() == Display.DEFAULT_DISPLAY;
+ }
+
+ @Override
+ protected int getDimenByName(Resources res, String resName) {
+ Integer mock = mDevice.resourceOverrides.get(resName);
+ return mock != null ? mock : super.getDimenByName(res, resName);
+ }
+
+ @Override
+ protected int getDimenByName(Resources res, String resName, String fallback) {
+ return getDimenByName(res, resName);
+ }
+
+ @Override
+ public CachedDisplayInfo getDisplayInfo(Context context, Display display) {
+ int rotation = display.getRotation();
+ Point size = new Point(mDevice.width, mDevice.height);
+ RotationUtils.rotateSize(size, rotation);
+ Rect cutout = new Rect(mDevice.cutout);
+ RotationUtils.rotateRect(cutout, rotation);
+ return new CachedDisplayInfo(getDisplayId(display), size, rotation, cutout);
+ }
+
+ @Override
+ public WindowBounds getRealBounds(Context windowContext, Display display,
+ CachedDisplayInfo info) {
+ return estimateInternalDisplayBounds(windowContext)
+ .get(getDisplayId(display)).second[display.getRotation()];
+ }
+
+ @Override
+ public WindowInsets normalizeWindowInsets(Context context, WindowInsets oldInsets,
+ Rect outInsets) {
+ outInsets.set(getRealBounds(context, context.getDisplay(),
+ getDisplayInfo(context, context.getDisplay())).insets);
+ return oldInsets;
+ }
+}
diff --git a/tests/src/com/android/launcher3/deviceemulator/models/DeviceEmulationData.java b/tests/src/com/android/launcher3/deviceemulator/models/DeviceEmulationData.java
new file mode 100644
index 0000000..8d275cc
--- /dev/null
+++ b/tests/src/com/android/launcher3/deviceemulator/models/DeviceEmulationData.java
@@ -0,0 +1,154 @@
+/*
+ * 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.deviceemulator.models;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.launcher3.ResourceUtils.NAVBAR_HEIGHT;
+import static com.android.launcher3.ResourceUtils.NAVBAR_HEIGHT_LANDSCAPE;
+import static com.android.launcher3.ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE;
+import static com.android.launcher3.ResourceUtils.getDimenByName;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.os.Build;
+import android.util.ArrayMap;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.IOUtils;
+import com.android.launcher3.util.IntArray;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Map;
+
+public class DeviceEmulationData {
+
+ public final int width;
+ public final int height;
+ public final int density;
+ public final String name;
+ public final String[] grids;
+ public final Rect cutout;
+ public final Map<String, Integer> resourceOverrides;
+
+ private static final String[] EMULATED_SYSTEM_RESOURCES = new String[]{
+ NAVBAR_HEIGHT,
+ NAVBAR_HEIGHT_LANDSCAPE,
+ NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE,
+ "status_bar_height",
+ };
+
+ public DeviceEmulationData(int width, int height, int density, Rect cutout, String name,
+ String[] grid,
+ Map<String, Integer> resourceOverrides) {
+ this.width = width;
+ this.height = height;
+ this.density = density;
+ this.name = name;
+ this.grids = grid;
+ this.cutout = cutout;
+ this.resourceOverrides = resourceOverrides;
+ }
+
+ public static DeviceEmulationData deviceFromJSON(JSONObject json) throws JSONException {
+ int width = json.getInt("width");
+ int height = json.getInt("height");
+ int density = json.getInt("density");
+ String name = json.getString("name");
+
+ JSONArray gridArray = json.getJSONArray("grids");
+ String[] grids = new String[gridArray.length()];
+ for (int i = 0, count = grids.length; i < count; i++) {
+ grids[i] = gridArray.getString(i);
+ }
+
+ IntArray deviceCutout = IntArray.fromConcatString(json.getString("cutout"));
+ Rect cutout = new Rect(deviceCutout.get(0), deviceCutout.get(1), deviceCutout.get(2),
+ deviceCutout.get(3));
+
+
+ JSONObject resourceOverridesJson = json.getJSONObject("resourceOverrides");
+ Map<String, Integer> resourceOverrides = new ArrayMap<>();
+ for (String key : resourceOverridesJson.keySet()) {
+ resourceOverrides.put(key, resourceOverridesJson.getInt(key));
+ }
+ return new DeviceEmulationData(width, height, density, cutout, name, grids,
+ resourceOverrides);
+ }
+
+ @Override
+ public String toString() {
+ JSONObject json = new JSONObject();
+ try {
+ json.put("width", width);
+ json.put("height", height);
+ json.put("density", density);
+ json.put("name", name);
+ json.put("cutout", IntArray.wrap(
+ cutout.left, cutout.top, cutout.right, cutout.bottom).toConcatString());
+
+ JSONArray gridArray = new JSONArray();
+ Arrays.stream(grids).forEach(gridArray::put);
+ json.put("grids", gridArray);
+
+
+ JSONObject resourceOverrides = new JSONObject();
+ for (Map.Entry<String, Integer> e : this.resourceOverrides.entrySet()) {
+ resourceOverrides.put(e.getKey(), e.getValue());
+ }
+ json.put("resourceOverrides", resourceOverrides);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return json.toString();
+ }
+
+ public static DeviceEmulationData getCurrentDeviceData(Context context) {
+ DisplayController.Info info = DisplayController.INSTANCE.get(context).getInfo();
+ String[] grids = InvariantDeviceProfile.INSTANCE.get(context)
+ .parseAllGridOptions(context).stream()
+ .map(go -> go.name).toArray(String[]::new);
+ String code = Build.MODEL.replaceAll("\\s", "").toLowerCase();
+
+ Map<String, Integer> resourceOverrides = new ArrayMap<>();
+ for (String s : EMULATED_SYSTEM_RESOURCES) {
+ resourceOverrides.put(s, getDimenByName(s, context.getResources(), 0));
+ }
+ return new DeviceEmulationData(info.currentSize.x, info.currentSize.y,
+ info.getDensityDpi(), info.cutout, code, grids, resourceOverrides);
+ }
+
+ public static DeviceEmulationData getDevice(String deviceCode) throws Exception {
+ return DeviceEmulationData.deviceFromJSON(readJSON().getJSONObject(deviceCode));
+ }
+
+ private static JSONObject readJSON() throws Exception {
+ Context context = getInstrumentation().getContext();
+ Resources myRes = context.getResources();
+ int resId = myRes.getIdentifier("devices", "raw", context.getPackageName());
+ try (InputStream is = myRes.openRawResource(resId)) {
+ return new JSONObject(new String(IOUtils.toByteArray(is)));
+ }
+ }
+
+}
diff --git a/tests/src/com/android/launcher3/folder/FolderNameProviderTest.java b/tests/src/com/android/launcher3/folder/FolderNameProviderTest.java
index 23e6235..9c15309 100644
--- a/tests/src/com/android/launcher3/folder/FolderNameProviderTest.java
+++ b/tests/src/com/android/launcher3/folder/FolderNameProviderTest.java
@@ -30,6 +30,7 @@
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.util.ActivityContextWrapper;
import com.android.launcher3.util.Executors;
import org.junit.Before;
@@ -47,7 +48,7 @@
@Before
public void setUp() {
- mContext = getApplicationContext();
+ mContext = new ActivityContextWrapper(getApplicationContext());
mItem1 = new WorkspaceItemInfo(new AppInfo(
new ComponentName("a.b.c", "a.b.c/a.b.c.d"),
"title1",
diff --git a/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt b/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt
new file mode 100644
index 0000000..d26381d
--- /dev/null
+++ b/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt
@@ -0,0 +1,162 @@
+/*
+ * 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.model
+
+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.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.LauncherModelHelper
+import java.util.UUID
+
+/**
+ * Base class for workspace related tests.
+ */
+abstract class AbstractWorkspaceModelTest {
+ companion object {
+ val emptyScreenSpaces = listOf(Rect(0, 0, 5, 5))
+ val fullScreenSpaces = emptyList<Rect>()
+ val nonEmptyScreenSpaces = listOf(Rect(1, 2, 3, 4))
+ }
+
+ protected lateinit var mTargetContext: Context
+ protected lateinit var mIdp: InvariantDeviceProfile
+ protected lateinit var mAppState: LauncherAppState
+ protected lateinit var mModelHelper: LauncherModelHelper
+ protected lateinit var mExistingScreens: IntArray
+ protected lateinit var mNewScreens: IntArray
+ protected lateinit var mScreenOccupancy: IntSparseArrayMap<GridOccupancy>
+
+ open fun setup() {
+ mModelHelper = LauncherModelHelper()
+ mTargetContext = mModelHelper.sandboxContext
+ mIdp = InvariantDeviceProfile.INSTANCE[mTargetContext]
+ mIdp.numRows = 5
+ mIdp.numColumns = mIdp.numRows
+ mAppState = LauncherAppState.getInstance(mTargetContext)
+ mExistingScreens = IntArray()
+ mScreenOccupancy = IntSparseArrayMap()
+ mNewScreens = IntArray()
+ }
+
+ open fun tearDown() {
+ mModelHelper.destroy()
+ }
+
+
+ /**
+ * 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)
+ }
+ }
+
+ /**
+ * Sets up the given workspaces with the given spaces, and fills the remaining space with items.
+ */
+ fun setupWorkspacesWithSpaces(
+ screen0: List<Rect>? = null,
+ screen1: List<Rect>? = null,
+ screen2: List<Rect>? = null,
+ screen3: List<Rect>? = null,
+ ) = listOf(screen0, screen1, screen2, screen3)
+ .let(this::setupWithSpaces)
+
+ private fun setupWithSpaces(workspaceSpaces: List<List<Rect>?>) {
+ var nextItemId = 1
+ workspaceSpaces.forEachIndexed { screenId, spaces ->
+ if (spaces != null) {
+ nextItemId = setupWorkspace(nextItemId, 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
+ val occupancy = GridOccupancy(mIdp.numColumns, mIdp.numRows)
+ occupancy.markCells(0, 0, mIdp.numColumns, mIdp.numRows, true)
+ spaces.forEach { spaceRect ->
+ occupancy.markCells(spaceRect, false)
+ }
+ mExistingScreens.add(screenId)
+ mScreenOccupancy.append(screenId, occupancy)
+ for (x in 0 until mIdp.numColumns) {
+ for (y in 0 until mIdp.numRows) {
+ if (!occupancy.cells[x][y]) {
+ continue
+ }
+ 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")) }
+
+ fun getNewItem(): WorkspaceItemInfo {
+ val itemPackage = UUID.randomUUID().toString()
+ return WorkspaceItemInfo()
+ .apply { intent = Intent().setComponent(ComponentName(itemPackage, itemPackage)) }
+ }
+}
+
+data class NewItemSpace(
+ val screenId: Int,
+ val cellX: Int,
+ val cellY: Int
+) {
+ fun toIntArray() = intArrayOf(screenId, cellX, cellY)
+
+ companion object {
+ fun fromIntArray(array: kotlin.IntArray) = NewItemSpace(array[0], array[1], array[2])
+ }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
deleted file mode 100644
index 8a4590a..0000000
--- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
+++ /dev/null
@@ -1,201 +0,0 @@
-package com.android.launcher3.model;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Rect;
-import android.util.Pair;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.model.BgDataModel.Callbacks;
-import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.util.ContentWriter;
-import com.android.launcher3.util.Executors;
-import com.android.launcher3.util.GridOccupancy;
-import com.android.launcher3.util.IntArray;
-import com.android.launcher3.util.IntSparseArrayMap;
-import com.android.launcher3.util.LauncherModelHelper;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Tests for {@link AddWorkspaceItemsTask}
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class AddWorkspaceItemsTaskTest {
-
- private final ComponentName mComponent1 = new ComponentName("a", "b");
- private final ComponentName mComponent2 = new ComponentName("b", "b");
-
- private Context mTargetContext;
- private InvariantDeviceProfile mIdp;
- private LauncherAppState mAppState;
- private LauncherModelHelper mModelHelper;
-
- private IntArray mExistingScreens;
- private IntArray mNewScreens;
- private IntSparseArrayMap<GridOccupancy> mScreenOccupancy;
-
- @Before
- public void setup() {
- mModelHelper = new LauncherModelHelper();
- mTargetContext = mModelHelper.sandboxContext;
- mIdp = InvariantDeviceProfile.INSTANCE.get(mTargetContext);
- mIdp.numColumns = mIdp.numRows = 5;
- mAppState = LauncherAppState.getInstance(mTargetContext);
-
- mExistingScreens = new IntArray();
- mScreenOccupancy = new IntSparseArrayMap<>();
- mNewScreens = new IntArray();
- }
-
- @After
- public void tearDown() {
- mModelHelper.destroy();
- }
-
- private AddWorkspaceItemsTask newTask(ItemInfo... items) {
- List<Pair<ItemInfo, Object>> list = new ArrayList<>();
- for (ItemInfo item : items) {
- list.add(Pair.create(item, null));
- }
- return new AddWorkspaceItemsTask(list);
- }
-
- @Test
- public void testFindSpaceForItem_prefers_second() throws Exception {
- // First screen has only one hole of size 1
- int nextId = setupWorkspaceWithHoles(1, 1, new Rect(2, 2, 3, 3));
-
- // Second screen has 2 holes of sizes 3x2 and 2x3
- setupWorkspaceWithHoles(nextId, 2, new Rect(2, 0, 5, 2), new Rect(0, 2, 2, 5));
-
- int[] spaceFound = newTask().findSpaceForItem(
- mAppState, mModelHelper.getBgDataModel(), mExistingScreens, mNewScreens, 1, 1);
- assertEquals(1, spaceFound[0]);
- assertTrue(mScreenOccupancy.get(spaceFound[0])
- .isRegionVacant(spaceFound[1], spaceFound[2], 1, 1));
-
- // Find a larger space
- spaceFound = newTask().findSpaceForItem(
- mAppState, mModelHelper.getBgDataModel(), mExistingScreens, mNewScreens, 2, 3);
- assertEquals(2, spaceFound[0]);
- assertTrue(mScreenOccupancy.get(spaceFound[0])
- .isRegionVacant(spaceFound[1], spaceFound[2], 2, 3));
- }
-
- @Test
- public void testFindSpaceForItem_adds_new_screen() throws Exception {
- // First screen has 2 holes of sizes 3x2 and 2x3
- setupWorkspaceWithHoles(1, 1, new Rect(2, 0, 5, 2), new Rect(0, 2, 2, 5));
-
- IntArray oldScreens = mExistingScreens.clone();
- int[] spaceFound = newTask().findSpaceForItem(
- mAppState, mModelHelper.getBgDataModel(), mExistingScreens, mNewScreens, 3, 3);
- assertFalse(oldScreens.contains(spaceFound[0]));
- assertTrue(mNewScreens.contains(spaceFound[0]));
- }
-
- @Test
- public void testAddItem_existing_item_ignored() throws Exception {
- WorkspaceItemInfo info = new WorkspaceItemInfo();
- info.intent = new Intent().setComponent(mComponent1);
-
- // Setup a screen with a hole
- setupWorkspaceWithHoles(1, 1, new Rect(2, 2, 3, 3));
-
- // Nothing was added
- assertTrue(mModelHelper.executeTaskForTest(newTask(info)).isEmpty());
- }
-
- @Test
- public void testAddItem_some_items_added() throws Exception {
- Callbacks callbacks = mock(Callbacks.class);
- Executors.MAIN_EXECUTOR.submit(() -> mModelHelper.getModel().addCallbacks(callbacks)).get();
-
- WorkspaceItemInfo info = new WorkspaceItemInfo();
- info.intent = new Intent().setComponent(mComponent1);
-
- WorkspaceItemInfo info2 = new WorkspaceItemInfo();
- info2.intent = new Intent().setComponent(mComponent2);
-
- // Setup a screen with a hole
- setupWorkspaceWithHoles(1, 1, new Rect(2, 2, 3, 3));
-
- mModelHelper.executeTaskForTest(newTask(info, info2)).get(0).run();
- ArgumentCaptor<ArrayList> notAnimated = ArgumentCaptor.forClass(ArrayList.class);
- ArgumentCaptor<ArrayList> animated = ArgumentCaptor.forClass(ArrayList.class);
-
- // only info2 should be added because info was already added to the workspace
- // in setupWorkspaceWithHoles()
- verify(callbacks).bindAppsAdded(any(IntArray.class), notAnimated.capture(),
- animated.capture());
- assertTrue(notAnimated.getValue().isEmpty());
-
- assertEquals(1, animated.getValue().size());
- assertTrue(animated.getValue().contains(info2));
- }
-
- private int setupWorkspaceWithHoles(int startId, int screenId, Rect... holes) throws Exception {
- return mModelHelper.executeSimpleTask(
- model -> writeWorkspaceWithHoles(model, startId, screenId, holes));
- }
-
- private int writeWorkspaceWithHoles(
- BgDataModel bgDataModel, int startId, int screenId, Rect... holes) {
- GridOccupancy occupancy = new GridOccupancy(mIdp.numColumns, mIdp.numRows);
- occupancy.markCells(0, 0, mIdp.numColumns, mIdp.numRows, true);
- for (Rect r : holes) {
- occupancy.markCells(r, false);
- }
-
- mExistingScreens.add(screenId);
- mScreenOccupancy.append(screenId, occupancy);
-
- for (int x = 0; x < mIdp.numColumns; x++) {
- for (int y = 0; y < mIdp.numRows; y++) {
- if (!occupancy.cells[x][y]) {
- continue;
- }
-
- WorkspaceItemInfo info = new WorkspaceItemInfo();
- info.intent = new Intent().setComponent(mComponent1);
- info.id = startId++;
- info.screenId = screenId;
- info.cellX = x;
- info.cellY = y;
- info.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
- bgDataModel.addItem(mTargetContext, info, false);
-
- ContentWriter writer = new ContentWriter(mTargetContext);
- info.writeToValues(writer);
- writer.put(Favorites._ID, info.id);
- mTargetContext.getContentResolver().insert(Favorites.CONTENT_URI,
- writer.getValues(mTargetContext));
- }
- }
- return startId;
- }
-}
diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
new file mode 100644
index 0000000..65d938b
--- /dev/null
+++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
@@ -0,0 +1,245 @@
+/*
+ * 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.model
+
+import android.util.Pair
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.model.data.WorkspaceItemInfo
+import com.android.launcher3.util.Executors
+import com.android.launcher3.util.IntArray
+import com.android.launcher3.util.same
+import com.android.launcher3.util.eq
+import com.android.launcher3.util.any
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+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.MockitoAnnotations
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.Mockito.times
+import org.mockito.Mockito.`when` as whenever
+
+/**
+ * Tests for [AddWorkspaceItemsTask]
+ */
+@SmallTest
+@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
+
+ @Mock
+ private lateinit var mWorkspaceItemSpaceFinder: WorkspaceItemSpaceFinder
+
+
+ @Before
+ override fun setup() {
+ super.setup()
+ MockitoAnnotations.initMocks(this)
+ Executors.MAIN_EXECUTOR.submit { mModelHelper.model.addCallbacks(mDataModelCallbacks) }
+ .get()
+ }
+
+ @After
+ override fun tearDown() {
+ super.tearDown()
+ }
+
+ @Test
+ fun givenNewItemAndNonEmptyPages_whenExecuteTask_thenAddNewItem() {
+ val itemToAdd = getNewItem()
+ val nonEmptyScreenIds = listOf(0, 1, 2)
+ givenNewItemSpaces(NewItemSpace(1, 2, 2))
+
+ val addedItems = testAddItems(nonEmptyScreenIds, itemToAdd)
+
+ assertThat(addedItems.size).isEqualTo(1)
+ assertThat(addedItems.first().itemInfo.screenId).isEqualTo(1)
+ assertThat(addedItems.first().isAnimated).isTrue()
+ verifyItemSpaceFinderCall(nonEmptyScreenIds, numberOfExpectedCall = 1)
+ }
+
+ @Test
+ fun givenNewAndExistingItems_whenExecuteTask_thenOnlyAddNewItem() {
+ val itemsToAdd = arrayOf(
+ getNewItem(),
+ getExistingItem()
+ )
+ givenNewItemSpaces(NewItemSpace(1, 0, 0))
+ val nonEmptyScreenIds = listOf(0)
+
+ val addedItems = testAddItems(nonEmptyScreenIds, *itemsToAdd)
+
+ assertThat(addedItems.size).isEqualTo(1)
+ assertThat(addedItems.first().itemInfo.screenId).isEqualTo(1)
+ assertThat(addedItems.first().isAnimated).isTrue()
+ verifyItemSpaceFinderCall(nonEmptyScreenIds, numberOfExpectedCall = 1)
+ }
+
+ @Test
+ fun givenOnlyExistingItem_whenExecuteTask_thenDoNotAddItem() {
+ val itemToAdd = getExistingItem()
+ givenNewItemSpaces(NewItemSpace(1, 0, 0))
+ val nonEmptyScreenIds = listOf(0)
+
+ val addedItems = testAddItems(nonEmptyScreenIds, itemToAdd)
+
+ assertThat(addedItems.size).isEqualTo(0)
+ verifyZeroInteractions(mWorkspaceItemSpaceFinder, mDataModelCallbacks)
+ }
+
+ @Test
+ fun givenNonSequentialScreenIds_whenExecuteTask_thenReturnNewScreenId() {
+ val itemToAdd = getNewItem()
+ givenNewItemSpaces(NewItemSpace(2, 1, 3))
+ val nonEmptyScreenIds = listOf(0, 2, 3)
+
+ val addedItems = testAddItems(nonEmptyScreenIds, itemToAdd)
+
+ assertThat(addedItems.size).isEqualTo(1)
+ assertThat(addedItems.first().itemInfo.screenId).isEqualTo(2)
+ assertThat(addedItems.first().isAnimated).isTrue()
+ verifyItemSpaceFinderCall(nonEmptyScreenIds, numberOfExpectedCall = 1)
+ }
+
+ @Test
+ fun givenMultipleItems_whenExecuteTask_thenAddThem() {
+ val itemsToAdd = arrayOf(
+ getNewItem(),
+ getExistingItem(),
+ getNewItem(),
+ getNewItem(),
+ getExistingItem(),
+ )
+ givenNewItemSpaces(
+ NewItemSpace(1, 3, 3),
+ NewItemSpace(2, 0, 0),
+ NewItemSpace(2, 0, 1),
+ )
+ val nonEmptyScreenIds = listOf(0, 1)
+
+ val addedItems = testAddItems(nonEmptyScreenIds, *itemsToAdd)
+
+ // Only the new items should be added
+ assertThat(addedItems.size).isEqualTo(3)
+
+ // Items that are added to the first screen should not be animated
+ val itemsAddedToFirstScreen = addedItems.filter { it.itemInfo.screenId == 1 }
+ assertThat(itemsAddedToFirstScreen.size).isEqualTo(1)
+ assertThat(itemsAddedToFirstScreen.first().isAnimated).isFalse()
+
+ // Items that are added to the second screen should be animated
+ val itemsAddedToSecondScreen = addedItems.filter { it.itemInfo.screenId == 2 }
+ assertThat(itemsAddedToSecondScreen.size).isEqualTo(2)
+ itemsAddedToSecondScreen.forEach {
+ assertThat(it.isAnimated).isTrue()
+ }
+ verifyItemSpaceFinderCall(nonEmptyScreenIds, numberOfExpectedCall = 3)
+ }
+
+ /**
+ * Sets up the item space data that will be returned from WorkspaceItemSpaceFinder.
+ */
+ private fun givenNewItemSpaces(vararg newItemSpaces: NewItemSpace) {
+ val spaceStack = newItemSpaces.toMutableList()
+ whenever(
+ mWorkspaceItemSpaceFinder.findSpaceForItem(
+ any(),
+ any(),
+ any(),
+ any(),
+ any(),
+ any()
+ )
+ )
+ .then { spaceStack.removeFirst().toIntArray() }
+ }
+
+ /**
+ * Verifies if WorkspaceItemSpaceFinder was called with proper arguments and how many times was
+ * it called.
+ */
+ private fun verifyItemSpaceFinderCall(
+ nonEmptyScreenIds: List<Int>,
+ numberOfExpectedCall: Int
+ ) {
+ verify(mWorkspaceItemSpaceFinder, times(numberOfExpectedCall))
+ .findSpaceForItem(
+ same(mAppState), same(mModelHelper.bgDataModel),
+ eq(IntArray.wrap(*nonEmptyScreenIds.toIntArray())), eq(IntArray()), eq(1), eq(1)
+ )
+ }
+
+ /**
+ * Sets up the workspaces with items, executes the task, collects the added items from the
+ * model callback then returns it.
+ */
+ private fun testAddItems(
+ nonEmptyScreenIds: List<Int>,
+ vararg itemsToAdd: WorkspaceItemInfo
+ ): 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) })
+
+ }
+
+ return addedItems
+ }
+
+ /**
+ * Creates the task with the given items and replaces the WorkspaceItemSpaceFinder dependency
+ * with a mock.
+ */
+ private fun newTask(vararg items: ItemInfo): AddWorkspaceItemsTask =
+ items.map { Pair.create(it, Any()) }
+ .toMutableList()
+ .let { AddWorkspaceItemsTask(it, mWorkspaceItemSpaceFinder) }
+}
+
+private data class AddedItem(
+ val itemInfo: ItemInfo,
+ val isAnimated: Boolean
+)
diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.java b/tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.java
deleted file mode 100644
index 005389e..0000000
--- a/tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.model;
-
-import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP;
-import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
-import static com.android.launcher3.LauncherSettings.Favorites.TMP_CONTENT_URI;
-import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
-import static com.android.launcher3.util.LauncherModelHelper.APP_ICON;
-import static com.android.launcher3.util.LauncherModelHelper.DESKTOP;
-import static com.android.launcher3.util.LauncherModelHelper.HOTSEAT;
-import static com.android.launcher3.util.LauncherModelHelper.SHORTCUT;
-import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.graphics.Point;
-import android.os.Process;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.pm.UserCache;
-import com.android.launcher3.util.LauncherModelHelper;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.HashMap;
-import java.util.HashSet;
-
-/** Unit tests for {@link GridSizeMigrationTaskV2} */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class GridSizeMigrationTaskV2Test {
-
- private LauncherModelHelper mModelHelper;
- private Context mContext;
- private SQLiteDatabase mDb;
-
- private HashSet<String> mValidPackages;
- private InvariantDeviceProfile mIdp;
-
- private final String testPackage1 = "com.android.launcher3.validpackage1";
- private final String testPackage2 = "com.android.launcher3.validpackage2";
- private final String testPackage3 = "com.android.launcher3.validpackage3";
- private final String testPackage4 = "com.android.launcher3.validpackage4";
- private final String testPackage5 = "com.android.launcher3.validpackage5";
- private final String testPackage6 = "com.android.launcher3.validpackage6";
- private final String testPackage7 = "com.android.launcher3.validpackage7";
- private final String testPackage8 = "com.android.launcher3.validpackage8";
- private final String testPackage9 = "com.android.launcher3.validpackage9";
- private final String testPackage10 = "com.android.launcher3.validpackage10";
-
- @Before
- public void setUp() {
- mModelHelper = new LauncherModelHelper();
- mContext = mModelHelper.sandboxContext;
- mDb = mModelHelper.provider.getDb();
-
- mValidPackages = new HashSet<>();
- mValidPackages.add(TEST_PACKAGE);
- mValidPackages.add(testPackage1);
- mValidPackages.add(testPackage2);
- mValidPackages.add(testPackage3);
- mValidPackages.add(testPackage4);
- mValidPackages.add(testPackage5);
- mValidPackages.add(testPackage6);
- mValidPackages.add(testPackage7);
- mValidPackages.add(testPackage8);
- mValidPackages.add(testPackage9);
- mValidPackages.add(testPackage10);
-
- mIdp = InvariantDeviceProfile.INSTANCE.get(mContext);
-
- long userSerial = UserCache.INSTANCE.get(mContext).getSerialNumberForUser(
- Process.myUserHandle());
- dropTable(mDb, LauncherSettings.Favorites.TMP_TABLE);
- LauncherSettings.Favorites.addTableToDb(mDb, userSerial, false,
- LauncherSettings.Favorites.TMP_TABLE);
- }
-
- @After
- public void tearDown() {
- mModelHelper.destroy();
- }
-
- @Test
- public void testMigration() throws Exception {
- int[] srcHotseatItems = {
- mModelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI),
- mModelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI),
- -1,
- mModelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI),
- mModelHelper.addItem(APP_ICON, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI),
- };
- mModelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage5, 5, TMP_CONTENT_URI);
- mModelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage6, 6, TMP_CONTENT_URI);
- mModelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 1, testPackage8, 8, TMP_CONTENT_URI);
- mModelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 2, testPackage9, 9, TMP_CONTENT_URI);
- mModelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 3, testPackage10, 10, TMP_CONTENT_URI);
-
- int[] destHotseatItems = {
- -1,
- mModelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2),
- -1,
- };
- mModelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage7);
-
- mIdp.numDatabaseHotseatIcons = 4;
- mIdp.numColumns = 4;
- mIdp.numRows = 4;
- GridSizeMigrationTaskV2.DbReader srcReader = new GridSizeMigrationTaskV2.DbReader(mDb,
- LauncherSettings.Favorites.TMP_TABLE, mContext, mValidPackages);
- GridSizeMigrationTaskV2.DbReader destReader = new GridSizeMigrationTaskV2.DbReader(mDb,
- LauncherSettings.Favorites.TABLE_NAME, mContext, mValidPackages);
- GridSizeMigrationTaskV2 task = new GridSizeMigrationTaskV2(mContext, mDb, srcReader,
- destReader, mIdp.numDatabaseHotseatIcons, new Point(mIdp.numColumns, mIdp.numRows));
- task.migrate(mIdp);
-
- // Check hotseat items
- Cursor c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
- new String[]{LauncherSettings.Favorites.SCREEN, LauncherSettings.Favorites.INTENT},
- "container=" + CONTAINER_HOTSEAT, null, LauncherSettings.Favorites.SCREEN, null);
- assertEquals(c.getCount(), mIdp.numDatabaseHotseatIcons);
- int screenIndex = c.getColumnIndex(LauncherSettings.Favorites.SCREEN);
- int intentIndex = c.getColumnIndex(LauncherSettings.Favorites.INTENT);
- c.moveToNext();
- assertEquals(c.getInt(screenIndex), 0);
- assertTrue(c.getString(intentIndex).contains(testPackage1));
- c.moveToNext();
- assertEquals(c.getInt(screenIndex), 1);
- assertTrue(c.getString(intentIndex).contains(testPackage2));
- c.moveToNext();
- assertEquals(c.getInt(screenIndex), 2);
- assertTrue(c.getString(intentIndex).contains(testPackage3));
- c.moveToNext();
- assertEquals(c.getInt(screenIndex), 3);
- assertTrue(c.getString(intentIndex).contains(testPackage4));
- c.close();
-
- // Check workspace items
- c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
- new String[]{LauncherSettings.Favorites.CELLX, LauncherSettings.Favorites.CELLY,
- LauncherSettings.Favorites.INTENT},
- "container=" + CONTAINER_DESKTOP, null, null, null);
- intentIndex = c.getColumnIndex(LauncherSettings.Favorites.INTENT);
- int cellXIndex = c.getColumnIndex(LauncherSettings.Favorites.CELLX);
- int cellYIndex = c.getColumnIndex(LauncherSettings.Favorites.CELLY);
-
- HashMap<String, Point> locMap = new HashMap<>();
- while (c.moveToNext()) {
- locMap.put(
- Intent.parseUri(c.getString(intentIndex), 0).getPackage(),
- new Point(c.getInt(cellXIndex), c.getInt(cellYIndex)));
- }
- c.close();
-
- assertEquals(locMap.size(), 6);
- assertEquals(new Point(0, 2), locMap.get(testPackage8));
- assertEquals(new Point(0, 3), locMap.get(testPackage6));
- assertEquals(new Point(1, 3), locMap.get(testPackage10));
- assertEquals(new Point(2, 3), locMap.get(testPackage5));
- assertEquals(new Point(3, 3), locMap.get(testPackage9));
- }
-
- @Test
- public void migrateToLargerHotseat() {
- int[] srcHotseatItems = {
- mModelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI),
- mModelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI),
- mModelHelper.addItem(APP_ICON, 2, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI),
- mModelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI),
- };
-
- int numSrcDatabaseHotseatIcons = srcHotseatItems.length;
- mIdp.numDatabaseHotseatIcons = 6;
- mIdp.numColumns = 4;
- mIdp.numRows = 4;
- GridSizeMigrationTaskV2.DbReader srcReader = new GridSizeMigrationTaskV2.DbReader(mDb,
- LauncherSettings.Favorites.TMP_TABLE, mContext, mValidPackages);
- GridSizeMigrationTaskV2.DbReader destReader = new GridSizeMigrationTaskV2.DbReader(mDb,
- LauncherSettings.Favorites.TABLE_NAME, mContext, mValidPackages);
- GridSizeMigrationTaskV2 task = new GridSizeMigrationTaskV2(mContext, mDb, srcReader,
- destReader, mIdp.numDatabaseHotseatIcons, new Point(mIdp.numColumns, mIdp.numRows));
- task.migrate(mIdp);
-
- // Check hotseat items
- Cursor c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
- new String[]{LauncherSettings.Favorites.SCREEN, LauncherSettings.Favorites.INTENT},
- "container=" + CONTAINER_HOTSEAT, null, LauncherSettings.Favorites.SCREEN, null);
- assertEquals(c.getCount(), numSrcDatabaseHotseatIcons);
- int screenIndex = c.getColumnIndex(LauncherSettings.Favorites.SCREEN);
- int intentIndex = c.getColumnIndex(LauncherSettings.Favorites.INTENT);
- c.moveToNext();
- assertEquals(c.getInt(screenIndex), 0);
- assertTrue(c.getString(intentIndex).contains(testPackage1));
- c.moveToNext();
- assertEquals(c.getInt(screenIndex), 1);
- assertTrue(c.getString(intentIndex).contains(testPackage2));
- c.moveToNext();
- assertEquals(c.getInt(screenIndex), 2);
- assertTrue(c.getString(intentIndex).contains(testPackage3));
- c.moveToNext();
- assertEquals(c.getInt(screenIndex), 3);
- assertTrue(c.getString(intentIndex).contains(testPackage4));
-
- c.close();
- }
-
- @Test
- public void migrateFromLargerHotseat() {
- int[] srcHotseatItems = {
- mModelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI),
- -1,
- mModelHelper.addItem(SHORTCUT, 2, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI),
- mModelHelper.addItem(APP_ICON, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI),
- mModelHelper.addItem(SHORTCUT, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI),
- mModelHelper.addItem(APP_ICON, 5, HOTSEAT, 0, 0, testPackage5, 5, TMP_CONTENT_URI),
- };
-
- mIdp.numDatabaseHotseatIcons = 4;
- mIdp.numColumns = 4;
- mIdp.numRows = 4;
- GridSizeMigrationTaskV2.DbReader srcReader = new GridSizeMigrationTaskV2.DbReader(mDb,
- LauncherSettings.Favorites.TMP_TABLE, mContext, mValidPackages);
- GridSizeMigrationTaskV2.DbReader destReader = new GridSizeMigrationTaskV2.DbReader(mDb,
- LauncherSettings.Favorites.TABLE_NAME, mContext, mValidPackages);
- GridSizeMigrationTaskV2 task = new GridSizeMigrationTaskV2(mContext, mDb, srcReader,
- destReader, mIdp.numDatabaseHotseatIcons, new Point(mIdp.numColumns, mIdp.numRows));
- task.migrate(mIdp);
-
- // Check hotseat items
- Cursor c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
- new String[]{LauncherSettings.Favorites.SCREEN, LauncherSettings.Favorites.INTENT},
- "container=" + CONTAINER_HOTSEAT, null, LauncherSettings.Favorites.SCREEN, null);
- assertEquals(c.getCount(), mIdp.numDatabaseHotseatIcons);
- int screenIndex = c.getColumnIndex(LauncherSettings.Favorites.SCREEN);
- int intentIndex = c.getColumnIndex(LauncherSettings.Favorites.INTENT);
- c.moveToNext();
- assertEquals(c.getInt(screenIndex), 0);
- assertTrue(c.getString(intentIndex).contains(testPackage1));
- c.moveToNext();
- assertEquals(c.getInt(screenIndex), 1);
- assertTrue(c.getString(intentIndex).contains(testPackage2));
- c.moveToNext();
- assertEquals(c.getInt(screenIndex), 2);
- assertTrue(c.getString(intentIndex).contains(testPackage3));
- c.moveToNext();
- assertEquals(c.getInt(screenIndex), 3);
- assertTrue(c.getString(intentIndex).contains(testPackage4));
-
- c.close();
- }
-}
diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.kt b/tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.kt
new file mode 100644
index 0000000..90d7b43
--- /dev/null
+++ b/tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.kt
@@ -0,0 +1,510 @@
+/*
+ * 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.model
+
+import android.content.Context
+import android.content.Intent
+import android.database.sqlite.SQLiteDatabase
+import android.graphics.Point
+import android.os.Process
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.InvariantDeviceProfile
+import com.android.launcher3.LauncherFiles
+import com.android.launcher3.LauncherSettings.Favorites.*
+import com.android.launcher3.config.FeatureFlags
+import com.android.launcher3.model.GridSizeMigrationTaskV2.DbReader
+import com.android.launcher3.pm.UserCache
+import com.android.launcher3.provider.LauncherDbUtils
+import com.android.launcher3.util.LauncherModelHelper
+import com.android.launcher3.util.LauncherModelHelper.*
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** Unit tests for [GridSizeMigrationTaskV2] */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class GridSizeMigrationTaskV2Test {
+ private lateinit var modelHelper: LauncherModelHelper
+ private lateinit var context: Context
+ private lateinit var db: SQLiteDatabase
+ private lateinit var validPackages: Set<String>
+ private lateinit var idp: InvariantDeviceProfile
+ private val testPackage1 = "com.android.launcher3.validpackage1"
+ private val testPackage2 = "com.android.launcher3.validpackage2"
+ private val testPackage3 = "com.android.launcher3.validpackage3"
+ private val testPackage4 = "com.android.launcher3.validpackage4"
+ private val testPackage5 = "com.android.launcher3.validpackage5"
+ private val testPackage6 = "com.android.launcher3.validpackage6"
+ private val testPackage7 = "com.android.launcher3.validpackage7"
+ private val testPackage8 = "com.android.launcher3.validpackage8"
+ private val testPackage9 = "com.android.launcher3.validpackage9"
+ private val testPackage10 = "com.android.launcher3.validpackage10"
+
+ @Before
+ fun setUp() {
+ modelHelper = LauncherModelHelper()
+ context = modelHelper.sandboxContext
+ db = modelHelper.provider.db
+
+ validPackages = setOf(
+ TEST_PACKAGE,
+ testPackage1,
+ testPackage2,
+ testPackage3,
+ testPackage4,
+ testPackage5,
+ testPackage6,
+ testPackage7,
+ testPackage8,
+ testPackage9,
+ testPackage10
+ )
+
+ idp = InvariantDeviceProfile.INSTANCE[context]
+ val userSerial = UserCache.INSTANCE[context].getSerialNumberForUser(Process.myUserHandle())
+ LauncherDbUtils.dropTable(db, TMP_TABLE)
+ addTableToDb(db, userSerial, false, TMP_TABLE)
+ }
+
+ @After
+ fun tearDown() {
+ modelHelper.destroy()
+ }
+
+ /**
+ * Old migration logic, should be modified once [FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC] is
+ * not needed anymore
+ */
+ @Test
+ @Throws(Exception::class)
+ fun testMigration() {
+ // Src Hotseat icons
+ modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
+ // Src grid icons
+ // _ _ _ _ _
+ // _ _ _ _ 5
+ // _ _ 6 _ 7
+ // _ _ 8 _ 9
+ // _ _ _ _ _
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 1, testPackage5, 5, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage6, 6, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 2, testPackage7, 7, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage8, 8, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 3, testPackage9, 9, TMP_CONTENT_URI)
+
+ // Dest hotseat icons
+ modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2)
+ // Dest grid icons
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage10)
+
+ idp.numDatabaseHotseatIcons = 4
+ idp.numColumns = 4
+ idp.numRows = 4
+ val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
+ val destReader = DbReader(db, TABLE_NAME, context, validPackages)
+ val task = GridSizeMigrationTaskV2(
+ context,
+ db,
+ srcReader,
+ destReader,
+ idp.numDatabaseHotseatIcons,
+ Point(idp.numColumns, idp.numRows)
+ )
+ task.migrate(DeviceGridState(context), DeviceGridState(idp))
+
+ // Check hotseat items
+ var c = context.contentResolver.query(
+ CONTENT_URI,
+ arrayOf(SCREEN, INTENT),
+ "container=$CONTAINER_HOTSEAT",
+ null,
+ SCREEN,
+ null
+ ) ?: throw IllegalStateException()
+
+ assertThat(c.count).isEqualTo(idp.numDatabaseHotseatIcons)
+
+ val screenIndex = c.getColumnIndex(SCREEN)
+ var intentIndex = c.getColumnIndex(INTENT)
+ c.moveToNext()
+ assertThat(c.getInt(screenIndex).toLong()).isEqualTo(0)
+ assertThat(c.getString(intentIndex)).contains(testPackage1)
+ c.moveToNext()
+ assertThat(c.getInt(screenIndex).toLong()).isEqualTo(1)
+ assertThat(c.getString(intentIndex)).contains(testPackage2)
+ c.moveToNext()
+ assertThat(c.getInt(screenIndex).toLong()).isEqualTo(2)
+ assertThat(c.getString(intentIndex)).contains(testPackage3)
+ c.moveToNext()
+ assertThat(c.getInt(screenIndex).toLong()).isEqualTo(3)
+ assertThat(c.getString(intentIndex)).contains(testPackage4)
+ c.close()
+
+ // Check workspace items
+ c = context.contentResolver.query(
+ CONTENT_URI,
+ arrayOf(CELLX, CELLY, INTENT),
+ "container=$CONTAINER_DESKTOP",
+ null,
+ null,
+ null
+ ) ?: throw IllegalStateException()
+
+ intentIndex = c.getColumnIndex(INTENT)
+ val cellXIndex = c.getColumnIndex(CELLX)
+ val cellYIndex = c.getColumnIndex(CELLY)
+ val locMap = HashMap<String, Point>()
+ while (c.moveToNext()) {
+ locMap[Intent.parseUri(c.getString(intentIndex), 0).getPackage()] =
+ Point(c.getInt(cellXIndex), c.getInt(cellYIndex))
+ }
+ c.close()
+ // Expected dest grid icons
+ // _ _ _ _
+ // 5 6 7 8
+ // 9 _ 10_
+ // _ _ _ _
+ assertThat(locMap.size.toLong()).isEqualTo(6)
+ assertThat(locMap[testPackage5]).isEqualTo(Point(0, 1))
+ assertThat(locMap[testPackage6]).isEqualTo(Point(1, 1))
+ assertThat(locMap[testPackage7]).isEqualTo(Point(2, 1))
+ assertThat(locMap[testPackage8]).isEqualTo(Point(3, 1))
+ assertThat(locMap[testPackage9]).isEqualTo(Point(0, 2))
+ assertThat(locMap[testPackage10]).isEqualTo(Point(2, 2))
+ }
+
+ @Test
+ fun migrateToLargerHotseat() {
+ val srcHotseatItems = intArrayOf(
+ modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI),
+ modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI),
+ modelHelper.addItem(APP_ICON, 2, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI),
+ modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
+ )
+ val numSrcDatabaseHotseatIcons = srcHotseatItems.size
+ idp.numDatabaseHotseatIcons = 6
+ idp.numColumns = 4
+ idp.numRows = 4
+ val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
+ val destReader = DbReader(db, TABLE_NAME, context, validPackages)
+ val task = GridSizeMigrationTaskV2(
+ context,
+ db,
+ srcReader,
+ destReader,
+ idp.numDatabaseHotseatIcons,
+ Point(idp.numColumns, idp.numRows)
+ )
+ task.migrate(DeviceGridState(context), DeviceGridState(idp))
+
+ // Check hotseat items
+ val c = context.contentResolver.query(
+ CONTENT_URI,
+ arrayOf(SCREEN, INTENT),
+ "container=$CONTAINER_HOTSEAT",
+ null,
+ SCREEN,
+ null
+ ) ?: throw IllegalStateException()
+
+ assertThat(c.count.toLong()).isEqualTo(numSrcDatabaseHotseatIcons.toLong())
+ val screenIndex = c.getColumnIndex(SCREEN)
+ val intentIndex = c.getColumnIndex(INTENT)
+ c.moveToNext()
+ assertThat(c.getInt(screenIndex)).isEqualTo(0)
+ assertThat(c.getString(intentIndex)).contains(testPackage1)
+
+ c.moveToNext()
+ assertThat(c.getInt(screenIndex)).isEqualTo(1)
+ assertThat(c.getString(intentIndex)).contains(testPackage2)
+
+ c.moveToNext()
+ assertThat(c.getInt(screenIndex)).isEqualTo(2)
+ assertThat(c.getString(intentIndex)).contains(testPackage3)
+
+ c.moveToNext()
+ assertThat(c.getInt(screenIndex)).isEqualTo(3)
+ assertThat(c.getString(intentIndex)).contains(testPackage4)
+
+ c.close()
+ }
+
+ @Test
+ fun migrateFromLargerHotseat() {
+ modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 2, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 5, HOTSEAT, 0, 0, testPackage5, 5, TMP_CONTENT_URI)
+
+ idp.numDatabaseHotseatIcons = 4
+ idp.numColumns = 4
+ idp.numRows = 4
+ val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
+ val destReader = DbReader(db, TABLE_NAME, context, validPackages)
+ val task = GridSizeMigrationTaskV2(
+ context,
+ db,
+ srcReader,
+ destReader,
+ idp.numDatabaseHotseatIcons,
+ Point(idp.numColumns, idp.numRows)
+ )
+ task.migrate(DeviceGridState(context), DeviceGridState(idp))
+
+ // Check hotseat items
+ val c = context.contentResolver.query(
+ CONTENT_URI,
+ arrayOf(SCREEN, INTENT),
+ "container=$CONTAINER_HOTSEAT",
+ null,
+ SCREEN,
+ null
+ ) ?: throw IllegalStateException()
+
+ assertThat(c.count.toLong()).isEqualTo(idp.numDatabaseHotseatIcons.toLong())
+ val screenIndex = c.getColumnIndex(SCREEN)
+ val intentIndex = c.getColumnIndex(INTENT)
+
+ c.moveToNext()
+ assertThat(c.getInt(screenIndex)).isEqualTo(0)
+ assertThat(c.getString(intentIndex)).contains(testPackage1)
+
+ c.moveToNext()
+ assertThat(c.getInt(screenIndex)).isEqualTo(1)
+ assertThat(c.getString(intentIndex)).contains(testPackage2)
+
+ c.moveToNext()
+ assertThat(c.getInt(screenIndex)).isEqualTo(2)
+ assertThat(c.getString(intentIndex)).contains(testPackage3)
+
+ c.moveToNext()
+ assertThat(c.getInt(screenIndex)).isEqualTo(3)
+ assertThat(c.getString(intentIndex)).contains(testPackage4)
+
+ c.close()
+ }
+
+ /**
+ * Migrating from a smaller grid to a large one should keep the pages
+ * if the column difference is less than 2
+ */
+ @Test
+ @Throws(Exception::class)
+ fun migrateFromSmallerGridSmallDifference() {
+ enableNewMigrationLogic("4,4")
+
+ // Setup src grid
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage1, 5, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage2, 6, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 3, 1, testPackage3, 7, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 3, 2, testPackage4, 8, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 2, DESKTOP, 3, 3, testPackage5, 9, TMP_CONTENT_URI)
+
+ idp.numDatabaseHotseatIcons = 4
+ idp.numColumns = 6
+ idp.numRows = 5
+
+ val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
+ val destReader = DbReader(db, TABLE_NAME, context, validPackages)
+ val task = GridSizeMigrationTaskV2(
+ context,
+ db,
+ srcReader,
+ destReader,
+ idp.numDatabaseHotseatIcons,
+ Point(idp.numColumns, idp.numRows)
+ )
+ task.migrate(DeviceGridState(context), DeviceGridState(idp))
+
+ // Get workspace items
+ val c = context.contentResolver.query(
+ CONTENT_URI,
+ arrayOf(INTENT, SCREEN),
+ "container=$CONTAINER_DESKTOP",
+ null,
+ null,
+ null
+ ) ?: throw IllegalStateException()
+ val intentIndex = c.getColumnIndex(INTENT)
+ val screenIndex = c.getColumnIndex(SCREEN)
+
+ // Get in which screen the icon is
+ val locMap = HashMap<String, Int>()
+ while (c.moveToNext()) {
+ locMap[Intent.parseUri(c.getString(intentIndex), 0).getPackage()] =
+ c.getInt(screenIndex)
+ }
+ c.close()
+ assertThat(locMap.size).isEqualTo(5)
+ assertThat(locMap[testPackage1]).isEqualTo(0)
+ assertThat(locMap[testPackage2]).isEqualTo(0)
+ assertThat(locMap[testPackage3]).isEqualTo(1)
+ assertThat(locMap[testPackage4]).isEqualTo(1)
+ assertThat(locMap[testPackage5]).isEqualTo(2)
+
+ disableNewMigrationLogic()
+ }
+
+ /**
+ * Migrating from a smaller grid to a large one should reflow the pages
+ * if the column difference is more than 2
+ */
+ @Test
+ @Throws(Exception::class)
+ fun migrateFromSmallerGridBigDifference() {
+ enableNewMigrationLogic("2,2")
+
+ // Setup src grid
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 1, testPackage1, 5, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 1, testPackage2, 6, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 0, 0, testPackage3, 7, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 1, 0, testPackage4, 8, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 2, DESKTOP, 0, 0, testPackage5, 9, TMP_CONTENT_URI)
+
+ idp.numDatabaseHotseatIcons = 4
+ idp.numColumns = 5
+ idp.numRows = 5
+ val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
+ val destReader = DbReader(db, TABLE_NAME, context, validPackages)
+ val task = GridSizeMigrationTaskV2(
+ context,
+ db,
+ srcReader,
+ destReader,
+ idp.numDatabaseHotseatIcons,
+ Point(idp.numColumns, idp.numRows)
+ )
+ task.migrate(DeviceGridState(context), DeviceGridState(idp))
+
+ // Get workspace items
+ val c = context.contentResolver.query(
+ CONTENT_URI,
+ arrayOf(INTENT, SCREEN),
+ "container=$CONTAINER_DESKTOP",
+ null,
+ null,
+ null
+ ) ?: throw IllegalStateException()
+
+ val intentIndex = c.getColumnIndex(INTENT)
+ val screenIndex = c.getColumnIndex(SCREEN)
+
+ // Get in which screen the icon is
+ val locMap = HashMap<String, Int>()
+ while (c.moveToNext()) {
+ locMap[Intent.parseUri(c.getString(intentIndex), 0).getPackage()] =
+ c.getInt(screenIndex)
+ }
+ c.close()
+
+ // All icons fit the first screen
+ assertThat(locMap.size).isEqualTo(5)
+ assertThat(locMap[testPackage1]).isEqualTo(0)
+ assertThat(locMap[testPackage2]).isEqualTo(0)
+ assertThat(locMap[testPackage3]).isEqualTo(0)
+ assertThat(locMap[testPackage4]).isEqualTo(0)
+ assertThat(locMap[testPackage5]).isEqualTo(0)
+ disableNewMigrationLogic()
+ }
+
+ /**
+ * Migrating from a larger grid to a smaller, we reflow from page 0
+ */
+ @Test
+ @Throws(Exception::class)
+ fun migrateFromLargerGrid() {
+ enableNewMigrationLogic("5,5")
+
+ // Setup src grid
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 1, testPackage1, 5, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 1, testPackage2, 6, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 0, 0, testPackage3, 7, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 1, 0, testPackage4, 8, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 2, DESKTOP, 0, 0, testPackage5, 9, TMP_CONTENT_URI)
+
+ idp.numDatabaseHotseatIcons = 4
+ idp.numColumns = 4
+ idp.numRows = 4
+ val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
+ val destReader = DbReader(db, TABLE_NAME, context, validPackages)
+ val task = GridSizeMigrationTaskV2(
+ context,
+ db,
+ srcReader,
+ destReader,
+ idp.numDatabaseHotseatIcons,
+ Point(idp.numColumns, idp.numRows)
+ )
+ task.migrate(DeviceGridState(context), DeviceGridState(idp))
+
+ // Get workspace items
+ val c = context.contentResolver.query(
+ CONTENT_URI,
+ arrayOf(INTENT, SCREEN),
+ "container=$CONTAINER_DESKTOP",
+ null,
+ null,
+ null
+ ) ?: throw IllegalStateException()
+ val intentIndex = c.getColumnIndex(INTENT)
+ val screenIndex = c.getColumnIndex(SCREEN)
+
+ // Get in which screen the icon is
+ val locMap = HashMap<String, Int>()
+ while (c.moveToNext()) {
+ locMap[Intent.parseUri(c.getString(intentIndex), 0).getPackage()] =
+ c.getInt(screenIndex)
+ }
+ c.close()
+
+ // All icons fit the first screen
+ assertThat(locMap.size).isEqualTo(5)
+ assertThat(locMap[testPackage1]).isEqualTo(0)
+ assertThat(locMap[testPackage2]).isEqualTo(0)
+ assertThat(locMap[testPackage3]).isEqualTo(0)
+ assertThat(locMap[testPackage4]).isEqualTo(0)
+ assertThat(locMap[testPackage5]).isEqualTo(0)
+
+ disableNewMigrationLogic()
+ }
+
+ private fun enableNewMigrationLogic(srcGridSize: String) {
+ context.getSharedPreferences(FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE)
+ .edit()
+ .putBoolean(FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC.key, true)
+ .commit()
+ context.getSharedPreferences(LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
+ .edit()
+ .putString(DeviceGridState.KEY_WORKSPACE_SIZE, srcGridSize)
+ .commit()
+ FeatureFlags.initialize(context)
+ }
+
+ private fun disableNewMigrationLogic() {
+ context.getSharedPreferences(FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE)
+ .edit()
+ .putBoolean(FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC.key, false)
+ .commit()
+ }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/model/WorkspaceItemSpaceFinderTest.kt b/tests/src/com/android/launcher3/model/WorkspaceItemSpaceFinderTest.kt
new file mode 100644
index 0000000..bfb1ac6
--- /dev/null
+++ b/tests/src/com/android/launcher3/model/WorkspaceItemSpaceFinderTest.kt
@@ -0,0 +1,171 @@
+/*
+ * 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.model
+
+import android.graphics.Rect
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Tests for [WorkspaceItemSpaceFinder]
+ */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class WorkspaceItemSpaceFinderTest : AbstractWorkspaceModelTest() {
+
+ private val mItemSpaceFinder = WorkspaceItemSpaceFinder()
+
+ @Before
+ override fun setup() {
+ super.setup()
+ }
+
+ @After
+ override fun tearDown() {
+ super.tearDown()
+ }
+
+ private fun findSpace(spanX: Int, spanY: Int): NewItemSpace =
+ mItemSpaceFinder.findSpaceForItem(
+ mAppState, mModelHelper.bgDataModel,
+ mExistingScreens, mNewScreens, spanX, spanY
+ )
+ .let { NewItemSpace.fromIntArray(it) }
+
+ private fun assertRegionVacant(newItemSpace: NewItemSpace, spanX: Int, spanY: Int) {
+ assertThat(
+ mScreenOccupancy[newItemSpace.screenId]
+ .isRegionVacant(newItemSpace.cellX, newItemSpace.cellY, spanX, spanY)
+ ).isTrue()
+ }
+
+ @Test
+ fun justEnoughSpaceOnFirstScreen_whenFindSpaceForItem_thenReturnFirstScreenId() {
+ setupWorkspacesWithSpaces(
+ // 3x2 space on screen 0, but it should be skipped
+ screen0 = listOf(Rect(2, 0, 5, 2)),
+ screen1 = listOf(Rect(2, 2, 3, 3)), // 1x1 space
+ // 2 spaces of sizes 3x2 and 2x3
+ screen2 = listOf(Rect(2, 0, 5, 2), Rect(0, 2, 2, 5)),
+ )
+
+ val spaceFound = findSpace(1, 1)
+
+ assertThat(spaceFound.screenId).isEqualTo(1)
+ assertRegionVacant(spaceFound, 1, 1)
+ }
+
+ @Test
+ fun notEnoughSpaceOnFirstScreen_whenFindSpaceForItem_thenReturnSecondScreenId() {
+ setupWorkspacesWithSpaces(
+ // 3x2 space on screen 0, but it should be skipped
+ screen0 = listOf(Rect(2, 0, 5, 2)),
+ screen1 = listOf(Rect(2, 2, 3, 3)), // 1x1 space
+ // 2 spaces of sizes 3x2 and 2x3
+ screen2 = listOf(Rect(2, 0, 5, 2), Rect(0, 2, 2, 5)),
+ )
+
+ // Find a larger space
+ val spaceFound = findSpace(2, 3)
+
+ assertThat(spaceFound.screenId).isEqualTo(2)
+ assertRegionVacant(spaceFound, 2, 3)
+ }
+
+ @Test
+ fun notEnoughSpaceOnExistingScreens_returnNewScreenId() {
+ setupWorkspacesWithSpaces(
+ // 3x2 space on screen 0, but it should be skipped
+ screen0 = listOf(Rect(2, 0, 5, 2)),
+ // 2 spaces of sizes 3x2 and 2x3
+ screen1 = listOf(Rect(2, 0, 5, 2), Rect(0, 2, 2, 5)),
+ // 2 spaces of sizes 1x2 and 2x2
+ screen2 = listOf(Rect(1, 0, 2, 2), Rect(3, 2, 5, 4)),
+ )
+
+ val oldScreens = mExistingScreens.clone()
+ val spaceFound = findSpace(3, 3)
+
+ assertThat(oldScreens.contains(spaceFound.screenId)).isFalse()
+ assertThat(mNewScreens.contains(spaceFound.screenId)).isTrue()
+ }
+
+ @Test
+ fun firstScreenIsEmptyButSecondIsNotEmpty_returnSecondScreenId() {
+ setupWorkspacesWithSpaces(
+ // 3x2 space on screen 0, but it should be skipped
+ screen0 = listOf(Rect(2, 0, 5, 2)),
+ // empty screens are skipped
+ screen2 = listOf(Rect(2, 0, 5, 2)), // 3x2 space
+ )
+
+ val spaceFound = findSpace(2, 1)
+
+ assertThat(spaceFound.screenId).isEqualTo(2)
+ assertRegionVacant(spaceFound, 2, 1)
+ }
+
+ @Test
+ fun twoEmptyMiddleScreens_returnThirdScreen() {
+ setupWorkspacesWithSpaces(
+ // 3x2 space on screen 0, but it should be skipped
+ screen0 = listOf(Rect(2, 0, 5, 2)),
+ // empty screens are skipped
+ screen3 = listOf(Rect(1, 1, 4, 4)), // 3x3 space
+ )
+
+ val spaceFound = findSpace(2, 3)
+
+ assertThat(spaceFound.screenId).isEqualTo(3)
+ assertRegionVacant(spaceFound, 2, 3)
+ }
+
+ @Test
+ fun allExistingPagesAreFull_returnNewScreenId() {
+ setupWorkspacesWithSpaces(
+ // 3x2 space on screen 0, but it should be skipped
+ screen0 = listOf(Rect(2, 0, 5, 2)),
+ screen1 = fullScreenSpaces,
+ screen2 = fullScreenSpaces,
+ )
+
+ val spaceFound = findSpace(2, 3)
+
+ assertThat(spaceFound.screenId).isEqualTo(3)
+ assertThat(mNewScreens.contains(spaceFound.screenId)).isTrue()
+ }
+
+ @Test
+ fun firstTwoPagesAreFull_and_ThirdPageIsEmpty_returnThirdPage() {
+ setupWorkspacesWithSpaces(
+ // 3x2 space on screen 0, but it should be skipped
+ screen0 = listOf(Rect(2, 0, 5, 2)),
+ screen1 = fullScreenSpaces, // full screens are skipped
+ screen2 = fullScreenSpaces, // full screens are skipped
+ screen3 = emptyScreenSpaces
+ )
+
+ val spaceFound = findSpace(3, 1)
+
+ assertThat(spaceFound.screenId).isEqualTo(3)
+ assertRegionVacant(spaceFound, 3, 1)
+ }
+}
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 075505e..6f8b9d2 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -33,6 +33,7 @@
import android.content.pm.LauncherApps;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.graphics.Point;
import android.os.Debug;
import android.os.Process;
import android.os.RemoteException;
@@ -54,6 +55,8 @@
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;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.LauncherInstrumentation.ContainerType;
import com.android.launcher3.tapl.TestHelpers;
@@ -65,6 +68,7 @@
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.TestStabilityRule;
@@ -126,14 +130,14 @@
private static String getActivityLeakErrorMessage(LauncherInstrumentation launcher) {
sActivityLeakReported = true;
return "Activity leak detector has found leaked activities, "
- + dumpHprofData(launcher) + ".";
+ + dumpHprofData(launcher, false) + ".";
}
- public static String dumpHprofData(LauncherInstrumentation launcher) {
+ public static String dumpHprofData(LauncherInstrumentation launcher, boolean intentionalLeak) {
+ if (intentionalLeak) return "intentional leak; not generating dump";
+
String result;
if (sDumpWasGenerated) {
- Log.d("b/195319692", "dump has already been generated by another test",
- new Exception());
result = "dump has already been generated by another test";
} else {
try {
@@ -148,7 +152,6 @@
"am dumpheap " + device.getLauncherPackageName() + " " + fileName);
}
sDumpWasGenerated = true;
- Log.d("b/195319692", "sDumpWasGenerated := true", new Exception());
result = "saved memory dump as an artifact";
} catch (Throwable e) {
Log.e(TAG, "dumpHprofData failed", e);
@@ -225,7 +228,8 @@
@Rule
public TestRule mOrderSensitiveRules = RuleChain
- .outerRule(new TestStabilityRule())
+ .outerRule(new SamplerRule())
+ .around(new TestStabilityRule())
.around(mActivityMonitor)
.around(getRulesInsideActivityMonitor());
@@ -510,7 +514,7 @@
"Launcher still active", launcher -> launcher == null, DEFAULT_UI_TIMEOUT);
}
- protected boolean isInBackground(Launcher launcher) {
+ protected boolean isInLaunchedApp(Launcher launcher) {
return launcher == null || !launcher.hasBeenResumed();
}
@@ -550,7 +554,7 @@
ordinal == TestProtocol.NORMAL_STATE_ORDINAL);
break;
}
- case ALL_APPS: {
+ case HOME_ALL_APPS: {
assertTrue(
"Launcher is not resumed in state: " + expectedContainerType,
isResumed);
@@ -565,7 +569,8 @@
ordinal == TestProtocol.OVERVIEW_STATE_ORDINAL);
break;
}
- case BACKGROUND: {
+ case TASKBAR_ALL_APPS:
+ case LAUNCHED_APP: {
assertTrue("Launcher is resumed in state: " + expectedContainerType,
!isResumed);
assertTrue(TestProtocol.stateOrdinalToString(ordinal),
@@ -578,10 +583,11 @@
}
} else {
assertTrue(
- "Container type is not BACKGROUND or FALLBACK_OVERVIEW: "
- + expectedContainerType,
- expectedContainerType == ContainerType.BACKGROUND ||
- expectedContainerType == ContainerType.FALLBACK_OVERVIEW);
+ "Container type is not LAUNCHED_APP, TASKBAR_ALL_APPS "
+ + "or FALLBACK_OVERVIEW: " + expectedContainerType,
+ expectedContainerType == ContainerType.LAUNCHED_APP
+ || expectedContainerType == ContainerType.TASKBAR_ALL_APPS
+ || expectedContainerType == ContainerType.FALLBACK_OVERVIEW);
}
}
@@ -601,4 +607,30 @@
protected void onLauncherActivityClose(Launcher launcher) {
}
+
+ protected HomeAppIcon createShortcutInCenterIfNotExist(String name) {
+ Point dimension = mLauncher.getWorkspace().getIconGridDimensions();
+ return createShortcutIfNotExist(name, dimension.x / 2, dimension.y / 2);
+ }
+
+ protected HomeAppIcon createShortcutIfNotExist(String name, Point cellPosition) {
+ return createShortcutIfNotExist(name, cellPosition.x, cellPosition.y);
+ }
+
+ protected HomeAppIcon createShortcutIfNotExist(String name, int cellX, int cellY) {
+ HomeAppIcon homeAppIcon = mLauncher.getWorkspace().tryGetWorkspaceAppIcon(name);
+ if (homeAppIcon == null) {
+ HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+ allApps.freeze();
+ try {
+ allApps.getAppIcon(name).dragToWorkspace(cellX, cellY);
+ } finally {
+ allApps.unfreeze();
+ }
+ homeAppIcon = mLauncher.getWorkspace().getWorkspaceAppIcon(name);
+ }
+ return homeAppIcon;
+ }
+
+
}
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 5b940a8..8a97c6b 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -18,12 +18,17 @@
import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static com.google.common.truth.Truth.assertThat;
+
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 android.content.Intent;
+import android.graphics.Point;
+
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
@@ -36,20 +41,33 @@
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.HomeAppIconMenu;
+import com.android.launcher3.tapl.HomeAppIconMenuItem;
import com.android.launcher3.tapl.Widgets;
import com.android.launcher3.tapl.Workspace;
+import com.android.launcher3.util.TestUtil;
+import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.launcher3.widget.picker.WidgetsFullSheet;
import com.android.launcher3.widget.picker.WidgetsRecyclerView;
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";
@Before
public void setUp() throws Exception {
@@ -100,7 +118,7 @@
launcher -> assertNotNull("Launcher internal state didn't switch to Showing Menu",
launcher.getOptionsPopup()));
// Check that pressHome works when the menu is shown.
- mLauncher.pressHome();
+ mLauncher.goHome();
}
@Test
@@ -112,7 +130,7 @@
} finally {
allApps.unfreeze();
}
- mLauncher.pressHome();
+ mLauncher.goHome();
}
public static void runAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) {
@@ -174,6 +192,7 @@
}
@Test
+ @ScreenRecord // b/202433017
public void testWorkspace() throws Exception {
final Workspace workspace = mLauncher.getWorkspace();
@@ -209,7 +228,7 @@
assertTrue("Launcher internal state is not Home", isInState(() -> LauncherState.NORMAL));
// Test starting a workspace app.
- final AppIcon app = workspace.getWorkspaceAppIcon("Chrome");
+ final HomeAppIcon app = workspace.getWorkspaceAppIcon("Chrome");
assertNotNull("No Chrome app in workspace", app);
}
@@ -222,7 +241,7 @@
"Launcher activity is the top activity; expecting another activity to be the "
+ "top "
+ "one",
- test.isInBackground(launcher)));
+ test.isInLaunchedApp(launcher)));
} finally {
allApps.unfreeze();
}
@@ -231,7 +250,7 @@
@Test
@PortraitLandscape
public void testAppIconLaunchFromAllAppsFromHome() throws Exception {
- final AllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+ final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
assertTrue("Launcher internal state is not All Apps",
isInState(() -> LauncherState.ALL_APPS));
@@ -263,7 +282,7 @@
executeOnLauncher(launcher -> assertTrue("Flinging backward didn't scroll widgets",
getWidgetsScroll(launcher) < flingForwardY));
- mLauncher.pressHome();
+ mLauncher.goHome();
waitForLauncherCondition("Widgets were not closed",
launcher -> getWidgetsView(launcher) == null);
}
@@ -280,9 +299,7 @@
@Test
@PortraitLandscape
public void testLaunchMenuItem() throws Exception {
- final AllApps allApps = mLauncher.
- getWorkspace().
- switchToAllApps();
+ final AllApps allApps = mLauncher.getWorkspace().switchToAllApps();
allApps.freeze();
try {
final AppIconMenu menu = allApps.
@@ -307,8 +324,7 @@
// 1. Open all apps and wait for load complete.
// 2. Drag icon to homescreen.
// 3. Verify that the icon works on homescreen.
- final AllApps allApps = mLauncher.getWorkspace().
- switchToAllApps();
+ final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
allApps.freeze();
try {
allApps.getAppIcon(APP_NAME).dragToWorkspace(false, false);
@@ -319,7 +335,7 @@
executeOnLauncher(launcher -> assertTrue(
"Launcher activity is the top activity; expecting another activity to be the top "
+ "one",
- isInBackground(launcher)));
+ isInLaunchedApp(launcher)));
}
@Test
@@ -328,18 +344,18 @@
// 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 AllApps allApps = mLauncher
+ final HomeAllApps allApps = mLauncher
.getWorkspace()
.switchToAllApps();
allApps.freeze();
try {
- final AppIconMenu menu = allApps
+ final HomeAppIconMenu menu = allApps
.getAppIcon(APP_NAME)
.openDeepShortcutMenu();
- final AppIconMenuItem menuItem0 = menu.getMenuItem(0);
- final AppIconMenuItem menuItem2 = menu.getMenuItem(2);
+ final HomeAppIconMenuItem menuItem0 = menu.getMenuItem(0);
+ final HomeAppIconMenuItem menuItem2 = menu.getMenuItem(2);
- final AppIconMenuItem menuItem;
+ final HomeAppIconMenuItem menuItem;
final String expectedShortcutName = "Shortcut 3";
if (menuItem0.getText().equals(expectedShortcutName)) {
@@ -358,50 +374,35 @@
}
}
- private AppIcon createShortcutIfNotExist(String name) {
- AppIcon appIcon = mLauncher.getWorkspace().tryGetWorkspaceAppIcon(name);
- if (appIcon == null) {
- AllApps allApps = mLauncher.getWorkspace().switchToAllApps();
- allApps.freeze();
- try {
- appIcon = allApps.getAppIcon(name);
- appIcon.dragToWorkspace(false, false);
- } finally {
- allApps.unfreeze();
- }
- appIcon = mLauncher.getWorkspace().getWorkspaceAppIcon(name);
- }
- return appIcon;
- }
-
- @Ignore("b/205014516")
@Test
@PortraitLandscape
- public void testDragToFolder() throws Exception {
- final AppIcon playStoreIcon = createShortcutIfNotExist("Play Store");
- final AppIcon gmailIcon = createShortcutIfNotExist("Gmail");
+ 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("Play Store");
- folder.getAppIcon("Gmail");
+ folder.getAppIcon(STORE_APP_NAME);
+ folder.getAppIcon(GMAIL_APP_NAME);
Workspace workspace = folder.close();
- assertNull("Gmail should be moved to a folder.",
- workspace.tryGetWorkspaceAppIcon("Gmail"));
- assertNull("Play Store should be moved to a folder.",
- workspace.tryGetWorkspaceAppIcon("Play Store"));
+ assertNull(STORE_APP_NAME + " should be moved to a folder.",
+ workspace.tryGetWorkspaceAppIcon(STORE_APP_NAME));
+ assertNull(GMAIL_APP_NAME + " should be moved to a folder.",
+ workspace.tryGetWorkspaceAppIcon(GMAIL_APP_NAME));
- final AppIcon youTubeIcon = createShortcutIfNotExist("YouTube");
-
- folderIcon = youTubeIcon.dragToIcon(folderIcon);
+ final HomeAppIcon mapIcon = createShortcutInCenterIfNotExist(MAPS_APP_NAME);
+ folderIcon = mapIcon.dragToIcon(folderIcon);
folder = folderIcon.open();
- folder.getAppIcon("YouTube");
- folder.close();
+ folder.getAppIcon(MAPS_APP_NAME);
+ workspace = folder.close();
+
+ assertNull(MAPS_APP_NAME + " should be moved to a folder.",
+ workspace.tryGetWorkspaceAppIcon(MAPS_APP_NAME));
}
- @Ignore("b/205027405")
@Test
@PortraitLandscape
public void testPressBack() throws Exception {
@@ -410,14 +411,7 @@
mLauncher.getWorkspace();
waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
- AllApps allApps = mLauncher.getWorkspace().switchToAllApps();
- allApps.freeze();
- try {
- allApps.getAppIcon(APP_NAME).dragToWorkspace(false, false);
- } finally {
- allApps.unfreeze();
- }
- mLauncher.getWorkspace().getWorkspaceAppIcon(APP_NAME).launch(getAppPackageName());
+ startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
mLauncher.pressBack();
mLauncher.getWorkspace();
waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
@@ -427,14 +421,122 @@
@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 AppIcon appIcon = createShortcutIfNotExist(appName);
- Workspace workspace = mLauncher.getWorkspace().deleteAppIcon(appIcon);
+ for (String appName : new String[]{"Gmail", "Play Store", APP_NAME}) {
+ final HomeAppIcon homeAppIcon = createShortcutInCenterIfNotExist(appName);
+ Workspace workspace = mLauncher.getWorkspace().deleteAppIcon(homeAppIcon);
assertNull(appName + " app was found after being deleted from workspace",
workspace.tryGetWorkspaceAppIcon(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();
+ }
+ }
+
+ @Test
+ @PortraitLandscape
+ public void testUninstallFromWorkspace() throws Exception {
+ TestUtil.installDummyApp();
+ try {
+ verifyAppUninstalledFromAllApps(
+ createShortcutInCenterIfNotExist(DUMMY_APP_NAME).uninstall(), DUMMY_APP_NAME);
+ } finally {
+ TestUtil.uninstallDummyApp();
+ }
+ }
+
+ @Test
+ @PortraitLandscape
+ public void testUninstallFromAllApps() throws Exception {
+ TestUtil.installDummyApp();
+ try {
+ Workspace workspace = mLauncher.getWorkspace();
+ final HomeAllApps allApps = workspace.switchToAllApps();
+ allApps.freeze();
+ try {
+ workspace = allApps.getAppIcon(DUMMY_APP_NAME).uninstall();
+ } finally {
+ allApps.unfreeze();
+ }
+ verifyAppUninstalledFromAllApps(workspace, DUMMY_APP_NAME);
+ } finally {
+ TestUtil.uninstallDummyApp();
+ }
+ }
+
+ @Test
+ @PortraitLandscape
+ public void testDragAppIconToWorkspaceCell() throws Exception {
+ Point[] targets = getCornersAndCenterPositions();
+
+ for (Point target : targets) {
+ 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);
+ }
+
+ // test to move a shortcut to other cell.
+ final HomeAppIcon launcherTestAppIcon = createShortcutInCenterIfNotExist(APP_NAME);
+ for (Point target : targets) {
+ launcherTestAppIcon.dragToWorkspace(target.x, target.y);
+ }
+ }
+
+ @Test
+ public void getIconsPosition_afterIconRemoved_notContained() throws IOException {
+ Point[] gridPositions = getCornersAndCenterPositions();
+ createShortcutIfNotExist(STORE_APP_NAME, gridPositions[0]);
+ createShortcutIfNotExist(MAPS_APP_NAME, gridPositions[1]);
+ TestUtil.installDummyApp();
+ 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();
+
+ assertNull(
+ DUMMY_APP_NAME + " app was found after being uninstalled",
+ mLauncher.getWorkspace().tryGetWorkspaceAppIcon(DUMMY_APP_NAME));
+
+ Map<String, Point> finalPositions =
+ mLauncher.getWorkspace().getWorkspaceIconsPositions();
+ assertThat(finalPositions).doesNotContainKey(DUMMY_APP_NAME);
+ } finally {
+ TestUtil.uninstallDummyApp();
+ }
+ }
+
+ /**
+ * @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();
}
diff --git a/tests/src/com/android/launcher3/ui/WorkProfileTest.java b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
index 939cfe1..35b4ca6 100644
--- a/tests/src/com/android/launcher3/ui/WorkProfileTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
@@ -25,11 +25,14 @@
import android.util.Log;
import android.view.View;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
+
import com.android.launcher3.R;
-import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.allapps.AllAppsPagedView;
import com.android.launcher3.allapps.WorkAdapterProvider;
import com.android.launcher3.allapps.WorkEduCard;
+import com.android.launcher3.allapps.WorkPausedCard;
import com.android.launcher3.allapps.WorkProfileManager;
import com.android.launcher3.tapl.LauncherInstrumentation;
@@ -38,10 +41,11 @@
import org.junit.Test;
import java.util.Objects;
+import java.util.function.Predicate;
public class WorkProfileTest extends AbstractLauncherUiTest {
- private static final int WORK_PAGE = AllAppsContainerView.AdapterHolder.WORK;
+ private static final int WORK_PAGE = ActivityAllAppsContainerView.AdapterHolder.WORK;
private int mProfileUserId;
@@ -130,12 +134,14 @@
return manager.getCurrentState() == WorkProfileManager.STATE_DISABLED;
}, LauncherInstrumentation.WAIT_TIME_MS);
+ waitForWorkCard("Work paused card not shown", view -> view instanceof WorkPausedCard);
+
// start work profile toggle ON test
executeOnLauncher(l -> {
- AllAppsContainerView allApps = l.getAppsView();
+ ActivityAllAppsContainerView<?> allApps = l.getAppsView();
assertEquals("Work tab is not focused", allApps.getCurrentPage(), WORK_PAGE);
- View workPausedCard = allApps.getActiveRecyclerView().findViewHolderForAdapterPosition(
- 0).itemView;
+ View workPausedCard = allApps.getActiveRecyclerView()
+ .findViewHolderForAdapterPosition(0).itemView;
workPausedCard.findViewById(R.id.enable_work_apps).performClick();
});
waitForLauncherCondition("Work profile toggle ON failed", launcher -> {
@@ -154,9 +160,19 @@
l.getAppsView().getWorkManager().reset();
});
- waitForLauncherCondition("Work profile education not shown",
- l -> l.getAppsView().getActiveRecyclerView()
- .findViewHolderForAdapterPosition(0).itemView instanceof WorkEduCard,
- LauncherInstrumentation.WAIT_TIME_MS);
+ waitForWorkCard("Work profile education not shown", view -> view instanceof WorkEduCard);
+ }
+
+ private void waitForWorkCard(String message, Predicate<View> workCardCheck) {
+ waitForLauncherCondition(message, l -> {
+ l.getAppsView().getAppsStore().disableDeferUpdates(DEFER_UPDATES_TEST);
+ ViewHolder holder = l.getAppsView().getActiveRecyclerView()
+ .findViewHolderForAdapterPosition(0);
+ try {
+ return holder != null && workCardCheck.test(holder.itemView);
+ } finally {
+ l.getAppsView().getAppsStore().enableDeferUpdates(DEFER_UPDATES_TEST);
+ }
+ }, LauncherInstrumentation.WAIT_TIME_MS);
}
}
diff --git a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
index ccbb662..0db719e 100644
--- a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
@@ -15,6 +15,9 @@
*/
package com.android.launcher3.ui.widget;
+import static android.app.PendingIntent.FLAG_MUTABLE;
+import static android.app.PendingIntent.FLAG_ONE_SHOT;
+
import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
import static org.junit.Assert.assertNotNull;
@@ -42,6 +45,7 @@
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;
@@ -77,6 +81,7 @@
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 &&
@@ -85,6 +90,7 @@
}
@Test
+ @ScreenRecord // b/215673732
public void testPinWidgetNoConfig_customPreview() throws Throwable {
// Command to set custom preview
Intent command = RequestPinItemActivity.getCommandIntent(
@@ -98,6 +104,7 @@
}
@Test
+ @ScreenRecord // b/215673732
public void testPinWidgetWithConfig() throws Throwable {
runTest("pinWidgetWithConfig", true,
(info, view) -> info instanceof LauncherAppWidgetInfo &&
@@ -140,7 +147,7 @@
// Set callback
PendingIntent callback = PendingIntent.getBroadcast(mTargetContext, 0,
- new Intent(mCallbackAction), PendingIntent.FLAG_ONE_SHOT);
+ new Intent(mCallbackAction), FLAG_ONE_SHOT | FLAG_MUTABLE);
mTargetContext.sendBroadcast(RequestPinItemActivity.getCommandIntent(
RequestPinItemActivity.class, "setCallback").putExtra(
RequestPinItemActivity.EXTRA_PARAM + "0", callback));
@@ -165,7 +172,7 @@
}
// Go back to home
- mLauncher.pressHome();
+ mLauncher.goHome();
Wait.atMost("", new ItemSearchCondition(itemMatcher), DEFAULT_ACTIVITY_TIMEOUT,
mLauncher);
}
diff --git a/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
new file mode 100644
index 0000000..e66810c
--- /dev/null
+++ b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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.ui.workspace;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.net.Uri;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.test.filters.LargeTest;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.icons.ThemedIconDrawable;
+import com.android.launcher3.tapl.HomeAllApps;
+import com.android.launcher3.tapl.HomeAppIcon;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.ui.TaplTestsLauncher3;
+
+import org.junit.Test;
+
+import java.util.ArrayDeque;
+import java.util.Queue;
+
+/**
+ * Tests for theme icon support in Launcher
+ *
+ * Note running these tests will clear the workspace on the device.
+ */
+@LargeTest
+public class ThemeIconsTest extends AbstractLauncherUiTest {
+
+ private static final String APP_NAME = "ThemeIconTestActivity";
+
+ @Test
+ public void testIconWithoutTheme() throws Exception {
+ setThemeEnabled(false);
+ TaplTestsLauncher3.initialize(this);
+
+ HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+ allApps.freeze();
+
+ try {
+ HomeAppIcon icon = allApps.getAppIcon(APP_NAME);
+ executeOnLauncher(l -> verifyIconTheme(l.getAppsView(), false));
+ icon.dragToWorkspace(false, false);
+ executeOnLauncher(l -> verifyIconTheme(l.getWorkspace(), false));
+ } finally {
+ allApps.unfreeze();
+ }
+ }
+
+ @Test
+ public void testIconWithTheme() throws Exception {
+ setThemeEnabled(true);
+ TaplTestsLauncher3.initialize(this);
+
+ HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
+ allApps.freeze();
+
+ try {
+ HomeAppIcon icon = allApps.getAppIcon(APP_NAME);
+ executeOnLauncher(l -> verifyIconTheme(l.getAppsView(), false));
+ icon.dragToWorkspace(false, false);
+ executeOnLauncher(l -> verifyIconTheme(l.getWorkspace(), true));
+ } finally {
+ allApps.unfreeze();
+ }
+ }
+
+ private void verifyIconTheme(ViewGroup parent, boolean isThemed) {
+ // Find the app icon
+ Queue<View> viewQueue = new ArrayDeque<>();
+ viewQueue.add(parent);
+ BubbleTextView icon = null;
+ while (!viewQueue.isEmpty()) {
+ View view = viewQueue.poll();
+ if (view instanceof ViewGroup) {
+ parent = (ViewGroup) view;
+ for (int i = parent.getChildCount() - 1; i >= 0; i--) {
+ viewQueue.add(parent.getChildAt(i));
+ }
+ } else if (view instanceof BubbleTextView) {
+ BubbleTextView btv = (BubbleTextView) view;
+ if (APP_NAME.equals(btv.getText())) {
+ icon = btv;
+ break;
+ }
+ }
+ }
+
+ assertNotNull(icon.getIcon());
+ assertEquals(isThemed, icon.getIcon() instanceof ThemedIconDrawable);
+ }
+
+ private void setThemeEnabled(boolean isEnabled) throws Exception {
+ Uri uri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(mTargetPackage + ".grid_control")
+ .appendPath("set_icon_themed")
+ .build();
+ ContentValues values = new ContentValues();
+ values.put("boolean_value", isEnabled);
+ try (ContentProviderClient client = mTargetContext.getContentResolver()
+ .acquireContentProviderClient(uri)) {
+ int result = client.update(uri, values, null);
+ assertTrue(result > 0);
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java b/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java
index b048cd4..f646b50 100644
--- a/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java
@@ -19,6 +19,7 @@
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 androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
@@ -47,20 +48,12 @@
@RunWith(AndroidJUnit4.class)
public class TwoPanelWorkspaceTest extends AbstractLauncherUiTest {
- Workspace mWorkspace;
-
@Before
public void setUp() throws Exception {
super.setUp();
TaplTestsLauncher3.initialize(this);
- mWorkspace = mLauncher.getWorkspace();
- }
- @Test
- public void testDragIconToRightPanel() {
- if (!mLauncher.isTwoPanels()) {
- return;
- }
+ assumeTrue(mLauncher.isTwoPanels());
// Pre verifying the screens
executeOnLauncher(launcher -> {
@@ -68,8 +61,14 @@
assertItemsOnPage(launcher, 0, "Play Store", "Maps");
assertPageEmpty(launcher, 1);
});
+ }
- mWorkspace.dragIcon(mWorkspace.getHotseatAppIcon("Chrome"), 1);
+ @Test
+ @PortraitLandscape
+ public void testDragIconToRightPanel() {
+ Workspace workspace = mLauncher.getWorkspace();
+
+ workspace.dragIcon(workspace.getHotseatAppIcon("Chrome"), 1);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1);
@@ -79,19 +78,65 @@
}
@Test
- public void testDragIconToPage2() {
- if (!mLauncher.isTwoPanels()) {
- return;
- }
+ @PortraitLandscape
+ public void testSinglePageDragIconWhenMultiplePageScrollingIsPossible() {
+ Workspace workspace = mLauncher.getWorkspace();
- // Pre verifying the screens
+ workspace.dragIcon(workspace.getHotseatAppIcon("Chrome"), 2);
+
+ workspace.flingBackward();
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 3);
+
executeOnLauncher(launcher -> {
- assertPagesExist(launcher, 0, 1);
- assertItemsOnPage(launcher, 0, "Play Store", "Maps");
+ assertPagesExist(launcher, 0, 1, 2, 3);
+ assertItemsOnPage(launcher, 0, "Play Store");
assertPageEmpty(launcher, 1);
+ assertItemsOnPage(launcher, 2, "Chrome");
+ assertItemsOnPage(launcher, 3, "Maps");
});
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Maps"), 2);
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 3);
+
+ executeOnLauncher(launcher -> {
+ assertPagesExist(launcher, 0, 1, 2, 3, 4, 5);
+ assertItemsOnPage(launcher, 0, "Play Store");
+ assertPageEmpty(launcher, 1);
+ assertItemsOnPage(launcher, 2, "Chrome");
+ assertPageEmpty(launcher, 3);
+ assertPageEmpty(launcher, 4);
+ assertItemsOnPage(launcher, 5, "Maps");
+ });
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), -1);
+
+ executeOnLauncher(launcher -> {
+ assertPagesExist(launcher, 0, 1, 2, 3);
+ assertItemsOnPage(launcher, 0, "Play Store");
+ assertPageEmpty(launcher, 1);
+ assertItemsOnPage(launcher, 2, "Chrome");
+ assertItemsOnPage(launcher, 3, "Maps");
+ });
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), -1);
+
+ workspace.flingForward();
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Chrome"), -2);
+
+ executeOnLauncher(launcher -> {
+ assertPagesExist(launcher, 0, 1);
+ assertItemsOnPage(launcher, 0, "Chrome", "Play Store");
+ assertItemsOnPage(launcher, 1, "Maps");
+ });
+ }
+
+ @Test
+ @PortraitLandscape
+ public void testDragIconToPage2() {
+ Workspace workspace = mLauncher.getWorkspace();
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 2);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 2, 3);
@@ -103,19 +148,11 @@
}
@Test
+ @PortraitLandscape
public void testDragIconToPage3() {
- if (!mLauncher.isTwoPanels()) {
- return;
- }
+ Workspace workspace = mLauncher.getWorkspace();
- // Pre verifying the screens
- executeOnLauncher(launcher -> {
- assertPagesExist(launcher, 0, 1);
- assertItemsOnPage(launcher, 0, "Play Store", "Maps");
- assertPageEmpty(launcher, 1);
- });
-
- mWorkspace.dragIcon(mWorkspace.getHotseatAppIcon("Phone"), 3);
+ workspace.dragIcon(workspace.getHotseatAppIcon("Phone"), 3);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 2, 3);
@@ -126,22 +163,59 @@
});
}
-
@Test
- public void testEmptyPageDoesNotGetRemovedIfPagePairIsNotEmpty() {
- if (!mLauncher.isTwoPanels()) {
- return;
- }
+ @PortraitLandscape
+ public void testMultiplePageDragIcon() {
+ Workspace workspace = mLauncher.getWorkspace();
- // Pre verifying the screens
+ workspace.dragIcon(workspace.getHotseatAppIcon("Messages"), 2);
+
+ workspace.flingBackward();
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 5);
+
executeOnLauncher(launcher -> {
- assertPagesExist(launcher, 0, 1);
- assertItemsOnPage(launcher, 0, "Play Store", "Maps");
+ assertPagesExist(launcher, 0, 1, 2, 3, 4, 5);
+ assertItemsOnPage(launcher, 0, "Play Store");
assertPageEmpty(launcher, 1);
+ assertItemsOnPage(launcher, 2, "Messages");
+ assertPageEmpty(launcher, 3);
+ assertPageEmpty(launcher, 4);
+ assertItemsOnPage(launcher, 5, "Maps");
});
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Maps"), 3);
- mWorkspace.dragIcon(mWorkspace.getHotseatAppIcon("Chrome"), 0);
+ workspace.flingBackward();
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Messages"), 4);
+
+ executeOnLauncher(launcher -> {
+ assertPagesExist(launcher, 0, 1, 4, 5, 6, 7);
+ assertItemsOnPage(launcher, 0, "Play Store");
+ assertPageEmpty(launcher, 1);
+ assertPageEmpty(launcher, 4);
+ assertItemsOnPage(launcher, 5, "Maps");
+ assertItemsOnPage(launcher, 6, "Messages");
+ assertPageEmpty(launcher, 7);
+ });
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Messages"), -3);
+
+ executeOnLauncher(launcher -> {
+ assertPagesExist(launcher, 0, 1, 4, 5);
+ assertItemsOnPage(launcher, 0, "Play Store");
+ assertItemsOnPage(launcher, 1, "Messages");
+ assertPageEmpty(launcher, 4);
+ assertItemsOnPage(launcher, 5, "Maps");
+ });
+ }
+
+ @Test
+ @PortraitLandscape
+ public void testEmptyPageDoesNotGetRemovedIfPagePairIsNotEmpty() {
+ Workspace workspace = mLauncher.getWorkspace();
+
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 3);
+ workspace.dragIcon(workspace.getHotseatAppIcon("Chrome"), 0);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 2, 3);
@@ -151,7 +225,7 @@
assertItemsOnPage(launcher, 3, "Maps");
});
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Maps"), -1);
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), -1);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 2, 3);
@@ -163,8 +237,8 @@
// Move Chrome to the right panel as well, to make sure pages are not deleted whichever
// page is the empty one
- mWorkspace.flingForward();
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Chrome"), 1);
+ workspace.flingForward();
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Chrome"), 1);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 2, 3);
@@ -175,57 +249,40 @@
});
}
-
@Test
+ @PortraitLandscape
public void testEmptyPagesGetRemovedIfBothPagesAreEmpty() {
- if (!mLauncher.isTwoPanels()) {
- return;
- }
+ Workspace workspace = mLauncher.getWorkspace();
- // Pre verifying the screens
- executeOnLauncher(launcher -> {
- assertPagesExist(launcher, 0, 1);
- assertItemsOnPage(launcher, 0, "Play Store", "Maps");
- assertPageEmpty(launcher, 1);
- });
-
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Play Store"), 2);
- mWorkspace.dragIcon(mWorkspace.getHotseatAppIcon("Camera"), 1);
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Play Store"), 2);
+ workspace.dragIcon(workspace.getHotseatAppIcon("Chrome"), 1);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 2, 3);
assertItemsOnPage(launcher, 0, "Maps");
assertPageEmpty(launcher, 1);
assertItemsOnPage(launcher, 2, "Play Store");
- assertItemsOnPage(launcher, 3, "Camera");
+ assertItemsOnPage(launcher, 3, "Chrome");
});
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Camera"), -1);
- mWorkspace.flingForward();
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Play Store"), -2);
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Chrome"), -1);
+ workspace.flingForward();
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Play Store"), -2);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1);
assertItemsOnPage(launcher, 0, "Play Store", "Maps");
- assertItemsOnPage(launcher, 1, "Camera");
+ assertItemsOnPage(launcher, 1, "Chrome");
});
}
@Test
+ @PortraitLandscape
public void testMiddleEmptyPagesGetRemoved() {
- if (!mLauncher.isTwoPanels()) {
- return;
- }
+ Workspace workspace = mLauncher.getWorkspace();
- // Pre verifying the screens
- executeOnLauncher(launcher -> {
- assertPagesExist(launcher, 0, 1);
- assertItemsOnPage(launcher, 0, "Play Store", "Maps");
- assertPageEmpty(launcher, 1);
- });
-
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Maps"), 2);
- mWorkspace.dragIcon(mWorkspace.getHotseatAppIcon("Messages"), 3);
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 2);
+ workspace.dragIcon(workspace.getHotseatAppIcon("Messages"), 3);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 2, 3, 4, 5);
@@ -237,8 +294,8 @@
assertItemsOnPage(launcher, 5, "Messages");
});
- mWorkspace.flingBackward();
- mWorkspace.dragIcon(mWorkspace.getWorkspaceAppIcon("Maps"), 2);
+ workspace.flingBackward();
+ workspace.dragIcon(workspace.getWorkspaceAppIcon("Maps"), 2);
executeOnLauncher(launcher -> {
assertPagesExist(launcher, 0, 1, 4, 5);
diff --git a/tests/src/com/android/launcher3/util/KotlinMockitoHelpers.kt b/tests/src/com/android/launcher3/util/KotlinMockitoHelpers.kt
new file mode 100644
index 0000000..57db13a
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/KotlinMockitoHelpers.kt
@@ -0,0 +1,117 @@
+/*
+ * 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
+
+/**
+ * Kotlin versions of popular mockito methods that can return null in situations when Kotlin expects
+ * a non-null value. Kotlin will throw an IllegalStateException when this takes place ("x must not
+ * be null"). To fix this, we can use methods that modify the return type to be nullable. This
+ * causes Kotlin to skip the null checks.
+ */
+
+import org.mockito.ArgumentCaptor
+import org.mockito.Mockito
+
+/**
+ * Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when
+ * null is returned.
+ *
+ * Generic T is nullable because implicitly bounded by Any?.
+ */
+fun <T> eq(obj: T): T = Mockito.eq<T>(obj)
+
+/**
+ * Returns Mockito.same() as nullable type to avoid java.lang.IllegalStateException when
+ * null is returned.
+ *
+ * Generic T is nullable because implicitly bounded by Any?.
+ */
+fun <T> same(obj: T): T = Mockito.same<T>(obj)
+
+/**
+ * Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when
+ * null is returned.
+ *
+ * Generic T is nullable because implicitly bounded by Any?.
+ */
+fun <T> any(type: Class<T>): T = Mockito.any<T>(type)
+inline fun <reified T> any(): T = any(T::class.java)
+
+/**
+ * Kotlin type-inferred version of Mockito.nullable()
+ */
+inline fun <reified T> nullable(): T? = Mockito.nullable(T::class.java)
+
+/**
+ * Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException
+ * when null is returned.
+ *
+ * Generic T is nullable because implicitly bounded by Any?.
+ */
+fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
+
+/**
+ * Helper function for creating an argumentCaptor in kotlin.
+ *
+ * Generic T is nullable because implicitly bounded by Any?.
+ */
+inline fun <reified T : Any> argumentCaptor(): ArgumentCaptor<T> =
+ ArgumentCaptor.forClass(T::class.java)
+
+/**
+ * Helper function for creating new mocks, without the need to pass in a [Class] instance.
+ *
+ * Generic T is nullable because implicitly bounded by Any?.
+ */
+inline fun <reified T : Any> mock(): T = Mockito.mock(T::class.java)
+
+/**
+ * A kotlin implemented wrapper of [ArgumentCaptor] which prevents the following exception when
+ * kotlin tests are mocking kotlin objects and the methods take non-null parameters:
+ *
+ * java.lang.NullPointerException: capture() must not be null
+ */
+class KotlinArgumentCaptor<T> constructor(clazz: Class<T>) {
+ private val wrapped: ArgumentCaptor<T> = ArgumentCaptor.forClass(clazz)
+ fun capture(): T = wrapped.capture()
+ val value: T
+ get() = wrapped.value
+}
+
+/**
+ * Helper function for creating an argumentCaptor in kotlin.
+ *
+ * Generic T is nullable because implicitly bounded by Any?.
+ */
+inline fun <reified T : Any> kotlinArgumentCaptor(): KotlinArgumentCaptor<T> =
+ KotlinArgumentCaptor(T::class.java)
+
+/**
+ * Helper function for creating and using a single-use ArgumentCaptor in kotlin.
+ *
+ * val captor = argumentCaptor<Foo>()
+ * verify(...).someMethod(captor.capture())
+ * val captured = captor.value
+ *
+ * becomes:
+ *
+ * val captured = withArgCaptor<Foo> { verify(...).someMethod(capture()) }
+ *
+ * NOTE: this uses the KotlinArgumentCaptor to avoid the NullPointerException.
+ */
+inline fun <reified T : Any> withArgCaptor(block: KotlinArgumentCaptor<T>.() -> Unit): T =
+ kotlinArgumentCaptor<T>().apply { block() }.value
diff --git a/tests/src/com/android/launcher3/util/LauncherModelHelper.java b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
index 59966ee..3324959 100644
--- a/tests/src/com/android/launcher3/util/LauncherModelHelper.java
+++ b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
@@ -67,6 +67,7 @@
import com.android.launcher3.testing.TestInformationProvider;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
+import com.android.launcher3.util.window.WindowManagerProxy;
import com.android.launcher3.widget.custom.CustomWidgetManager;
import org.mockito.ArgumentCaptor;
@@ -501,7 +502,7 @@
LauncherAppState.INSTANCE, InvariantDeviceProfile.INSTANCE,
DisplayController.INSTANCE, CustomWidgetManager.INSTANCE,
SettingsCache.INSTANCE, PluginManagerWrapper.INSTANCE,
- ItemInstallQueue.INSTANCE);
+ ItemInstallQueue.INSTANCE, WindowManagerProxy.INSTANCE);
mPm = spy(getBaseContext().getPackageManager());
mDbDir = new File(getCacheDir(), UUID.randomUUID().toString());
}
diff --git a/tests/src/com/android/launcher3/util/MultiAdditivePropertyTest.kt b/tests/src/com/android/launcher3/util/MultiAdditivePropertyTest.kt
new file mode 100644
index 0000000..309d055
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/MultiAdditivePropertyTest.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.util
+
+import android.view.View
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** Unit tests for [MultiAdditivePropertyFactory] */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class MultiAdditivePropertyTest {
+
+ private val received = mutableListOf<Float>()
+
+ private val factory =
+ object : MultiAdditivePropertyFactory<View?>("Test", View.TRANSLATION_X) {
+ override fun apply(obj: View?, value: Float) {
+ received.add(value)
+ }
+ }
+
+ private val p1 = factory.get(1)
+ private val p2 = factory.get(2)
+ private val p3 = factory.get(3)
+
+ @Test
+ fun set_sameIndexes_allApplied() {
+ val v1 = 50f
+ val v2 = 100f
+ p1.set(null, v1)
+ p1.set(null, v1)
+ p1.set(null, v2)
+
+ assertThat(received).containsExactly(v1, v1, v2)
+ }
+
+ @Test
+ fun set_differentIndexes_aggregationApplied() {
+ val v1 = 50f
+ val v2 = 100f
+ val v3 = 150f
+ p1.set(null, v1)
+ p2.set(null, v2)
+ p3.set(null, v3)
+
+ assertThat(received).containsExactly(v1, v1 + v2, v1 + v2 + v3)
+ }
+}
diff --git a/tests/src/com/android/launcher3/util/MultiScalePropertyTest.kt b/tests/src/com/android/launcher3/util/MultiScalePropertyTest.kt
new file mode 100644
index 0000000..7d92214
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/MultiScalePropertyTest.kt
@@ -0,0 +1,109 @@
+/*
+ * 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
+
+import android.view.View
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** Unit tests for [MultiScalePropertyFactory] */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class MultiScalePropertyTest {
+
+ private val received = mutableListOf<Float>()
+
+ private val factory =
+ object : MultiScalePropertyFactory<View?>("Test") {
+ override fun apply(obj: View?, value: Float) {
+ received.add(value)
+ }
+ }
+
+ private val p1 = factory.get(1)
+ private val p2 = factory.get(2)
+ private val p3 = factory.get(3)
+
+ @Test
+ fun set_multipleSame_bothAppliedd() {
+ p1.set(null, 0.5f)
+ p1.set(null, 0.5f)
+
+ assertThat(received).containsExactly(0.5f, 0.5f)
+ }
+
+ @Test
+ fun set_differentIndexes_oneValuesNotCounted() {
+ val v1 = 0.5f
+ val v2 = 1.0f
+ p1.set(null, v1)
+ p2.set(null, v2)
+
+ assertThat(received).containsExactly(v1, v1)
+ }
+
+ @Test
+ fun set_onlyOneSetToOne_oneApplied() {
+ p1.set(null, 1.0f)
+
+ assertThat(received).containsExactly(1.0f)
+ }
+
+ @Test
+ fun set_onlyOneLessThanOne_applied() {
+ p1.set(null, 0.5f)
+
+ assertThat(received).containsExactly(0.5f)
+ }
+
+ @Test
+ fun set_differentIndexes_boundToMin() {
+ val v1 = 0.5f
+ val v2 = 0.6f
+ p1.set(null, v1)
+ p2.set(null, v2)
+
+ assertThat(received).containsExactly(v1, v1)
+ }
+
+ @Test
+ fun set_allHigherThanOne_boundToMax() {
+ val v1 = 3.0f
+ val v2 = 2.0f
+ val v3 = 1.0f
+ p1.set(null, v1)
+ p2.set(null, v2)
+ p3.set(null, v3)
+
+ assertThat(received).containsExactly(v1, v1, v1)
+ }
+
+ @Test
+ fun set_differentIndexes_firstModified_aggregationApplied() {
+ val v1 = 0.5f
+ val v2 = 0.6f
+ val v3 = 4f
+ p1.set(null, v1)
+ p2.set(null, v2)
+ p3.set(null, v3)
+
+ assertThat(received).containsExactly(v1, v1, v1 * v2 * v3)
+ }
+}
diff --git a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
index 65aaa24..4c41d7e 100644
--- a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
+++ b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
@@ -84,7 +84,7 @@
@Override
protected void failed(Throwable e, Description description) {
- onError(mDevice, description, e);
+ onError(mLauncher, description, e);
}
static File diagFile(Description description, String prefix, String ext) {
@@ -93,7 +93,9 @@
+ description.getMethodName() + "." + ext);
}
- public static void onError(UiDevice device, Description description, Throwable e) {
+ public static void onError(LauncherInstrumentation launcher, Description description,
+ Throwable e) {
+ final UiDevice device = launcher.getDevice();
Log.d("b/196820244", "onError 1");
if (device == null) return;
Log.d("b/196820244", "onError 2");
@@ -128,6 +130,13 @@
}
dumpCommand("logcat -d -s TestRunner", diagFile(description, "FilteredLogcat", "txt"));
+
+ // Dump bugreport
+ final String systemAnomalyMessage = launcher.getSystemAnomalyMessage(false, false);
+ if (systemAnomalyMessage != null) {
+ Log.d(TAG, "Saving bugreport, system anomaly message: " + systemAnomalyMessage, e);
+ dumpCommand("bugreportz -s", diagFile(description, "Bugreport", "zip"));
+ }
}
private static void dumpStringCommand(String cmd, OutputStream out) throws IOException {
diff --git a/tests/src/com/android/launcher3/util/rule/SamplerRule.java b/tests/src/com/android/launcher3/util/rule/SamplerRule.java
new file mode 100644
index 0000000..6125f2a
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/rule/SamplerRule.java
@@ -0,0 +1,129 @@
+/*
+ * 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 android.os.SystemClock;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * A rule that generates a file that helps diagnosing cases when the test process was terminated
+ * because the test execution took too long, and tests that ran for too long even without being
+ * terminated. If the process was terminated or the test was long, the test leaves an artifact with
+ * stack traces of all threads, every SAMPLE_INTERVAL_MS. This will help understanding where we
+ * stuck.
+ */
+public class SamplerRule implements TestRule {
+ private static final int TOO_LONG_TEST_MS = 180000;
+ private static final int SAMPLE_INTERVAL_MS = 3000;
+
+ public static Thread startThread(Description description) {
+ Thread thread =
+ new Thread() {
+ @Override
+ public void run() {
+ // Write all-threads stack stace every SAMPLE_INTERVAL_MS while the test
+ // is running.
+ // After the test finishes, delete that file. If the test process is
+ // terminated due to timeout, the trace file won't be deleted.
+ final File file = getFile();
+
+ final long startTime = SystemClock.elapsedRealtime();
+ try (OutputStreamWriter outputStreamWriter =
+ new OutputStreamWriter(
+ new BufferedOutputStream(
+ new FileOutputStream(file)))) {
+ writeSamples(outputStreamWriter);
+ } catch (IOException | InterruptedException e) {
+ // Simply suppressing the exceptions, nothing to do here.
+ } finally {
+ // If the process is not killed, then there was no test timeout, and
+ // we are not interested in the trace file, unless the test ran too
+ // long.
+ if (SystemClock.elapsedRealtime() - startTime < TOO_LONG_TEST_MS) {
+ file.delete();
+ }
+ }
+ }
+
+ private File getFile() {
+ final String strDate = new SimpleDateFormat("HH:mm:ss").format(new Date());
+
+ final String descStr = description.getTestClass().getSimpleName() + "."
+ + description.getMethodName();
+ return artifactFile(
+ "ThreadStackSamples-" + strDate + "-" + descStr + ".txt");
+ }
+
+ private void writeSamples(OutputStreamWriter writer)
+ throws IOException, InterruptedException {
+ int count = 0;
+ while (true) {
+ writer.write(
+ "#"
+ + (count++)
+ + " =============================================\r\n");
+ for (StackTraceElement[] stack : getAllStackTraces().values()) {
+ writer.write("---------------------\r\n");
+ for (StackTraceElement frame : stack) {
+ writer.write(frame.toString() + "\r\n");
+ }
+ }
+ writer.flush();
+
+ sleep(SAMPLE_INTERVAL_MS);
+ }
+ }
+ };
+
+ thread.start();
+ return thread;
+ }
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ final Thread traceThread = startThread(description);
+ try {
+ base.evaluate();
+ } finally {
+ traceThread.interrupt();
+ traceThread.join();
+ }
+ }
+ };
+ }
+
+ private static File artifactFile(String fileName) {
+ return new File(
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getFilesDir(),
+ fileName);
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java b/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java
index 0582bc9..98eb32e 100644
--- a/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java
+++ b/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java
@@ -22,8 +22,6 @@
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiObject2;
-import com.android.launcher3.testing.TestProtocol;
-
import java.util.regex.Pattern;
public class AddToHomeScreenPrompt {
@@ -44,19 +42,10 @@
public void addAutomatically() {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
- if (mLauncher.getNavigationModel()
- != LauncherInstrumentation.NavigationModel.THREE_BUTTON) {
- if (!mLauncher.isLauncher3()) {
- mLauncher.expectEvent(
- TestProtocol.SEQUENCE_TIS,
- LauncherInstrumentation.EVENT_TOUCH_DOWN_TIS);
- mLauncher.expectEvent(
- TestProtocol.SEQUENCE_TIS, LauncherInstrumentation.EVENT_TOUCH_UP_TIS);
- }
- }
- mLauncher.waitForObjectInContainer(
- mWidgetCell.getParent().getParent().getParent().getParent(),
- By.text(ADD_AUTOMATICALLY)).click();
+ mLauncher.clickObject(
+ mLauncher.waitForObjectInContainer(
+ mWidgetCell.getParent().getParent().getParent().getParent(),
+ 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 78301e4..bfb115d 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -22,6 +22,7 @@
import android.widget.TextView;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.Direction;
@@ -35,7 +36,7 @@
/**
* Operations on AllApps opened from Home. Also a parent for All Apps opened from Overview.
*/
-public class AllApps extends LauncherInstrumentation.VisibleContainer {
+public abstract class AllApps extends LauncherInstrumentation.VisibleContainer {
private static final int MAX_SCROLL_ATTEMPTS = 40;
private final int mHeight;
@@ -50,14 +51,8 @@
// Wait for the recycler to populate.
mLauncher.waitForObjectInContainer(appListRecycler, By.clazz(TextView.class));
verifyNotFrozen("All apps freeze flags upon opening all apps");
- mIconHeight = mLauncher.getTestInfo(
- TestProtocol.REQUEST_ICON_HEIGHT).
- getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
- }
-
- @Override
- protected LauncherInstrumentation.ContainerType getContainerType() {
- return LauncherInstrumentation.ContainerType.ALL_APPS;
+ mIconHeight = mLauncher.getTestInfo(TestProtocol.REQUEST_ICON_HEIGHT)
+ .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
private boolean hasClickableIcon(UiObject2 allAppsContainer, UiObject2 appListRecycler,
@@ -79,7 +74,7 @@
LauncherInstrumentation.log("hasClickableIcon: icon has insufficient height");
return false;
}
- if (iconCenterInSearchBox(allAppsContainer, icon)) {
+ if (hasSearchBox() && iconCenterInSearchBox(allAppsContainer, icon)) {
LauncherInstrumentation.log("hasClickableIcon: icon center is under search box");
return false;
}
@@ -98,21 +93,21 @@
}
/**
- * Finds an icon. Fails if the icon doesn't exist. Scrolls the app list when needed to make
- * sure the icon is visible.
+ * Finds an icon. If the icon doesn't exist, return null.
+ * Scrolls the app list when needed to make sure the icon is visible.
*
* @param appName name of the app.
- * @return The app.
+ * @return The app if found, and null if not found.
*/
- @NonNull
- public AppIcon getAppIcon(String appName) {
+ @Nullable
+ public AppIcon tryGetAppIcon(String appName) {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"getting app icon " + appName + " on all apps")) {
final UiObject2 allAppsContainer = verifyActiveContainer();
final UiObject2 appListRecycler = mLauncher.waitForObjectInContainer(allAppsContainer,
"apps_list_view");
- final UiObject2 searchBox = getSearchBox(allAppsContainer);
+ final UiObject2 searchBox = hasSearchBox() ? getSearchBox(allAppsContainer) : null;
int deviceHeight = mLauncher.getRealDisplaySize().y;
int bottomGestureStartOnScreen = mLauncher.getBottomGestureStartOnScreen();
@@ -133,8 +128,10 @@
mLauncher.getVisibleBounds(icon).top
< bottomGestureStartOnScreen)
.collect(Collectors.toList()),
- mLauncher.getVisibleBounds(searchBox).bottom
- - mLauncher.getVisibleBounds(allAppsContainer).top);
+ hasSearchBox()
+ ? mLauncher.getVisibleBounds(searchBox).bottom
+ - mLauncher.getVisibleBounds(allAppsContainer).top
+ : 0);
verifyActiveContainer();
final int newScroll = getAllAppsScroll();
mLauncher.assertTrue(
@@ -150,29 +147,49 @@
}
verifyActiveContainer();
}
-
// Ignore bottom offset selection here as there might not be any scroll more scroll
// region available.
- mLauncher.assertTrue("Unable to scroll to a clickable icon: " + appName,
- hasClickableIcon(allAppsContainer, appListRecycler, appIconSelector,
- deviceHeight));
+ if (hasClickableIcon(
+ allAppsContainer, appListRecycler, appIconSelector, deviceHeight)) {
- final UiObject2 appIcon = mLauncher.waitForObjectInContainer(appListRecycler,
- appIconSelector);
- return new AppIcon(mLauncher, appIcon);
+ final UiObject2 appIcon = mLauncher.waitForObjectInContainer(appListRecycler,
+ appIconSelector);
+ return createAppIcon(appIcon);
+ } else {
+ return null;
+ }
}
}
+ /**
+ * Finds an icon. Fails if the icon doesn't exist. Scrolls the app list when needed to make
+ * sure the icon is visible.
+ *
+ * @param appName name of the app.
+ * @return The app.
+ */
+ @NonNull
+ public AppIcon getAppIcon(String appName) {
+ AppIcon appIcon = tryGetAppIcon(appName);
+ mLauncher.assertNotNull("Unable to scroll to a clickable icon: " + appName, appIcon);
+ return appIcon;
+ }
+
+ @NonNull
+ protected abstract AppIcon createAppIcon(UiObject2 icon);
+
+ protected abstract boolean hasSearchBox();
+
private void scrollBackToBeginning() {
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to scroll back in all apps")) {
LauncherInstrumentation.log("Scrolling to the beginning");
final UiObject2 allAppsContainer = verifyActiveContainer();
- final UiObject2 searchBox = getSearchBox(allAppsContainer);
+ final UiObject2 searchBox = hasSearchBox() ? getSearchBox(allAppsContainer) : null;
int attempts = 0;
- final Rect margins =
- new Rect(0, mLauncher.getVisibleBounds(searchBox).bottom + 1, 0, 5);
+ final Rect margins = new Rect(
+ 0, hasSearchBox() ? mLauncher.getVisibleBounds(searchBox).bottom + 1 : 0, 0, 5);
for (int scroll = getAllAppsScroll();
scroll != 0;
@@ -184,7 +201,11 @@
++attempts <= MAX_SCROLL_ATTEMPTS);
mLauncher.scroll(
- allAppsContainer, Direction.UP, margins, 12, false);
+ allAppsContainer,
+ Direction.UP,
+ margins,
+ /* steps= */ 12,
+ /* slowDown= */ false);
}
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("scrolled up")) {
@@ -213,7 +234,11 @@
final UiObject2 allAppsContainer = verifyActiveContainer();
// Start the gesture in the center to avoid starting at elements near the top.
mLauncher.scroll(
- allAppsContainer, Direction.DOWN, new Rect(0, 0, 0, mHeight / 2), 10, false);
+ allAppsContainer,
+ Direction.DOWN,
+ new Rect(0, 0, 0, mHeight / 2),
+ /* steps= */ 10,
+ /* slowDown= */ false);
verifyActiveContainer();
}
}
@@ -228,7 +253,11 @@
final UiObject2 allAppsContainer = verifyActiveContainer();
// Start the gesture in the center, for symmetry with forward.
mLauncher.scroll(
- allAppsContainer, Direction.UP, new Rect(0, mHeight / 2, 0, 0), 10, false);
+ allAppsContainer,
+ Direction.UP,
+ new Rect(0, mHeight / 2, 0, 0),
+ /* steps= */ 10,
+ /*slowDown= */ false);
verifyActiveContainer();
}
}
@@ -253,4 +282,4 @@
if (testInfo == null) return;
mLauncher.assertEquals(message, 0, testInfo.getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD));
}
-}
+}
\ No newline at end of file
diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsAppIcon.java b/tests/tapl/com/android/launcher3/tapl/AllAppsAppIcon.java
new file mode 100644
index 0000000..8adce29
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/AllAppsAppIcon.java
@@ -0,0 +1,38 @@
+/*
+ * 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.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+import java.util.regex.Pattern;
+
+/**
+ * App icon in all apps.
+ */
+final class AllAppsAppIcon extends HomeAppIcon {
+
+ private static final Pattern LONG_CLICK_EVENT = Pattern.compile("onAllAppsItemLongClick");
+
+ AllAppsAppIcon(LauncherInstrumentation launcher, UiObject2 icon) {
+ super(launcher, icon);
+ }
+
+ @Override
+ protected Pattern getLongClickEvent() {
+ return LONG_CLICK_EVENT;
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java b/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
deleted file mode 100644
index 835790d..0000000
--- a/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
+++ /dev/null
@@ -1,67 +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.tapl;
-
-import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
-
-import android.graphics.Point;
-
-import androidx.annotation.NonNull;
-import androidx.test.uiautomator.UiObject2;
-
-import com.android.launcher3.testing.TestProtocol;
-
-/**
- * Operations on AllApps opened from Overview.
- */
-public final class AllAppsFromOverview extends AllApps {
-
- AllAppsFromOverview(LauncherInstrumentation launcher) {
- super(launcher);
- verifyActiveContainer();
- }
-
- /**
- * Swipes down to switch back to Overview whence we came from.
- *
- * @return the overview panel.
- */
- @NonNull
- public Overview switchBackToOverview() {
- try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
- LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "want to switch back from all apps to overview")) {
- final UiObject2 allAppsContainer = verifyActiveContainer();
- // Swipe from the search box to the bottom.
- final UiObject2 qsb = mLauncher.waitForObjectInContainer(
- allAppsContainer, "search_container_all_apps");
- final Point start = qsb.getVisibleCenter();
- final int swipeHeight = mLauncher.getTestInfo(
- TestProtocol.REQUEST_ALL_APPS_TO_OVERVIEW_SWIPE_HEIGHT).
- getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
-
- final int endY = start.y + swipeHeight;
- LauncherInstrumentation.log("AllAppsFromOverview.switchBackToOverview before swipe");
- mLauncher.swipeToState(start.x, start.y, start.x, endY, 60, OVERVIEW_STATE_ORDINAL,
- LauncherInstrumentation.GestureScope.INSIDE);
-
- try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("swiped down")) {
- return new Overview(mLauncher);
- }
- }
- }
-}
diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java b/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java
new file mode 100644
index 0000000..5164025
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java
@@ -0,0 +1,51 @@
+/*
+ * 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.tapl;
+
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * Operations on AllApps opened from the Taskbar.
+ */
+public class AllAppsFromTaskbar extends AllApps {
+
+ AllAppsFromTaskbar(LauncherInstrumentation launcher) {
+ super(launcher);
+ }
+
+ @Override
+ protected LauncherInstrumentation.ContainerType getContainerType() {
+ return LauncherInstrumentation.ContainerType.TASKBAR_ALL_APPS;
+ }
+
+ @NonNull
+ @Override
+ public TaskbarAppIcon getAppIcon(String appName) {
+ return (TaskbarAppIcon) super.getAppIcon(appName);
+ }
+
+ @NonNull
+ @Override
+ protected TaskbarAppIcon createAppIcon(UiObject2 icon) {
+ return new TaskbarAppIcon(mLauncher, icon);
+ }
+
+ @Override
+ protected boolean hasSearchBox() {
+ return false;
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIcon.java b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
index 6da59da..e28f0af 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIcon.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
@@ -16,11 +16,8 @@
package com.android.launcher3.tapl;
-import android.graphics.Point;
-import android.graphics.Rect;
import android.widget.TextView;
-import androidx.annotation.NonNull;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiObject2;
@@ -30,11 +27,9 @@
import java.util.regex.Pattern;
/**
- * App icon, whether in all apps or in workspace/
+ * App icon, whether in all apps, workspace or the taskbar.
*/
-public final class AppIcon extends Launchable implements FolderDragTarget {
-
- private static final Pattern LONG_CLICK_EVENT = Pattern.compile("onAllAppsItemLongClick");
+public abstract class AppIcon extends Launchable {
AppIcon(LauncherInstrumentation launcher, UiObject2 icon) {
super(launcher, icon);
@@ -44,13 +39,19 @@
return By.clazz(TextView.class).text(appName).pkg(launcher.getLauncherPackageName());
}
+ static BySelector getAnyAppIconSelector() {
+ return By.clazz(TextView.class);
+ }
+
+ protected abstract Pattern getLongClickEvent();
+
/**
* Long-clicks the icon to open its menu.
*/
public AppIconMenu openMenu() {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
- return new AppIconMenu(mLauncher, mLauncher.clickAndGet(
- mObject, "popup_container", LONG_CLICK_EVENT));
+ return createMenu(mLauncher.clickAndGet(
+ mObject, /* resName= */ "popup_container", getLongClickEvent()));
}
}
@@ -59,42 +60,21 @@
*/
public AppIconMenu openDeepShortcutMenu() {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
- return new AppIconMenu(mLauncher, mLauncher.clickAndGet(
- mObject, "deep_shortcuts_container", LONG_CLICK_EVENT));
+ return createMenu(mLauncher.clickAndGet(
+ mObject, /* resName= */ "deep_shortcuts_container", getLongClickEvent()));
}
}
- /**
- * Drag the AppIcon to the given position of other icon. The drag must result in a folder.
- *
- * @param target the destination icon.
- */
- @NonNull
- public FolderIcon dragToIcon(FolderDragTarget target) {
- try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
- LauncherInstrumentation.Closable c = mLauncher.addContextLayer("want to drag icon")) {
- final Rect dropBounds = target.getDropLocationBounds();
- Workspace.dragIconToWorkspace(
- mLauncher, this,
- () -> {
- final Rect bounds = target.getDropLocationBounds();
- return new Point(bounds.centerX(), bounds.centerY());
- },
- getLongPressIndicator());
- FolderIcon result = target.getTargetFolder(dropBounds);
- mLauncher.assertTrue("Can't find the target folder.", result != null);
- return result;
- }
- }
+ protected abstract AppIconMenu createMenu(UiObject2 menu);
@Override
protected void addExpectedEventsForLongClick() {
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT);
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, getLongClickEvent());
}
@Override
- protected String getLongPressIndicator() {
- return "popup_container";
+ protected void waitForLongPressConfirmation() {
+ mLauncher.waitForLauncherObject("popup_container");
}
@Override
@@ -106,20 +86,4 @@
protected String launchableType() {
return "app icon";
}
-
- @Override
- public Rect getDropLocationBounds() {
- return mLauncher.getVisibleBounds(mObject);
- }
-
- @Override
- public FolderIcon getTargetFolder(Rect bounds) {
- for (FolderIcon folderIcon : mLauncher.getWorkspace().getFolderIcons()) {
- final Rect folderIconBounds = folderIcon.getDropLocationBounds();
- if (bounds.contains(folderIconBounds.centerX(), folderIconBounds.centerY())) {
- return folderIcon;
- }
- }
- return null;
- }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java b/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
index 7f28151..82d9630 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
@@ -25,9 +25,9 @@
/**
* Context menu of an app icon.
*/
-public class AppIconMenu {
- private final LauncherInstrumentation mLauncher;
- private final UiObject2 mDeepShortcutsContainer;
+public abstract class AppIconMenu {
+ protected final LauncherInstrumentation mLauncher;
+ protected final UiObject2 mDeepShortcutsContainer;
AppIconMenu(LauncherInstrumentation launcher,
UiObject2 deepShortcutsContainer) {
@@ -42,6 +42,17 @@
final List<UiObject2> menuItems = mLauncher.getObjectsInContainer(mDeepShortcutsContainer,
"bubble_text");
assertTrue(menuItems.size() > itemNumber);
- return new AppIconMenuItem(mLauncher, menuItems.get(itemNumber));
+ return createMenuItem(menuItems.get(itemNumber));
}
+
+ /**
+ * Returns a menu item with the given text. Fails if it doesn't exist.
+ */
+ public AppIconMenuItem getMenuItem(String shortcutText) {
+ final UiObject2 menuItem = mLauncher.waitForObjectInContainer(mDeepShortcutsContainer,
+ AppIcon.getAppIconSelector(shortcutText, mLauncher));
+ return createMenuItem(menuItem);
+ }
+
+ protected abstract AppIconMenuItem createMenuItem(UiObject2 menuItem);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java b/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java
index ac0db08..5cf5aba 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java
@@ -23,7 +23,7 @@
/**
* Menu item in an app icon menu.
*/
-public class AppIconMenuItem extends Launchable {
+public abstract class AppIconMenuItem extends Launchable {
AppIconMenuItem(LauncherInstrumentation launcher, UiObject2 shortcut) {
super(launcher, shortcut);
@@ -41,8 +41,8 @@
}
@Override
- protected String getLongPressIndicator() {
- return "drop_target_bar";
+ protected void waitForLongPressConfirmation() {
+ mLauncher.waitForLauncherObject("drop_target_bar");
}
@Override
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 4eaecca..589e13c 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -37,7 +37,7 @@
* Indicates the base state with a UI other than Overview running as foreground. It can also
* indicate Launcher as long as Launcher is not in Overview state.
*/
-public class Background extends LauncherInstrumentation.VisibleContainer {
+public abstract class Background extends LauncherInstrumentation.VisibleContainer {
private static final int ZERO_BUTTON_SWIPE_UP_GESTURE_DURATION = 500;
private static final Pattern SQUARE_BUTTON_EVENT = Pattern.compile("onOverviewToggle");
@@ -45,11 +45,6 @@
super(launcher);
}
- @Override
- protected LauncherInstrumentation.ContainerType getContainerType() {
- return LauncherInstrumentation.ContainerType.BACKGROUND;
- }
-
/**
* Swipes up or presses the square button to switch to Overview.
* Returns the base overview, which can be either in Launcher or the fallback recents.
@@ -80,7 +75,8 @@
protected void goToOverviewUnchecked() {
switch (mLauncher.getNavigationModel()) {
case ZERO_BUTTON: {
- sendDownPointerToEnterOverviewToLauncher();
+ 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
@@ -89,16 +85,17 @@
// 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(this::sendSwipeUpAndHoldToEnterOverviewGestureToLauncher,
+ mLauncher.runToState(
+ () -> sendSwipeUpAndHoldToEnterOverviewGestureToLauncher(downTime),
OVERVIEW_STATE_ORDINAL, swipeAndHoldToEnterOverviewActionName);
- sendUpPointerToEnterOverviewToLauncher();
+ 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(
- this::sendSwipeUpAndHoldToEnterOverviewGestureToLauncher,
+ () -> sendSwipeUpAndHoldToEnterOverviewGestureToLauncher(downTime),
event -> TestProtocol.PAUSE_DETECTED_MESSAGE.equals(
event.getClassName().toString()),
() -> "Pause wasn't detected",
@@ -127,38 +124,13 @@
}
String upPointerToEnterOverviewActionName =
"sending UP pointer to enter overview";
- mLauncher.runToState(this::sendUpPointerToEnterOverviewToLauncher,
+ mLauncher.runToState(() -> sendUpPointerToEnterOverviewToLauncher(downTime),
OVERVIEW_STATE_ORDINAL, upPointerToEnterOverviewActionName);
}
}
break;
}
- case TWO_BUTTON: {
- final int startX;
- final int startY;
- final int endX;
- final int endY;
- final int swipeLength = mLauncher.getTestInfo(getSwipeHeightRequestName()).
- getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD) + mLauncher.getTouchSlop();
-
- if (mLauncher.getDevice().isNaturalOrientation()) {
- startX = endX = mLauncher.getDevice().getDisplayWidth() / 2;
- startY = getSwipeStartY();
- endY = startY - swipeLength;
- } else {
- startX = getSwipeStartX();
- // TODO(b/184059820) make horizontal swipe use swipe width not height, for the
- // moment just double the swipe length.
- endX = startX - swipeLength * 2;
- startY = endY = mLauncher.getDevice().getDisplayHeight() / 2;
- }
-
- mLauncher.swipeToState(startX, startY, endX, endY, 10, OVERVIEW_STATE_ORDINAL,
- LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
- break;
- }
-
case THREE_BUTTON:
if (mLauncher.isTablet()) {
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
@@ -178,21 +150,24 @@
private void expectSwitchToOverviewEvents() {
}
- private void sendDownPointerToEnterOverviewToLauncher() {
+ private void sendDownPointerToEnterOverviewToLauncher(long downTime) {
final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
final int startY = getSwipeStartY();
final Point start = new Point(centerX, startY);
- final long downTime = SystemClock.uptimeMillis();
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, gestureScope);
+
+ if (!mLauncher.isLauncher3()) {
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_PILFER,
+ LauncherInstrumentation.EVENT_PILFER_POINTERS);
+ }
}
- private void sendSwipeUpAndHoldToEnterOverviewGestureToLauncher() {
+ private void sendSwipeUpAndHoldToEnterOverviewGestureToLauncher(long downTime) {
final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
final int startY = getSwipeStartY();
final int swipeHeight = mLauncher.getTestInfo(getSwipeHeightRequestName()).getInt(
@@ -200,7 +175,6 @@
final Point start = new Point(centerX, startY);
final Point end =
new Point(centerX, startY - swipeHeight - mLauncher.getTouchSlop());
- final long downTime = SystemClock.uptimeMillis();
final LauncherInstrumentation.GestureScope gestureScope =
zeroButtonToOverviewGestureStartsInLauncher()
? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
@@ -215,35 +189,35 @@
gestureScope);
}
- private void sendUpPointerToEnterOverviewToLauncher() {
+ private void sendUpPointerToEnterOverviewToLauncher(long downTime) {
final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
final int startY = getSwipeStartY();
final int swipeHeight = mLauncher.getTestInfo(getSwipeHeightRequestName()).getInt(
TestProtocol.TEST_INFO_RESPONSE_FIELD);
final Point end =
new Point(centerX, startY - swipeHeight - mLauncher.getTouchSlop());
- final long downTime = SystemClock.uptimeMillis();
+
final LauncherInstrumentation.GestureScope gestureScope =
zeroButtonToOverviewGestureStartsInLauncher()
- ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
- : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER;
+ ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER
+ : LauncherInstrumentation.GestureScope.OUTSIDE_WITHOUT_PILFER;
mLauncher.sendPointer(downTime, SystemClock.uptimeMillis(),
MotionEvent.ACTION_UP, end, gestureScope);
}
@NonNull
- public Background quickSwitchToPreviousApp() {
+ public LaunchedAppState quickSwitchToPreviousApp() {
boolean toRight = true;
quickSwitch(toRight);
- return new Background(mLauncher);
+ return new LaunchedAppState(mLauncher);
}
@NonNull
- public Background quickSwitchToPreviousAppSwipeLeft() {
+ public LaunchedAppState quickSwitchToPreviousAppSwipeLeft() {
boolean toRight = false;
quickSwitch(toRight);
- return new Background(mLauncher);
+ return new LaunchedAppState(mLauncher);
}
@NonNull
@@ -253,11 +227,7 @@
"want to quick switch to the previous app")) {
verifyActiveContainer();
final boolean launcherWasVisible = mLauncher.isLauncherVisible();
- boolean transposeInLandscape = false;
switch (mLauncher.getNavigationModel()) {
- case TWO_BUTTON:
- transposeInLandscape = true;
- // Fall through, zero button and two button modes behave the same.
case ZERO_BUTTON: {
final int startX;
final int startY;
@@ -265,33 +235,17 @@
final int endY;
final int cornerRadius = (int) Math.ceil(mLauncher.getWindowCornerRadius());
if (toRight) {
- if (mLauncher.getDevice().isNaturalOrientation() || !transposeInLandscape) {
- // 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 top right of the screen.
- startX = getSwipeStartX();
- startY = mLauncher.getRealDisplaySize().y - 1 - cornerRadius;
- endX = startX;
- endY = cornerRadius;
- }
+ // Swipe from the bottom left to the bottom right of the screen.
+ startX = cornerRadius;
+ startY = getSwipeStartY();
+ endX = mLauncher.getDevice().getDisplayWidth() - cornerRadius;
+ endY = startY;
} else {
- if (mLauncher.getDevice().isNaturalOrientation() || !transposeInLandscape) {
- // Swipe from the bottom right to the bottom left of the screen.
- startX = mLauncher.getDevice().getDisplayWidth() - cornerRadius;
- startY = getSwipeStartY();
- endX = cornerRadius;
- endY = startY;
- } else {
- // Swipe from the bottom left to the top left of the screen.
- startX = getSwipeStartX();
- startY = cornerRadius;
- endX = startX;
- endY = mLauncher.getRealDisplaySize().y - 1 - cornerRadius;
- }
+ // 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()
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index 3eb8cf1..b7bca02 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -127,7 +127,8 @@
OverviewTask task = getCurrentTask();
mLauncher.assertNotNull("current task is null", task);
- mLauncher.scrollLeftByDistance(verifyActiveContainer(), task.getVisibleWidth());
+ mLauncher.scrollLeftByDistance(verifyActiveContainer(),
+ task.getVisibleWidth() + mLauncher.getOverviewPageSpacing());
try (LauncherInstrumentation.Closable c2 =
mLauncher.addContextLayer("scrolled task off screen")) {
diff --git a/tests/tapl/com/android/launcher3/tapl/Folder.java b/tests/tapl/com/android/launcher3/tapl/Folder.java
index dba308d..26f0a8b 100644
--- a/tests/tapl/com/android/launcher3/tapl/Folder.java
+++ b/tests/tapl/com/android/launcher3/tapl/Folder.java
@@ -40,10 +40,10 @@
* Find an app icon with given name or raise assertion error.
*/
@NonNull
- public AppIcon getAppIcon(String appName) {
+ public HomeAppIcon getAppIcon(String appName) {
try (LauncherInstrumentation.Closable ignored = mLauncher.addContextLayer(
"Want to get app icon in folder")) {
- return new AppIcon(mLauncher,
+ return new WorkspaceAppIcon(mLauncher,
mLauncher.waitForObjectInContainer(
mContainer,
AppIcon.getAppIconSelector(appName, mLauncher)));
diff --git a/tests/tapl/com/android/launcher3/tapl/FolderDragTarget.java b/tests/tapl/com/android/launcher3/tapl/FolderDragTarget.java
index d797418..2c60668 100644
--- a/tests/tapl/com/android/launcher3/tapl/FolderDragTarget.java
+++ b/tests/tapl/com/android/launcher3/tapl/FolderDragTarget.java
@@ -19,7 +19,10 @@
import android.graphics.Rect;
public interface FolderDragTarget {
+
+ /** This method requires public access, however should not be called in tests. */
Rect getDropLocationBounds();
+ /** This method requires public access, however should not be called in tests. */
FolderIcon getTargetFolder(Rect bounds);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/FolderIcon.java b/tests/tapl/com/android/launcher3/tapl/FolderIcon.java
index 2e79d70..9b4717f 100644
--- a/tests/tapl/com/android/launcher3/tapl/FolderIcon.java
+++ b/tests/tapl/com/android/launcher3/tapl/FolderIcon.java
@@ -52,11 +52,13 @@
return new Folder(mLauncher);
}
+ /** This method requires public access, however should not be called in tests. */
@Override
public Rect getDropLocationBounds() {
return mLauncher.getVisibleBounds(mObject.getParent());
}
+ /** This method requires public access, however should not be called in tests. */
@Override
public FolderIcon getTargetFolder(Rect bounds) {
return this;
diff --git a/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java
new file mode 100644
index 0000000..c275f3b
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java
@@ -0,0 +1,48 @@
+/*
+ * 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.tapl;
+
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiObject2;
+
+public class HomeAllApps extends AllApps {
+
+ HomeAllApps(LauncherInstrumentation launcher) {
+ super(launcher);
+ }
+
+ @Override
+ protected LauncherInstrumentation.ContainerType getContainerType() {
+ return LauncherInstrumentation.ContainerType.HOME_ALL_APPS;
+ }
+
+ @NonNull
+ @Override
+ public HomeAppIcon getAppIcon(String appName) {
+ return (AllAppsAppIcon) super.getAppIcon(appName);
+ }
+
+ @NonNull
+ @Override
+ protected HomeAppIcon createAppIcon(UiObject2 icon) {
+ return new AllAppsAppIcon(mLauncher, icon);
+ }
+
+ @Override
+ protected boolean hasSearchBox() {
+ return true;
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java b/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java
new file mode 100644
index 0000000..71d8ba9
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java
@@ -0,0 +1,142 @@
+/*
+ * 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.tapl;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiObject2;
+
+import java.util.function.Supplier;
+
+/**
+ * App icon on the workspace or all apps.
+ */
+public abstract class HomeAppIcon extends AppIcon implements FolderDragTarget, WorkspaceDragSource {
+
+ private final String mAppName;
+
+ HomeAppIcon(LauncherInstrumentation launcher, UiObject2 icon) {
+ super(launcher, icon);
+ mAppName = icon.getText();
+ }
+
+ /**
+ * Drag the AppIcon to the given position of other icon. The drag must result in a folder.
+ *
+ * @param target the destination icon.
+ */
+ @NonNull
+ public FolderIcon dragToIcon(FolderDragTarget target) {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c = mLauncher.addContextLayer("want to drag icon")) {
+ final Rect dropBounds = target.getDropLocationBounds();
+ Workspace.dragIconToWorkspace(
+ mLauncher, this,
+ () -> {
+ final Rect bounds = target.getDropLocationBounds();
+ return new Point(bounds.centerX(), bounds.centerY());
+ });
+ FolderIcon result = target.getTargetFolder(dropBounds);
+ mLauncher.assertTrue("Can't find the target folder.", result != null);
+ return result;
+ }
+ }
+
+ /** This method requires public access, however should not be called in tests. */
+ @Override
+ public Rect getDropLocationBounds() {
+ return mLauncher.getVisibleBounds(mObject);
+ }
+
+ /** This method requires public access, however should not be called in tests. */
+ @Override
+ public FolderIcon getTargetFolder(Rect bounds) {
+ for (FolderIcon folderIcon : mLauncher.getWorkspace().getFolderIcons()) {
+ final Rect folderIconBounds = folderIcon.getDropLocationBounds();
+ if (bounds.contains(folderIconBounds.centerX(), folderIconBounds.centerY())) {
+ return folderIcon;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public HomeAppIconMenu openDeepShortcutMenu() {
+ return (HomeAppIconMenu) super.openDeepShortcutMenu();
+ }
+
+ @Override
+ protected HomeAppIconMenu createMenu(UiObject2 menu) {
+ return new HomeAppIconMenu(mLauncher, menu);
+ }
+
+ /**
+ * Uninstall the appIcon by dragging it to the 'uninstall' drop point of the drop_target_bar.
+ *
+ * @return validated workspace after the existing appIcon being uninstalled.
+ */
+ public Workspace uninstall() {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "uninstalling app icon")) {
+ return Workspace.uninstallAppIcon(
+ mLauncher, this,
+ this::addExpectedEventsForLongClick
+ );
+ }
+ }
+
+ /**
+ * Drag an object to the given cell in workspace. The target cell must be empty.
+ *
+ * @param cellX zero based column number, starting from the left of the screen.
+ * @param cellY zero based row number, starting from the top of the screen.
+ */
+ public HomeAppIcon dragToWorkspace(int cellX, int cellY) {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ String.format("want to drag the icon to cell(%d, %d)", cellX, cellY))
+ ) {
+ final Supplier<Point> dest = () -> Workspace.getCellCenter(mLauncher, cellX, cellY);
+ Workspace.dragIconToWorkspace(
+ mLauncher,
+ /* launchable= */ this,
+ dest,
+ () -> addExpectedEventsForLongClick(),
+ /*expectDropEvents= */ null);
+ try (LauncherInstrumentation.Closable ignore = mLauncher.addContextLayer("dragged")) {
+ WorkspaceAppIcon appIcon =
+ (WorkspaceAppIcon) mLauncher.getWorkspace().getWorkspaceAppIcon(mAppName);
+ mLauncher.assertTrue(
+ String.format(
+ "The %s icon should be in the cell (%d, %d).", mAppName, cellX,
+ cellY),
+ appIcon.isInCell(cellX, cellY));
+ return appIcon;
+ }
+ }
+ }
+
+
+ /** 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/HomeAppIconMenu.java b/tests/tapl/com/android/launcher3/tapl/HomeAppIconMenu.java
new file mode 100644
index 0000000..71fb6c0
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/HomeAppIconMenu.java
@@ -0,0 +1,39 @@
+/*
+ * 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.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * Context menu of a home screen app icon.
+ */
+public final class HomeAppIconMenu extends AppIconMenu {
+
+ HomeAppIconMenu(LauncherInstrumentation launcher,
+ UiObject2 deepShortcutsContainer) {
+ super(launcher, deepShortcutsContainer);
+ }
+
+ @Override
+ public HomeAppIconMenuItem getMenuItem(int itemNumber) {
+ return (HomeAppIconMenuItem) super.getMenuItem(itemNumber);
+ }
+
+ @Override
+ protected HomeAppIconMenuItem createMenuItem(UiObject2 menuItem) {
+ return new HomeAppIconMenuItem(mLauncher, menuItem);
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/HomeAppIconMenuItem.java b/tests/tapl/com/android/launcher3/tapl/HomeAppIconMenuItem.java
new file mode 100644
index 0000000..1ff0c10
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/HomeAppIconMenuItem.java
@@ -0,0 +1,35 @@
+/*
+ * 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.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * Menu item in a home screen app icon menu.
+ */
+public final class HomeAppIconMenuItem extends AppIconMenuItem implements WorkspaceDragSource {
+
+ HomeAppIconMenuItem(LauncherInstrumentation launcher,
+ UiObject2 shortcut) {
+ super(launcher, shortcut);
+ }
+
+ /** 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/HomeQsb.java b/tests/tapl/com/android/launcher3/tapl/HomeQsb.java
new file mode 100644
index 0000000..5f92199
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/HomeQsb.java
@@ -0,0 +1,45 @@
+/*
+ * 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.tapl;
+
+/**
+ * Operations on home screen qsb.
+ */
+public class HomeQsb {
+
+ private final LauncherInstrumentation mLauncher;
+
+ HomeQsb(LauncherInstrumentation launcher) {
+ mLauncher = launcher;
+ mLauncher.waitForLauncherObject("search_container_hotseat");
+ }
+
+ /**
+ * Show search result page from tapping qsb.
+ */
+ public SearchResultFromQsb showSearchResult() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to open search result page");
+ LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
+ mLauncher.clickLauncherObject(
+ mLauncher.waitForLauncherObject("search_container_hotseat"));
+ try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer(
+ "clicked qsb to open search result page")) {
+ return new SearchResultFromQsb(mLauncher);
+ }
+ }
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 7ec5208..33fea2d 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -16,19 +16,25 @@
package com.android.launcher3.tapl;
-import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
+import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
import android.graphics.Point;
+import android.view.MotionEvent;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
+import com.android.launcher3.testing.TestProtocol;
+
/**
* Ancestor for AppIcon and AppMenuItem.
*/
-abstract class Launchable {
+public abstract class Launchable {
+
+ protected static final int DEFAULT_DRAG_STEPS = 10;
+
protected final LauncherInstrumentation mLauncher;
protected final UiObject2 mObject;
@@ -45,7 +51,7 @@
/**
* Clicks the object to launch its app.
*/
- public Background launch(String expectedPackageName) {
+ public LaunchedAppState launch(String expectedPackageName) {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
return launch(By.pkg(expectedPackageName));
}
@@ -55,59 +61,96 @@
protected abstract String launchableType();
- private Background launch(BySelector selector) {
- try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ private LaunchedAppState launch(BySelector selector) {
+ try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
"want to launch an app from " + launchableType())) {
LauncherInstrumentation.log("Launchable.launch before click "
+ mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
- final String label = mObject.getText();
- mLauncher.executeAndWaitForEvent(
- () -> {
- mLauncher.clickLauncherObject(mObject);
- expectActivityStartEvents();
- },
- event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
- () -> "Launching an app didn't open a new window: " + label,
- "clicking " + launchableType());
+ mLauncher.clickLauncherObject(mObject);
- try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("clicked")) {
- mLauncher.assertTrue(
- "App didn't start: " + label + " (" + selector + ")",
- TestHelpers.wait(Until.hasObject(selector),
- LauncherInstrumentation.WAIT_TIME_MS));
- return new Background(mLauncher);
+ try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
+ expectActivityStartEvents();
+ return assertAppLaunched(selector);
}
}
}
- /**
- * Drags an object to the center of homescreen.
- *
- * @param startsActivity whether it's expected to start an activity.
- * @param isWidgetShortcut whether we drag a widget shortcut
- */
- public void dragToWorkspace(boolean startsActivity, boolean isWidgetShortcut) {
- try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
- final Point launchableCenter = getObject().getVisibleCenter();
- final Point displaySize = mLauncher.getRealDisplaySize();
- final int width = displaySize.x / 2;
- Workspace.dragIconToWorkspace(
- mLauncher,
- this,
- new Point(
- launchableCenter.x >= width
- ? launchableCenter.x - width / 2
- : launchableCenter.x + width / 2,
- displaySize.y / 2),
- getLongPressIndicator(),
- startsActivity,
- isWidgetShortcut,
- () -> addExpectedEventsForLongClick());
+ protected LaunchedAppState assertAppLaunched(BySelector selector) {
+ mLauncher.assertTrue(
+ "App didn't start: (" + selector + ")",
+ mLauncher.getDevice().wait(Until.hasObject(selector),
+ LauncherInstrumentation.WAIT_TIME_MS));
+ return new LaunchedAppState(mLauncher);
+ }
+
+ Point startDrag(long downTime, Runnable expectLongClickEvents, boolean runToSpringLoadedState) {
+ final Point iconCenter = getObject().getVisibleCenter();
+ final Point dragStartCenter = new Point(iconCenter.x,
+ iconCenter.y - getStartDragThreshold());
+
+ if (runToSpringLoadedState) {
+ mLauncher.runToState(() -> movePointerForStartDrag(
+ downTime,
+ iconCenter,
+ dragStartCenter,
+ expectLongClickEvents),
+ SPRING_LOADED_STATE_ORDINAL, "long-pressing and triggering drag start");
+ } else {
+ movePointerForStartDrag(
+ downTime,
+ iconCenter,
+ dragStartCenter,
+ expectLongClickEvents);
}
+
+ return dragStartCenter;
+ }
+
+ /**
+ * Waits for a confirmation that a long press has successfully been triggered.
+ *
+ * This method waits for a view to either appear or disappear to confirm that the long press
+ * has been triggered and fails if no confirmation is received before the default timeout.
+ */
+ protected abstract void waitForLongPressConfirmation();
+
+ /**
+ * Drags this Launchable a short distance before starting a full drag.
+ *
+ * This is necessary for shortcuts, which require being dragged beyond a threshold to close
+ * their container and start drag callbacks.
+ */
+ private void movePointerForStartDrag(
+ long downTime,
+ Point iconCenter,
+ Point dragStartCenter,
+ Runnable expectLongClickEvents) {
+ mLauncher.sendPointer(
+ downTime,
+ downTime,
+ MotionEvent.ACTION_DOWN,
+ iconCenter,
+ LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.log("movePointerForStartDrag: sent down");
+ expectLongClickEvents.run();
+ waitForLongPressConfirmation();
+ LauncherInstrumentation.log("movePointerForStartDrag: indicator");
+ mLauncher.movePointer(
+ iconCenter,
+ dragStartCenter,
+ DEFAULT_DRAG_STEPS,
+ /* isDecelerating= */ false,
+ downTime,
+ downTime,
+ /* slowDown= */ true,
+ LauncherInstrumentation.GestureScope.INSIDE);
+ }
+
+ private int getStartDragThreshold() {
+ return mLauncher.getTestInfo(TestProtocol.REQUEST_START_DRAG_THRESHOLD).getInt(
+ TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
protected abstract void addExpectedEventsForLongClick();
-
- protected abstract String getLongPressIndicator();
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
new file mode 100644
index 0000000..046d36b
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
@@ -0,0 +1,156 @@
+/*
+ * 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.tapl;
+
+import static com.android.launcher3.testing.TestProtocol.REQUEST_DISABLE_MANUAL_TASKBAR_STASHING;
+import static com.android.launcher3.testing.TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING;
+import static com.android.launcher3.testing.TestProtocol.REQUEST_STASHED_TASKBAR_HEIGHT;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.view.MotionEvent;
+
+import androidx.test.uiautomator.By;
+
+import com.android.launcher3.testing.TestProtocol;
+
+/**
+ * Background state operations specific to when an app has been launched.
+ */
+public final class LaunchedAppState extends Background {
+
+ // More drag steps than Launchables to give the window manager time to register the drag.
+ private static final int DEFAULT_DRAG_STEPS = 35;
+
+ LaunchedAppState(LauncherInstrumentation launcher) {
+ super(launcher);
+ }
+
+ @Override
+ protected LauncherInstrumentation.ContainerType getContainerType() {
+ return LauncherInstrumentation.ContainerType.LAUNCHED_APP;
+ }
+
+ /**
+ * Returns the taskbar.
+ *
+ * The taskbar must already be visible when calling this method.
+ */
+ public Taskbar getTaskbar() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to get the taskbar")) {
+ mLauncher.waitForLauncherObject("taskbar_view");
+
+ return new Taskbar(mLauncher);
+ }
+ }
+
+ /**
+ * Returns the Taskbar in a visible state.
+ *
+ * The taskbar must already be hidden when calling this method.
+ */
+ public Taskbar showTaskbar() {
+ mLauncher.getTestInfo(REQUEST_ENABLE_MANUAL_TASKBAR_STASHING);
+
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "want to show the taskbar")) {
+ mLauncher.waitUntilLauncherObjectGone("taskbar_view");
+
+ final long downTime = SystemClock.uptimeMillis();
+ final int unstashTargetY = mLauncher.getRealDisplaySize().y
+ - (mLauncher.getTestInfo(REQUEST_STASHED_TASKBAR_HEIGHT)
+ .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD) / 2);
+ final Point unstashTarget = new Point(
+ mLauncher.getRealDisplaySize().x / 2, unstashTargetY);
+
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, unstashTarget,
+ LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
+ LauncherInstrumentation.log("showTaskbar: sent down");
+
+ try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("pressed down")) {
+ mLauncher.waitForLauncherObject("taskbar_view");
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, unstashTarget,
+ LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
+
+ return new Taskbar(mLauncher);
+ }
+ } finally {
+ mLauncher.getTestInfo(REQUEST_DISABLE_MANUAL_TASKBAR_STASHING);
+ }
+ }
+
+ static void dragToSplitscreen(
+ LauncherInstrumentation launcher,
+ Launchable launchable,
+ String expectedNewPackageName,
+ String expectedExistingPackageName) {
+ try (LauncherInstrumentation.Closable c1 = launcher.addContextLayer(
+ "want to drag taskbar item to splitscreen")) {
+ final Point displaySize = launcher.getRealDisplaySize();
+ // Drag to the center of the top-left quadrant of the screen, this point will work in
+ // both portrait and landscape.
+ final Point endPoint = new Point(displaySize.x / 4, displaySize.y / 4);
+ final long downTime = SystemClock.uptimeMillis();
+ // Use mObject before starting drag since the system drag and drop moves the original
+ // view.
+ Point itemVisibleCenter = launchable.mObject.getVisibleCenter();
+ Rect itemVisibleBounds = launcher.getVisibleBounds(launchable.mObject);
+ String itemLabel = launchable.mObject.getText();
+
+ Point dragStart = launchable.startDrag(
+ downTime,
+ launchable::addExpectedEventsForLongClick,
+ /* runToSpringLoadedState= */ false);
+
+ try (LauncherInstrumentation.Closable c2 = launcher.addContextLayer(
+ "started item drag")) {
+ launcher.movePointer(
+ dragStart,
+ endPoint,
+ DEFAULT_DRAG_STEPS,
+ /* isDecelerating= */ true,
+ downTime,
+ SystemClock.uptimeMillis(),
+ /* slowDown= */ false,
+ LauncherInstrumentation.GestureScope.INSIDE);
+
+ try (LauncherInstrumentation.Closable c3 = launcher.addContextLayer(
+ "moved pointer to drop point")) {
+ LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: "
+ + "before drop " + itemVisibleCenter + " in " + itemVisibleBounds);
+ launcher.sendPointer(
+ downTime,
+ SystemClock.uptimeMillis(),
+ MotionEvent.ACTION_UP,
+ endPoint,
+ LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER);
+ LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: "
+ + "after drop");
+
+ try (LauncherInstrumentation.Closable c4 = launcher.addContextLayer(
+ "dropped item")) {
+ launchable.assertAppLaunched(By.pkg(expectedNewPackageName));
+ launchable.assertAppLaunched(By.pkg(expectedExistingPackageName));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 631e8f1..9d25b1b 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -66,6 +66,7 @@
import androidx.test.uiautomator.Until;
import com.android.launcher3.ResourceUtils;
+import com.android.launcher3.testing.TestInformationRequest;
import com.android.launcher3.testing.TestProtocol;
import com.android.systemui.shared.system.ContextUtils;
import com.android.systemui.shared.system.QuickStepContract;
@@ -98,18 +99,19 @@
public final class LauncherInstrumentation {
private static final String TAG = "Tapl";
- private static final int ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME = 20;
+ private static final int ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME = 15;
private static final int GESTURE_STEP_MS = 16;
private static final long FORCE_PAUSE_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(2);
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");
- private static final Pattern EVENT_PILFER_POINTERS = Pattern.compile("pilferPointers");
+ 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_KEY_BACK_DOWN = getKeyEventPattern("ACTION_DOWN", "KEYCODE_BACK");
static final Pattern EVENT_KEY_BACK_UP = getKeyEventPattern("ACTION_UP", "KEYCODE_BACK");
@@ -121,20 +123,23 @@
// Types for launcher containers that the user is interacting with. "Background" is a
// pseudo-container corresponding to inactive launcher covered by another app.
public enum ContainerType {
- WORKSPACE, ALL_APPS, OVERVIEW, WIDGETS, BACKGROUND, FALLBACK_OVERVIEW
+ WORKSPACE, HOME_ALL_APPS, OVERVIEW, WIDGETS, FALLBACK_OVERVIEW, LAUNCHED_APP,
+ TASKBAR_ALL_APPS
}
- public enum NavigationModel {ZERO_BUTTON, TWO_BUTTON, THREE_BUTTON}
+ 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.
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,
}
// Base class for launcher containers.
- static abstract class VisibleContainer {
+ abstract static class VisibleContainer {
protected final LauncherInstrumentation mLauncher;
protected VisibleContainer(LauncherInstrumentation launcher) {
@@ -165,6 +170,7 @@
private static final String OVERVIEW_RES_ID = "overview_panel";
private static final String WIDGETS_RES_ID = "primary_widgets_list_view";
private static final String CONTEXT_MENU_RES_ID = "popup_container";
+ private static final String TASKBAR_RES_ID = "taskbar_view";
public static final int WAIT_TIME_MS = 60000;
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
private static final String ANDROID_PACKAGE = "android";
@@ -219,11 +225,6 @@
public LauncherInstrumentation(Instrumentation instrumentation) {
mInstrumentation = instrumentation;
mDevice = UiDevice.getInstance(instrumentation);
- try {
- mDevice.executeShellCommand("am wait-for-broadcast-idle");
- } catch (IOException e) {
- log("Failed to wait for broadcast idle");
- }
// Launcher should run in test harness so that custom accessibility protocol between
// Launcher and TAPL is enabled. In-process tests enable this protocol with a direct call
@@ -301,9 +302,13 @@
}
Bundle getTestInfo(String request, String arg) {
+ return getTestInfo(request, arg, null);
+ }
+
+ Bundle getTestInfo(String request, String arg, Bundle extra) {
try (ContentProviderClient client = getContext().getContentResolver()
.acquireContentProviderClient(mTestProviderUri)) {
- return client.call(request, arg, null);
+ return client.call(request, arg, extra);
} catch (DeadObjectException e) {
fail("Launcher crashed");
return null;
@@ -312,6 +317,12 @@
}
}
+ Bundle getTestInfo(TestInformationRequest request) {
+ Bundle extra = new Bundle();
+ extra.putParcelable(TestProtocol.TEST_INFO_REQUEST_FIELD, request);
+ return getTestInfo(request.getRequestName(), null, extra);
+ }
+
Insets getTargetInsets() {
return getTestInfo(TestProtocol.REQUEST_TARGET_INSETS)
.getParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD);
@@ -342,6 +353,11 @@
.getParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD));
}
+ int getOverviewPageSpacing() {
+ return getTestInfo(TestProtocol.REQUEST_GET_OVERVIEW_PAGE_SPACING)
+ .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
+ }
+
float getExactScreenCenterX() {
return getRealDisplaySize().x / 2f;
}
@@ -386,8 +402,6 @@
public static NavigationModel getNavigationModel(int currentInteractionMode) {
if (QuickStepContract.isGesturalMode(currentInteractionMode)) {
return NavigationModel.ZERO_BUTTON;
- } else if (QuickStepContract.isSwipeUpMode(currentInteractionMode)) {
- return NavigationModel.TWO_BUTTON;
} else if (QuickStepContract.isLegacyMode(currentInteractionMode)) {
return NavigationModel.THREE_BUTTON;
}
@@ -421,18 +435,19 @@
}
}
- private String getSystemAnomalyMessage(
+ public String getSystemAnomalyMessage(
boolean ignoreNavmodeChangeStates, boolean ignoreOnlySystemUiViews) {
try {
{
final StringBuilder sb = new StringBuilder();
- UiObject2 object = mDevice.findObject(By.res("android", "alertTitle"));
+ UiObject2 object =
+ mDevice.findObject(By.res("android", "alertTitle").pkg("android"));
if (object != null) {
sb.append("TITLE: ").append(object.getText());
}
- object = mDevice.findObject(By.res("android", "message"));
+ object = mDevice.findObject(By.res("android", "message").pkg("android"));
if (object != null) {
sb.append(" PACKAGE: ").append(object.getApplicationPackage())
.append(" MESSAGE: ").append(object.getText());
@@ -511,7 +526,7 @@
if (hasLauncherObject(OVERVIEW_RES_ID)) return "Overview";
if (hasLauncherObject(WORKSPACE_RES_ID)) return "Workspace";
if (hasLauncherObject(APPS_RES_ID)) return "AllApps";
- return "Background (" + getVisiblePackages() + ")";
+ return "LaunchedApp (" + getVisiblePackages() + ")";
}
public void setSystemHealthSupplier(Function<Long, String> supplier) {
@@ -703,35 +718,54 @@
waitUntilLauncherObjectGone(APPS_RES_ID);
waitUntilLauncherObjectGone(OVERVIEW_RES_ID);
waitUntilLauncherObjectGone(WIDGETS_RES_ID);
+ waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+
return waitForLauncherObject(WORKSPACE_RES_ID);
}
case WIDGETS: {
waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
waitUntilLauncherObjectGone(APPS_RES_ID);
waitUntilLauncherObjectGone(OVERVIEW_RES_ID);
+ waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+
return waitForLauncherObject(WIDGETS_RES_ID);
}
- case ALL_APPS: {
+ case TASKBAR_ALL_APPS:
+ case HOME_ALL_APPS: {
waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
waitUntilLauncherObjectGone(OVERVIEW_RES_ID);
waitUntilLauncherObjectGone(WIDGETS_RES_ID);
+ waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+
return waitForLauncherObject(APPS_RES_ID);
}
case OVERVIEW: {
waitUntilLauncherObjectGone(APPS_RES_ID);
waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
waitUntilLauncherObjectGone(WIDGETS_RES_ID);
+ waitUntilLauncherObjectGone(TASKBAR_RES_ID);
return waitForLauncherObject(OVERVIEW_RES_ID);
}
case FALLBACK_OVERVIEW: {
+ waitUntilLauncherObjectGone(APPS_RES_ID);
+ waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
+ waitUntilLauncherObjectGone(WIDGETS_RES_ID);
+ waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+
return waitForFallbackLauncherObject(OVERVIEW_RES_ID);
}
- case BACKGROUND: {
+ case LAUNCHED_APP: {
waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
waitUntilLauncherObjectGone(APPS_RES_ID);
waitUntilLauncherObjectGone(OVERVIEW_RES_ID);
waitUntilLauncherObjectGone(WIDGETS_RES_ID);
+
+ if (isTablet() && !isFallbackOverview()) {
+ waitForLauncherObject(TASKBAR_RES_ID);
+ } else {
+ waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+ }
return null;
}
default:
@@ -808,6 +842,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;
linearGesture(
@@ -824,11 +860,21 @@
}
/**
+ * @return the Workspace object.
+ * @deprecated use goHome().
+ * Presses nav bar home button.
+ */
+ @Deprecated
+ public Workspace pressHome() {
+ return goHome();
+ }
+
+ /**
* Presses nav bar home button.
*
* @return the Workspace object.
*/
- public Workspace pressHome() {
+ public Workspace goHome() {
try (LauncherInstrumentation.Closable e = eventsCheck();
LauncherInstrumentation.Closable c = addContextLayer("want to switch to home")) {
waitForLauncherInitialized();
@@ -843,8 +889,13 @@
setForcePauseTimeout(FORCE_PAUSE_TIMEOUT_MS);
final Point displaySize = getRealDisplaySize();
+ // The swipe up to home gesture starts from inside the launcher when the user is
+ // already home. Otherwise, the gesture can start inside the launcher process if the
+ // taskbar is visible.
boolean gestureStartFromLauncher = isTablet()
- ? !isLauncher3() || hasLauncherObject(WORKSPACE_RES_ID)
+ ? !isLauncher3()
+ || hasLauncherObject(WORKSPACE_RES_ID)
+ || hasLauncherObject(TASKBAR_RES_ID)
: isLauncherVisible();
// CLose floating views before going back to home.
@@ -859,7 +910,7 @@
swipeToState(
displaySize.x / 2, displaySize.y - 1,
- displaySize.x / 2, 0,
+ displaySize.x / 2, displaySize.y / 2,
ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME, NORMAL_STATE_ORDINAL,
gestureStartFromLauncher ? GestureScope.INSIDE_TO_OUTSIDE
: GestureScope.OUTSIDE_WITH_PILFER);
@@ -868,10 +919,6 @@
log("Hierarchy before clicking home:");
dumpViewHierarchy();
action = "clicking home button";
- if (!isLauncher3() && getNavigationModel() == NavigationModel.TWO_BUTTON) {
- expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
- expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
- }
if (isTablet()) {
expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_UP);
@@ -903,18 +950,17 @@
if (getNavigationModel() == NavigationModel.ZERO_BUTTON) {
final Point displaySize = getRealDisplaySize();
final GestureScope gestureScope =
- launcherVisible ? GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER
- : GestureScope.OUTSIDE_WITHOUT_PILFER;
- linearGesture(0, displaySize.y / 2, displaySize.x / 2, displaySize.y / 2,
+ 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);
} else {
waitForNavigationUiObject("back").click();
if (isTablet()) {
expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_UP);
- } else if (!isLauncher3() && getNavigationModel() == NavigationModel.TWO_BUTTON) {
- expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
- expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
}
}
if (launcherVisible) {
@@ -952,14 +998,14 @@
}
/**
- * Gets the Workspace object if the current state is "background home", i.e. some other app is
- * active. Fails if the launcher is not in that state.
+ * Gets the LaunchedApp object if another app is active. Fails if the launcher is not in that
+ * state.
*
- * @return Background object.
+ * @return LaunchedApp object.
*/
@NonNull
- public Background getBackground() {
- return new Background(this);
+ public LaunchedAppState getLaunchedAppState() {
+ return new LaunchedAppState(this);
}
/**
@@ -996,32 +1042,17 @@
}
/**
- * Gets the All Apps object if the current state is showing the all apps panel opened by swiping
- * from workspace. Fails if the launcher is not in that state. Please don't call this method if
- * App Apps was opened by swiping up from Overview, as it won't fail and will return an
- * incorrect object.
+ * Gets the homescreen All Apps object if the current state is showing the all apps panel opened
+ * by swiping from workspace. Fails if the launcher is not in that state. Please don't call this
+ * method if App Apps was opened by swiping up from Overview, as it won't fail and will return
+ * an incorrect object.
*
- * @return All Aps object.
+ * @return Home All Apps object.
*/
@NonNull
- public AllApps getAllApps() {
+ public HomeAllApps getAllApps() {
try (LauncherInstrumentation.Closable c = addContextLayer("want to get all apps object")) {
- return new AllApps(this);
- }
- }
-
- /**
- * Gets the All Apps object if the current state is showing the all apps panel opened by swiping
- * from overview. Fails if the launcher is not in that state. Please don't call this method if
- * App Apps was opened by swiping up from home, as it won't fail and will return an
- * incorrect object.
- *
- * @return All Aps object.
- */
- @NonNull
- public AllAppsFromOverview getAllAppsFromOverview() {
- try (LauncherInstrumentation.Closable c = addContextLayer("want to get all apps object")) {
- return new AllAppsFromOverview(this);
+ return new HomeAllApps(this);
}
}
@@ -1111,13 +1142,21 @@
@NonNull
UiObject2 waitForObjectInContainer(UiObject2 container, BySelector selector) {
+ return waitForObjectsInContainer(container, selector).get(0);
+ }
+
+ @NonNull
+ List<UiObject2> waitForObjectsInContainer(
+ UiObject2 container, BySelector selector) {
try {
- final UiObject2 object = container.wait(
- Until.findObject(selector),
+ final List<UiObject2> objects = container.wait(
+ Until.findObjects(selector),
WAIT_TIME_MS);
- assertNotNull("Can't find a view in Launcher, id: " + selector + " in container: "
- + container.getResourceName(), object);
- return object;
+ assertNotNull("Can't find views in Launcher, id: " + selector + " in container: "
+ + container.getResourceName(), objects);
+ assertTrue("Can't find views in Launcher, id: " + selector + " in container: "
+ + container.getResourceName(), objects.size() > 0);
+ return objects;
} catch (StaleObjectException e) {
fail("The container disappeared from screen");
return null;
@@ -1276,13 +1315,11 @@
}
int getRightGestureStartOnScreen() {
- return getRealDisplaySize().x - getWindowInsets().right;
+ return getRealDisplaySize().x - getWindowInsets().right - 1;
}
- void clickLauncherObject(UiObject2 object) {
- waitForObjectEnabled(object, "clickLauncherObject");
- expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_TOUCH_DOWN);
- expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_TOUCH_UP);
+ void clickObject(UiObject2 object) {
+ waitForObjectEnabled(object, "clickObject");
if (!isLauncher3() && getNavigationModel() != NavigationModel.THREE_BUTTON) {
expectEvent(TestProtocol.SEQUENCE_TIS, LauncherInstrumentation.EVENT_TOUCH_DOWN_TIS);
expectEvent(TestProtocol.SEQUENCE_TIS, LauncherInstrumentation.EVENT_TOUCH_UP_TIS);
@@ -1290,10 +1327,14 @@
object.click();
}
+ void clickLauncherObject(UiObject2 object) {
+ expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_TOUCH_DOWN);
+ expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_TOUCH_UP);
+ clickObject(object);
+ }
+
void scrollToLastVisibleRow(
- UiObject2 container,
- Collection<UiObject2> items,
- int topPaddingInContainer) {
+ UiObject2 container, Collection<UiObject2> items, int topPaddingInContainer) {
final UiObject2 lowestItem = Collections.max(items, (i1, i2) ->
Integer.compare(getVisibleBounds(i1).top, getVisibleBounds(i2).top));
@@ -1316,21 +1357,19 @@
containerRect.height() - distance - bottomGestureMarginInContainer,
0,
bottomGestureMarginInContainer),
- 10,
- true);
+ /* steps= */ 10,
+ /* slowDown= */ true);
}
void scrollLeftByDistance(UiObject2 container, int distance) {
final Rect containerRect = getVisibleBounds(container);
final int rightGestureMarginInContainer = getRightGestureMarginInContainer(container);
+ final int leftGestureMargin = getTargetInsets().left + getEdgeSensitivityWidth();
scroll(
container,
Direction.LEFT,
- new Rect(
- 0,
- containerRect.width() - distance - rightGestureMarginInContainer,
- 0,
- rightGestureMarginInContainer),
+ new Rect(leftGestureMargin, 0,
+ containerRect.width() - distance - rightGestureMarginInContainer, 0),
10,
true);
}
@@ -1400,13 +1439,13 @@
final Point end = new Point(endX, endY);
sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start, gestureScope);
final long endTime = movePointer(
- start, end, steps, false, downTime, slowDown, gestureScope);
+ start, end, steps, false, downTime, downTime, slowDown, gestureScope);
sendPointer(downTime, endTime, MotionEvent.ACTION_UP, end, gestureScope);
}
- long movePointer(Point start, Point end, int steps, boolean isDecelerating,
- long downTime, boolean slowDown, GestureScope gestureScope) {
- long endTime = movePointer(downTime, downTime, steps * GESTURE_STEP_MS,
+ 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,
isDecelerating, start, end, gestureScope);
if (slowDown) {
endTime = movePointer(downTime, endTime + GESTURE_STEP_MS, 5 * GESTURE_STEP_MS, end,
@@ -1445,35 +1484,45 @@
0, 0, 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
}
+ private boolean hasTIS() {
+ return getTestInfo(TestProtocol.REQUEST_HAS_TIS).getBoolean(TestProtocol.REQUEST_HAS_TIS);
+ }
+
+
public void sendPointer(long downTime, long currentTime, int action, Point point,
GestureScope gestureScope) {
- final boolean notLauncher3 = !isLauncher3();
+ final boolean hasTIS = hasTIS();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
- && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER) {
+ && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
+ && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE) {
expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
}
- if (notLauncher3 && getNavigationModel() != NavigationModel.THREE_BUTTON) {
+ if (hasTIS && getNavigationModel() != NavigationModel.THREE_BUTTON) {
expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
}
break;
case MotionEvent.ACTION_UP:
- if (notLauncher3 && gestureScope != GestureScope.INSIDE
+ if (hasTIS && gestureScope != GestureScope.INSIDE
&& gestureScope != GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER
&& (gestureScope == GestureScope.OUTSIDE_WITH_PILFER
|| gestureScope == GestureScope.INSIDE_TO_OUTSIDE)) {
expectEvent(TestProtocol.SEQUENCE_PILFER, EVENT_PILFER_POINTERS);
}
if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
- && gestureScope != GestureScope.OUTSIDE_WITHOUT_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 (notLauncher3 && getNavigationModel() != NavigationModel.THREE_BUTTON) {
- expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
+ 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;
}
@@ -1503,11 +1552,11 @@
// vx0: initial speed at the x-dimension, set as twice the avg speed
// dx: the constant deceleration at the x-dimension
- double vx0 = 2 * (to.x - from.x) / duration;
+ double vx0 = 2.0 * (to.x - from.x) / duration;
double dx = vx0 / duration;
// vy0: initial speed at the y-dimension, set as twice the avg speed
// dy: the constant deceleration at the y-dimension
- double vy0 = 2 * (to.y - from.y) / duration;
+ double vy0 = 2.0 * (to.y - from.y) / duration;
double dy = vy0 / duration;
for (long i = 0; i < steps; ++i) {
@@ -1596,9 +1645,10 @@
}
Point getRealDisplaySize() {
- final Point size = new Point();
- getContext().getSystemService(WindowManager.class).getDefaultDisplay().getRealSize(size);
- return size;
+ final Rect displayBounds = getContext().getSystemService(WindowManager.class)
+ .getMaximumWindowMetrics()
+ .getBounds();
+ return new Point(displayBounds.width(), displayBounds.height());
}
public void enableDebugTracing() {
@@ -1642,6 +1692,29 @@
getTestInfo(TestProtocol.REQUEST_CLEAR_DATA);
}
+ /**
+ * Reloads the workspace with a test layout that includes the Test Activity app icon on the
+ * hotseat.
+ */
+ public void useTestWorkspaceLayoutOnReload() {
+ getTestInfo(TestProtocol.REQUEST_USE_TEST_WORKSPACE_LAYOUT);
+ }
+
+ /** Reloads the workspace with the default layout defined by the user's grid size selection. */
+ public void useDefaultWorkspaceLayoutOnReload() {
+ getTestInfo(TestProtocol.REQUEST_USE_DEFAULT_WORKSPACE_LAYOUT);
+ }
+
+ /** Shows the taskbar if it is hidden, otherwise does nothing. */
+ public void showTaskbarIfHidden() {
+ getTestInfo(TestProtocol.REQUEST_UNSTASH_TASKBAR_IF_STASHED);
+ }
+
+ public List<String> getHotseatIconNames() {
+ return getTestInfo(TestProtocol.REQUEST_HOTSEAT_ICON_NAMES)
+ .getStringArrayList(TestProtocol.TEST_INFO_RESPONSE_FIELD);
+ }
+
private String[] getActivities() {
return getTestInfo(TestProtocol.REQUEST_GET_ACTIVITIES)
.getStringArray(TestProtocol.TEST_INFO_RESPONSE_FIELD);
@@ -1758,4 +1831,4 @@
return ResourceUtils.getBoolByName(
"config_supportsRoundedCornersOnWindows", resources, false);
}
-}
\ No newline at end of file
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java b/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java
deleted file mode 100644
index 42b6bc9..0000000
--- a/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2020 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.annotation.NonNull;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.UiObject2;
-import androidx.test.uiautomator.Until;
-
-import com.android.launcher3.testing.TestProtocol;
-
-public class OptionsPopupMenuItem {
-
- private final LauncherInstrumentation mLauncher;
- private final UiObject2 mObject;
-
- OptionsPopupMenuItem(@NonNull LauncherInstrumentation launcher, @NonNull UiObject2 shortcut) {
- mLauncher = launcher;
- mObject = shortcut;
- }
-
- /**
- * Clicks the option.
- */
- @NonNull
- public void launch(@NonNull String expectedPackageName) {
- try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
- LauncherInstrumentation.log("OptionsPopupMenuItem before click "
- + mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
- mLauncher.clickLauncherObject(mObject);
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_START);
- mLauncher.assertTrue(
- "App didn't start: " + By.pkg(expectedPackageName),
- mLauncher.getDevice().wait(Until.hasObject(By.pkg(expectedPackageName)),
- LauncherInstrumentation.WAIT_TIME_MS));
- }
- }
-}
diff --git a/tests/tapl/com/android/launcher3/tapl/Overview.java b/tests/tapl/com/android/launcher3/tapl/Overview.java
index 0d06be3..66a51a5 100644
--- a/tests/tapl/com/android/launcher3/tapl/Overview.java
+++ b/tests/tapl/com/android/launcher3/tapl/Overview.java
@@ -16,12 +16,7 @@
package com.android.launcher3.tapl;
-import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
-
-import androidx.annotation.NonNull;
-
import com.android.launcher3.tapl.LauncherInstrumentation.ContainerType;
-import com.android.launcher3.testing.TestProtocol;
/**
* Overview pane.
@@ -37,38 +32,6 @@
return LauncherInstrumentation.ContainerType.OVERVIEW;
}
- /**
- * Swipes up to All Apps.
- *
- * @return the App Apps object.
- */
- @NonNull
- public AllAppsFromOverview switchToAllApps() {
- try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
- LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "want to switch from overview to all apps")) {
- verifyActiveContainer();
-
- // Swipe from an app icon to the top.
- LauncherInstrumentation.log("Overview.switchToAllApps before swipe");
- mLauncher.swipeToState(
- mLauncher.getDevice().getDisplayWidth() / 2,
- mLauncher.getTestInfo(
- TestProtocol.REQUEST_HOTSEAT_TOP).
- getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD),
- mLauncher.getDevice().getDisplayWidth() / 2,
- 0,
- 12,
- ALL_APPS_STATE_ORDINAL,
- LauncherInstrumentation.GestureScope.INSIDE);
-
- try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
- "swiped all way up from overview")) {
- return new AllAppsFromOverview(mLauncher);
- }
- }
- }
-
@Override
public void dismissAllTasks() {
super.dismissAllTasks();
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
index c8c06e4..2f44bb6 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
@@ -48,7 +48,7 @@
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
"clicked screenshot button")) {
UiObject2 closeScreenshot = mLauncher.waitForSystemUiObject(
- "global_screenshot_dismiss_image");
+ "screenshot_dismiss_image");
if (mLauncher.getNavigationModel()
!= LauncherInstrumentation.NavigationModel.THREE_BUTTON) {
mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS,
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
index a860e7d..c8caa42 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -127,7 +127,7 @@
/**
* Clicks at the task.
*/
- public Background open() {
+ public LaunchedAppState open() {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
verifyActiveContainer();
mLauncher.executeAndWaitForEvent(
@@ -137,7 +137,7 @@
+ mTask.getParent().getContentDescription(),
"clicking an overview task");
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, TASK_START_EVENT);
- return new Background(mLauncher);
+ return new LaunchedAppState(mLauncher);
}
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
new file mode 100644
index 0000000..82652c7
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
@@ -0,0 +1,50 @@
+/*
+ * 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.tapl;
+
+import android.widget.TextView;
+
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * Operations on search result page opened from home screen qsb.
+ */
+public class SearchResultFromQsb {
+ // The input resource id in the search box.
+ private static final String INPUT_RES = "input";
+ private final LauncherInstrumentation mLauncher;
+
+ SearchResultFromQsb(LauncherInstrumentation launcher) {
+ mLauncher = launcher;
+ mLauncher.waitForLauncherObject("search_container_all_apps");
+ }
+
+ /** Set the input to the search input edit text and update search results. */
+ 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);
+ }
+ }
+
+ /** Find the app from search results with app name. */
+ public Launchable findAppIcon(String appName) {
+ UiObject2 icon = mLauncher.waitForLauncherObject(By.clazz(TextView.class).text(appName));
+ return new AllAppsAppIcon(mLauncher, icon);
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/SplitscreenDragSource.java b/tests/tapl/com/android/launcher3/tapl/SplitscreenDragSource.java
new file mode 100644
index 0000000..ce1c3c0
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/SplitscreenDragSource.java
@@ -0,0 +1,39 @@
+/*
+ * 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.tapl;
+
+/** Launchable that can serve as a source for dragging and dropping to splitscreen. */
+interface SplitscreenDragSource {
+
+ /**
+ * Drags this app icon to the left (landscape) or bottom (portrait) of the screen, launching it
+ * in splitscreen.
+ *
+ * @param expectedNewPackageName package name of the app being dragged
+ * @param expectedExistingPackageName package name of the already-launched app
+ */
+ default void dragToSplitscreen(
+ String expectedNewPackageName, String expectedExistingPackageName) {
+ Launchable launchable = getLaunchable();
+ LauncherInstrumentation launcher = launchable.mLauncher;
+ try (LauncherInstrumentation.Closable e = launcher.eventsCheck()) {
+ LaunchedAppState.dragToSplitscreen(
+ launcher, launchable, expectedNewPackageName, expectedExistingPackageName);
+ }
+ }
+
+ Launchable getLaunchable();
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/Taskbar.java b/tests/tapl/com/android/launcher3/tapl/Taskbar.java
new file mode 100644
index 0000000..b5a08c3
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/Taskbar.java
@@ -0,0 +1,123 @@
+/*
+ * 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.tapl;
+
+import static com.android.launcher3.testing.TestProtocol.REQUEST_DISABLE_MANUAL_TASKBAR_STASHING;
+import static com.android.launcher3.testing.TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING;
+
+import android.graphics.Point;
+import android.os.SystemClock;
+import android.text.TextUtils;
+import android.view.MotionEvent;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiObject2;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Operations on the Taskbar from LaunchedApp.
+ */
+public final class Taskbar {
+
+ private final LauncherInstrumentation mLauncher;
+
+ Taskbar(LauncherInstrumentation launcher) {
+ mLauncher = launcher;
+ }
+
+ /**
+ * Returns an app icon with the given name. This fails if the icon is not found.
+ */
+ @NonNull
+ public TaskbarAppIcon getAppIcon(String appName) {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to get a taskbar icon")) {
+ return new TaskbarAppIcon(mLauncher, mLauncher.waitForObjectInContainer(
+ mLauncher.waitForLauncherObject("taskbar_view"),
+ AppIcon.getAppIconSelector(appName, mLauncher)));
+ }
+ }
+
+ /**
+ * Hides this taskbar.
+ *
+ * The taskbar must already be visible when calling this method.
+ */
+ public void hide() {
+ mLauncher.getTestInfo(REQUEST_ENABLE_MANUAL_TASKBAR_STASHING);
+
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to hide the taskbar");
+ LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
+ mLauncher.waitForLauncherObject("taskbar_view");
+
+ final long downTime = SystemClock.uptimeMillis();
+ Point stashTarget = new Point(
+ mLauncher.getRealDisplaySize().x - 1, mLauncher.getRealDisplaySize().y - 1);
+
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, stashTarget,
+ LauncherInstrumentation.GestureScope.INSIDE);
+ LauncherInstrumentation.log("hideTaskbar: sent down");
+
+ try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("pressed down")) {
+ mLauncher.waitUntilLauncherObjectGone("taskbar_view");
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, stashTarget,
+ LauncherInstrumentation.GestureScope.INSIDE);
+ }
+ } finally {
+ mLauncher.getTestInfo(REQUEST_DISABLE_MANUAL_TASKBAR_STASHING);
+ }
+ }
+
+ /**
+ * Opens the Taskbar all apps page.
+ */
+ public AllAppsFromTaskbar openAllApps() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to open taskbar all apps");
+ LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
+
+ mLauncher.clickLauncherObject(mLauncher.waitForObjectInContainer(
+ mLauncher.waitForLauncherObject("taskbar_view"), getAllAppsButtonSelector()));
+
+ return new AllAppsFromTaskbar(mLauncher);
+ }
+ }
+
+ /** Returns a list of app icon names on the Taskbar */
+ public List<String> getIconNames() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to get all taskbar icons")) {
+ return mLauncher.waitForObjectsInContainer(
+ mLauncher.waitForLauncherObject("taskbar_view"),
+ AppIcon.getAnyAppIconSelector())
+ .stream()
+ .map(UiObject2::getText)
+ .filter(text -> !TextUtils.isEmpty(text)) // Filter out the all apps button
+ .collect(Collectors.toList());
+ }
+ }
+
+ private static BySelector getAllAppsButtonSelector() {
+ // Look for an icon with no text
+ return By.clazz(TextView.class).text("");
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/TaskbarAppIcon.java b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIcon.java
new file mode 100644
index 0000000..099acd4
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIcon.java
@@ -0,0 +1,52 @@
+/*
+ * 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.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+import java.util.regex.Pattern;
+
+/**
+ * App icon specifically on the Taskbar.
+ */
+public final class TaskbarAppIcon extends AppIcon implements SplitscreenDragSource {
+
+ private static final Pattern LONG_CLICK_EVENT = Pattern.compile("onTaskbarItemLongClick");
+
+ TaskbarAppIcon(LauncherInstrumentation launcher, UiObject2 icon) {
+ super(launcher, icon);
+ }
+
+ @Override
+ protected Pattern getLongClickEvent() {
+ return LONG_CLICK_EVENT;
+ }
+
+ @Override
+ public TaskbarAppIconMenu openDeepShortcutMenu() {
+ return (TaskbarAppIconMenu) super.openDeepShortcutMenu();
+ }
+
+ @Override
+ protected TaskbarAppIconMenu createMenu(UiObject2 menu) {
+ return new TaskbarAppIconMenu(mLauncher, menu);
+ }
+
+ @Override
+ public Launchable getLaunchable() {
+ return this;
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenu.java b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenu.java
new file mode 100644
index 0000000..1f137c5
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenu.java
@@ -0,0 +1,38 @@
+/*
+ * 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.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * Context menu of a Taskbar app icon.
+ */
+public final class TaskbarAppIconMenu extends AppIconMenu {
+
+ TaskbarAppIconMenu(LauncherInstrumentation launcher, UiObject2 deepShortcutsContainer) {
+ super(launcher, deepShortcutsContainer);
+ }
+
+ @Override
+ public TaskbarAppIconMenuItem getMenuItem(String shortcutText) {
+ return (TaskbarAppIconMenuItem) super.getMenuItem(shortcutText);
+ }
+
+ @Override
+ protected TaskbarAppIconMenuItem createMenuItem(UiObject2 menuItem) {
+ return new TaskbarAppIconMenuItem(mLauncher, menuItem);
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenuItem.java b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenuItem.java
new file mode 100644
index 0000000..69a8a08
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenuItem.java
@@ -0,0 +1,57 @@
+/*
+ * 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.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+import com.android.launcher3.testing.TestProtocol;
+
+import java.util.regex.Pattern;
+
+/**
+ * Menu item in a Taskbar app icon menu.
+ */
+public final class TaskbarAppIconMenuItem extends AppIconMenuItem implements SplitscreenDragSource {
+
+ private static final Pattern LONG_CLICK_EVENT = Pattern.compile("onTaskbarItemLongClick");
+
+ TaskbarAppIconMenuItem(
+ LauncherInstrumentation launcher, UiObject2 shortcut) {
+ super(launcher, shortcut);
+ }
+
+ @Override
+ protected void addExpectedEventsForLongClick() {
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT);
+ }
+
+ @Override
+ protected void waitForLongPressConfirmation() {
+ // On long-press, the popup container closes and the system drag-and-drop begins. This
+ // only leaves launcher views that were previously visible.
+ mLauncher.waitUntilLauncherObjectGone("popup_container");
+ }
+
+ @Override
+ protected String launchableType() {
+ return "taskbar app icon menu item";
+ }
+
+ @Override
+ public Launchable getLaunchable() {
+ return this;
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/Widget.java b/tests/tapl/com/android/launcher3/tapl/Widget.java
index f569ef4..2346249 100644
--- a/tests/tapl/com/android/launcher3/tapl/Widget.java
+++ b/tests/tapl/com/android/launcher3/tapl/Widget.java
@@ -30,7 +30,7 @@
/**
* Widget in workspace or a widget list.
*/
-public final class Widget extends Launchable {
+public final class Widget extends Launchable implements WorkspaceDragSource {
private static final Pattern LONG_CLICK_EVENT = Pattern.compile("Widgets.onLongClick");
@@ -39,8 +39,8 @@
}
@Override
- protected String getLongPressIndicator() {
- return "drop_target_bar";
+ protected void waitForLongPressConfirmation() {
+ mLauncher.waitForLauncherObject("drop_target_bar");
}
@Override
@@ -57,6 +57,12 @@
return "widget";
}
+ /** This method requires public access, however should not be called in tests. */
+ @Override
+ public Launchable getLaunchable() {
+ return this;
+ }
+
/**
* Drags a non-configurable widget from the widgets container to the workspace and returns the
* resize frame that is shown after the widget is added.
diff --git a/tests/tapl/com/android/launcher3/tapl/Widgets.java b/tests/tapl/com/android/launcher3/tapl/Widgets.java
index 0bac2ca..7fd68c0 100644
--- a/tests/tapl/com/android/launcher3/tapl/Widgets.java
+++ b/tests/tapl/com/android/launcher3/tapl/Widgets.java
@@ -115,6 +115,7 @@
final BySelector labelSelector = By.clazz("android.widget.TextView").text(labelText);
final BySelector previewSelector = By.res(mLauncher.getLauncherPackageName(),
"widget_preview");
+ final int bottomGestureStartOnScreen = mLauncher.getBottomGestureStartOnScreen();
int i = 0;
for (; ; ) {
final Collection<UiObject2> tableRows = mLauncher.getChildren(widgetsContainer);
@@ -126,6 +127,9 @@
if (label == null) {
continue;
}
+ if (widget.getVisibleCenter().y >= bottomGestureStartOnScreen) {
+ continue;
+ }
mLauncher.assertEquals(
"View is not WidgetCell",
"com.android.launcher3.widget.WidgetCell",
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 3f0d7fd..eb7f05b 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -16,10 +16,12 @@
package com.android.launcher3.tapl;
+import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_SCROLLED;
+
import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL;
-import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
+import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertTrue;
import android.graphics.Point;
@@ -31,12 +33,17 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.Direction;
+import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.testing.WorkspaceCellCenterRequest;
import java.util.List;
+import java.util.Map;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -49,6 +56,7 @@
private static final int DEFAULT_DRAG_STEPS = 10;
private static final String DROP_BAR_RES_ID = "drop_target_bar";
private static final String DELETE_TARGET_TEXT_ID = "delete_target_text";
+ private static final String UNINSTALL_TARGET_TEXT_ID = "uninstall_target_text";
static final Pattern EVENT_CTRL_W_DOWN = Pattern.compile(
"Key event: KeyEvent.*?action=ACTION_DOWN.*?keyCode=KEYCODE_W"
@@ -56,7 +64,7 @@
static final Pattern EVENT_CTRL_W_UP = Pattern.compile(
"Key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_W"
+ ".*?metaState=META_CTRL_ON");
- private static final Pattern LONG_CLICK_EVENT = Pattern.compile("onWorkspaceItemLongClick");
+ static final Pattern LONG_CLICK_EVENT = Pattern.compile("onWorkspaceItemLongClick");
private final UiObject2 mHotseat;
@@ -71,7 +79,7 @@
* @return the All Apps object.
*/
@NonNull
- public AllApps switchToAllApps() {
+ public HomeAllApps switchToAllApps() {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c =
mLauncher.addContextLayer("want to switch from workspace to all apps")) {
@@ -81,8 +89,8 @@
final int windowCornerRadius = (int) Math.ceil(mLauncher.getWindowCornerRadius());
final int startY = deviceHeight - Math.max(bottomGestureMargin, windowCornerRadius) - 1;
final int swipeHeight = mLauncher.getTestInfo(
- TestProtocol.REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT).
- getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
+ TestProtocol.REQUEST_HOME_TO_ALL_APPS_SWIPE_HEIGHT)
+ .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD);
LauncherInstrumentation.log(
"switchToAllApps: deviceHeight = " + deviceHeight + ", startY = " + startY
+ ", swipeHeight = " + swipeHeight + ", slop = "
@@ -98,25 +106,37 @@
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
"swiped to all apps")) {
- return new AllApps(mLauncher);
+ return new HomeAllApps(mLauncher);
}
}
}
/**
+ * Returns the home qsb.
+ *
+ * The qsb must already be visible when calling this method.
+ */
+ public HomeQsb getQsb() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to get the home qsb")) {
+ return new HomeQsb(mLauncher);
+ }
+ }
+
+ /**
* Returns an icon for the app, if currently visible.
*
* @param appName name of the app
* @return app icon, if found, null otherwise.
*/
@Nullable
- public AppIcon tryGetWorkspaceAppIcon(String appName) {
+ public HomeAppIcon tryGetWorkspaceAppIcon(String appName) {
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to get a workspace icon")) {
final UiObject2 workspace = verifyActiveContainer();
final UiObject2 icon = workspace.findObject(
AppIcon.getAppIconSelector(appName, mLauncher));
- return icon != null ? new AppIcon(mLauncher, icon) : null;
+ return icon != null ? new WorkspaceAppIcon(mLauncher, icon) : null;
}
}
@@ -128,10 +148,10 @@
* @return app icon.
*/
@NonNull
- public AppIcon getWorkspaceAppIcon(String appName) {
+ public HomeAppIcon getWorkspaceAppIcon(String appName) {
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to get a workspace icon")) {
- return new AppIcon(mLauncher,
+ return new WorkspaceAppIcon(mLauncher,
mLauncher.waitForObjectInContainer(
verifyActiveContainer(),
AppIcon.getAppIconSelector(appName, mLauncher)));
@@ -165,33 +185,39 @@
}
/**
- * Drags an icon to the (currentPage + pageDelta) page if the page already exists.
- * If the target page doesn't exist, the icon will be put onto an existing page that is the
- * closest to the target page.
+ * Drags an icon to the (currentPage + pageDelta) page.
+ * If the target page doesn't exist yet, a new page will be created.
+ * In case the target page can't be created (e.g. existing pages are 0, 1, current: 0,
+ * pageDelta: 3, the latest page that can be created is 2) the icon will be dragged onto the
+ * page that can be created and is closest to the target page.
*
- * @param appIcon - icon to drag.
- * @param pageDelta - how many pages should the icon be dragged from the current page.
- * It can be a negative value.
+ * @param homeAppIcon - icon to drag.
+ * @param pageDelta - how many pages should the icon be dragged from the current page.
+ * It can be a negative value. currentPage + pageDelta should be greater
+ * than or equal to 0.
*/
- public void dragIcon(AppIcon appIcon, int pageDelta) {
+ public void dragIcon(HomeAppIcon homeAppIcon, int pageDelta) {
+ if (mHotseat.getVisibleBounds().height() > mHotseat.getVisibleBounds().width()) {
+ throw new UnsupportedOperationException(
+ "dragIcon does NOT support dragging when the hotseat is on the side.");
+ }
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
final UiObject2 workspace = verifyActiveContainer();
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"dragging icon to page with delta: " + pageDelta)) {
- dragIcon(workspace, appIcon, pageDelta);
+ dragIcon(workspace, homeAppIcon, pageDelta);
verifyActiveContainer();
}
}
}
- private void dragIcon(UiObject2 workspace, AppIcon appIcon, int pageDelta) {
+ private void dragIcon(UiObject2 workspace, HomeAppIcon homeAppIcon, int pageDelta) {
int pageWidth = mLauncher.getDevice().getDisplayWidth() / pagesPerScreen();
int targetX = (pageWidth / 2) + pageWidth * pageDelta;
dragIconToWorkspace(
mLauncher,
- appIcon,
+ homeAppIcon,
new Point(targetX, mLauncher.getVisibleBounds(workspace).centerY()),
- "popup_container",
false,
false,
() -> mLauncher.expectEvent(
@@ -204,42 +230,52 @@
}
@NonNull
- public AppIcon getHotseatAppIcon(String appName) {
- return new AppIcon(mLauncher, mLauncher.waitForObjectInContainer(
+ public HomeAppIcon getHotseatAppIcon(String appName) {
+ return new WorkspaceAppIcon(mLauncher, mLauncher.waitForObjectInContainer(
mHotseat, AppIcon.getAppIconSelector(appName, mLauncher)));
}
- private static int getStartDragThreshold(LauncherInstrumentation launcher) {
- return launcher.getTestInfo(TestProtocol.REQUEST_START_DRAG_THRESHOLD).getInt(
- TestProtocol.TEST_INFO_RESPONSE_FIELD);
- }
-
- /*
- * Get the center point of the delete icon in the drop target bar.
+ /**
+ * @return map of text -> center of the view. In case of icons with the same name, the one with
+ * lower x coordinate is selected.
*/
- private Point getDeleteDropPoint() {
- return mLauncher.waitForObjectInContainer(
- mLauncher.waitForLauncherObject(DROP_BAR_RES_ID),
- DELETE_TARGET_TEXT_ID).getVisibleCenter();
+ public Map<String, Point> getWorkspaceIconsPositions() {
+ final UiObject2 workspace = verifyActiveContainer();
+ List<UiObject2> workspaceIcons =
+ mLauncher.waitForObjectsInContainer(workspace, AppIcon.getAnyAppIconSelector());
+ return workspaceIcons.stream()
+ .collect(
+ Collectors.toMap(
+ /* keyMapper= */ UiObject2::getText,
+ /* valueMapper= */ UiObject2::getVisibleCenter,
+ /* mergeFunction= */ (p1, p2) -> p1.x < p2.x ? p1 : p2));
+ }
+ /*
+ * Get the center point of the delete/uninstall icon in the drop target bar.
+ */
+ private static Point getDropPointFromDropTargetBar(
+ LauncherInstrumentation launcher, String targetId) {
+ return launcher.waitForObjectInContainer(
+ launcher.waitForLauncherObject(DROP_BAR_RES_ID),
+ targetId).getVisibleCenter();
}
/**
* Delete the appIcon from the workspace.
*
- * @param appIcon to be deleted.
+ * @param homeAppIcon to be deleted.
* @return validated workspace after the existing appIcon being deleted.
*/
- public Workspace deleteAppIcon(AppIcon appIcon) {
+ public Workspace deleteAppIcon(HomeAppIcon homeAppIcon) {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"removing app icon from workspace")) {
dragIconToWorkspace(
- mLauncher, appIcon,
- () -> getDeleteDropPoint(),
- true, /* decelerating */
- appIcon.getLongPressIndicator(),
+ mLauncher,
+ homeAppIcon,
+ () -> getDropPointFromDropTargetBar(mLauncher, DELETE_TARGET_TEXT_ID),
() -> mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT),
- null);
+ /* expectDropEvents= */ null);
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
"dragged the app to the drop bar")) {
@@ -249,6 +285,67 @@
}
/**
+ * Uninstall the appIcon by dragging it to the 'uninstall' drop point of the drop_target_bar.
+ *
+ * @param launcher the root TAPL instrumentation object of {@link
+ * LauncherInstrumentation} type.
+ * @param homeAppIcon to be uninstalled.
+ * @param launcher the root TAPL instrumentation object of {@link
+ * LauncherInstrumentation} type.
+ * @param homeAppIcon to be uninstalled.
+ * @param expectLongClickEvents the runnable to be executed to verify expected longclick event.
+ * @return validated workspace after the existing appIcon being uninstalled.
+ */
+ static Workspace uninstallAppIcon(LauncherInstrumentation launcher, HomeAppIcon homeAppIcon,
+ Runnable expectLongClickEvents) {
+ try (LauncherInstrumentation.Closable c = launcher.addContextLayer(
+ "uninstalling app icon")) {
+ dragIconToWorkspace(
+ launcher,
+ homeAppIcon,
+ () -> getDropPointFromDropTargetBar(launcher, UNINSTALL_TARGET_TEXT_ID),
+ expectLongClickEvents,
+ /* expectDropEvents= */null);
+
+ launcher.waitUntilLauncherObjectGone(DROP_BAR_RES_ID);
+
+ final BySelector installerAlert = By.text(Pattern.compile(
+ "Do you want to uninstall this app\\?",
+ Pattern.DOTALL | Pattern.MULTILINE));
+ final UiDevice device = launcher.getDevice();
+ assertTrue("uninstall alert is not shown", device.wait(
+ 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);
+ assertTrue("Uninstall alert is not dismissed after clicking OK", device.wait(
+ Until.gone(installerAlert), LauncherInstrumentation.WAIT_TIME_MS));
+
+ try (LauncherInstrumentation.Closable c1 = launcher.addContextLayer(
+ "uninstalled app by dragging to the drop bar")) {
+ return new Workspace(launcher);
+ }
+ }
+ }
+
+ /**
+ * Get cell layout's grids size. The return point's x and y values are the cell counts in X and
+ * Y directions respectively, not the values in pixels.
+ */
+ public Point getIconGridDimensions() {
+ int[] countXY = mLauncher.getTestInfo(
+ TestProtocol.REQUEST_WORKSPACE_CELL_LAYOUT_SIZE).getIntArray(
+ TestProtocol.TEST_INFO_RESPONSE_FIELD);
+ return new Point(countXY[0], countXY[1]);
+ }
+
+ static Point getCellCenter(LauncherInstrumentation launcher, int cellX, int cellY) {
+ return launcher.getTestInfo(WorkspaceCellCenterRequest.builder().setCellX(
+ cellX).setCellY(cellY).build()).getParcelable(
+ TestProtocol.TEST_INFO_RESPONSE_FIELD);
+ }
+
+ /**
* Finds folder icons in the current workspace.
*
* @return a list of folder icons.
@@ -259,31 +356,6 @@
o -> new FolderIcon(mLauncher, o)).collect(Collectors.toList());
}
- /**
- * Drag an icon up with a short distance that makes workspace go to spring loaded state.
- *
- * @return the position after dragging.
- */
- private static Point dragIconToSpringLoaded(LauncherInstrumentation launcher, long downTime,
- UiObject2 icon,
- String longPressIndicator, Runnable expectLongClickEvents) {
- final Point iconCenter = icon.getVisibleCenter();
- final Point dragStartCenter = new Point(iconCenter.x,
- iconCenter.y - getStartDragThreshold(launcher));
-
- launcher.runToState(() -> {
- launcher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN,
- iconCenter, LauncherInstrumentation.GestureScope.INSIDE);
- LauncherInstrumentation.log("dragIconToSpringLoaded: sent down");
- expectLongClickEvents.run();
- launcher.waitForLauncherObject(longPressIndicator);
- LauncherInstrumentation.log("dragIconToSpringLoaded: indicator");
- launcher.movePointer(iconCenter, dragStartCenter, DEFAULT_DRAG_STEPS, false,
- downTime, true, LauncherInstrumentation.GestureScope.INSIDE);
- }, SPRING_LOADED_STATE_ORDINAL, "long-pressing and triggering drag start");
- return dragStartCenter;
- }
-
private static void dropDraggedIcon(LauncherInstrumentation launcher, Point dest, long downTime,
@Nullable Runnable expectedEvents) {
launcher.runToState(
@@ -300,36 +372,57 @@
}
static void dragIconToWorkspace(LauncherInstrumentation launcher, Launchable launchable,
- Point dest, String longPressIndicator, boolean startsActivity, boolean isWidgetShortcut,
+ Point dest, boolean startsActivity, boolean isWidgetShortcut,
Runnable expectLongClickEvents) {
Runnable expectDropEvents = null;
if (startsActivity || isWidgetShortcut) {
expectDropEvents = () -> launcher.expectEvent(TestProtocol.SEQUENCE_MAIN,
LauncherInstrumentation.EVENT_START);
}
- dragIconToWorkspace(launcher, launchable, () -> dest, false, longPressIndicator,
- expectLongClickEvents, expectDropEvents);
+ dragIconToWorkspace(
+ launcher, launchable, () -> dest, expectLongClickEvents, expectDropEvents);
}
/**
- * Drag icon in workspace to else where.
+ * Drag icon in workspace to else where and drop it immediately.
+ * (There is no slow down time before drop event)
* This function expects the launchable is inside the workspace and there is no drop event.
*/
- static void dragIconToWorkspace(LauncherInstrumentation launcher, Launchable launchable,
- Supplier<Point> destSupplier, String longPressIndicator) {
- dragIconToWorkspace(launcher, launchable, destSupplier, false, longPressIndicator,
- () -> launcher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT), null);
+ static void dragIconToWorkspace(
+ LauncherInstrumentation launcher, Launchable launchable, Supplier<Point> destSupplier) {
+ dragIconToWorkspace(
+ launcher,
+ launchable,
+ destSupplier,
+ /* isDecelerating= */ false,
+ () -> launcher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT),
+ /* expectDropEvents= */ null);
}
static void dragIconToWorkspace(
- LauncherInstrumentation launcher, Launchable launchable, Supplier<Point> dest,
- boolean isDecelerating, String longPressIndicator, Runnable expectLongClickEvents,
+ LauncherInstrumentation launcher,
+ Launchable launchable,
+ Supplier<Point> dest,
+ Runnable expectLongClickEvents,
+ @Nullable Runnable expectDropEvents) {
+ dragIconToWorkspace(launcher, launchable, dest, /* isDecelerating */ true,
+ expectLongClickEvents, expectDropEvents);
+ }
+
+ static void dragIconToWorkspace(
+ LauncherInstrumentation launcher,
+ Launchable launchable,
+ Supplier<Point> dest,
+ boolean isDecelerating,
+ Runnable expectLongClickEvents,
@Nullable Runnable expectDropEvents) {
try (LauncherInstrumentation.Closable ignored = launcher.addContextLayer(
"want to drag icon to workspace")) {
final long downTime = SystemClock.uptimeMillis();
- Point dragStart = dragIconToSpringLoaded(launcher, downTime,
- launchable.getObject(), longPressIndicator, expectLongClickEvents);
+ Point dragStart = launchable.startDrag(
+ downTime,
+ expectLongClickEvents,
+ /* runToSpringLoadedState= */ true);
Point targetDest = dest.get();
int displayX = launcher.getRealDisplaySize().x;
@@ -338,9 +431,11 @@
while (targetDest.x > displayX || targetDest.x < 0) {
int edgeX = targetDest.x > 0 ? displayX : 0;
Point screenEdge = new Point(edgeX, targetDest.y);
- launcher.movePointer(dragStart, screenEdge, DEFAULT_DRAG_STEPS, isDecelerating,
- downTime, true, LauncherInstrumentation.GestureScope.INSIDE);
- launcher.waitForIdle(); // Wait for the page change to happen
+ Point finalDragStart = dragStart;
+ executeAndWaitForPageScroll(launcher,
+ () -> launcher.movePointer(finalDragStart, screenEdge, DEFAULT_DRAG_STEPS,
+ true, downTime, downTime, true,
+ LauncherInstrumentation.GestureScope.INSIDE));
targetDest.x += displayX * (targetDest.x > 0 ? -1 : 1);
dragStart = screenEdge;
}
@@ -348,11 +443,19 @@
// targetDest.x is now between 0 and displayX so we found the target page,
// we just have to put move the icon to the destination and drop it
launcher.movePointer(dragStart, targetDest, DEFAULT_DRAG_STEPS, isDecelerating,
- downTime, true, LauncherInstrumentation.GestureScope.INSIDE);
+ downTime, SystemClock.uptimeMillis(), false,
+ LauncherInstrumentation.GestureScope.INSIDE);
dropDraggedIcon(launcher, targetDest, downTime, expectDropEvents);
}
}
+ private static void executeAndWaitForPageScroll(LauncherInstrumentation launcher,
+ Runnable command) {
+ launcher.executeAndWaitForEvent(command,
+ event -> event.getEventType() == TYPE_VIEW_SCROLLED,
+ () -> "Page scroll didn't happen", "Scrolling page");
+ }
+
/**
* Flings to get to screens on the right. Waits for scrolling and a possible overscroll
* recoil to complete.
@@ -429,4 +532,4 @@
return widget != null ? new Widget(mLauncher, widget) : null;
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/WorkspaceAppIcon.java b/tests/tapl/com/android/launcher3/tapl/WorkspaceAppIcon.java
new file mode 100644
index 0000000..114e6a5
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/WorkspaceAppIcon.java
@@ -0,0 +1,43 @@
+/*
+ * 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.tapl;
+
+import android.graphics.Point;
+
+import androidx.test.uiautomator.UiObject2;
+
+import java.util.regex.Pattern;
+
+/**
+ * App icon in workspace.
+ */
+final class WorkspaceAppIcon extends HomeAppIcon {
+
+ WorkspaceAppIcon(LauncherInstrumentation launcher, UiObject2 icon) {
+ super(launcher, icon);
+ }
+
+ @Override
+ protected Pattern getLongClickEvent() {
+ return Workspace.LONG_CLICK_EVENT;
+ }
+
+ boolean isInCell(int cellX, int cellY) {
+ final Point center = Workspace.getCellCenter(mLauncher, cellX, cellY);
+ return mObject.getParent().getVisibleBounds().contains(center.x, center.y);
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java b/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java
new file mode 100644
index 0000000..d8d4420
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java
@@ -0,0 +1,52 @@
+/*
+ * 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.tapl;
+
+import android.graphics.Point;
+
+/** Launchable that can serve as a source for dragging and dropping to the workspace. */
+interface WorkspaceDragSource {
+
+ /**
+ * Drags an object to the center of homescreen.
+ *
+ * @param startsActivity whether it's expected to start an activity.
+ * @param isWidgetShortcut whether we drag a widget shortcut
+ */
+ default void dragToWorkspace(boolean startsActivity, boolean isWidgetShortcut) {
+ Launchable launchable = getLaunchable();
+ LauncherInstrumentation launcher = launchable.mLauncher;
+ try (LauncherInstrumentation.Closable e = launcher.eventsCheck()) {
+ final Point launchableCenter = launchable.getObject().getVisibleCenter();
+ final Point displaySize = launcher.getRealDisplaySize();
+ final int width = displaySize.x / 2;
+ Workspace.dragIconToWorkspace(
+ launcher,
+ launchable,
+ new Point(
+ launchableCenter.x >= width
+ ? launchableCenter.x - width / 2
+ : launchableCenter.x + width / 2,
+ displaySize.y / 2),
+ startsActivity,
+ isWidgetShortcut,
+ launchable::addExpectedEventsForLongClick);
+ }
+ }
+
+ /** This method requires public access, however should not be called in tests. */
+ Launchable getLaunchable();
+}