[automerger skipped] Import translations. DO NOT MERGE ANYWHERE am: 5f02b2d52c -s ours
am skip reason: subject contains skip directive
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/17937863
Change-Id: Ibef2d2371414b7d35b903df4892506dca573cc85
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..1bfaf66 100644
--- a/go/quickstep/res/values-am/strings.xml
+++ b/go/quickstep/res/values-am/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-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..2e76e2d 100644
--- a/go/quickstep/res/values-or/strings.xml
+++ b/go/quickstep/res/values-or/strings.xml
@@ -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..0be8cce 100644
--- a/go/quickstep/res/values-ro/strings.xml
+++ b/go/quickstep/res/values-ro/strings.xml
@@ -16,4 +16,5 @@
<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="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..c287446 100644
--- a/go/quickstep/src/com/android/launcher3/AppSharing.java
+++ b/go/quickstep/src/com/android/launcher3/AppSharing.java
@@ -22,13 +22,22 @@
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 java.io.File;
@@ -44,6 +53,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 +65,68 @@
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) {
+ if (!isEnabled()) {
+ showCannotShareToast(view.getContext());
+ return;
+ }
+
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
@@ -118,15 +154,55 @@
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) {
+ CharSequence text = (mSharingEnabledForUser)
+ ? context.getText(R.string.toast_p2p_app_not_shareable)
+ : context.getText(R.string.blocked_by_policy);
+ 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/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..a24a588 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.
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..a1566f0 100644
--- a/quickstep/protos_overrides/launcher_atom_extension.proto
+++ b/quickstep/protos_overrides/launcher_atom_extension.proto
@@ -23,20 +23,37 @@
// Message name should match with launcher_atom_extension.proto message at
// the AOSP level.
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.
message DeviceSearchResultContainer{
optional int32 query_length = 1;
-}
+ optional SearchAttributes search_attributes = 2;
-// Represents on-device search result container with results from spell-corrected query.
-message CorrectedDeviceSearchResultContainer{
- optional int32 query_length = 1;
-}
+ 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..1b3f1cd 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -76,6 +76,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 +98,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..6daa895 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -76,6 +76,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 +98,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 df51dab..fe9af18 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -76,6 +76,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 +98,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..a6a7e38 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -76,6 +76,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 +98,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..3650658 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -76,6 +76,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 +98,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..6af2f1f 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -76,6 +76,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 +98,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..41ab4a6 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -76,6 +76,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 +98,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..e5eedbb 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -76,6 +76,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 +98,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..1d9d3d4 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -76,6 +76,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 +98,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 4b593df..46a9fec 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -76,6 +76,7 @@
<string name="allset_title" msgid="5021126669778966707">"Sve je spremno!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Prevucite prema gore da odete na početnu stranicu"</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 +98,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..da445ab 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -76,6 +76,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 +98,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..2e30961 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -76,6 +76,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 +98,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..fe069d7 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -76,6 +76,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 +98,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 be3a4f7..24a153b 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -76,6 +76,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 +98,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..3c24a13 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -76,6 +76,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 +98,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..88a2c67 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -76,6 +76,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 +98,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 487ea72..88a2c67 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -76,6 +76,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 +98,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..88a2c67 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -76,6 +76,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 +98,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..88a2c67 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -76,6 +76,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 +98,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..1ad2874 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -76,6 +76,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 +98,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 e3f3cdf..5c29ff8 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -76,6 +76,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 +98,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 adf6a42..6dfda23 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -76,6 +76,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 +98,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..5d88a75 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -76,6 +76,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 +98,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 1858625..077cb02 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -76,6 +76,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 +98,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..380e412 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -76,6 +76,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 +98,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 9244c6b..d74cfb7 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -76,6 +76,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 +98,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..447d483 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -76,6 +76,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 +98,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..6fd3401 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -76,6 +76,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 +98,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 234d611..f409e47 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -76,6 +76,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">"Todo está listo para 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 +98,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..c8c488e 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -76,6 +76,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 +98,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 87868f8..1842321 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -76,6 +76,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 +98,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..41e7922 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -76,6 +76,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 +98,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..fb90e09 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -76,6 +76,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 +98,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 598f9fa..0679d52 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -76,6 +76,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 +98,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 87db483..09b80e4 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -76,6 +76,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 +98,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..947e7ee 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -76,6 +76,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 +98,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 0d91ccf..044da60 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -76,6 +76,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 +98,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..29951d0 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -76,6 +76,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 +98,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 b4460bc..6f2567b 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -76,6 +76,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 +98,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..88281ec 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -76,6 +76,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 +98,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..fa95cc2 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -76,6 +76,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 +98,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 9b8c997..c3ea1b0 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -76,6 +76,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 +98,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 37cfcfe..42858c8 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -76,6 +76,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 +98,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 c46efa4..9ff90d4 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -76,6 +76,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 +98,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 bc39735..b3a6ca4 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -76,6 +76,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 +98,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..eb2b835 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -76,6 +76,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 +98,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..8bf7353 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -76,6 +76,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 +98,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..12b7afd 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -76,6 +76,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 +98,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 1afe079..fab6b6e 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -76,6 +76,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 +98,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 eed4a7a..07343f4 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -76,6 +76,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 +98,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..730d0d1 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -76,6 +76,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 +98,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 897c7f3..d658fe3 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -76,6 +76,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 +98,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..322f00f 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -76,6 +76,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 +98,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 dbc4105..ba0af80 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -76,6 +76,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 +98,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 e2ae437..f4fb8fa 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -70,12 +70,13 @@
<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>
- <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Prøv på nytt"</string>
+ <string name="gesture_tutorial_try_again" msgid="65962545858556697">"Prøv igjen"</string>
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Bra!"</string>
<string name="gesture_tutorial_step" msgid="1279786122817620968">"Veiledning <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
<string name="allset_title" msgid="5021126669778966707">"Alt er klart!"</string>
<string name="allset_hint" msgid="2384632994739392447">"Sveip opp for å gå til startskjermen"</string>
<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 +98,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 638a4c6..cac768a 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -76,6 +76,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 +98,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 61dacbb..4c02ea1 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -76,6 +76,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 +98,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..b76da38 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -76,6 +76,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 +98,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..212492d 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -76,6 +76,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 +98,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 1b4617f..d8bbb43 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -76,6 +76,7 @@
<string name="allset_title" msgid="5021126669778966707">"Wszystko gotowe"</string>
<string name="allset_hint" msgid="2384632994739392447">"Aby przejść na stronę główną, 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 +98,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..a3110eb 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -76,6 +76,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 +98,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 f9252b2..305a1d8 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -76,6 +76,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 +98,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..0294ada 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -76,6 +76,7 @@
<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_description_tablet" msgid="7332070270570039247">"Sunteți gata să folosiți 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_screenshot" msgid="8171125848358142917">"Captură de ecran"</string>
@@ -97,4 +98,13 @@
<string name="taskbar_edu_previous" msgid="459202320127201702">"Înapoi"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Închideți"</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">"Mutați în stânga sus"</string>
+ <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mutați în dreapta jos"</string>
</resources>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index 105da96..6b36b5a 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -76,6 +76,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 +98,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..360f189 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -76,6 +76,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 +98,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 46467ac..5281c57 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -76,6 +76,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 +98,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 d9aade7..87ed18a 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -76,6 +76,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 +98,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 f973b06..828b440 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -76,6 +76,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 +98,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..8e5dcba 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -76,6 +76,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 +98,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..bb9eaba 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -76,6 +76,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 +98,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..27b728b 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -76,6 +76,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 +98,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/quickstep/res/values-sw600dp-land/dimens.xml b/quickstep/res/values-sw600dp-land/dimens.xml
new file mode 100644
index 0000000..4e3c02c
--- /dev/null
+++ b/quickstep/res/values-sw600dp-land/dimens.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.
+*/
+-->
+<resources>
+ <dimen name="overview_actions_top_margin_gesture">19.1dp</dimen>
+ <dimen name="overview_actions_bottom_margin_gesture">10dp</dimen>
+ <dimen name="overview_grid_side_margin">52dp</dimen>
+ <dimen name="overview_page_spacing">38dp</dimen>
+</resources>
diff --git a/quickstep/res/values-sw600dp/dimens.xml b/quickstep/res/values-sw600dp/dimens.xml
index 5d9e059..223a5e9 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>
+
+ <dimen name="overview_task_margin">12dp</dimen>
+ <dimen name="overview_task_margin_grid">4dp</dimen>
+ <dimen name="overview_actions_button_spacing">36dp</dimen>
+ <dimen name="overview_actions_top_margin_gesture">19.37dp</dimen>
+ <dimen name="overview_actions_bottom_margin_gesture">22dp</dimen>
+ <dimen name="overview_grid_side_margin">60dp</dimen>
+ <dimen name="overview_grid_row_spacing">36dp</dimen>
+ <dimen name="overview_page_spacing">36dp</dimen>
+ <dimen name="task_thumbnail_icon_drawable_size_grid">32dp</dimen>
</resources>
diff --git a/quickstep/res/values-sw720dp/dimens.xml b/quickstep/res/values-sw720dp/dimens.xml
index 2831a6f..e381cb0 100644
--- a/quickstep/res/values-sw720dp/dimens.xml
+++ b/quickstep/res/values-sw720dp/dimens.xml
@@ -15,7 +15,11 @@
*/
-->
<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>
+ <dimen name="overview_task_margin">16dp</dimen>
+ <dimen name="overview_task_margin_grid">16dp</dimen>
+ <dimen name="overview_grid_side_margin">64dp</dimen>
+ <dimen name="overview_grid_row_spacing">36dp</dimen>
+ <dimen name="overview_page_spacing">44dp</dimen>
+ <dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
+ <dimen name="task_thumbnail_icon_drawable_size_grid">44dp</dimen>
</resources>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index a6f8530..0144430 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -76,6 +76,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 +98,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 eaa3e8b..9d80fe1 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -76,6 +76,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 +98,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 2caa536..95b6c21 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -76,6 +76,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 +98,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..53084e2 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -76,6 +76,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 +98,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..0e2cffb 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -76,6 +76,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 +98,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..a6b9a6c 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -76,6 +76,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 +98,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..975a184 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -76,6 +76,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 +98,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..27ca1d0 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -76,6 +76,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 +98,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..883653b 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -76,6 +76,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 +98,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..73b194d 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -76,6 +76,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 +98,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..123a016 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -76,6 +76,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 +98,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..a2b204f 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -76,6 +76,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 +98,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..41f6a7a 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -76,6 +76,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 +98,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..3f08cf3 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -17,7 +17,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 +26,25 @@
<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>
<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_task_margin_grid">0dp</dimen>
<item name="overview_max_scale" format="float" type="dimen">0.7</item>
<!-- Overrideable in overlay that provides the Overview Actions. -->
<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_top_margin_gesture">28dp</dimen>
+ <dimen name="overview_actions_bottom_margin_gesture">28dp</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>
<!-- These speeds are in dp/s -->
<dimen name="max_task_dismiss_drag_velocity">2.25dp</dimen>
@@ -121,8 +110,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 +126,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 +181,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 +259,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..f80deeb 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -182,8 +182,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 +238,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..fe24c4b 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -21,27 +21,30 @@
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.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 +64,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 +92,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 +127,6 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- SysUINavigationMode.INSTANCE.get(this).addModeChangeListener(this);
addMultiWindowModeChangedListener(mDepthController);
initUnfoldTransitionProgressProvider();
}
@@ -154,8 +156,6 @@
mUnfoldTransitionProgressProvider.destroy();
}
- SysUINavigationMode.INSTANCE.get(this).removeModeChangeListener(this);
-
mTISBindHelper.onDestroy();
if (mTaskbarManager != null) {
mTaskbarManager.clearActivity(this);
@@ -182,14 +182,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
@@ -298,15 +290,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.updateVerticalMargin(DisplayController.getNavigationMode(this));
mAppTransitionManager = new QuickstepTransitionManager(this);
mAppTransitionManager.registerRemoteAnimations();
@@ -335,9 +326,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 +379,7 @@
@Override
public boolean supportsAdaptiveIconAnimation(View clickedView) {
- return mAppTransitionManager.hasControlRemoteAppTransitionPermission()
- && FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM.get();
+ return mAppTransitionManager.hasControlRemoteAppTransitionPermission();
}
@Override
@@ -426,7 +419,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 +449,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 +467,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 +486,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 +527,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 +597,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 +613,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..0f3474e 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);
@@ -520,7 +520,7 @@
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,8 +581,8 @@
}
}
- // Pause page indicator animations as they lead to layer trashing.
- mLauncher.getWorkspace().getPageIndicator().pauseAnimations();
+ // Pause expensive view updates as they can lead to layer thrashing and skipped frames.
+ mLauncher.pauseExpensiveViewUpdates();
endListener = () -> {
viewsToAnimate.forEach(view -> {
@@ -592,7 +592,7 @@
if (scrimEnabled) {
mLauncher.getScrimView().setBackgroundColor(Color.TRANSPARENT);
}
- mLauncher.getWorkspace().getPageIndicator().skipAnimationsToEnd();
+ mLauncher.resumeExpensiveViewUpdates();
};
}
@@ -707,6 +707,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 +1156,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 +1167,7 @@
unregisterRemoteAnimations();
unregisterRemoteTransitions();
mStartingWindowListener.setTransitionManager(null);
- SystemUiProxy.INSTANCE.getNoCreate().setStartingWindowListener(null);
+ SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(null);
}
private void unregisterRemoteAnimations() {
@@ -1176,11 +1191,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 +1215,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 +1352,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) {
FloatingIconView floatingIconView = null;
FloatingWidgetView floatingWidget = null;
RectF targetRect = new RectF();
@@ -1353,8 +1386,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.
@@ -1388,7 +1420,7 @@
final float floatingWidgetAlpha = isTransluscent ? 0 : 1;
FloatingWidgetView finalFloatingWidget = floatingWidget;
- RectFSpringAnim.OnUpdateListener runner = new SpringAnimRunner(targets, targetRect,
+ RectFSpringAnim.OnUpdateListener runner = new SpringAnimRunner(targets, targetRect,
windowTargetBounds) {
@Override
public void onUpdate(RectF currentRectF, float progress) {
@@ -1403,6 +1435,10 @@
}
};
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));
}
// Use a fixed velocity to start the animation.
@@ -1412,6 +1448,7 @@
anim.start(mLauncher, velocityPxPerS);
}
});
+ return anim;
}
/**
@@ -1536,6 +1573,103 @@
}
/**
+ * 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) {
+ 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);
+ 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 {
@@ -1575,83 +1709,12 @@
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));
mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL);
- result.setAnimation(anim, mLauncher);
+ result.setAnimation(pair.second, mLauncher);
}
}
diff --git a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
index 1b0f967..0284ae4 100644
--- a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
@@ -16,7 +16,7 @@
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;
@@ -34,23 +34,17 @@
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 +52,6 @@
ALL_APPS_LABEL
}
- private final Launcher mLauncher;
private final TextPaint mPaint = new TextPaint();
private DividerType mDividerType = DividerType.NONE;
@@ -86,7 +79,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 +93,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 +105,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 +194,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 +212,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,51 +239,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());
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index 9ad8bb2..1dec737 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -31,8 +31,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 +43,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 +64,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 +78,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 +95,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 +118,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 +156,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 +174,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 +195,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 +229,6 @@
boolean predictionsEnabled = predictionCount > 0;
if (predictionsEnabled != mPredictionsEnabled) {
mPredictionsEnabled = predictionsEnabled;
- mLauncher.reapplyUi(false /* cancelCurrentAnimation */);
updateVisibility();
}
mParent.onHeightUpdated();
@@ -237,11 +242,10 @@
@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);
}
@@ -263,6 +267,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..62a8da7 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -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) {
@@ -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..5c66944 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;
@@ -137,12 +140,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 +178,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 +298,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..9c3daea 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();
@@ -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..0e534f4 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();
}
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..86310fa
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.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.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(view, 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/search/SearchSessionManager.java b/quickstep/src/com/android/launcher3/search/SearchSessionManager.java
new file mode 100644
index 0000000..da85793
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/search/SearchSessionManager.java
@@ -0,0 +1,84 @@
+/*
+ * 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.search;
+
+import android.app.search.SearchSession;
+import android.content.Context;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.UiThread;
+
+import com.android.launcher3.R;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.util.ResourceBasedOverride;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+
+/** Manages an all apps search session. */
+public class SearchSessionManager implements ResourceBasedOverride {
+
+ /** Entry state for the search session (e.g. from all apps). */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {ZERO_ALLAPPS, ZERO_QSB})
+ public @interface ZeroEntryState {}
+ public static final int ZERO_ALLAPPS = 1;
+ public static final int ZERO_QSB = 2;
+
+ /** Creates a {@link SearchSessionManager} instance. */
+ public static SearchSessionManager newInstance(Context context) {
+ return Overrides.getObject(
+ SearchSessionManager.class, context, R.string.search_session_manager_class);
+ }
+
+ /** The current {@link SearchSession}. */
+ @UiThread
+ public void setSearchSession(SearchSession session) {}
+
+ /** {@code true} if IME is shown. */
+ public void setIsImeShown(boolean value) {}
+
+ /** Returns {@code true} if IME is enabled. */
+ public boolean getIsImeEnabled() {
+ return false;
+ }
+
+ /** The current entry state for search. */
+ public @ZeroEntryState int getEntryState() {
+ return ZERO_ALLAPPS;
+ }
+
+ /**
+ * When user enters all apps surface via tap on home widget, set the state to
+ * {@code #ZERO_QSB}. When user exits, reset to {@code #ZERO_ALLAPPS}
+ */
+ public void setEntryState(@ZeroEntryState int state) {}
+
+ /** This will be called before opening all apps, to prepare zero state suggestions. */
+ public void prepareZeroState() {}
+
+ /** Apply predicted items for the search zero state. */
+ public void setZeroStatePredictedItems(List<ItemInfo> items) {}
+
+ /** Returns {@code true} if the session is valid and should be enabled. */
+ public boolean isValidSession() {
+ return false;
+ }
+
+ /** Called when the search session is destroyed. */
+ public void onDestroy() {}
+}
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..4e1f54c
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar;
+
+import android.content.Context;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
+
+import com.android.launcher3.DeviceProfile;
+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<>();
+
+ protected DeviceProfile mDeviceProfile;
+
+ 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 DeviceProfile getDeviceProfile() {
+ return mDeviceProfile;
+ }
+
+ @Override
+ public final List<OnDeviceProfileChangeListener> getOnDeviceProfileChangeListeners() {
+ return mDPChangeListeners;
+ }
+
+ /** Updates the {@link DeviceProfile} instance to the latest representation of the screen. */
+ public abstract void updateDeviceProfile(DeviceProfile dp);
+
+ /** 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..cf56248
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java
@@ -0,0 +1,42 @@
+/*
+ * 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);
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 5e8db69..793d987 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -27,6 +27,7 @@
import android.view.WindowManagerGlobal;
import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.DeviceProfile;
@@ -34,11 +35,10 @@
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;
@@ -113,6 +113,29 @@
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();
+ }
+
/**
* Should be called from onResume() and onPause(), and animates the Taskbar accordingly.
*/
@@ -211,9 +234,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 +243,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);
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 50637a1..f65b907 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -22,6 +22,7 @@
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 +33,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 +43,25 @@
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.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 +69,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 +105,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;
@@ -121,11 +141,21 @@
// 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;
+
public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) {
mContext = context;
mNavButtonsView = navButtonsView;
@@ -146,27 +176,30 @@
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
@@ -177,12 +210,12 @@
0, 1));
// 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 +237,74 @@
& 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();
}
- // 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 +326,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 +361,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 +375,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);
@@ -274,16 +388,20 @@
// home and recents buttons
- View homeButton = addButton(R.drawable.ic_sysbar_home, BUTTON_HOME, navContainer,
+ 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));
View recentsButton = addButton(R.drawable.ic_sysbar_recent, BUTTON_RECENTS,
navContainer, navButtonController, R.id.recent_apps);
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,7 +496,7 @@
/**
* 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);
@@ -389,6 +507,20 @@
}
}
+ /**
+ * 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;
@@ -439,7 +571,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 +582,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 +615,100 @@
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();
}
private class RotationButtonListener implements RotationButton.RotationButtonUpdatesCallback {
@@ -585,6 +813,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/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..b349637 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -15,16 +15,18 @@
*/
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.app.ActivityOptions;
@@ -34,56 +36,66 @@
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.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 +103,60 @@
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 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));
+ super(windowContext);
mDeviceProfile = dp;
- 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_FORCE_VISIBLE), 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 +166,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 +186,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),
+ new TaskbarInsetsController(this));
}
public void init(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 +210,16 @@
mWindowManager.addView(mDragLayer, mWindowLayoutParams);
}
- /** Updates the Device profile instance to the latest representation of the screen. */
+ @Override
public void updateDeviceProfile(DeviceProfile dp) {
mDeviceProfile = dp;
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) {
@@ -222,6 +227,35 @@
mDeviceProfile.updateIconSize(1, resources);
float iconScale = taskbarIconSize / mDeviceProfile.iconSizePx;
mDeviceProfile.updateIconSize(iconScale, resources);
+ mDeviceProfile.updateAllAppsIconSize(1, resources); // Leave all apps unscaled.
+ }
+
+ @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) {
@@ -229,7 +263,15 @@
}
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 +282,8 @@
return mRightCorner == null ? 0 : mRightCorner.getRadius();
}
- @Override
- public LayoutInflater getLayoutInflater() {
- return mLayoutInflater;
+ public WindowManager.LayoutParams getWindowLayoutParams() {
+ return mWindowLayoutParams;
}
@Override
@@ -251,11 +292,6 @@
}
@Override
- public DeviceProfile getDeviceProfile() {
- return mDeviceProfile;
- }
-
- @Override
public Rect getFolderBoundingBox() {
return mControllers.taskbarDragLayerController.getFolderBoundingBox();
}
@@ -271,14 +307,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 +362,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 +448,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 +512,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 +559,7 @@
}
}
mWindowLayoutParams.height = height;
- mWindowLayoutParams.providedInternalImeInsets =
- Insets.of(0, height - mTaskbarHeightForIme, 0, 0);
+ mControllers.taskbarInsetsController.onTaskbarWindowHeightOrInsetsChanged();
mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
}
@@ -470,10 +571,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 +615,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 +652,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 +677,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 +687,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 +726,14 @@
return mIsUserSetupComplete;
}
+ protected boolean isNavBarKidsModeActive() {
+ return mIsNavBarKidsMode && isThreeButtonNav();
+ }
+
+ protected boolean isNavBarForceVisible() {
+ return mIsNavBarForceVisible;
+ }
+
/**
* Called when we determine the touchable region.
*
@@ -582,4 +754,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..ff08e3d 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;
@@ -65,7 +75,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 +94,9 @@
this.taskbarEduController = taskbarEduController;
this.taskbarAutohideSuspendController = taskbarAutoHideSuspendController;
this.taskbarPopupController = taskbarPopupController;
+ this.taskbarForceVisibleImmersiveController = taskbarForceVisibleImmersiveController;
+ this.taskbarAllAppsController = taskbarAllAppsController;
+ this.taskbarInsetsController = taskbarInsetsController;
}
/**
@@ -102,6 +118,19 @@
stashedHandleViewController.init(this);
taskbarStashController.init(this, sharedState);
taskbarEduController.init(this);
+ taskbarPopupController.init(this);
+ taskbarForceVisibleImmersiveController.init(this);
+ taskbarAllAppsController.init(this, sharedState);
+ 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) {
@@ -127,6 +156,13 @@
taskbarViewController.onDestroy();
stashedHandleViewController.onDestroy();
taskbarAutohideSuspendController.onDestroy();
+ taskbarPopupController.onDestroy();
+ taskbarForceVisibleImmersiveController.onDestroy();
+ taskbarAllAppsController.onDestroy();
+ navButtonController.onDestroy();
+ taskbarInsetsController.onDestroy();
+
+ mControllersToLog = null;
}
/**
@@ -141,4 +177,29 @@
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;
+ }
+
+ for (LoggableTaskbarController controller : mControllersToLog) {
+ controller.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..5c10565 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,25 @@
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;
/**
* 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 +94,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 +112,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 +146,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 +155,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 +167,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 +294,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 +306,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 +319,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 +367,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 +378,7 @@
}
}
- private void onSystemDragStarted() {
+ private void onSystemDragStarted(BubbleTextView btv) {
mIsSystemDragInProgress = true;
mActivity.getDragLayer().setOnDragListener((view, dragEvent) -> {
switch (dragEvent.getAction()) {
@@ -322,7 +387,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 +404,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 +424,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.
+ ItemInfoMatcher 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.
+ ItemInfoMatcher 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 +552,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..3e2695c 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,13 @@
public int getTaskbarBackgroundHeight() {
return mActivity.getDeviceProfile().taskbarSize;
}
+
+ /**
+ * Returns touch controllers.
+ */
+ public TouchController[] getTouchControllers() {
+ return new TouchController[]{mActivity.getDragController(),
+ mControllers.taskbarForceVisibleImmersiveController};
+ }
}
}
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..9870a2e
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -0,0 +1,146 @@
+/*
+ * 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.view.WindowManager
+import com.android.launcher3.AbstractFloatingView
+import com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_ALL_APPS
+import com.android.launcher3.R
+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)
+
+ // 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
+ )
+ )
+
+ windowLayoutParams.providedInternalInsets = arrayOfNulls<Insets>(ITYPE_SIZE)
+ windowLayoutParams.providedInternalImeInsets = arrayOfNulls<Insets>(ITYPE_SIZE)
+
+ onTaskbarWindowHeightOrInsetsChanged()
+
+ windowLayoutParams.insetsRoundedCornerFrame = true
+ }
+
+ fun onDestroy() {}
+
+ fun onTaskbarWindowHeightOrInsetsChanged() {
+ var reducingSize = getReducingInsetsForTaskbarInsetsHeight(
+ controllers.taskbarStashController.contentHeightToReportToApps)
+ windowLayoutParams.providedInternalInsets[ITYPE_EXTRA_NAVIGATION_BAR] = reducingSize
+ reducingSize = getReducingInsetsForTaskbarInsetsHeight(
+ controllers.taskbarStashController.tappableHeightToReportToApps)
+ windowLayoutParams.providedInternalInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT] = reducingSize
+
+ reducingSize = getReducingInsetsForTaskbarInsetsHeight(taskbarHeightForIme)
+ windowLayoutParams.providedInternalImeInsets[ITYPE_EXTRA_NAVIGATION_BAR] = reducingSize
+ windowLayoutParams.providedInternalImeInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT] = 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.TOUCHABLE_INSETS_CONTENT
+ }
+ )
+ 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..36e6420 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -26,15 +26,20 @@
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.DeviceProfile;
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.util.HashMap;
@@ -70,9 +75,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 +97,9 @@
mLauncherState = toState;
}
updateStateForFlag(FLAG_TRANSITION_STATE_RUNNING, true);
- applyState();
+ if (!mShouldDelayLauncherStateAnim) {
+ applyState();
+ }
}
@Override
@@ -97,6 +111,8 @@
};
public void init(TaskbarControllers controllers, BaseQuickstepLauncher launcher) {
+ mCanSyncViews = false;
+
mControllers = controllers;
mLauncher = launcher;
@@ -116,9 +132,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 +146,8 @@
mIconAlphaForHome.setConsumer(null);
mLauncher.getHotseat().setIconsAlpha(1f);
mLauncher.getStateManager().removeStateListener(mStateListener);
+
+ mCanSyncViews = true;
}
public Animator createAnimToLauncher(@NonNull LauncherState toState,
@@ -144,12 +166,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 +179,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 +259,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 +321,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));
}
@@ -347,7 +384,7 @@
}
private void onIconAlignmentRatioChangedForStateTransition() {
- if (!isResumed()) {
+ if (!isResumed() && mTaskBarRecentsAnimationListener == null) {
return;
}
onIconAlignmentRatioChanged(this::getCurrentIconAlignmentRatioForLauncherState);
@@ -362,6 +399,27 @@
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);
+
+ // Sync the first frame where we swap taskbar and hotseat.
+ if (firstFrameVisChanged && mCanSyncViews && !Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ DeviceProfile dp = mLauncher.getDeviceProfile();
+
+ // Do all the heavy work before the sync.
+ mControllers.taskbarViewController.createIconAlignmentControllerIfNotExists(dp);
+
+ ViewRootSync.synchronizeNextDraw(mLauncher.getHotseat(),
+ mControllers.taskbarActivityContext.getDragLayer(),
+ () -> updateIconAlignment(alignment));
+ } else {
+ updateIconAlignment(alignment);
+ }
+ }
+
+ private void updateIconAlignment(float alignment) {
mControllers.taskbarViewController.setLauncherIconAlignment(
alignment, mLauncher.getDeviceProfile());
@@ -391,7 +449,8 @@
@Override
public void onRecentsAnimationCanceled(HashMap<Integer, ThumbnailData> thumbnailDatas) {
- endGestureStateOverride(true);
+ boolean isInOverview = mLauncher.isInState(LauncherState.OVERVIEW);
+ endGestureStateOverride(!isInOverview);
}
@Override
@@ -401,6 +460,7 @@
private void endGestureStateOverride(boolean finishedToApp) {
mCallbacks.removeListener(this);
+ mTaskBarRecentsAnimationListener = null;
// Update the resumed state immediately to ensure a seamless handoff
boolean launcherResumed = !finishedToApp;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index bec717d..e02a9d7 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,44 @@
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.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,38 +86,66 @@
*/
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));
}
@@ -127,29 +159,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();
@@ -196,6 +221,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 +251,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)
@@ -288,10 +315,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 +327,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..62392ee 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,6 +30,7 @@
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;
@@ -50,8 +52,6 @@
// Initialized in init.
private TaskbarControllers mControllers;
- private boolean mBindInProgress = false;
-
public TaskbarModelCallbacks(
TaskbarActivityContext context, TaskbarView container) {
mContext = context;
@@ -64,14 +64,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();
}
@@ -157,11 +157,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 +198,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..c6dbc87 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -15,35 +15,72 @@
*/
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.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,12 +92,44 @@
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();
@@ -71,20 +140,149 @@
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..a5c55b0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
@@ -24,4 +24,6 @@
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..f34759d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -19,6 +19,7 @@
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 +28,28 @@
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.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 +58,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 +148,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,10 +162,9 @@
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) {
@@ -173,12 +190,8 @@
&& mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF);
boolean isInSetup = !mActivity.isUserSetupComplete() || sharedState.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 +201,34 @@
* Returns whether the taskbar can visually stash into a handle based on the current device
* state.
*/
- private boolean supportsVisualStashing() {
+ public boolean supportsVisualStashing() {
return !mActivity.isThreeButtonNav();
}
/**
* 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 +246,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 +272,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();
+ }
+
+ private 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 +330,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 +341,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.
*/
@@ -388,7 +454,7 @@
@Override
public void onAnimationStart(Animator animation) {
mIsStashed = isStashed;
- onIsStashed(mIsStashed);
+ onIsStashedChanged(mIsStashed);
}
@Override
@@ -425,17 +491,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 +534,41 @@
*/
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(TaskbarAllAppsSlideInView.DEFAULT_CLOSE_DURATION);
+ }
+ }
+
+ /**
* When hiding the IME, delay the unstash animation to align with the end of the transition.
*/
private long getTaskbarStashStartDelayForIme() {
@@ -510,6 +611,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 +630,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 +645,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,6 +716,14 @@
}
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.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index abad906..d5c399b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -19,8 +19,8 @@
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.util.stream.Stream;
@@ -54,7 +54,8 @@
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 +68,22 @@
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();
+ }
+ }
}
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..7548398 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -22,29 +22,40 @@
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.ItemInfoMatcher;
+import com.android.launcher3.util.LauncherBindableItemsContainer;
import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.AllAppsButton;
+import com.android.launcher3.views.DoubleShadowBubbleTextView;
/**
* 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 +74,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 +107,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 +139,10 @@
mIconLongClickListener = mControllerCallbacks.getIconOnLongClickListener();
setOnLongClickListener(mControllerCallbacks.getBackgroundOnLongClickListener());
+
+ if (mAllAppsButton != null) {
+ mAllAppsButton.setOnClickListener(mControllerCallbacks.getAllAppsButtonClickListener());
+ }
}
private void removeAndRecycle(View view) {
@@ -120,6 +162,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 +236,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 +312,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 +359,13 @@
return icons;
}
+ /**
+ * Returns the all apps button in the taskbar.
+ */
+ public View getAllAppsButtonView() {
+ return mAllAppsButton;
+ }
+
// FolderIconParent implemented methods.
@Override
@@ -330,4 +406,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(ItemInfoMatcher... matchers) {
+ for (ItemInfoMatcher 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.matchesInfo(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..6416720 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,24 @@
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;
+
/**
* 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;
@@ -61,6 +74,9 @@
this::updateTranslationY);
private AnimatedFloat mTaskbarNavButtonTranslationY;
+ private final AnimatedFloat mThemeIconsBackground = new AnimatedFloat(
+ this::updateIconsBackground);
+
private final TaskbarModelCallbacks mModelCallbacks;
// Initialized in init.
@@ -71,6 +87,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 +101,7 @@
mControllers = controllers;
mTaskbarView.init(new TaskbarViewCallbacks());
mTaskbarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;
+ mThemeIconsColor = ThemedIconDrawable.getColors(mTaskbarView.getContext())[0];
mTaskbarIconScaleForStash.updateValue(1f);
@@ -134,18 +153,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 +165,10 @@
return mTaskbarView.getIconViews();
}
+ public View getAllAppsButtonView() {
+ return mTaskbarView.getAllAppsButtonView();
+ }
+
public AnimatedFloat getTaskbarIconScaleForStash() {
return mTaskbarIconScaleForStash;
}
@@ -178,6 +191,25 @@
+ mTaskbarIconTranslationYForStash.value);
}
+ private void updateIconsBackground() {
+ mTaskbarView.setThemedIconsBackgroundColor(
+ ColorUtils.blendARGB(
+ mThemeIconsColor,
+ mTaskbarView.mThemeIconsBackground,
+ mThemeIconsBackground.value
+ ));
+ }
+
+ /**
+ * Creates the icon alignment controller if it does not already exist.
+ * @param launcherDp Launcher device profile.
+ */
+ public void createIconAlignmentControllerIfNotExists(DeviceProfile launcherDp) {
+ if (mIconAlignControllerLazy == null) {
+ mIconAlignControllerLazy = createIconAlignmentController(launcherDp);
+ }
+ }
+
/**
* Sets the taskbar icon alignment relative to Launcher hotseat icons
* @param alignmentRatio [0, 1]
@@ -185,9 +217,7 @@
* 1 => fully aligned
*/
public void setLauncherIconAlignment(float alignmentRatio, DeviceProfile launcherDp) {
- if (mIconAlignControllerLazy == null) {
- mIconAlignControllerLazy = createIconAlignmentController(launcherDp);
- }
+ createIconAlignmentControllerIfNotExists(launcherDp);
mIconAlignControllerLazy.setPlayFraction(alignmentRatio);
if (alignmentRatio <= 0 || alignmentRatio >= 1) {
// Cleanup lazy controller so that it is created again in next animation
@@ -203,14 +233,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);
+ if (Utilities.isDarkTheme(mTaskbarView.getContext())) {
+ setter.addFloat(mThemeIconsBackground, VALUE, 0f, 1f, LINEAR);
+ }
+
int collapsedHeight = mActivity.getDefaultTaskbarWindowHeight();
int expandedHeight = Math.max(collapsedHeight,
mActivity.getDeviceProfile().taskbarSize + offsetY);
@@ -220,13 +256,31 @@
int count = mTaskbarView.getChildCount();
for (int i = 0; i < count; 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 = -1;
+ if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get() && i == count - 1) {
+ // 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().inv.numShownHotseatIcons;
+
+ 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();
@@ -243,6 +297,24 @@
}
/**
+ * 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(ItemInfoMatcher matcher) {
+ ItemInfoMatcher 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 +322,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 +341,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..1cdbdb2
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java
@@ -0,0 +1,255 @@
+/*
+ * 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.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
+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;
+ mDeviceProfile = taskbarContext.getDeviceProfile();
+ 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);
+ mWindowController = windowController;
+ mAllAppsViewController = new TaskbarAllAppsViewController(
+ this,
+ slideInView,
+ windowController,
+ taskbarStashController);
+ mAppsView = slideInView.getAppsView();
+
+ mWillTaskbarBeVisuallyStashed = taskbarStashController.supportsVisualStashing();
+ mStashedTaskbarHeight = taskbarStashController.getStashedHeight();
+ }
+
+ TaskbarAllAppsViewController getAllAppsViewController() {
+ return mAllAppsViewController;
+ }
+
+ @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 updateDeviceProfile(DeviceProfile dp) {
+ mDeviceProfile = dp;
+
+ AbstractFloatingView.closeAllOpenViewsExcept(this, false, TYPE_REBIND_SAFE);
+
+ dispatchDeviceProfileChanged();
+ }
+
+ @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..9fca8eb
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
@@ -0,0 +1,248 @@
+/*
+ * 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 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.DeviceProfile.OnDeviceProfileChangeListener;
+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.launcher3.taskbar.TaskbarSharedState;
+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 implements OnDeviceProfileChangeListener {
+
+ 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 TaskbarControllers mControllers;
+ private TaskbarSharedState mSharedState;
+ /** 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) {
+ mTaskbarContext = context;
+ mProxyView = new TaskbarAllAppsProxyView(mTaskbarContext);
+ mLayoutParams = createLayoutParams();
+ }
+
+ /** Initialize the controller. */
+ public void init(TaskbarControllers controllers, TaskbarSharedState sharedState) {
+ if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
+ return;
+ }
+ mControllers = controllers;
+ mSharedState = sharedState;
+
+ /*
+ * Recreate All Apps if it was open in the previous Taskbar instance (e.g. the configuration
+ * changed).
+ */
+ if (mSharedState.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();
+ mSharedState.allAppsVisible = true;
+
+ mAllAppsContext = new TaskbarAllAppsContext(mTaskbarContext,
+ this,
+ mControllers.taskbarStashController);
+ mAllAppsContext.getDragController().init(mControllers);
+ mTaskbarContext.addOnDeviceProfileChangeListener(this);
+ 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);
+ mSharedState.allAppsVisible = false;
+ onDestroy();
+ }
+
+ /** Destroys the controller and any All Apps window if present. */
+ public void onDestroy() {
+ TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
+ mTaskbarContext.removeOnDeviceProfileChangeListener(this);
+ Optional.ofNullable(mAllAppsContext)
+ .map(c -> c.getSystemService(WindowManager.class))
+ .ifPresent(m -> m.removeView(mAllAppsContext.getDragLayer()));
+ mAllAppsContext = null;
+ }
+
+ 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;
+ }
+
+ @Override
+ public void onDeviceProfileChanged(DeviceProfile dp) {
+ Optional.ofNullable(mAllAppsContext).ifPresent(c -> c.updateDeviceProfile(dp));
+ }
+
+ /**
+ * 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..a37ebac
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -0,0 +1,146 @@
+/*
+ * 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.anim.Interpolators.AGGRESSIVE_EASE;
+
+import android.animation.PropertyValuesHolder;
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+
+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 {
+ static final int DEFAULT_OPEN_DURATION = 500;
+ public static final int DEFAULT_CLOSE_DURATION = 200;
+
+ 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(DEFAULT_OPEN_DURATION).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, DEFAULT_CLOSE_DURATION);
+ }
+
+ @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..f19b7de
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.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.taskbar.allapps;
+
+import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_IN_APP_ALL_APPS;
+import static com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView.DEFAULT_OPEN_DURATION;
+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(DEFAULT_OPEN_DURATION);
+ 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..351ec4a 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;
@@ -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..f32b315 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -68,15 +68,14 @@
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.DisplayController;
+import com.android.launcher3.util.DisplayController.NavigationMode;
import com.android.launcher3.util.ItemInfoMatcher;
-import com.android.launcher3.util.OnboardingPrefs;
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;
@@ -162,7 +161,7 @@
}
@Override
- protected OnboardingPrefs createOnboardingPrefs(SharedPreferences sharedPrefs) {
+ protected QuickstepOnboardingPrefs createOnboardingPrefs(SharedPreferences sharedPrefs) {
return new QuickstepOnboardingPrefs(this, sharedPrefs);
}
@@ -235,8 +234,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) {
@@ -262,7 +263,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 +303,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..86f26c3 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));
// 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/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index 8f89d30..cd14b3f 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -23,7 +23,6 @@
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;
/**
@@ -33,26 +32,18 @@
private static final int STATE_FLAGS = FLAG_WORKSPACE_INACCESSIBLE | FLAG_CLOSE_POPUPS;
- 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;
+ return 150;
}
@Override
public String getDescription(Launcher launcher) {
- AllAppsContainerView appsView = launcher.getAppsView();
- return appsView.getDescription();
+ return launcher.getAppsView().getDescription();
}
@Override
@@ -62,18 +53,20 @@
@Override
public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
- ScaleAndTranslation scaleAndTranslation = LauncherState.OVERVIEW
- .getWorkspaceScaleAndTranslation(launcher);
- scaleAndTranslation.scale = 1;
+ ScaleAndTranslation scaleAndTranslation =
+ new ScaleAndTranslation(NO_SCALE, NO_OFFSET, NO_OFFSET);
+ if (launcher.getDeviceProfile().isTablet) {
+ scaleAndTranslation.scale = 0.97f;
+ } else {
+ ScaleAndTranslation overviewScaleAndTranslation = LauncherState.OVERVIEW
+ .getWorkspaceScaleAndTranslation(launcher);
+ scaleAndTranslation.translationX = overviewScaleAndTranslation.translationX;
+ scaleAndTranslation.translationY = overviewScaleAndTranslation.translationY;
+ }
return scaleAndTranslation;
}
@Override
- public boolean isTaskbarStashed(Launcher launcher) {
- return true;
- }
-
- @Override
protected float getDepthUnchecked(Context context) {
// The scrim fades in at approximately 50% of the swipe gesture.
// This means that the depth should be greater than 1, in order to fully zoom out.
@@ -82,12 +75,20 @@
@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;
+ return ALL_APPS_CONTENT | HOTSEAT_ICONS;
}
@Override
@@ -97,6 +98,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/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 08d0a80..236454e 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -26,8 +26,8 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
+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;
@@ -58,7 +58,7 @@
@Override
public int getTransitionDuration(Context context) {
// 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
@@ -103,7 +103,7 @@
@Override
public boolean displayOverviewTasksAsGrid(DeviceProfile deviceProfile) {
- return deviceProfile.overviewShowAsGrid;
+ return deviceProfile.isTablet;
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index 75cf5cb..b1d83e7 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;
@@ -60,7 +60,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 +97,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 +118,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 +139,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,7 +172,8 @@
} 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();
}
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..7ec1243 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;
@@ -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 {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index dadc706..2ca59eb 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -41,7 +41,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;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index 59ade49..27a55c3 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -23,6 +23,8 @@
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.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
@@ -126,9 +128,12 @@
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));
+ boolean isTablet = mLauncher.getDeviceProfile().isTablet;
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, isTablet
+ ? INSTANT
+ : 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));
@@ -137,9 +142,12 @@
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));
+ boolean isTablet = mLauncher.getDeviceProfile().isTablet;
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, isTablet
+ ? FINAL_FRAME
+ : 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));
@@ -221,13 +229,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
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..b90e820 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -32,10 +32,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;
@@ -102,7 +102,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 +113,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;
@@ -564,26 +564,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 +770,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 +789,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 +821,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;
@@ -851,7 +836,7 @@
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
@@ -984,7 +969,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 +985,7 @@
mStateCallback.setState(STATE_RESUME_LAST_TASK);
}
if (mRecentsAnimationTargets != null) {
- setDividerShown(true, true /* immediate */);
+ setDividerShown(true /* shown */, true /* immediate */);
}
break;
}
@@ -1022,35 +1006,41 @@
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;
}
final GestureEndTarget endTarget;
- final boolean goingToNewTask;
+ final boolean canGoToNewTask;
if (mRecentsView != null) {
if (!hasTargets()) {
// If there are no running tasks, then we can assume that this is a continuation of
// the last gesture, but after the recents animation has finished
- goingToNewTask = true;
+ canGoToNewTask = true;
} else {
final int runningTaskIndex = mRecentsView.getRunningTaskIndex();
final int taskToLaunch = mRecentsView.getNextPage();
- goingToNewTask = runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex;
+ canGoToNewTask = runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex;
}
} else {
- goingToNewTask = false;
+ canGoToNewTask = 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 (canGoToNewTask && 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) {
+ } else if (canGoToNewTask) {
endTarget = NEW_TASK;
} else {
endTarget = !reachedOverviewThreshold ? LAST_TASK : HOME;
@@ -1058,26 +1048,22 @@
} else {
endTarget = reachedOverviewThreshold && mGestureStarted
? RECENTS
- : goingToNewTask
+ : canGoToNewTask
? NEW_TASK
: LAST_TASK;
}
} else {
// If swiping at a diagonal, base end target on the faster velocity.
boolean isSwipeUp = endVelocity < 0;
- boolean willGoToNewTaskOnSwipeUp =
- goingToNewTask && Math.abs(velocity.x) > Math.abs(endVelocity);
+ boolean willGoToNewTask =
+ canGoToNewTask && Math.abs(velocity.x) > Math.abs(endVelocity);
- if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp && !willGoToNewTaskOnSwipeUp) {
- endTarget = HOME;
- } else if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp) {
- // If swiping at a diagonal, base end target on the faster velocity.
- endTarget = NEW_TASK;
+ if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp) {
+ endTarget = willGoToNewTask ? NEW_TASK : HOME;
} else if (isSwipeUp) {
- endTarget = !reachedOverviewThreshold && willGoToNewTaskOnSwipeUp
- ? NEW_TASK : RECENTS;
+ endTarget = (!reachedOverviewThreshold && willGoToNewTask) ? NEW_TASK : RECENTS;
} else {
- endTarget = goingToNewTask ? NEW_TASK : LAST_TASK;
+ endTarget = willGoToNewTask ? NEW_TASK : LAST_TASK; // Swipe is downward.
}
}
@@ -1155,6 +1141,8 @@
duration = Math.max(duration, mRecentsView.getScroller().getDuration());
}
}
+ } else if (endTarget == LAST_TASK && mRecentsView != null) {
+ mRecentsView.snapToPage(mRecentsView.getCurrentPage(), Math.toIntExact(duration));
}
// Let RecentsView handle the scrolling to the task, which we launch in startNewTask()
@@ -1198,10 +1186,10 @@
// 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 +1264,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 +1372,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 +1397,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 +1405,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 +1445,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 +1652,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 +1759,7 @@
private void maybeFinishSwipeToHome() {
if (mIsSwipingPipToHome && mSwipePipToHomeAnimators[0] != null) {
SystemUiProxy.INSTANCE.get(mContext).stopSwipePipToHome(
+ mSwipePipToHomeAnimator.getTaskId(),
mSwipePipToHomeAnimator.getComponentName(),
mSwipePipToHomeAnimator.getDestinationBounds(),
mSwipePipToHomeAnimator.getContentOverlay());
@@ -1774,8 +1774,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 +1918,7 @@
@Override
public void onRecentsAnimationFinished(RecentsAnimationController controller) {
if (!controller.getFinishTargetIsLauncher()) {
- setDividerShown(true, false /* immediate */);
+ setDividerShown(true /* shown */, false /* immediate */);
}
mRecentsAnimationController = null;
mRecentsAnimationTargets = null;
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..9686510 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -19,9 +19,9 @@
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.util.DisplayController.getNavigationMode;
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,9 +55,10 @@
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;
@@ -68,6 +69,7 @@
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;
@@ -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,7 +222,7 @@
*/
public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect) {
Resources res = context.getResources();
- if (dp.overviewShowAsGrid) {
+ if (dp.isTablet) {
Rect gridRect = new Rect();
calculateGridSize(context, dp, gridRect);
@@ -355,10 +362,9 @@
/** 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);
+ return OverviewActionsView.getOverviewActionsBottomMarginPx(getNavigationMode(context), dp)
+ + OverviewActionsView.getOverviewActionsTopMarginPx(getNavigationMode(context), dp)
+ + dp.overviewActionsHeight;
}
/**
@@ -480,7 +486,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..7feec2c 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;
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..10a3a2e 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);
@@ -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..921674a
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
@@ -0,0 +1,323 @@
+/*
+ * 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.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.MathUtils;
+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.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;
+
+ 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) {
+ SystemUiProxy.INSTANCE.get(mLauncher).setBackToLauncherCallback(
+ 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);
+ }
+ }
+
+ public void onBackStarted() { }
+ });
+ }
+
+ 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() {
+ SystemUiProxy.INSTANCE.get(mLauncher).clearBackToLauncherCallback();
+ }
+
+ 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 = MathUtils.lerp(1, MIN_WINDOW_SCALE, progress) * screenWidth;
+ // The final width is derived from interpolating between the follow with and progress width
+ // using gesture progress.
+ float width = MathUtils.lerp(followWidth, progressWidth, progress);
+ 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(
+ MathUtils.lerp(mCancelRect.left, mStartRect.left, progress),
+ MathUtils.lerp(mCancelRect.top, mStartRect.top, progress),
+ MathUtils.lerp(mCancelRect.right, mStartRect.right, progress),
+ MathUtils.lerp(mCancelRect.bottom, mStartRect.bottom, progress));
+
+ float cornerRadius = Utilities.mapRange(
+ progress, mWindowScaleEndCornerRadius, 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();
+ }
+
+ Pair<RectFSpringAnim, AnimatorSet> pair =
+ mQuickstepTransitionManager.createWallpaperOpenAnimations(
+ new RemoteAnimationTargetCompat[]{mBackTarget},
+ new RemoteAnimationTargetCompat[]{},
+ false /* fromUnlock */,
+ mCurrentRect);
+ 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..42f9eb6 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;
}
}
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..ef81449 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,15 @@
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;
+ }
}
- 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..fe31f1d 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
@@ -145,6 +145,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 +192,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 99a02e1..920ed71 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;
@@ -43,35 +45,30 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_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;
@@ -82,30 +79,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();
@@ -129,6 +123,7 @@
}
};
+ private int mGestureBlockingTaskId = -1;
private Region mExclusionRegion;
private SystemGestureExclusionListenerCompat mExclusionListener;
@@ -143,10 +138,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
@@ -175,25 +168,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) {
@@ -262,56 +240,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() {
@@ -388,11 +346,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,8 +421,8 @@
/**
* @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;
}
/**
@@ -577,8 +541,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;
}
@@ -599,6 +562,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..d11d50b 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 =
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..088e1cf 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.
*/
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..5ef89d3 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) {
@@ -720,15 +766,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 +830,59 @@
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}. */
+ public void clearBackToLauncherCallback() {
+ 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..f094d71 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,28 @@
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[] nonAppTargets =
- SystemUiProxy.INSTANCE.getNoCreate()
- .onGoingToRecentsLegacy(false, nonHomeApps);
+ 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.get(mCtx)
+ .onGoingToRecentsLegacy(false, nonHomeApps);
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode()
&& activityInterface.getCreatedActivity() != null) {
@@ -187,6 +203,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 +230,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..300f085 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));
}
}
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 276e1c2..d94e5f1 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -55,7 +55,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 +118,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 +129,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 +156,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 +191,7 @@
mApplicationContext = taskThumbnailView.getContext().getApplicationContext();
mThumbnailView = taskThumbnailView;
mImageApi = new ImageActionsApi(
- mApplicationContext, mThumbnailView::getThumbnail);
+ mApplicationContext, mThumbnailView::getThumbnail);
}
protected T getActionsView() {
@@ -264,7 +265,8 @@
/**
* Gets the modal state system shortcut.
*/
- public SystemShortcut getModalStateSystemShortcut(WorkspaceItemInfo itemInfo) {
+ public SystemShortcut getModalStateSystemShortcut(WorkspaceItemInfo itemInfo,
+ View original) {
return null;
}
@@ -278,9 +280,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.
*
@@ -321,8 +324,10 @@
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..29f2123 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;
@@ -47,6 +48,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 +170,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 +199,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 +274,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 +286,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 +392,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 +414,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 +435,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 +455,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 +486,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 +501,7 @@
}
for (int i = 0; i < nonAppTargets.length; ++i) {
- final SurfaceControl leash = appTargets[i].leash.getSurfaceControl();
+ final SurfaceControl leash = appTargets[i].leash;
if (nonAppTargets[i].windowType == TYPE_DOCK_DIVIDER && leash != null) {
openingTargets.add(leash);
}
@@ -561,7 +574,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 +660,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..80bc329
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/TopTaskTracker.java
@@ -0,0 +1,248 @@
+/*
+ * 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.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 static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT;
+
+import android.app.ActivityManager.RunningTaskInfo;
+import android.content.Context;
+
+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 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;
+ }
+ }
+
+ private void resetTaskId(StagedSplitTaskPosition taskPosition) {
+ taskPosition.taskId = -1;
+ }
+
+ /**
+ * @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;
+ }
+
+
+ /**
+ * 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);
+ }
+ return new CachedTaskInfo(new ArrayList<>(mOrderedTaskList));
+ }
+
+ /**
+ * 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 {
+
+ private final RunningTaskInfo mTopTask;
+ private final List<RunningTaskInfo> mAllCachedTasks;
+
+ CachedTaskInfo(List<RunningTaskInfo> allCachedTasks) {
+ mAllCachedTasks = allCachedTasks;
+ mTopTask = allCachedTasks.get(0);
+ }
+
+ public int getTaskId() {
+ return mTopTask.taskId;
+ }
+
+ /**
+ * Returns true if the root of the task chooser activity
+ */
+ public boolean isRootChooseActivity() {
+ return 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.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.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 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) {
+ 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..0078d55 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();
@@ -169,16 +160,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;
@@ -317,6 +310,13 @@
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);
+ }
}
private static boolean sConnected = false;
@@ -352,8 +352,6 @@
private InputMonitorCompat mInputMonitorCompat;
private InputEventReceiver mInputEventReceiver;
- private DisplayManager mDisplayManager;
-
private TaskbarManager mTaskbarManager;
private Function<GestureState, AnimatedFloat> mSwipeUpProxyProvider = i -> null;
@@ -365,7 +363,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 +370,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 +387,8 @@
}
}
- private void initInputMonitor() {
- disposeEventHandlers();
+ private void initInputMonitor(String reason) {
+ disposeEventHandlers("Initializing input monitor due to: " + reason);
if (mDeviceState.isButtonNavMode()) {
return;
@@ -408,18 +404,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 +421,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)
@@ -535,7 +527,7 @@
mInputConsumer.unregisterInputConsumer();
mOverviewComponentObserver.onDestroy();
}
- disposeEventHandlers();
+ disposeEventHandlers("TouchInteractionService onDestroy()");
mDeviceState.destroy();
SystemUiProxy.INSTANCE.get(this).clearProxy();
ProtoTracer.INSTANCE.get(this).stop();
@@ -544,7 +536,6 @@
getSystemService(AccessibilityManager.class)
.unregisterSystemAction(SYSTEM_ACTION_ID_ALL_APPS);
- LauncherSplitScreenListener.INSTANCE.get(this).destroy();
mTaskbarManager.destroy();
sConnected = false;
super.onDestroy();
@@ -562,15 +553,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 +637,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 +652,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 +693,14 @@
}
// 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()) {
+ if (mDeviceState.isBubblesExpanded() || mDeviceState.isSystemUiDialogShowing()) {
base = new SysUiOverlayInputConsumer(
getBaseContext(), mDeviceState, mInputMonitorCompat);
}
@@ -767,17 +747,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 +764,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);
@@ -970,7 +950,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 +963,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..5094d49 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)).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..c9ee2db 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,7 @@
public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsState>
implements StateListener<RecentsState> {
- private RunningTaskInfo mHomeTaskInfo;
+ private Task mHomeTask;
public FallbackRecentsView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -85,11 +85,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[0];
+ onGestureAnimationStart(homeTask, rotationTouchHelper);
}
/**
@@ -102,8 +103,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 +129,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 +138,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 +167,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 +180,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 +189,7 @@
@Override
public void setRunningTaskHidden(boolean isHidden) {
- if (mHomeTaskInfo != null) {
+ if (mHomeTask != null) {
// Always keep the home task hidden
isHidden = true;
}
@@ -258,4 +258,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..9705bb6 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsState.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
@@ -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..11f0ff3 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) {
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..db19c45 100644
--- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -21,7 +21,6 @@
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,6 +51,7 @@
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.quickstep.AnimatedFloat;
@@ -110,6 +110,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 -> {
@@ -217,8 +223,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);
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..9ba5577 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
@@ -57,14 +57,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 +117,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..6254313 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
@@ -51,7 +51,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..09640c6 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
@@ -61,7 +61,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..6a8894e 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;
@@ -63,7 +64,7 @@
private static final String 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;
}
@@ -319,6 +322,9 @@
}
void hideFeedback() {
+ if (mFeedbackView.getVisibility() != View.VISIBLE) {
+ return;
+ }
cancelQueuedGestureAnimation();
mFeedbackView.clearAnimation();
mFeedbackView.setVisibility(View.INVISIBLE);
@@ -425,22 +431,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 +521,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() {
@@ -578,7 +609,7 @@
R.id.gesture_tutorial_dialog_confirm_button);
if (confirmButton != null) {
confirmButton.setOnClickListener(v -> {
- sandboxActivity.closeTutorial();
+ mTutorialFragment.closeTutorial(true);
tutorialDialog.dismiss();
});
} else {
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index 2fd7cde..33e800d 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -20,12 +20,13 @@
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 +42,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 +76,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 +151,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();
@@ -296,6 +310,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 +325,10 @@
}
void onAttachedToWindow() {
+ StatsLogManager statsLogManager = getStatsLogManager();
+ if (statsLogManager != null) {
+ logTutorialStepShown(statsLogManager);
+ }
mEdgeBackGestureHandler.setViewGroupParent(getRootView());
}
@@ -341,8 +362,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 +386,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 +433,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..10c56c9 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
*/
@@ -116,8 +135,7 @@
}
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,13 +394,21 @@
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) {
@@ -386,8 +423,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,7 +441,71 @@
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;
+
+ 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 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
+ );
}
}
@@ -534,6 +634,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 +664,36 @@
return 0;
}
+ private static int getSearchAttributes(LauncherAtom.ItemInfo info) {
+ 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/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..b1e2eac 100644
--- a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -92,7 +92,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.
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..19a48db
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
@@ -0,0 +1,46 @@
+/*
+ * 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.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();
+ }
+}
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..54420de 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,33 @@
}
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);
}
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 +213,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 +268,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..45aaf35 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;
@@ -174,4 +175,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..99a2d6f 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -16,6 +16,8 @@
package com.android.quickstep.views;
+import static com.android.launcher3.util.DisplayController.NavigationMode.THREE_BUTTONS;
+
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -33,10 +35,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;
@@ -145,14 +148,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,12 +198,27 @@
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() {
+ boolean alignFor3ButtonTaskbar = mDp.isTaskbarPresent &&
+ DisplayController.getNavigationMode(getContext()) == THREE_BUTTONS;
+ 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;
}
@@ -216,7 +234,7 @@
*/
public void setDp(DeviceProfile dp) {
mDp = dp;
- updateVerticalMargin(SysUINavigationMode.getMode(getContext()));
+ updateVerticalMargin(DisplayController.getNavigationMode(getContext()));
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
dp.isVerticalBarLayout() ? 0 : dp.overviewActionsButtonSpacing,
@@ -241,14 +259,13 @@
}
/** Get the top margin associated with the action buttons in Overview. */
- public static int getOverviewActionsTopMarginPx(
- SysUINavigationMode.Mode mode, DeviceProfile dp) {
+ public static int getOverviewActionsTopMarginPx(NavigationMode 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) {
+ if (mode == NavigationMode.THREE_BUTTONS) {
return dp.overviewActionsMarginThreeButtonPx;
}
@@ -256,18 +273,29 @@
}
/** 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;
+ public static int getOverviewActionsBottomMarginPx(NavigationMode mode, DeviceProfile dp) {
+ int bottomInset = dp.getInsets().bottom;
if (dp.isVerticalBarLayout()) {
- return inset;
+ return bottomInset;
}
- if (mode == SysUINavigationMode.Mode.THREE_BUTTONS) {
- return dp.overviewActionsMarginThreeButtonPx + inset;
+ if (mode == NavigationMode.THREE_BUTTONS) {
+ int bottomMargin = dp.overviewActionsMarginThreeButtonPx + bottomInset;
+ if (dp.isTaskbarPresent) {
+ // Align vertically, using taskbar height + mDp.taskbarOffsetY() to estimate where
+ // the button nav top is.
+ int actionsTop = (dp.heightPx - bottomMargin - bottomInset)
+ - dp.overviewActionsHeight;
+ int navTop = dp.heightPx - (dp.taskbarSize + dp.getTaskbarOffsetY());
+ bottomMargin -=
+ navTop - actionsTop + ((dp.taskbarSize - dp.overviewActionsHeight) / 2);
+ }
+ return bottomMargin;
}
- return dp.overviewActionsBottomMarginGesturePx + inset;
+ // There is no bottom inset when taskbar is present, use stashed taskbar as padding instead.
+ return dp.overviewActionsBottomMarginGesturePx
+ + (dp.isTaskbarPresent ? dp.stashedTaskbarSize : bottomInset);
}
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 7218cd7..49bf827 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;
@@ -382,7 +385,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 +428,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();
@@ -538,6 +542,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 +619,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 +627,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
@@ -694,6 +702,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 +880,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();
@@ -1075,10 +1093,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) {
@@ -1182,9 +1205,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 +1304,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 +1355,7 @@
* required to focus the task in grid.
*/
public void moveFocusedTaskToFront() {
- if (!mActivity.getDeviceProfile().overviewShowAsGrid) {
+ if (!mActivity.getDeviceProfile().isTablet) {
return;
}
@@ -1367,6 +1396,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;
}
@@ -1799,7 +1831,7 @@
@Override
protected int getDestinationPage(int scaledScroll) {
- if (!mActivity.getDeviceProfile().overviewShowAsGrid) {
+ if (!mActivity.getDeviceProfile().isTablet) {
return super.getDestinationPage(scaledScroll);
}
@@ -2053,14 +2085,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 +2213,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 +2224,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 +2234,16 @@
* 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) {
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 +2255,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 +2268,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 +2290,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;
}
@@ -2696,19 +2726,38 @@
*/
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 {
+ mSplitSelectSource.view.setVisibility(INVISIBLE);
+ mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
+ mSplitSelectSource.view, null,
+ mSplitSelectSource.drawable, startingTaskRect);
+ mFirstFloatingTaskView.setAlpha(1);
+ mFirstFloatingTaskView.addAnimation(anim, startingTaskRect,
+ mTempRect, true /* 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);
}
});
}
@@ -3268,7 +3317,7 @@
return;
}
mActionsView.setSplitButtonVisible(
- mActivity.getDeviceProfile().overviewShowAsGrid && getTaskViewCount() > 1);
+ mActivity.getDeviceProfile().isTablet && getTaskViewCount() > 1);
}
/**
@@ -3859,9 +3908,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,29 +3978,53 @@
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
@@ -3968,29 +4042,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 +4105,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 +4124,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 +4327,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 +4445,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 +4501,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 +4517,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 +4565,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 +4576,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 +4670,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;
@@ -4946,6 +5058,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 +5161,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..bff8651 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;
@@ -291,17 +290,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 +300,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 +452,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..8869ff1 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;
@@ -614,10 +627,7 @@
// 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);
- }
+ SystemUiProxy.INSTANCE.get(getContext()).setSplitScreenMinimized(false);
mIsClickableAsLiveTile = false;
RemoteAnimationTargets targets;
@@ -642,6 +652,7 @@
// 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;
}
@@ -663,6 +674,9 @@
@Override
public void onAnimationEnd(Animator animator) {
+ if (mTask != null && mTask.key.displayId != getRootViewDisplayId()) {
+ launchTaskAnimated();
+ }
mIsClickableAsLiveTile = true;
}
});
@@ -680,11 +694,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 +717,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 +759,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);
}
@@ -825,12 +847,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 +866,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 +882,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 +898,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 +931,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 +992,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();
@@ -1006,7 +1028,7 @@
@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 +1045,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 +1445,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 +1545,8 @@
private int getRootViewDisplayId() {
- return getRootView().getDisplay().getDisplayId();
+ Display display = getRootView().getDisplay();
+ return display != null ? display.getDisplayId() : DEFAULT_DISPLAY;
}
/**
@@ -1534,7 +1557,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 +1574,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/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..4d38822 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;
@@ -84,7 +82,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 +100,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 +125,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 +134,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 +149,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 +166,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 +198,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));
}
@@ -210,21 +208,22 @@
@PortraitLandscape
public void testBackground() throws Exception {
startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
- final Background background = getAndAssertBackground();
+ 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 +238,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 +252,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 +267,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 +287,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(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
mLauncher.pressBack();
mLauncher.getWorkspace();
waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
@@ -322,15 +311,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 +332,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 +365,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..ba93975
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
@@ -0,0 +1,155 @@
+/*
+ * 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 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
+ @PortraitLandscape
+ public void testLaunchAppInSplitscreen() throws Exception {
+ getTaskbar().getAppIcon(TEST_APP_NAME).dragToSplitscreen(
+ TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
+ }
+
+ @Test
+ @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
+ @PortraitLandscape
+ public void testLaunchAppInSplitscreen_FromTaskbarAllApps() throws Exception {
+ getTaskbar().openAllApps()
+ .getAppIcon(TEST_APP_NAME)
+ .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
+ }
+
+ @Test
+ @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..30b972f
--- /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_50"
+ android:lStar="98" />
+</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..3ad38bc
--- /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_50"
+ 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..2d0895e
--- /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_50"
+ 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..7674b43
--- /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_50"
+ 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..17cb54f
--- /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_50"
+ 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..a6150f1
--- /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_50"
+ android:lStar="48" />
+</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/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..f6a6156 100644
--- a/res/layout/all_apps_fast_scroller.xml
+++ b/res/layout/all_apps_fast_scroller.xml
@@ -21,7 +21,7 @@
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_marginEnd="@dimen/fastscroll_popup_margin" />
<com.android.launcher3.views.RecyclerViewFastScroller
@@ -30,7 +30,7 @@
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_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/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/work_apps_edu.xml b/res/layout/work_apps_edu.xml
index 1517087..73200de 100644
--- a/res/layout/work_apps_edu.xml
+++ b/res/layout/work_apps_edu.xml
@@ -19,37 +19,49 @@
android:layout_marginTop="8dp"
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_marginRight="@dimen/work_card_margin"
android:text="@string/work_profile_edu_work_apps"
- android:textAlignment="center"
- android:textSize="20sp" />
-
- <Button
+ 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:background="@drawable/rounded_action_button"
+ android:padding="@dimen/rounded_button_padding"
+ android:layout_alignParentRight="true">
+ <ImageButton
+ android:layout_width="@dimen/x_icon_size"
+ android:layout_height="@dimen/x_icon_size"
+ android:id="@+id/action_btn"
+ android:src="@drawable/ic_remove_no_shadow"
+ android:layout_gravity="center"
+ android:padding="@dimen/x_icon_padding" />
+ </FrameLayout>
+ </RelativeLayout>
- android:textSize="14sp" />
- </LinearLayout>
+ </RelativeLayout>
+
+
+
</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..c536d77 100644
--- a/res/layout/work_mode_fab.xml
+++ b/res/layout/work_mode_fab.xml
@@ -29,4 +29,6 @@
android:drawableStart="@drawable/ic_corp_off"
android:layout_marginBottom="@dimen/work_fab_margin"
android:layout_marginEnd="@dimen/work_fab_margin"
+ 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..471bcc5 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>
@@ -79,10 +79,10 @@
<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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index f75e7e1..73bbdd1 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 1fcce91..774977c 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>
@@ -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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 5dc35cb..cb1581f 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>
@@ -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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index c2ca56d..aa19e28 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index f1dcef4..ddcb256 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 3d6bde4..43e5e90 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 661c710..9c65708 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index 299a014..38be6e2 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 50b2b3c..fbf9fce 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index a0f03c8..9eba6b8 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 8cf9c23..3b38e62 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>
@@ -79,10 +79,10 @@
<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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index ee339c4..284f2d9 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 3a1fde5..0dc06cd 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index b78db22..2b67848 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 29a726c..4853509 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 & 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,7 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Show notification dots"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Add app icons to the home screen"</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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index 29a726c..4853509 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 & 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,7 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Show notification dots"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Add app icons to the home screen"</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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 29a726c..4853509 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 & 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,7 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Show notification dots"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Add app icons to the home screen"</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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 29a726c..4853509 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 & 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,7 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Show notification dots"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Add app icons to the home screen"</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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index f975d5c..90cd6cd 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,7 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"Show notification dots"</string>
- <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Add app icons to Home screen"</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 +124,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 +145,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>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 314a3af..b67397b 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 87eb67a..a6f07da 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index e483041..ee31cef 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 90da2b1..2798733 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index a7b1020..a569816 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 874c85d..707dc9a 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 9a77c87..ff7faad 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index af81a13..ce4add7 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,7 @@
<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="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,12 +124,20 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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>
+ <string name="item_removed" msgid="851119963877842327">"L\'élément a bien été supprimé."</string>
<string name="undo" msgid="4151576204245173321">"Annuler"</string>
<string name="action_move" msgid="4339390619886385032">"Déplacer l\'élément"</string>
<string name="move_to_empty_cell" msgid="2833711483015685619">"Déplacer vers la ligne <xliff:g id="NUMBER_0">%1$s</xliff:g>, colonne <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string>
@@ -141,7 +149,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>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index b43afed..6e42995 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index 3b71546..b2d2654 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,24 +65,24 @@
<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="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,7 @@
<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="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,12 +124,20 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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>
+ <string name="item_removed" msgid="851119963877842327">"આઇટમ દૂર કરી"</string>
<string name="undo" msgid="4151576204245173321">"રદ કરો"</string>
<string name="action_move" msgid="4339390619886385032">"આઇટમ ખસેડો"</string>
<string name="move_to_empty_cell" msgid="2833711483015685619">"<xliff:g id="NUMBER_0">%1$s</xliff:g> પંક્તિ <xliff:g id="NUMBER_1">%2$s</xliff:g> કૉલમ પર ખસેડો"</string>
@@ -141,7 +149,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>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index c7f2d9c..bdb16cc 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,16 +105,16 @@
<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_on" msgid="1679848116452218908">"चालू"</string>
<string name="notification_dots_desc_off" msgid="1760796511504341095">"चालू"</string>
<string name="title_missing_notification_access" msgid="7503287056163941064">"सूचना के ऐक्सेस की ज़रूरत है"</string>
<string name="msg_missing_notification_access" msgid="281113995110910548">"सूचना बिंदु दिखाने के लिए, <xliff:g id="NAME">%1$s</xliff:g> के ऐप्लिकेशन सूचना चालू करें"</string>
<string name="title_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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 75e47a1..cc7f067 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 71a8d69..9cd705c 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 3d65a3e..e8124a6 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>
@@ -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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index f106774..07ebae9 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 1397b88..3645bb9 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index db6a22a..c56ce0b 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>
@@ -77,12 +77,12 @@
<string name="install_drop_target_label" msgid="2539096853673231757">"Installa"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Non suggerire app"</string>
<string name="pin_prediction" msgid="4196423321649756498">"Blocca previsione"</string>
- <string name="permlab_install_shortcut" msgid="5632423390354674437">"Aggiunta di scorciatoie"</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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index a852587..0aa3f11 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index f1db158..9ac4b94 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>
@@ -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">"ON"</string>
@@ -114,7 +114,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index a0cbbc7..6f66155 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index 48bb2eb..8b738e4 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>
@@ -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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index a98151e..b0a3234 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,24 +65,24 @@
<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="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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 4eedd5b..7d9f8d9 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>
@@ -47,12 +47,12 @@
<string name="widgets_full_sheet_search_bar_hint" msgid="8484659090860596457">"ಹುಡುಕಿ"</string>
<string name="widgets_full_sheet_cancel_button_description" msgid="5766167035728653605">"ಹುಡುಕಾಟ ಪೆಟ್ಟಿಗೆಯಿಂದ ಪಠ್ಯವನ್ನು ತೆರವುಗೊಳಿಸಿ"</string>
<string name="no_widgets_available" msgid="4337693382501046170">"ವಿಜೆಟ್ಗಳು ಮತ್ತು ಶಾರ್ಟ್ಕಟ್ಗಳು ಲಭ್ಯವಿಲ್ಲ"</string>
- <string name="no_search_results" msgid="3787956167293097509">"ಯಾವುದೇ ವಿಜೆಟ್ಗಳು ಅಥವಾ ಶಾರ್ಟ್ಕಟ್ಗಳು ಪತ್ತೆಯಾಗಿಲ್ಲ"</string>
+ <string name="no_search_results" msgid="3787956167293097509">"ಯಾವುದೇ ವಿಜೆಟ್ಗಳು ಅಥವಾ ಶಾರ್ಟ್ಕಟ್ಗಳು ಕಂಡುಬಂದಿಲ್ಲ"</string>
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"ವೈಯಕ್ತಿಕ"</string>
<string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ಕೆಲಸ"</string>
<string name="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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 9859752..22a9b3c 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 1d4df09..c235b3d 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>
@@ -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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
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..66ff43d 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index e4fdfc6..66933ac 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index f02d4fb..3eed085 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 2f69e30..a45391f 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>
@@ -77,12 +77,12 @@
<string name="install_drop_target_label" msgid="2539096853673231757">"Инсталирај"</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="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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index e0e7d4a..5a1ee03 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,24 +65,24 @@
<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="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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index e6fcefa..b222ba9 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index e798a3d..0f03074 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,7 +114,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index d39a213..f24038c 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 laman 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index e6434b6..c53b912 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,24 +65,24 @@
<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="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,7 @@
<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="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,12 +124,20 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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>
+ <string name="item_removed" msgid="851119963877842327">"၎င်းအား ဖယ်ရှားပြီး၏"</string>
<string name="undo" msgid="4151576204245173321">"နောက်ပြန်ရန်"</string>
<string name="action_move" msgid="4339390619886385032">"၎င်းအား ရွှေ့ပါ"</string>
<string name="move_to_empty_cell" msgid="2833711483015685619">"အတန်း <xliff:g id="NUMBER_0">%1$s</xliff:g> အတိုင် <xliff:g id="NUMBER_1">%2$s</xliff:g> သို့ ရွှေ့ပါ"</string>
@@ -141,7 +149,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>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 8093939..416f204 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index ded1efd..1e212be 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,24 +65,24 @@
<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="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">"गृह स्क्रिन %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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
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 51730a0..d534bc4 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">"Wanneer 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 5612191..2bfb8a1 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 35a279b..222247b 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 565a7b0..a7c1c18 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,7 +105,7 @@
<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_desc_on" msgid="1679848116452218908">"Włączono"</string>
@@ -114,7 +114,7 @@
<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="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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
@@ -153,7 +161,7 @@
<string name="action_dismiss_notification" msgid="5909461085055959187">"Zamknij"</string>
<string name="accessibility_close" msgid="2277148124685870734">"Zamknij"</string>
<string name="notification_dismissed" msgid="6002233469409822874">"Powiadomienie odrzucone"</string>
- <string name="all_apps_personal_tab" msgid="4190252696685155002">"Prywatne"</string>
+ <string name="all_apps_personal_tab" msgid="4190252696685155002">"Osobiste"</string>
<string name="all_apps_work_tab" msgid="4884822796154055118">"Służbowe"</string>
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Profil służbowy"</string>
<string name="work_profile_edu_work_apps" msgid="7895468576497746520">"Aplikacje służbowe mają plakietki i są widoczne dla administratora IT"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 61e6a67..6cb77d7 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 7beedcb..40edba2 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 14db745..85703dd 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/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 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ți lung widgetul pentru a-l muta pe ecranul de pornire"</string>
+ <string name="add_to_home_screen" msgid="9168649446635919791">"Adăugați 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>
@@ -52,7 +52,7 @@
<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="widget_education_content" msgid="1731667670753497052">"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_close_button" msgid="8676165703104836580">"OK"</string>
<string name="widget_reconfigure_button_content_description" msgid="8811472721881205250">"Modificați setările pentru widgeturi"</string>
@@ -65,7 +65,7 @@
<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="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>
@@ -79,10 +79,10 @@
<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">"citiți 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ți 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>
@@ -90,7 +90,7 @@
<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="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>
@@ -105,7 +105,7 @@
<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ți 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>
@@ -114,7 +114,7 @@
<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="auto_add_shortcuts_label" msgid="4926805029653694105">"Adăugați 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>
@@ -124,9 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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_add_to_workspace" msgid="215894119683164916">"Adăugați pe ecranul de pornire"</string>
<string name="action_move_here" msgid="2170188780612570250">"Mutați 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>
@@ -141,7 +149,7 @@
<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="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_move_to_workspace" msgid="39528912300293768">"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>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 07e14f5..90add40 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index 17531bd..61b91c6 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index a5c27a3..f85c1f5 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,7 @@
<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="auto_add_shortcuts_label" msgid="4926805029653694105">"Pridať 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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index f235606..f374fca 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,7 @@
<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="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,12 +124,20 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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>
+ <string name="item_removed" msgid="851119963877842327">"Element je bil odstranjen"</string>
<string name="undo" msgid="4151576204245173321">"Razveljavi"</string>
<string name="action_move" msgid="4339390619886385032">"Premik elementa"</string>
<string name="move_to_empty_cell" msgid="2833711483015685619">"Premik v <xliff:g id="NUMBER_0">%1$s</xliff:g>. vrstico <xliff:g id="NUMBER_1">%2$s</xliff:g>. stolpca"</string>
@@ -141,7 +149,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>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 88ed4fa..31af388 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 99769c2..6b5fe2b 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index e590ec9..a8c4d1b 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 0f5810b..1a7f2a4 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,24 +65,24 @@
<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>
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Orodha ya programu za binafsi"</string>
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Orodha ya programu za kazini"</string>
<string name="remove_drop_target_label" msgid="7812859488053230776">"Ondoa"</string>
- <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Ondoa"</string>
+ <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Sakinua"</string>
<string name="app_info_drop_target_label" msgid="692894985365717661">"Maelezo ya programu"</string>
<string name="install_drop_target_label" msgid="2539096853673231757">"Sakinisha"</string>
<string name="dismiss_prediction_label" msgid="3357562989568808658">"Isipendekeze programu"</string>
<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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-sw600dp-land/dimens.xml b/res/values-sw600dp-land/dimens.xml
new file mode 100644
index 0000000..dce09e3
--- /dev/null
+++ b/res/values-sw600dp-land/dimens.xml
@@ -0,0 +1,32 @@
+<?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>
+<!-- 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/dimens.xml b/res/values-sw600dp/dimens.xml
index 3727932..eb347f2 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -20,4 +20,33 @@
<!-- 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..439ea93
--- /dev/null
+++ b/res/values-sw720dp-land/dimens.xml
@@ -0,0 +1,37 @@
+<?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>
+<!-- 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..fad8c95
--- /dev/null
+++ b/res/values-sw720dp/dimens.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.
+-->
+
+<resources>
+<!-- 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_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 2fa95f8..b9c7cb5 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index a343ec0..0976af7 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,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,24 +65,24 @@
<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="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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 7ca3bbc..6423bb4 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>
@@ -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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 49465c5..a737102 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index d71961d..b74e52b 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,7 @@
<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="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,12 +124,20 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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>
+ <string name="item_removed" msgid="851119963877842327">"Öğe kaldırıldı"</string>
<string name="undo" msgid="4151576204245173321">"Geri al"</string>
<string name="action_move" msgid="4339390619886385032">"Öğeyi taşı"</string>
<string name="move_to_empty_cell" msgid="2833711483015685619">"<xliff:g id="NUMBER_0">%1$s</xliff:g>. satır <xliff:g id="NUMBER_1">%2$s</xliff:g>. sütuna taşı"</string>
@@ -141,7 +149,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>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 998ad84..619b993 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index 1b4a3d1..3fdad53 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 8984af8..58f1f4e 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
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..6a9a9b3 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index f11f020..ea7d37e 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -32,13 +32,13 @@
<string name="split_screen_position_left" msgid="7537793098851830883">"左分屏"</string>
<string name="split_screen_position_right" msgid="1569377524925193369">"右分屏"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s 的应用信息"</string>
- <string name="long_press_widget_to_add" msgid="3587712543577675817">"轻触并按住即可移动微件。"</string>
+ <string name="long_press_widget_to_add" msgid="3587712543577675817">"轻触并按住微件即可移动该微件。"</string>
<string name="long_accessible_way_to_add" msgid="2733588281439571974">"点按两次并按住微件即可移动该微件或使用自定义操作。"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"宽 %1$d,高 %2$d"</string>
<string name="widget_preview_context_description" msgid="9045841361655787574">"“<xliff:g id="WIDGET_NAME">%1$s</xliff:g>”微件"</string>
- <string name="add_item_request_drag_hint" msgid="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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index a278327..4e2c060 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index a2cfcc7..8394459 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 1208eb2..dc378f7 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,7 @@
<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="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 +124,17 @@
<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>
+ <!-- no translation found for dialog_update_title (114234265740994042) -->
+ <skip />
+ <!-- no translation found for dialog_update_message (4176784553982226114) -->
+ <skip />
+ <!-- no translation found for dialog_update (2178028071796141234) -->
+ <skip />
+ <!-- no translation found for dialog_remove (6510806469849709407) -->
+ <skip />
<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 +149,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>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 08570eb..dd3e08b 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,6 +152,9 @@
<!-- 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" />
@@ -182,76 +193,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..5ecd929 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -22,9 +22,6 @@
<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>
@@ -69,6 +66,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 +85,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 +138,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 +156,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 +164,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..52ff3f0 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -19,19 +19,29 @@
<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>
<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>
@@ -46,8 +56,14 @@
<dimen name="workspace_page_indicator_overlap_workspace">0dp</dimen>
<!-- Drop target bar -->
- <dimen name="dynamic_grid_drop_target_size">52dp</dimen>
+ <dimen name="dynamic_grid_drop_target_size">56dp</dimen>
<dimen name="drop_target_vertical_gap">20dp</dimen>
+ <dimen name="drop_target_top_margin">36dp</dimen>
+ <dimen name="drop_target_bottom_margin">16dp</dimen>
+
+ <!-- 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>
@@ -84,8 +100,10 @@
<dimen name="fastscroll_end_margin">-26dp</dimen>
<!-- All Apps -->
- <dimen name="all_apps_open_vertical_translate">320dp</dimen>
+ <dimen name="all_apps_starting_vertical_translate">320dp</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 +113,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,6 +127,8 @@
<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>
<!-- The size of corner radius of the arrow in the arrow toast. -->
<dimen name="arrow_toast_corner_radius">2dp</dimen>
@@ -121,18 +144,25 @@
<!-- 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_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_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>
@@ -194,6 +224,9 @@
<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">22dp</dimen>
<!-- the distance an icon must be dragged before button drop targets accept it -->
<dimen name="drag_distanceThreshold">30dp</dimen>
@@ -258,15 +291,15 @@
<!-- 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 -->
<dimen name="bg_round_rect_radius">8dp</dimen>
@@ -314,6 +347,7 @@
<!-- 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. -->
@@ -330,33 +364,36 @@
<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_top_margin_gesture">0dp</dimen>
+ <dimen name="overview_actions_bottom_margin_gesture">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_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>
+ <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 -->
<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..7ad1412 100644
--- a/res/values/id.xml
+++ b/res/values/id.xml
@@ -34,4 +34,7 @@
<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" />
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 868b5f3..ffa1e3f 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] -->
@@ -278,7 +278,7 @@
<string name="notification_dots_service_title">Show notification dots</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 +303,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 +323,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 +368,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>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 818a032..864bb58 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -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..07ce598 100644
--- a/res/xml/device_profiles.xml
+++ b/res/xml/device_profiles.xml
@@ -140,10 +140,13 @@
launcher:name="6_by_5"
launcher:numRows="5"
launcher:numColumns="6"
+ launcher:numSearchContainerColumns="3"
launcher:numFolderRows="3"
launcher:numFolderColumns="3"
launcher:numHotseatIcons="6"
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 +155,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/paddings_6x5.xml b/res/xml/paddings_6x5.xml
new file mode 100644
index 0000000..a958ec7
--- /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="80dp">
+ <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="280dp">
+ <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..90869c2 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,26 @@
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_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 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 +208,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..74ec7ee 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,10 @@
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.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;
@@ -146,10 +147,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")
@@ -240,6 +245,10 @@
super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
+ public void setHideBadge(boolean hideBadge) {
+ mHideBadge = hideBadge;
+ }
+
/**
* Resets the view so it can be recycled.
*/
@@ -295,7 +304,7 @@
@Override
public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
- if (delegate instanceof LauncherAccessibilityDelegate) {
+ if (delegate instanceof BaseAccessibilityDelegate) {
super.setAccessibilityDelegate(delegate);
} else {
// NO-OP
@@ -363,9 +372,12 @@
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.color = iconDrawable.getIconColor();
setIcon(iconDrawable);
applyLabel(info);
}
@@ -631,12 +643,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 +672,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 +865,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;
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 38d5077..0b07c95 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -140,7 +140,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;
}
@@ -218,6 +218,7 @@
final Rect to = getIconRect(d);
final float scale = (float) to.width() / dragView.getMeasuredWidth();
dragView.detachContentView(/* reattachToPreviousParent= */ true);
+
mDropTargetBar.deferOnDragEnd();
Runnable onAnimationEndRunnable = () -> {
@@ -323,6 +324,40 @@
hideTooltip();
}
+
+ /**
+ * Reduce the size of the text until it fits or reaches a minimum.
+ *
+ * The minimum size is defined by {@code R.dimen.button_drop_target_min_text_size} and
+ * it diminishes by intervals defined by
+ * {@code R.dimen.button_drop_target_resize_text_increment}
+ * This functionality is very similar to the option
+ * {@link TextView#setAutoSizeTextTypeWithDefaults(int)} but can't be used in this view because
+ * the layout width is {@code WRAP_CONTENT}.
+ *
+ * @param availableWidth Available width in the button to fit the text, used in
+ * {@code ButtonDropTarget#isTextTruncated(int)}
+ * @return The biggest text size in SP that makes the text fit or if the text can't fit returns
+ * the min available value
+ */
+ public float resizeTextToFit(int availableWidth) {
+ float minSize = Utilities.pxToSp(getResources()
+ .getDimensionPixelSize(R.dimen.button_drop_target_min_text_size));
+ float step = Utilities.pxToSp(getResources()
+ .getDimensionPixelSize(R.dimen.button_drop_target_resize_text_increment));
+ float textSize = Utilities.pxToSp(getTextSize());
+
+ while (textSize > minSize) {
+ if (isTextTruncated(availableWidth)) {
+ textSize -= step;
+ setTextSize(textSize);
+ } else {
+ return textSize;
+ }
+ }
+ return minSize;
+ }
+
public boolean isTextTruncated(int availableWidth) {
availableWidth -= (getPaddingLeft() + getPaddingRight() + mDrawable.getIntrinsicWidth()
+ getCompoundDrawablePadding());
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index adb1613..87bbac6 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -93,7 +93,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 +148,8 @@
private boolean mVisualizeDropLocation = true;
private RectF mVisualizeGridRect = new RectF();
private Paint mVisualizeGridPaint = new Paint();
- private int mGridVisualizationPadding;
+ private int mGridVisualizationPaddingX;
+ private int mGridVisualizationPaddingY;
private int mGridVisualizationRoundingRadius;
private float mGridAlpha = 0f;
private int mGridColor = 0;
@@ -238,12 +239,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 +261,10 @@
mBackground.setAlpha(0);
mGridColor = Themes.getAttrColor(getContext(), R.attr.workspaceAccentColor);
- mGridVisualizationPadding =
- res.getDimensionPixelSize(R.dimen.grid_visualization_cell_spacing);
+ mGridVisualizationPaddingX = res.getDimensionPixelSize(
+ R.dimen.grid_visualization_horizontal_cell_spacing);
+ mGridVisualizationPaddingY = res.getDimensionPixelSize(
+ R.dimen.grid_visualization_vertical_cell_spacing);
mGridVisualizationRoundingRadius =
res.getDimensionPixelSize(R.dimen.grid_visualization_rounding_radius);
mReorderPreviewAnimationMagnitude = (REORDER_PREVIEW_MAGNITUDE * deviceProfile.iconSizePx);
@@ -366,6 +364,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 +377,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 +594,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, mGridVisualizationPaddingX);
+ int paddingY = Math.min((mCellHeight - dp.iconSizePx) / 2, mGridVisualizationPaddingY);
mVisualizeGridRect.set(paddingX, paddingY,
mCellWidth - paddingX,
mCellHeight - paddingY);
@@ -1159,9 +1190,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 +1203,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 +2275,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) {
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index d2b9dfe..33bb0a5 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,18 +97,16 @@
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 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;
private final int extraSpace;
@@ -157,33 +162,39 @@
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 overviewActionsHeight;
public final int overviewActionsMarginThreeButtonPx;
public final int overviewActionsTopMarginGesturePx;
public final int overviewActionsBottomMarginGesturePx;
@@ -197,8 +208,13 @@
// 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;
// Insets
private final Rect mInsets = new Rect();
@@ -216,6 +232,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,57 +240,62 @@
/** 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);
@@ -281,8 +303,14 @@
desiredWorkspaceHorizontalMarginPx = getHorizontalMarginPx(inv, res);
desiredWorkspaceHorizontalMarginOriginalPx = desiredWorkspaceHorizontalMarginPx;
- 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 =
@@ -290,31 +318,14 @@
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 +335,72 @@
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);
workspaceSpringLoadedBottomSpace =
res.getDimensionPixelSize(R.dimen.dynamic_grid_min_spring_loaded_space);
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.
+ boolean 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);
+ qsbWidth = calculateQsbWidth();
+ } 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);
+ qsbWidth = 0;
+ }
+ 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);
+ hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics);
updateHotseatIconSize(
- pxFromDp(inv.iconSize[InvariantDeviceProfile.INDEX_DEFAULT], mMetrics, 1f));
+ 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,32 +408,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);
- }
+ overviewActionsTopMarginGesturePx = res.getDimensionPixelSize(
+ R.dimen.overview_actions_top_margin_gesture);
+ overviewActionsBottomMarginGesturePx = res.getDimensionPixelSize(
+ R.dimen.overview_actions_bottom_margin_gesture);
+ 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);
overviewActionsMarginThreeButtonPx = res.getDimensionPixelSize(
R.dimen.overview_actions_margin_three_button);
// Grid task's top margin is only overviewTaskIconSizePx + overviewTaskMarginGridPx, but
@@ -401,9 +425,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,6 +479,12 @@
// 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();
flingToDeleteThresholdVelocity = res.getDimensionPixelSize(
@@ -469,6 +497,16 @@
new DotRenderer(allAppsIconSizePx, dotPath, DEFAULT_DOT_SIZE);
}
+ private int calculateQsbWidth() {
+ int columns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
+
+ return cellWidthPx * columns
+ + cellLayoutBorderSpacePx.x * (columns - 1)
+ - (cellWidthPx - iconSizePx) // left and right cell space
+ - iconSizePx * numShownHotseatIcons
+ - hotseatBorderSpace * numShownHotseatIcons;
+ }
+
private int getHorizontalMarginPx(InvariantDeviceProfile idp, Resources res) {
if (isVerticalBarLayout()) {
return 0;
@@ -493,21 +531,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 +567,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 +598,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 +631,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 +654,12 @@
private int updateAvailableDimensions(Resources res) {
updateIconSize(1f, res);
+ updateWorkspacePadding();
Point workspacePadding = getTotalWorkspacePadding();
// Check to see if the icons fit within the available height.
float usedHeight = getCellLayoutHeight();
- final int maxHeight = availableHeightPx - workspacePadding.y;
+ final int maxHeight = getWorkspaceHeight(workspacePadding);
float extraHeight = Math.max(0, maxHeight - usedHeight);
float scaleY = maxHeight / usedHeight;
boolean shouldScale = scaleY < 1f;
@@ -623,10 +669,7 @@
// 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 = getCellLayoutWidth() + (desiredWorkspaceHorizontalMarginPx * 2);
// We do not subtract padding here, as we also scale the workspace padding if needed.
scaleX = availableWidthPx / usedWidth;
shouldScale = true;
@@ -643,7 +686,14 @@
}
private int getCellLayoutHeight() {
- return (cellHeightPx * inv.numRows) + (cellLayoutBorderSpacePx.y * (inv.numRows - 1));
+ return (cellHeightPx * inv.numRows) + (cellLayoutBorderSpacePx.y * (inv.numRows - 1))
+ + cellLayoutPaddingPx.top + cellLayoutPaddingPx.bottom;
+ }
+
+ private int getCellLayoutWidth() {
+ int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
+ return (cellWidthPx * numColumns) + (cellLayoutBorderSpacePx.x * (numColumns - 1))
+ + cellLayoutPaddingPx.left + cellLayoutPaddingPx.right;
}
/**
@@ -665,7 +715,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 +742,59 @@
}
// 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();
-
- if (isVerticalLayout) {
- hideWorkspaceLabelsIfNotEnoughSpace();
- }
+ updateAllAppsIconSize(scale, res);
// 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));
+ hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics, scale);
+ if (isQsbInline) {
+ qsbWidth = calculateQsbWidth();
} else {
- workspaceSpringLoadShrinkFactor =
- res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f;
+ qsbWidth = 0;
}
+ updateHotseatIconSize(iconSizePx);
// Folder icon
folderIconSizePx = IconNormalizer.getNormalizedCircleSize(iconSizePx);
folderIconOffsetYPx = (iconSizePx - folderIconSizePx) / 2;
}
+
+ /**
+ * Updates the iconSize for allApps* variants.
+ */
+ public void updateAllAppsIconSize(float scale, Resources res) {
+ allAppsBorderSpacePx = new Point(
+ pxFromDp(inv.allAppsBorderSpaces[mTypeIndex].x, mMetrics, scale),
+ pxFromDp(inv.allAppsBorderSpaces[mTypeIndex].y, mMetrics, scale));
+ if (isScalableGrid) {
+ allAppsIconSizePx =
+ pxFromDp(inv.allAppsIconSize[mTypeIndex], mMetrics);
+ allAppsIconTextSizePx =
+ pxFromSp(inv.allAppsIconTextSize[mTypeIndex], mMetrics);
+ allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx;
+ // 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);
+ } else {
+ float invIconSizeDp = inv.iconSize[mTypeIndex];
+ float invIconTextSizeSp = inv.iconTextSize[mTypeIndex];
+ allAppsIconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mMetrics, scale));
+ allAppsIconTextSizePx = (int) (pxFromSp(invIconTextSizeSp, mMetrics) * scale);
+ allAppsIconDrawablePaddingPx = (int) (iconDrawablePaddingOriginalPx * scale);
+ allAppsCellWidthPx = allAppsIconSizePx + (2 * allAppsIconDrawablePaddingPx);
+ allAppsCellHeightPx = getCellSize().y;
+ }
+
+ updateAllAppsContainerWidth(res);
+ if (isVerticalBarLayout()) {
+ hideWorkspaceLabelsIfNotEnoughSpace();
+ }
+ }
+
private void updateAvailableFolderCellDimensions(Resources res) {
updateFolderCellSize(1f, res);
@@ -763,11 +826,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 +862,6 @@
public void updateInsets(Rect insets) {
mInsets.set(insets);
- updateWorkspacePadding();
}
/**
@@ -826,23 +888,69 @@
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 screenHeightPx = getWorkspaceHeight(padding);
+ result.y = calculateCellHeight(screenHeightPx, cellLayoutBorderSpacePx.y, inv.numRows);
return result;
}
+ /**
+ * 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 getWorkspaceSpringLoadShrunkTop() {
+ workspaceSpringLoadShrunkTop = mInsets.top + dropTargetBarTopMarginPx + dropTargetBarSizePx
+ + dropTargetBarBottomMarginPx;
+ return workspaceSpringLoadShrunkTop;
+ }
+
+ /**
+ * Gets the scaled bottom of the workspace in px for the spring-loaded edit state.
+ */
+ public float getWorkspaceSpringLoadShrunkBottom() {
+ int topOfHotseat = hotseatBarSizePx + springLoadedHotseatBarTopMarginPx;
+ workspaceSpringLoadShrunkBottom =
+ heightPx - (isVerticalBarLayout() ? getVerticalHotseatLastItemBottomOffset()
+ : topOfHotseat);
+ return workspaceSpringLoadShrunkBottom;
+ }
+
+ /**
+ * Gets the minimum visible amount of the next workspace page when in the spring-loaded state.
+ */
+ public float getWorkspaceSpringLoadedMinimumNextPageVisible() {
+ return getCellSize().x / 2f;
+ }
+
public int getWorkspaceWidth() {
return getWorkspaceWidth(getTotalWorkspacePadding());
}
public int getWorkspaceWidth(Point workspacePadding) {
int cellLayoutTotalPadding =
- isTwoPanels ? 4 * cellLayoutPaddingLeftRightPx : 2 * cellLayoutPaddingLeftRightPx;
+ (isTwoPanels ? 2 : 1) * (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right);
return availableWidthPx - workspacePadding.x - cellLayoutTotalPadding;
}
+ private int getWorkspaceHeight(Point workspacePadding) {
+ return availableHeightPx - workspacePadding.y - (cellLayoutPaddingPx.top
+ + cellLayoutPaddingPx.bottom);
+ }
+
public Point getTotalWorkspacePadding() {
- updateWorkspacePadding();
return new Point(workspacePadding.left + workspacePadding.right,
workspacePadding.top + workspacePadding.bottom);
}
@@ -868,12 +976,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,32 +1003,51 @@
*/
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) {
+ boolean isRtl = Utilities.isRtl(context.getResources());
int hotseatHeight = workspacePadding.bottom;
int taskbarOffset = getTaskbarOffsetY();
- int hotseatTopDiff = hotseatHeight - taskbarOffset;
+ // Push icons to the side
+ int additionalQsbSpace = isQsbInline ? qsbWidth + hotseatBorderSpace : 0;
+
+ // Center the QSB vertically with hotseat
+ int hotseatTopPadding = hotseatHeight - taskbarOffset - hotseatCellHeightPx;
int endOffset = ApiWrapper.getHotseatEndOffset(context);
- int requiredWidth = iconSizePx * numShownHotseatIcons;
+ int requiredWidth = iconSizePx * numShownHotseatIcons
+ + hotseatBorderSpace * (numShownHotseatIcons - 1)
+ + additionalQsbSpace;
- 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);
+ int hotseatWidth = Math.min(requiredWidth, availableWidthPx - endOffset);
+ int sideSpacing = (availableWidthPx - hotseatWidth) / 2;
+ mHotseatPadding.set(sideSpacing, hotseatTopPadding, sideSpacing, taskbarOffset);
+
+ 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;
@@ -920,14 +1061,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 +1075,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,8 +1087,8 @@
// Note that taskbarSize = 0 unless isTaskbarPresent.
return Math.min(qsbBottomMarginPx + taskbarSize, freeSpace);
} else {
- return (int) (freeSpace * QSB_CENTER_FACTOR)
- + (isTaskbarPresent ? taskbarSize : mInsets.bottom);
+ return (int) (freeSpace * mQsbCenterFactor)
+ + (isTaskbarPresent ? taskbarSize : mInsets.bottom);
}
}
@@ -953,7 +1096,11 @@
* Returns the number of pixels the taskbar is translated from the bottom of the screen.
*/
public int getTaskbarOffsetY() {
- return (getQsbOffsetY() - taskbarSize) / 2;
+ if (isQsbInline) {
+ return getQsbOffsetY() - (Math.abs(hotseatQsbHeight - hotseatCellHeightPx) / 2);
+ } else {
+ return (getQsbOffsetY() - taskbarSize) / 2;
+ }
}
/**
@@ -1003,6 +1150,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 +1194,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 +1204,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 +1232,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,12 +1255,20 @@
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 + pxToDpStr("hotseatCellHeightPx", hotseatCellHeightPx));
@@ -1110,7 +1278,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 +1313,44 @@
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("overviewActionsMarginThreeButtonPx",
+ overviewActionsMarginThreeButtonPx));
+ writer.println(prefix + pxToDpStr("overviewActionsTopMarginGesturePx",
+ overviewActionsTopMarginGesturePx));
+ writer.println(prefix + pxToDpStr("overviewActionsBottomMarginGesturePx",
+ overviewActionsBottomMarginGesturePx));
+ 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));
}
- 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.smallestScreenWidthDp = (int) info.smallestSizeDp(bounds);
return c.createConfigurationContext(config);
}
@@ -1159,6 +1368,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 +1407,7 @@
private boolean mIsMultiWindowMode = false;
private Boolean mTransposeLayoutWithOrientation;
+ private Boolean mIsGestureMode;
public Builder(Context context, InvariantDeviceProfile inv, Info info) {
mContext = context;
@@ -1197,6 +1436,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 +1448,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..ec3629d 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;
@@ -41,6 +39,8 @@
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.testing.TestProtocol;
+import java.util.Arrays;
+
/*
* The top bar containing various drop targets: Delete/App Info/Uninstall.
*/
@@ -94,30 +94,28 @@
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;
+
setLayoutParams(lp);
for (ButtonDropTarget button : mDropTargets) {
button.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.dropTargetTextSizePx);
@@ -139,24 +137,25 @@
int height = MeasureSpec.getSize(heightMeasureSpec);
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);
-
- for (ButtonDropTarget button : mDropTargets) {
- if (button.getVisibility() != GONE) {
- button.setTextVisible(false);
- button.measure(widthSpec, heightSpec);
- }
- }
- } else {
+ if (visibleCount > 0) {
int availableWidth = width / visibleCount;
boolean textVisible = true;
- for (ButtonDropTarget buttons : mDropTargets) {
- if (buttons.getVisibility() != GONE) {
- textVisible = textVisible && !buttons.isTextTruncated(availableWidth);
+ boolean textResized = false;
+ float textSize = mDropTargets[0].getTextSize();
+ for (ButtonDropTarget button : mDropTargets) {
+ if (button.getVisibility() == GONE) {
+ continue;
+ }
+ if (button.isTextTruncated(availableWidth)) {
+ textSize = Math.min(textSize, button.resizeTextToFit(availableWidth));
+ textResized = true;
+ }
+ textVisible = textVisible && !button.isTextTruncated(availableWidth);
+ }
+
+ if (textResized) {
+ for (ButtonDropTarget button : mDropTargets) {
+ button.setTextSize(textSize);
}
}
@@ -176,31 +175,90 @@
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int visibleCount = getVisibleButtonsCount();
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;
- }
- }
- } else {
- int frameSize = (right - left) / visibleCount;
+ Launcher launcher = Launcher.getLauncher(getContext());
+ Workspace<?> workspace = launcher.getWorkspace();
+ DeviceProfile dp = launcher.getDeviceProfile();
+ int buttonHorizontalPadding = dp.dropTargetHorizontalPaddingPx;
+ int buttonVerticalPadding = dp.dropTargetVerticalPaddingPx;
+ int barCenter = (right - left) / 2;
- 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;
+ ButtonDropTarget[] visibleButtons = Arrays.stream(mDropTargets)
+ .filter(b -> b.getVisibility() != GONE)
+ .toArray(ButtonDropTarget[]::new);
+ Arrays.stream(visibleButtons).forEach(
+ b -> b.setPadding(buttonHorizontalPadding, buttonVerticalPadding,
+ buttonHorizontalPadding, buttonVerticalPadding));
+
+ if (visibleCount == 1) {
+ ButtonDropTarget button = visibleButtons[0];
+ button.layout(barCenter - (button.getMeasuredWidth() / 2), 0,
+ barCenter + (button.getMeasuredWidth() / 2), button.getMeasuredHeight());
+ } else if (visibleCount == 2) {
+ int buttonGap = dp.dropTargetGapPx;
+
+ if (dp.isTwoPanels) {
+ ButtonDropTarget leftButton = visibleButtons[0];
+ leftButton.layout(barCenter - leftButton.getMeasuredWidth() - (buttonGap / 2), 0,
+ barCenter - (buttonGap / 2), leftButton.getMeasuredHeight());
+
+ ButtonDropTarget rightButton = visibleButtons[1];
+ rightButton.layout(barCenter + (buttonGap / 2), 0,
+ barCenter + rightButton.getMeasuredWidth() + (buttonGap / 2),
+ rightButton.getMeasuredHeight());
+ } else if (dp.isTablet) {
+ int numberOfMargins = visibleCount - 1;
+ int buttonWidths = Arrays.stream(mDropTargets)
+ .filter(b -> b.getVisibility() != GONE)
+ .mapToInt(ButtonDropTarget::getMeasuredWidth)
+ .sum();
+ int totalWidth = buttonWidths + (numberOfMargins * buttonGap);
+ int buttonsStartMargin = barCenter - (totalWidth / 2);
+
+ int start = buttonsStartMargin;
+ for (ButtonDropTarget button : visibleButtons) {
+ int margin = (start != buttonsStartMargin) ? buttonGap : 0;
+ button.layout(start + margin, 0, start + margin + button.getMeasuredWidth(),
+ button.getMeasuredHeight());
+ start += button.getMeasuredWidth() + margin;
}
+ } else if (mIsVertical) {
+ // Center buttons over workspace, not screen.
+ int verticalCenter = (workspace.getRight() - workspace.getLeft()) / 2;
+ ButtonDropTarget leftButton = visibleButtons[0];
+ leftButton.layout(verticalCenter - leftButton.getMeasuredWidth() - (buttonGap / 2),
+ 0, verticalCenter - (buttonGap / 2), leftButton.getMeasuredHeight());
+
+ ButtonDropTarget rightButton = visibleButtons[1];
+ rightButton.layout(verticalCenter + (buttonGap / 2), 0,
+ verticalCenter + rightButton.getMeasuredWidth() + (buttonGap / 2),
+ rightButton.getMeasuredHeight());
+ } else if (dp.isPhone) {
+ // Buttons aligned to outer edges of scaled workspace.
+ float shrunkTop = dp.getWorkspaceSpringLoadShrunkTop();
+ float shrunkBottom = dp.getWorkspaceSpringLoadShrunkBottom();
+ float scale =
+ (shrunkBottom - shrunkTop) / launcher.getWorkspace().getNormalChildHeight();
+ int workspaceWidth = (int) (launcher.getWorkspace().getNormalChildWidth() * scale);
+ int start = barCenter - (workspaceWidth / 2);
+ int end = barCenter + (workspaceWidth / 2);
+
+ ButtonDropTarget leftButton = visibleButtons[0];
+ ButtonDropTarget rightButton = visibleButtons[1];
+
+ // If the text within the buttons is too long, the buttons can overlap
+ int overlap = start + leftButton.getMeasuredWidth() + rightButton.getMeasuredWidth()
+ - end;
+ if (overlap > 0) {
+ end += overlap;
+ }
+
+ leftButton.layout(start, 0, start + leftButton.getMeasuredWidth(),
+ leftButton.getMeasuredHeight());
+ rightButton.layout(end - rightButton.getMeasuredWidth(), 0, end,
+ rightButton.getMeasuredHeight());
}
}
}
diff --git a/src/com/android/launcher3/BaseRecyclerView.java b/src/com/android/launcher3/FastScrollRecyclerView.java
similarity index 95%
rename from src/com/android/launcher3/BaseRecyclerView.java
rename to src/com/android/launcher3/FastScrollRecyclerView.java
index 9369bdc..a60d143 100644
--- a/src/com/android/launcher3/BaseRecyclerView.java
+++ b/src/com/android/launcher3/FastScrollRecyclerView.java
@@ -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);
}
@@ -206,4 +206,4 @@
}
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..a9db5ce 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,7 +173,16 @@
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- int width = getShortcutsAndWidgets().getMeasuredWidth();
+ int width;
+ if (mActivity.getDeviceProfile().isQsbInline) {
+ width = mActivity.getDeviceProfile().qsbWidth;
+ } else {
+ MarginLayoutParams qsbParams = (MarginLayoutParams) mQsb.getLayoutParams();
+ width = getShortcutsAndWidgets().getMeasuredWidth()
+ - qsbParams.getMarginStart()
+ - qsbParams.getMarginEnd();
+ }
+
mQsb.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mQsbHeight, MeasureSpec.EXACTLY));
}
@@ -183,7 +192,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..36c1797 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,6 +55,7 @@
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;
@@ -94,18 +96,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 +124,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
@@ -154,6 +167,7 @@
public String dbFile;
public int defaultLayoutId;
int demoModeLayoutId;
+ boolean[] inlineQsb = new boolean[COUNT_SIZES];
/**
* An immutable list of supported profiles.
@@ -169,8 +183,7 @@
private final ArrayList<OnIDPChangeListener> mChangeListeners = new ArrayList<>();
@VisibleForTesting
- public InvariantDeviceProfile() {
- }
+ public InvariantDeviceProfile() { }
@TargetApi(23)
private InvariantDeviceProfile(Context context) {
@@ -183,7 +196,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 +251,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 +261,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 +277,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 +322,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 +352,30 @@
horizontalMargin = displayOption.horizontalMargin;
numShownHotseatIcons = closestProfile.numHotseatIcons;
+ numShrunkenHotseatIcons = closestProfile.numShrunkenHotseatIcons;
numDatabaseHotseatIcons = deviceType == TYPE_MULTI_DISPLAY
? closestProfile.numDatabaseHotseatIcons : closestProfile.numHotseatIcons;
+ 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 +385,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();
@@ -393,8 +425,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) {
@@ -593,10 +625,14 @@
float screenWidth = config.screenWidthDp * res.getDisplayMetrics().density;
float screenHeight = config.screenHeightDp * res.getDisplayMetrics().density;
- return getBestMatch(screenWidth, screenHeight);
+ return getBestMatch(screenWidth, screenHeight,
+ WindowManagerProxy.INSTANCE.get(context).getRotation(context));
}
- 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 +642,8 @@
if (diff < minDiff) {
minDiff = diff;
bestMatch = profile;
+ } else if (diff == minDiff && profile.rotationHint == rotation) {
+ bestMatch = profile;
}
}
return bestMatch;
@@ -671,6 +709,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,6 +718,7 @@
private final int numAllAppsColumns;
private final int numDatabaseAllAppsColumns;
private final int numHotseatIcons;
+ private final int numShrunkenHotseatIcons;
private final int numDatabaseHotseatIcons;
private final String dbFile;
@@ -697,6 +737,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,6 +755,8 @@
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);
@@ -744,22 +788,34 @@
@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];
+ 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 +826,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 +1049,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 +1066,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 +1089,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..463280b 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,13 @@
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.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 +143,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 +153,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;
@@ -179,8 +183,6 @@
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;
@@ -209,7 +211,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 +226,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 +234,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 +301,7 @@
private Configuration mOldConfig;
@Thunk
- Workspace mWorkspace;
+ Workspace<?> mWorkspace;
@Thunk
DragLayer mDragLayer;
private DragController mDragController;
@@ -315,7 +318,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 +336,7 @@
private Runnable mOnDeferredActivityLaunchCallback;
private ViewOnDrawExecutor mPendingExecutor;
+ private OnPreDrawListener mOnInitialBindListener;
private LauncherModel mModel;
private ModelWriter mModelWriter;
@@ -347,7 +351,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 +384,8 @@
protected InstanceId mAllAppsSessionLogId;
private LauncherState mPrevLauncherState;
+ private StringCache mStringCache;
+
@Override
@TargetApi(Build.VERSION_CODES.S)
protected void onCreate(Bundle savedInstanceState) {
@@ -426,8 +432,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 +499,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 +510,9 @@
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
setContentView(getRootView());
+ if (mOnInitialBindListener != null) {
+ getRootView().getViewTreeObserver().addOnPreDrawListener(mOnInitialBindListener);
+ }
getRootView().dispatchInsets();
// Listen for broadcasts
@@ -519,7 +526,7 @@
}
mOverlayManager = getDefaultOverlay();
PluginManagerWrapper.INSTANCE.get(this).addPluginListener(this,
- OverlayPlugin.class, false /* allowedMultiple */);
+ LauncherOverlayPlugin.class, false /* allowedMultiple */);
mRotationHelper.initialize();
TraceHelper.INSTANCE.endSection(traceToken);
@@ -536,21 +543,22 @@
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 +575,7 @@
}
@Override
- protected void dispatchDeviceProfileChanged() {
+ public void dispatchDeviceProfileChanged() {
super.dispatchDeviceProfileChanged();
mOverlayManager.onDeviceProvideChanged();
}
@@ -576,7 +584,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 +637,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 +691,8 @@
return !isWorkspaceLoading();
}
+ @NonNull
+ @Override
public PopupDataProvider getPopupDataProvider() {
return mPopupDataProvider;
}
@@ -956,7 +972,7 @@
hideKeyboard();
logStopAndResume(false /* isResume */);
mAppWidgetHost.setActivityStarted(false);
- NotificationListener.removeNotificationsChangedListener();
+ NotificationListener.removeNotificationsChangedListener(getPopupDataProvider());
}
@Override
@@ -985,13 +1001,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 +1100,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 +1145,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 +1169,7 @@
mOverlayManager.onActivityResumed(this);
}
+ AbstractFloatingView.closeAllOpenViewsExcept(this, false, TYPE_REBIND_SAFE);
TraceHelper.INSTANCE.endSection(traceToken);
}
@@ -1476,11 +1502,12 @@
return mDragLayer;
}
- public AllAppsContainerView getAppsView() {
+ @Override
+ public ActivityAllAppsContainerView<Launcher> getAppsView() {
return mAppsView;
}
- public Workspace getWorkspace() {
+ public Workspace<?> getWorkspace() {
return mWorkspace;
}
@@ -1550,6 +1577,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 +1606,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 +1618,11 @@
getStateManager().goToState(ALL_APPS, alreadyOnHome);
}
+ private void showAllAppsWorkTabFromIntent(boolean alreadyOnHome) {
+ showAllAppsFromIntent(alreadyOnHome);
+ mAppsView.switchToTab(BaseAllAppsContainerView.AdapterHolder.WORK);
+ }
+
/**
* Handles gesture nav contract
*/
@@ -1638,13 +1673,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 +1774,11 @@
return mWorkspaceLoading;
}
+ @Override
+ public boolean isBindingItems() {
+ return mWorkspaceLoading;
+ }
+
private void setWorkspaceLoading(boolean value) {
mWorkspaceLoading = value;
}
@@ -2014,7 +2049,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 +2340,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,6 +2387,9 @@
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;
@@ -2360,6 +2398,10 @@
} else {
Log.d(TAG, desc);
getModelWriter().deleteItemFromDatabase(item);
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.MISSING_PROMISE_ICON,
+ TAG + "bindItems failed for item=" + item);
+ }
continue;
}
}
@@ -2629,36 +2671,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,
@@ -2732,7 +2750,7 @@
packageName);
if (supportsAllAppsState && isInState(LauncherState.ALL_APPS)) {
- return getFirstMatch(Collections.singletonList(mAppsView.getActiveRecyclerView()),
+ return getFirstMatch(Collections.singletonList(mAppsView.getActiveAppsRecyclerView()),
preferredItem, packageAndUserAndApp);
} else {
List<ViewGroup> containers = new ArrayList<>(mWorkspace.getPanelCount() + 1);
@@ -2741,14 +2759,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));
}
}
@@ -2798,6 +2810,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.
@@ -2875,6 +2898,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
@@ -3153,4 +3186,16 @@
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();
+ }
+
+ /** Resumes view updates at the end of the app launch animation. */
+ public void resumeExpensiveViewUpdates() {
+ getWorkspace().getPageIndicator().skipAnimationsToEnd();
+ }
+
}
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..4501159 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -36,6 +36,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 +62,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();
@@ -98,7 +99,7 @@
Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
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 +139,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/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..baee49f 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;
@@ -91,6 +92,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];
/**
@@ -288,6 +297,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 +346,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..0a1d25c 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -775,7 +775,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 +799,7 @@
return pageScrollChanged;
}
- protected int getChildGap() {
+ protected int getChildGap(int fromIndex, int toIndex) {
return 0;
}
@@ -1195,8 +1195,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 +1322,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 +1440,7 @@
return Math.abs(velocity) > threshold;
}
- private void resetTouchState() {
+ protected void resetTouchState() {
releaseVelocityTracker();
mIsBeingDragged = false;
mActivePointerId = INVALID_POINTER;
diff --git a/src/com/android/launcher3/ResourceUtils.java b/src/com/android/launcher3/ResourceUtils.java
index ece123d..1c36db1 100644
--- a/src/com/android/launcher3/ResourceUtils.java
+++ b/src/com/android/launcher3/ResourceUtils.java
@@ -28,6 +28,9 @@
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 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..5b037e4 100644
--- a/src/com/android/launcher3/SecondaryDropTarget.java
+++ b/src/com/android/launcher3/SecondaryDropTarget.java
@@ -8,6 +8,7 @@
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.DISMISS_PREDICTION;
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 +47,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;
@@ -220,7 +222,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 +267,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 +279,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 +315,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..8358f2a 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;
}
@@ -485,6 +494,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 +624,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 +691,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 +750,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 +765,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 +888,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..ed01660 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;
@@ -92,7 +91,7 @@
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.SearchActionItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.pageindicators.WorkspacePageIndicator;
+import com.android.launcher3.pageindicators.PageIndicator;
import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.statemanager.StateManager.StateHandler;
@@ -113,6 +112,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 +122,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 +132,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 +147,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;
@@ -324,37 +326,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 +565,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 +631,7 @@
mLauncher.getStateManager().getState(), newScreen, insertIndex);
updatePageScrollValues();
- updateWorkspaceScreensPadding();
+ updateCellLayoutPadding();
return newScreen;
}
@@ -1136,6 +1115,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 +1195,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 +1222,10 @@
announcePageForAccessibility();
}
mOverlayShown = false;
+
+ // Let the Launcher activity know that the overlay is no longer visible.
+ mLauncher.onOverlayVisibilityChanged(mOverlayShown);
+
tryRunOverlayCallback();
}
@@ -2474,21 +2465,27 @@
}
}
+ // 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 + 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
+ IntSet pageIndexesToVerify = IntSet.wrap(nextPage - 1, nextPage
+ + (isTwoPanelEnabled() ? 2 : 1));
for (int pageIndex : pageIndexesToVerify) {
if (layout != null || isPageInTransition()) {
break;
}
+
+ // 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));
layout = verifyInsidePage(pageIndex, touchX, touchY);
}
@@ -2497,12 +2494,16 @@
// on one panel just choose the current page.
if (layout == null && nextPage >= 0 && nextPage < getPageCount()) {
if (isTwoPanelEnabled()) {
+ // When determining which panel to use within a single screen, we always use
+ // the centroid of the object rather than the finger.
+ touchX = centerX;
nextPage = getScreenCenter(getScrollX()) > touchX
? (mIsRtl ? nextPage + 1 : nextPage) // left side
: (mIsRtl ? nextPage : nextPage + 1); // right side
}
layout = (CellLayout) getChildAt(nextPage);
}
+
if (layout != mDragTargetLayout) {
setCurrentDropLayout(layout);
setCurrentDragOverlappingLayout(layout);
@@ -2752,6 +2753,12 @@
info = ((AppInfo) info).makeWorkspaceItem();
d.dragInfo = info;
}
+ 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;
+ }
if (info instanceof SearchActionItemInfo) {
info = ((SearchActionItemInfo) info).createWorkspaceItem(
mLauncher.getModel());
@@ -2832,7 +2839,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 +2849,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 +2903,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;
@@ -3279,9 +3295,12 @@
}
}
- public void removeAbandonedPromise(String packageName, UserHandle user) {
- ItemInfoMatcher matcher = ItemInfoMatcher.ofPackages(
- Collections.singleton(packageName), user);
+ /**
+ * Remove workspace icons & widget information related to items in matcher.
+ *
+ * @param matcher the matcher generated by the caller.
+ */
+ public void persistRemoveItemsByMatcher(ItemInfoMatcher matcher) {
mLauncher.getModelWriter().deleteItemsFromDatabase(matcher);
removeItemsByMatcher(matcher);
}
@@ -3388,7 +3407,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..84b95ec 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -18,10 +18,12 @@
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.HINT_STATE;
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
@@ -37,15 +39,18 @@
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 +67,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;
}
@@ -115,20 +126,22 @@
&& 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);
}
@@ -144,6 +157,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 +210,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 +243,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..14b2431
--- /dev/null
+++ b/src/com/android/launcher3/accessibility/BaseAccessibilityDelegate.java
@@ -0,0 +1,192 @@
+/*
+ * 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.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.popup.PopupContainerWithArrow;
+import com.android.launcher3.util.Thunk;
+import com.android.launcher3.views.ActivityContext;
+
+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, item)) {
+ 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, ItemInfo info) {
+ return PopupContainerWithArrow.canShow(host, info);
+ }
+
+ 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..12eb837 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -10,27 +10,19 @@
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.DragView;
import com.android.launcher3.folder.Folder;
@@ -57,7 +49,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";
@@ -73,25 +65,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 +91,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 +99,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()));
}
@@ -183,31 +139,7 @@
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) {
@@ -221,74 +153,22 @@
} 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;
} 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 +195,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 +203,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 +214,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 +222,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 +262,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 +291,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 +300,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 +352,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 AppInfo) {
+ WorkspaceItemInfo info = ((AppInfo) item).makeWorkspaceItem();
+ 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..16a2823
--- /dev/null
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -0,0 +1,300 @@
+/*
+ * 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.search.SearchAdapterProvider;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.views.AppLauncher;
+
+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);
+ }
+
+ /** Invoke when the search results change. */
+ public void onSearchResultsChanged() {
+ 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(), showTabs);
+ layoutAboveSearchContainer(rvContainer);
+ layoutAboveSearchContainer(getSearchRecyclerView());
+ } else {
+ layoutBelowSearchContainer(rvContainer, showTabs);
+ layoutBelowSearchContainer(getSearchRecyclerView(), showTabs);
+ }
+
+ 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
+ protected 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/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index d5c9a53..58df50c 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,7 +116,7 @@
*/
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++) {
if (!isViewType(items.get(i).viewType, VIEW_TYPE_MASK_ICON)) {
@@ -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..18c6788 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -19,6 +19,7 @@
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 +37,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;
@@ -53,13 +53,13 @@
/**
* 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();
@@ -74,8 +74,8 @@
};
// The empty-search result background
- private AllAppsBackgroundDrawable mEmptySearchBackground;
- private int mEmptySearchBackgroundTopOffset;
+ protected AllAppsBackgroundDrawable mEmptySearchBackground;
+ protected int mEmptySearchBackgroundTopOffset;
private ArrayList<View> mAutoSizedOverlays = new ArrayList<>();
@@ -104,16 +104,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 +137,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);
}
@@ -201,9 +201,10 @@
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);
@@ -222,8 +223,7 @@
&& mEmptySearchBackground != null && mEmptySearchBackground.getAlpha() > 0) {
mEmptySearchBackground.setHotspot(e.getX(), e.getY());
}
- hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
- getApplicationWindowToken());
+ hideKeyboardAsync(ActivityContext.lookupContext(getContext()), getApplicationWindowToken());
return result;
}
@@ -359,13 +359,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 +368,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;
}
@@ -470,7 +463,7 @@
* Returns distance between left and right app icons
*/
public int getTabWidth() {
- DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
+ DeviceProfile grid = ActivityContext.lookupContext(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..723bc65 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,59 @@
}
};
- 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.getAppsRecyclerViewContainer()
+ .getTranslationY();
+ } else {
+ return controller.getAppsViewPullbackTranslationY().get(
+ controller.mAppsView);
+ }
+ }
+
+ @Override
+ public void setValue(AllAppsTransitionController controller, float translation) {
+ if (controller.mIsTablet) {
+ controller.mAppsView.getAppsRecyclerViewContainer().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.getAppsRecyclerViewContainer().getAlpha();
+ } else {
+ return controller.getAppsViewPullbackAlpha().getValue();
+ }
+ }
+
+ @Override
+ public void setValue(AllAppsTransitionController controller, float alpha) {
+ if (controller.mIsTablet) {
+ controller.mAppsView.getAppsRecyclerViewContainer().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 +144,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 +170,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 +190,29 @@
*/
public void setProgress(float progress) {
mProgress = progress;
- mAppsView.setTranslationY(mProgress * mShiftRange);
+ getAppsViewProgressTranslationY().set(mAppsView, mProgress * mShiftRange);
}
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 +231,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,12 +249,14 @@
}
// 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);
+ // Use ANIM_VERTICAL_PROGRESS's interpolator to determine state transition threshold.
+ builder.setInterpolator(verticalProgressInterpolator);
setAlphas(toState, config, builder);
@@ -187,7 +278,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 +293,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 +302,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..42374b8 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -18,12 +18,14 @@
import android.content.Context;
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
+import androidx.annotation.Nullable;
+
+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.util.LabelComparator;
+import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList;
import java.util.Collections;
@@ -35,8 +37,11 @@
/**
* 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";
@@ -64,10 +69,11 @@
}
- 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,21 +84,23 @@
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;
- 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) {
@@ -103,7 +111,7 @@
/**
* Sets the adapter to notify when this dataset changes.
*/
- public void setAdapter(AllAppsGridAdapter adapter) {
+ public void setAdapter(BaseAllAppsAdapter<T> adapter) {
mAdapter = adapter;
}
@@ -165,38 +173,41 @@
}
/**
- * 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;
+ mSearchResults.clear();
+ if (results != null) {
+ mSearchResults.addAll(results);
+ }
+ updateAdapterItems();
+ return true;
}
- public boolean appendSearchResults(ArrayList<AdapterItem> results) {
- if (mSearchResults != null && results != null && results.size() > 0) {
+ /** Appends results to search. */
+ public void appendSearchResults(ArrayList<AdapterItem> results) {
+ if (hasSearchResults() && results != null && results.size() > 0) {
updateSearchAdapterItems(results, mSearchResults.size());
+ mSearchResults.addAll(results);
refreshRecyclerView();
- return true;
}
- return false;
}
void updateSearchAdapterItems(ArrayList<AdapterItem> list, int offset) {
@@ -216,11 +227,14 @@
*/
@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()) {
+ if (mItemFilter == null || mItemFilter.matches(app, null) || hasSearchResults()) {
mApps.add(app);
}
}
@@ -229,7 +243,7 @@
// 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
@@ -256,7 +270,7 @@
}
// Recompose the set of adapter items from the current set of apps
- if (mSearchResults == null) {
+ if (mSearchResults.isEmpty()) {
updateAdapterItems();
}
}
@@ -290,7 +304,18 @@
// Recreate the filtered and sectioned apps (for convenience for the grid layout) from the
// ordered set of sections
- if (!hasFilter()) {
+ if (hasSearchResults()) {
+ if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
+ // Append the search market item
+ if (hasNoFilteredResults()) {
+ mSearchResults.add(AdapterItem.asEmptySearch(position++));
+ } else {
+ mSearchResults.add(AdapterItem.asAllAppsDivider(position++));
+ }
+ mSearchResults.add(AdapterItem.asMarketSearch(position++));
+ }
+ updateSearchAdapterItems(mSearchResults, 0);
+ } else {
mAccessibilityResultsCount = mApps.size();
if (mWorkAdapterProvider != null) {
position += mWorkAdapterProvider.addWorkItems(mAdapterItems);
@@ -317,20 +342,8 @@
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++));
-
- }
}
- if (mNumAppsPerRow != 0) {
+ 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 +351,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++;
}
@@ -359,12 +372,13 @@
float rowFraction = 1f / mNumAppRowsInAdapter;
for (FastScrollSectionInfo info : mFastScrollerSections) {
AdapterItem item = info.fastScrollToItem;
- if (!AllAppsGridAdapter.isIconViewType(item.viewType)) {
+ if (!BaseAllAppsAdapter.isIconViewType(item.viewType)) {
info.touchFraction = 0f;
continue;
}
- float subRowFraction = item.rowAppIndex * (rowFraction / mNumAppsPerRow);
+ float subRowFraction =
+ item.rowAppIndex * (rowFraction / mNumAppsPerRowAllApps);
info.touchFraction = item.rowIndex * rowFraction + subRowFraction;
}
break;
@@ -373,7 +387,7 @@
float cumulativeTouchFraction = 0f;
for (FastScrollSectionInfo info : mFastScrollerSections) {
AdapterItem item = info.fastScrollToItem;
- if (!AllAppsGridAdapter.isIconViewType(item.viewType)) {
+ if (!BaseAllAppsAdapter.isIconViewType(item.viewType)) {
info.touchFraction = 0f;
continue;
}
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..976284d
--- /dev/null
+++ b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
@@ -0,0 +1,333 @@
+/*
+ * 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.model.data.ItemInfoWithIcon;
+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 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;
+ }
+ }
+
+ 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();
+ 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 (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..6a44989
--- /dev/null
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -0,0 +1,824 @@
+/*
+ * 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.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.AppInfo;
+import com.android.launcher3.util.ItemInfoMatcher;
+import com.android.launcher3.util.Themes;
+import com.android.launcher3.views.ActivityContext;
+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;
+
+/**
+ * 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 ItemInfoMatcher 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 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);
+ mHeaderProtectionColor = Themes.getAttrColor(context, R.attr.allappsHeaderProtectionColor);
+
+ mWorkManager = new WorkProfileManager(
+ mActivityContext.getSystemService(UserManager.class),
+ this,
+ Utilities.getPrefs(mActivityContext));
+ 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() {
+ boolean hasWorkApps = false;
+ for (AppInfo app : mAllAppsStore.getApps()) {
+ if (mWorkManager.getMatcher().matches(app, null)) {
+ hasWorkApps = true;
+ break;
+ }
+ }
+ mHasWorkApps = hasWorkApps;
+ if (!mAH.get(AdapterHolder.MAIN).mAppsList.hasSearchResults()) {
+ rebindAdapters();
+ if (hasWorkApps) {
+ mWorkManager.reset();
+ }
+ }
+ }
+
+ /**
+ * Returns whether the view itself will handle the touch event or not.
+ */
+ public boolean shouldContainerScroll(MotionEvent ev) {
+ // Scroll if not within the container view (e.g. over large-screen scrim).
+ if (!mActivityContext.getDragLayer().isEventOverView(this, ev)) {
+ return true;
+ }
+ if (mActivityContext.getDragLayer().isEventOverView(mBottomSheetHandleArea, ev)) {
+ return true;
+ }
+ if (isSearching()) {
+ return mAH.get(AdapterHolder.SEARCH).mRecyclerView
+ .shouldContainerScroll(ev, mActivityContext.getDragLayer());
+ }
+ AllAppsRecyclerView rv = getActiveAppsRecyclerView();
+ if (rv == null) {
+ return true;
+ }
+ if (rv.getScrollbar().getThumbOffsetY() >= 0
+ && mActivityContext.getDragLayer().isEventOverView(rv.getScrollbar(), ev)) {
+ return false;
+ }
+ return rv.shouldContainerScroll(ev, mActivityContext.getDragLayer());
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ AllAppsRecyclerView rv = getActiveAppsRecyclerView();
+ 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 = getActiveAppsRecyclerView();
+ 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;
+ }
+
+ /** 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 apps recycler view in the container (may be hidden for search results). */
+ public AllAppsRecyclerView getActiveAppsRecyclerView() {
+ if (!mUsingTabs || isPersonalTab()) {
+ return mAH.get(AdapterHolder.MAIN).mRecyclerView;
+ } else {
+ return mAH.get(AdapterHolder.WORK).mRecyclerView;
+ }
+ }
+
+ protected boolean isPersonalTab() {
+ return 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 && getActiveAppsRecyclerView() != null) {
+ getActiveAppsRecyclerView().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, componentName) -> 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();
+
+ for (int i = 0; i < mAH.size(); i++) {
+ mAH.get(i).mPadding.bottom = insets.bottom;
+ mAH.get(i).mPadding.left = mAH.get(i).mPadding.right = grid.allAppsLeftRightPadding;
+ mAH.get(i).applyPadding();
+ }
+
+ MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
+ int leftRightMargin = grid.allAppsLeftRightMargin;
+ mlp.leftMargin = insets.left + leftRightMargin;
+ mlp.rightMargin = insets.right + leftRightMargin;
+ setLayoutParams(mlp);
+
+ if (grid.isVerticalBarLayout()) {
+ setPadding(grid.workspacePadding.left, 0, grid.workspacePadding.right, 0);
+ } else {
+ setPadding(0, grid.allAppsTopPadding, 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);
+ }
+ }
+
+ protected void rebindAdapters() {
+ rebindAdapters(false /* force */);
+ }
+
+ protected void rebindAdapters(boolean force) {
+ updateSearchResultsVisibility();
+
+ boolean showTabs = shouldShowTabs();
+ if (showTabs == mUsingTabs && !force) {
+ return;
+ }
+ mUsingTabs = showTabs;
+
+ if (isSearching()) {
+ return;
+ }
+
+ replaceAppsRVContainer(mUsingTabs);
+ 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);
+ }
+ });
+ findViewById(R.id.tab_work)
+ .setOnClickListener((View view) -> {
+ if (mViewPager.snapToPage(AdapterHolder.WORK)) {
+ mActivityContext.getStatsLogManager().logger()
+ .log(LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB);
+ }
+ });
+ 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);
+ }
+ mHeader.setActiveRV(getCurrentPage());
+ }
+
+ 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;
+ }
+
+ public View getAppsRecyclerViewContainer() {
+ return mViewPager != null ? mViewPager : findViewById(R.id.apps_list_view);
+ }
+
+ public SearchRecyclerView getSearchRecyclerView() {
+ return mSearchRecyclerView;
+ }
+
+ @Override
+ public void onActivePageChanged(int currentActivePage) {
+ mHeader.setActiveRV(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 mViewPager == null ? getActiveAppsRecyclerView() : mViewPager;
+ }
+
+ /** The current page visible in all apps. */
+ public int getCurrentPage() {
+ return isSearching()
+ ? AdapterHolder.SEARCH
+ : mViewPager == null ? AdapterHolder.MAIN : mViewPager.getCurrentPage();
+ }
+
+ /** The scroll bar for the active recycler view. */
+ public RecyclerViewFastScroller getScrollBar() {
+ AllAppsRecyclerView rv = getActiveAppsRecyclerView();
+ return rv == null ? null : rv.getScrollbar();
+ }
+
+ void setupHeader() {
+ mHeader.setVisibility(View.VISIBLE);
+ mHeader.setup(
+ mAH.get(AdapterHolder.MAIN).mRecyclerView,
+ mAH.get(AdapterHolder.WORK).mRecyclerView,
+ (SearchRecyclerView) mAH.get(AdapterHolder.SEARCH).mRecyclerView,
+ getCurrentPage(),
+ /* tabsHidden= */ mAH.get(AdapterHolder.WORK).mRecyclerView == null);
+
+ int padding = mHeader.getMaxTranslation();
+ for (int i = 0; i < mAH.size(); i++) {
+ mAH.get(i).mPadding.top = padding;
+ mAH.get(i).applyPadding();
+ if (mAH.get(i).mRecyclerView != null) {
+ mAH.get(i).mRecyclerView.scrollToTop();
+ }
+ }
+ }
+
+ /** @see View#setVerticalFadingEdgeEnabled(boolean). */
+ public void setRecyclerViewVerticalFadingEdgeEnabled(boolean enabled) {
+ for (int i = 0; i < mAH.size(); i++) {
+ mAH.get(i).applyVerticalFadingEdgeEnabled(enabled);
+ }
+ }
+
+ 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 = (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))));
+ }
+ });
+ }
+
+ /** 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();
+ 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);
+
+ protected 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;
+ boolean mVerticalFadingEdge;
+
+ 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 ItemInfoMatcher 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());
+ applyVerticalFadingEdgeEnabled(mVerticalFadingEdge);
+ 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 void applyVerticalFadingEdgeEnabled(boolean enabled) {
+ mVerticalFadingEdge = enabled;
+ mRecyclerView.setVerticalFadingEdgeEnabled(!mUsingTabs && mVerticalFadingEdge);
+ }
+
+ private boolean isWork() {
+ return mType == WORK;
+ }
+
+ private boolean isSearch() {
+ return mType == SEARCH;
+ }
+ }
+}
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index 85ee636..3e717bd 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -30,12 +30,13 @@
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;
@@ -72,7 +73,8 @@
moved(current);
applyVerticalMove();
if (headerCollapsed != mHeaderCollapsed) {
- AllAppsContainerView parent = (AllAppsContainerView) getParent();
+ BaseAllAppsContainerView<?> parent =
+ (BaseAllAppsContainerView<?>) getParent();
parent.invalidateHeader();
}
}
@@ -81,13 +83,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 +101,6 @@
protected boolean mTabsHidden;
protected int mMaxTranslation;
- private boolean mMainRVActive = true;
private boolean mCollapsed = false;
@@ -117,8 +121,14 @@
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
@@ -193,7 +203,7 @@
updateExpectedHeight();
if (mMaxTranslation != oldMaxHeight) {
- AllAppsContainerView parent = (AllAppsContainerView) getParent();
+ BaseAllAppsContainerView<?> parent = (BaseAllAppsContainerView<?>) getParent();
if (parent != null) {
parent.setupHeader();
}
@@ -222,7 +232,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,10 +241,10 @@
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 = setupRV(mMainRV, mainRV);
+ mWorkRV = setupRV(mWorkRV, workRV);
+ mSearchRV = (SearchRecyclerView) setupRV(mSearchRV, searchRV);
+ setActiveRV(activeRV);
reset(false);
}
@@ -252,11 +263,15 @@
for (FloatingHeaderRow row : mAllRows) {
mMaxTranslation += row.getExpectedHeight();
}
+ if (!mTabsHidden) {
+ mMaxTranslation += mHeaderBottomAdjustment;
+ }
}
- public void setMainActive(boolean active) {
- mCurrentRV = active ? mMainRV : mWorkRV;
- mMainRVActive = active;
+ public void setActiveRV(int rvType) {
+ mCurrentRV =
+ rvType == AdapterHolder.MAIN ? mMainRV
+ : rvType == AdapterHolder.WORK ? mWorkRV : mSearchRV;
}
public int getMaxTranslation() {
@@ -314,15 +329,20 @@
mTabLayout.setTranslationY(mTranslationY);
- int clipHeight = mHeaderTopPadding - getPaddingBottom();
- mRVClip.top = mTabsHidden ? clipHeight : 0;
- mHeaderClip.top = clipHeight;
+ int clipTop = mHeaderTopPadding - mHeaderTopAdjustment;
+ 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,8 +409,8 @@
}
private void calcOffset(Point p) {
- p.x = getLeft() - mCurrentRV.getLeft() - mParent.getLeft();
- p.y = getTop() - mCurrentRV.getTop() - mParent.getTop();
+ p.x = getLeft() - mCurrentRV.getLeft() - ((ViewGroup) mCurrentRV.getParent()).getLeft();
+ p.y = getTop() - mCurrentRV.getTop() - ((ViewGroup) mCurrentRV.getParent()).getTop();
}
public boolean hasVisibleContent() {
@@ -413,7 +433,7 @@
@Override
public void setInsets(Rect insets) {
- DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
+ DeviceProfile grid = ActivityContext.lookupContext(getContext()).getDeviceProfile();
for (FloatingHeaderRow row : mAllRows) {
row.setInsets(insets, grid);
}
@@ -444,5 +464,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..8601819 100644
--- a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
@@ -16,7 +16,6 @@
package com.android.launcher3.allapps;
import android.content.Context;
-import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
@@ -26,9 +25,7 @@
/**
* 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 +37,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 +53,9 @@
@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);
- }
}
diff --git a/src/com/android/launcher3/allapps/SearchRecyclerView.java b/src/com/android/launcher3/allapps/SearchRecyclerView.java
new file mode 100644
index 0000000..435668a
--- /dev/null
+++ b/src/com/android/launcher3/allapps/SearchRecyclerView.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.allapps;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+/** 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;
+ }
+}
diff --git a/src/com/android/launcher3/allapps/SearchUiManager.java b/src/com/android/launcher3/allapps/SearchUiManager.java
index 7478b53..6299657 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,7 @@
* sets highlight result's title
*/
default void setFocusedResultTitle(@Nullable CharSequence title) { }
+
+ /** Refresh the currently displayed list of results. */
+ default void refreshResults() {}
}
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..ce44958 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.Button;
+import android.widget.TextView;
import com.android.launcher3.R;
+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);
+
}
/**
diff --git a/src/com/android/launcher3/allapps/WorkEduCard.java b/src/com/android/launcher3/allapps/WorkEduCard.java
index 9db7bf0..fa9a8f6 100644
--- a/src/com/android/launcher3/allapps/WorkEduCard.java
+++ b/src/com/android/launcher3/allapps/WorkEduCard.java
@@ -23,16 +23,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 +48,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);
@@ -69,13 +71,14 @@
super.onFinishInflate();
findViewById(R.id.action_btn).setOnClickListener(this);
MarginLayoutParams lp = ((MarginLayoutParams) findViewById(R.id.wrapper).getLayoutParams());
- lp.width = mLauncher.getAppsView().getActiveRecyclerView().getTabWidth();
+ lp.width = mActivityContext.getAppsView().getActiveAppsRecyclerView().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
@@ -97,8 +100,8 @@
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);
}
diff --git a/src/com/android/launcher3/allapps/WorkModeSwitch.java b/src/com/android/launcher3/allapps/WorkModeSwitch.java
index be01581..733577e 100644
--- a/src/com/android/launcher3/allapps/WorkModeSwitch.java
+++ b/src/com/android/launcher3/allapps/WorkModeSwitch.java
@@ -26,12 +26,12 @@
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.Utilities;
import com.android.launcher3.anim.KeyboardInsetAnimationCallback;
+import com.android.launcher3.model.StringCache;
+import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip;
/**
@@ -73,8 +73,14 @@
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
@@ -91,7 +97,7 @@
@Override
public void onActivePageChanged(int page) {
- mOnWorkTab = page == AllAppsContainerView.AdapterHolder.WORK;
+ mOnWorkTab = page == ActivityAllAppsContainerView.AdapterHolder.WORK;
updateVisibility();
}
@@ -99,9 +105,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 +127,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..6203cea 100644
--- a/src/com/android/launcher3/allapps/WorkProfileManager.java
+++ b/src/com/android/launcher3/allapps/WorkProfileManager.java
@@ -26,12 +26,15 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
+import android.view.ViewGroup;
+import android.view.WindowInsets;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip;
@@ -39,7 +42,8 @@
import java.lang.annotation.RetentionPolicy;
/**
- * 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 +54,6 @@
public static final int STATE_DISABLED = 2;
public static final int STATE_TRANSITION = 3;
-
private final UserManager mUserManager;
/**
@@ -65,7 +68,7 @@
public @interface WorkProfileState {
}
- private final AllAppsContainerView mAllApps;
+ private final BaseAllAppsContainerView<?> mAllApps;
private final WorkAdapterProvider mAdapterProvider;
private final ItemInfoMatcher mMatcher;
@@ -75,11 +78,11 @@
private int mCurrentState;
- public WorkProfileManager(UserManager userManager, AllAppsContainerView allApps,
+ public WorkProfileManager(UserManager userManager, BaseAllAppsContainerView<?> allApps,
SharedPreferences preferences) {
mUserManager = userManager;
mAllApps = allApps;
- mAdapterProvider = new WorkAdapterProvider(preferences);
+ mAdapterProvider = new WorkAdapterProvider(allApps.mActivityContext, preferences);
mMatcher = mAllApps.mPersonalMatcher.negate();
}
@@ -118,7 +121,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 +129,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(
@@ -138,6 +141,18 @@
mWorkModeSwitch = (WorkModeSwitch) mAllApps.getLayoutInflater().inflate(
R.layout.work_mode_fab, mAllApps, false);
}
+ int workFabMarginBottom =
+ mWorkModeSwitch.getResources().getDimensionPixelSize(R.dimen.work_fab_margin);
+ if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+ workFabMarginBottom <<= 1; // Double margin to add space above search bar.
+ workFabMarginBottom +=
+ mWorkModeSwitch.getResources().getDimensionPixelSize(R.dimen.qsb_widget_height);
+ }
+ if (!mAllApps.mActivityContext.getDeviceProfile().isGestureMode){
+ workFabMarginBottom += mAllApps.mActivityContext.getDeviceProfile().getInsets().bottom;
+ }
+ ((ViewGroup.MarginLayoutParams) mWorkModeSwitch.getLayoutParams()).bottomMargin =
+ workFabMarginBottom;
if (mWorkModeSwitch.getParent() != mAllApps) {
mAllApps.addView(mWorkModeSwitch);
}
@@ -147,9 +162,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,7 +172,6 @@
mWorkModeSwitch = null;
}
-
public WorkAdapterProvider getAdapterProvider() {
return mAdapterProvider;
}
@@ -172,8 +185,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..4bd106f 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -32,17 +32,17 @@
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 +53,12 @@
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 AlphabeticalAppsList<?> mSearchResultsList;
+ private ActivityAllAppsContainerView<?> mAppsView;
// The amount of pixels to shift down and overlap with the rest of the content.
private final int mContentOverlap;
@@ -74,7 +74,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 +82,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
@@ -102,8 +102,8 @@
// Update the width to match the grid padding
DeviceProfile dp = mLauncher.getDeviceProfile();
int myRequestedWidth = getSize(widthMeasureSpec);
- int rowWidth = myRequestedWidth - mAppsView.getActiveRecyclerView().getPaddingLeft()
- - mAppsView.getActiveRecyclerView().getPaddingRight();
+ int rowWidth = myRequestedWidth - mAppsView.getActiveAppsRecyclerView().getPaddingLeft()
+ - mAppsView.getActiveAppsRecyclerView().getPaddingRight();
int cellWidth = DeviceProfile.calculateCellWidth(rowWidth,
dp.cellLayoutBorderSpacePx.x, dp.numShownHotseatIcons);
@@ -130,11 +130,11 @@
}
@Override
- public void initializeSearch(AllAppsContainerView appsView) {
- mApps = appsView.getApps();
+ public void initializeSearch(ActivityAllAppsContainerView<?> appsView) {
+ mSearchResultsList = appsView.getSearchResultList();
mAppsView = appsView;
mSearchBarController.initialize(
- new DefaultAppSearchAlgorithm(mLauncher),
+ new DefaultAppSearchAlgorithm(getContext()),
this, mLauncher, this);
}
@@ -170,7 +170,7 @@
@Override
public void onSearchResult(String query, ArrayList<AdapterItem> items) {
if (items != null) {
- mApps.setSearchResults(items);
+ mSearchResultsList.setSearchResults(items);
notifyResultChanged();
mAppsView.setLastSearchQuery(query);
}
@@ -179,14 +179,14 @@
@Override
public void onAppendSearchResult(String query, ArrayList<AdapterItem> items) {
if (items != null) {
- mApps.appendSearchResults(items);
+ mSearchResultsList.appendSearchResults(items);
notifyResultChanged();
}
}
@Override
public void clearSearchResult() {
- if (mApps.setSearchResults(null)) {
+ if (mSearchResultsList.setSearchResults(null)) {
notifyResultChanged();
}
diff --git a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
index 1f854c6..222c8fe 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;
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/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..5a46ce1 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -47,6 +47,13 @@
public static final Interpolator DEACCEL_2_5 = new DecelerateInterpolator(2.5f);
public static final Interpolator DEACCEL_3 = new DecelerateInterpolator(3f);
+ /**
+ * The decelerating emphasized interpolator. Used for hero / emphasized movement of content that
+ * is appearing e.g. when coming from off screen
+ */
+ public static final Interpolator EMPHASIZED_DECELERATE = new PathInterpolator(
+ 0.05f, 0.7f, 0.1f, 1f);
+
public static final Interpolator ACCEL_DEACCEL = new AccelerateDecelerateInterpolator();
public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
@@ -145,8 +152,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 +163,30 @@
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(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.
+ */
+ public static float clampToProgress(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 (progress - lowerBound) / (upperBound - lowerBound);
}
/**
diff --git a/src/com/android/launcher3/anim/PendingAnimation.java b/src/com/android/launcher3/anim/PendingAnimation.java
index 3ab893b..1300ce7 100644
--- a/src/com/android/launcher3/anim/PendingAnimation.java
+++ b/src/com/android/launcher3/anim/PendingAnimation.java
@@ -77,6 +77,13 @@
addAnimationHoldersRecur(a, mDuration, springProperty, mAnimHolders);
}
+ /**
+ * Configures interpolator of the underlying AnimatorSet.
+ */
+ public void setInterpolator(TimeInterpolator interpolator) {
+ mAnim.setInterpolator(interpolator);
+ }
+
@Override
public void setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
if (view == null || view.getAlpha() == alpha) {
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..626e15c 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,33 @@
"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_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 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/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..a3945fd 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();
}));
@@ -565,19 +578,4 @@
iv.setImageDrawable(drawable);
return iv;
}
-
- /**
- * Removes any stray DragView from the DragLayer.
- */
- public static void removeAllViews(ActivityContext activity) {
- BaseDragLayer dragLayer = activity.getDragLayer();
- // Iterate in reverse order. DragView is added later to the dragLayer,
- // and will be one of the last views.
- for (int i = dragLayer.getChildCount() - 1; i >= 0; i--) {
- View child = dragLayer.getChildAt(i);
- if (child instanceof DragView) {
- dragLayer.removeView(child);
- }
- }
- }
}
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/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..8916519 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;
@@ -101,6 +102,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,10 +133,13 @@
*/
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.
@@ -198,13 +204,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 +282,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 +562,7 @@
a.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
- mState = STATE_ANIMATING;
+ setState(STATE_ANIMATING);
mCurrentAnimator = a;
}
@@ -686,7 +687,7 @@
@Override
public void onAnimationEnd(Animator animation) {
- mState = STATE_OPEN;
+ setState(STATE_OPEN);
announceAccessibilityChanges();
AccessibilityManagerCompat.sendFolderOpenedEventToTest(getContext());
@@ -862,7 +863,7 @@
}
mSuppressFolderDeletion = false;
clearDragInfo();
- mState = STATE_SMALL;
+ setState(STATE_CLOSED);
mContent.setCurrentPage(0);
}
@@ -1655,4 +1656,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..5fe2435 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;
@@ -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;
diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java
index 9c1b24d..2b621bd 100644
--- a/src/com/android/launcher3/folder/FolderNameProvider.java
+++ b/src/com/android/launcher3/folder/FolderNameProvider.java
@@ -101,13 +101,14 @@
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));
+ String workFolderName = context.getString(R.string.work_folder_name);
+ setAsLastSuggestion(nameInfos, workFolderName);
}
// If all the icons are from same package (e.g., main icon, shortcut, shortcut)
@@ -121,7 +122,8 @@
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());
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/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..a11bd4f 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;
@@ -88,6 +86,7 @@
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
+import com.android.launcher3.util.window.WindowManagerProxy;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
import com.android.launcher3.widget.BaseLauncherAppWidgetHostView;
@@ -112,7 +111,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 +128,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);
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 +187,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 +224,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 +419,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 +451,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..2b6e426 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,69 @@
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),
+ ;
// ADD MORE
@@ -556,7 +624,7 @@
}
/**
- * Helps to construct and write the log message.
+ * Helps to construct and log launcher event.
*/
public interface StatsLogger {
@@ -656,6 +724,64 @@
}
/**
+ * Helps to construct and log latency event.
+ */
+ public interface StatsLatencyLogger {
+
+ enum LatencyType {
+ UNKNOWN(0),
+ COLD(1),
+ HOT(2);
+
+ 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 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 +792,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..ca91296 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -15,21 +15,17 @@
*/
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;
@@ -39,9 +35,8 @@
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 +51,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 +79,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,11 +89,19 @@
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;
}
}
@@ -107,7 +122,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];
@@ -126,6 +141,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 +152,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 +165,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 {
@@ -163,6 +187,9 @@
// 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 +293,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..b8c9762 100644
--- a/src/com/android/launcher3/model/AllAppsList.java
+++ b/src/com/android/launcher3/model/AllAppsList.java
@@ -143,6 +143,8 @@
if (loadIcon) {
mIconCache.getTitleAndIcon(info, activityInfo, false /* useLowResIcon */);
info.sectionName = mIndex.computeSectionName(info.title);
+ } else {
+ info.title = "";
}
data.add(info);
@@ -167,6 +169,8 @@
if (loadIcon) {
mIconCache.getTitleAndIcon(promiseAppInfo, promiseAppInfo.usingLowResIcon());
promiseAppInfo.sectionName = mIndex.computeSectionName(promiseAppInfo.title);
+ } else {
+ promiseAppInfo.title = "";
}
data.add(promiseAppInfo);
diff --git a/src/com/android/launcher3/model/BaseLoaderResults.java b/src/com/android/launcher3/model/BaseLoaderResults.java
index d270cc5..6c4cfb9 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;
@@ -110,6 +111,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 +168,7 @@
return idleLock;
}
- private static class WorkspaceBinder {
+ private class WorkspaceBinder {
private final Executor mUiExecutor;
private final Callbacks mCallbacks;
@@ -226,6 +263,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/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index d3351dc..866d18a 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -114,6 +114,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 +234,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:
@@ -506,5 +510,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..5fac7cf 100644
--- a/src/com/android/launcher3/model/FirstScreenBroadcast.java
+++ b/src/com/android/launcher3/model/FirstScreenBroadcast.java
@@ -135,6 +135,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))
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
index ca680b7..e36d4cf 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,13 +205,13 @@
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;
}
@@ -225,13 +231,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 +255,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 +377,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 +395,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 +431,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 +514,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 +523,7 @@
new ArrayMap<>();
DbReader(SQLiteDatabase db, String tableName, Context context,
- HashSet<String> validPackages) {
+ Set<String> validPackages) {
mDb = db;
mTableName = tableName;
mContext = context;
@@ -734,7 +754,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..df6768d 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;
@@ -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/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 83fb3d1..d47edff 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -112,7 +112,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 +134,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 +148,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 +161,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
diff --git a/src/com/android/launcher3/model/StringCache.java b/src/com/android/launcher3/model/StringCache.java
new file mode 100644
index 0000000..663a463
--- /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.";
+
+ /**
+ * 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";
+
+ /**
+ * Work folder name.
+ */
+ private static final String WORK_FOLDER_NAME = PREFIX + "WORK_FOLDER_NAME";
+
+ /**
+ * 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/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/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..cc22601 100644
--- a/src/com/android/launcher3/model/data/SearchActionItemInfo.java
+++ b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
@@ -28,7 +28,6 @@
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;
@@ -176,9 +175,7 @@
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);
- }
+ info.bitmap = info.bitmap.withBadgeInfo(pkgInfo.bitmap);
return info;
});
}
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..484b879 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;
}
@@ -216,7 +218,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 +227,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 +248,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 +280,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 +292,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 +332,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 +375,7 @@
}
}
- private void updateHiddenShortcuts() {
+ protected void updateHiddenShortcuts() {
int allowedCount = mNotificationContainer != null
? MAX_SHORTCUTS_IF_NOTIFICATIONS : MAX_SHORTCUTS;
@@ -363,7 +386,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 +405,7 @@
}
view.setTag(info);
view.setOnClickListener(info);
+ return view;
}
/**
@@ -442,7 +471,7 @@
};
}
- private void updateNotificationHeader() {
+ protected void updateNotificationHeader() {
ItemInfoWithIcon itemInfo = (ItemInfoWithIcon) mOriginalIcon.getTag();
DotInfo dotInfo = mActivityContext.getDotInfoForItem(itemInfo);
if (mNotificationContainer != null && dotInfo != null) {
@@ -504,112 +533,6 @@
}
/**
- * 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) {
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/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..73aa296 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,16 @@
private LauncherModel mModel;
private BaseDragLayer mDragLayer;
- private AllAppsContainerView mAppsView;
+ // TODO(b/216191717): Verify all apps works on secondary display.
+ 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 +147,8 @@
return mAppDrawerShown;
}
- public AllAppsContainerView getAppsView() {
+ @Override
+ public ActivityAllAppsContainerView<SecondaryDisplayLauncher> getAppsView() {
return mAppsView;
}
@@ -225,6 +230,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..e906c95 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,13 +113,17 @@
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 maxWidth =
+ grid.allAppsCellWidthPx * grid.numShownAllAppsColumns + horizontalPadding;
int appsWidth = Math.min(width, maxWidth);
- int maxHeight = grid.allAppsCellHeightPx * grid.numShownAllAppsColumns + padding;
+ int maxHeight =
+ grid.allAppsCellHeightPx * grid.numShownAllAppsColumns + verticalPadding;
int appsHeight = Math.min(height, maxHeight);
mAppsView.measure(
@@ -177,15 +182,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/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/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/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
index 867fd99..8b425da 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;
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index d52594e..7e9d56d 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;
@@ -47,33 +46,28 @@
@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 shrunkTop = grid.getWorkspaceSpringLoadShrunkTop();
+ float shrunkBottom = grid.getWorkspaceSpringLoadShrunkBottom();
+ float scale = Math.min((shrunkBottom - shrunkTop) / ws.getNormalChildHeight(), 1f);
+
+ // Reduce scale if next pages would not be visible after scaling the workspace
+ float scaledWorkspaceWidth = ws.getWidth() * scale;
+ float maxAvailableWidth =
+ ws.getWidth() - (2 * grid.getWorkspaceSpringLoadedMinimumNextPageVisible());
+ if (scaledWorkspaceWidth > maxAvailableWidth) {
+ scale *= maxAvailableWidth / scaledWorkspaceWidth;
}
- 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 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..f04e685 100644
--- a/src/com/android/launcher3/states/StateAnimationConfig.java
+++ b/src/com/android/launcher3/states/StateAnimationConfig.java
@@ -62,6 +62,7 @@
ANIM_OVERVIEW_MODAL,
ANIM_DEPTH,
ANIM_OVERVIEW_ACTIONS_FADE,
+ ANIM_WORKSPACE_PAGE_TRANSLATE_X,
})
@Retention(RetentionPolicy.SOURCE)
public @interface AnimType {}
@@ -80,8 +81,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 = 16;
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..ee8f85d 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 -> {
@@ -95,7 +108,7 @@
case TestProtocol.REQUEST_APPS_LIST_SCROLL_Y: {
return getLauncherUIProperty(Bundle::putInt,
- l -> l.getAppsView().getActiveRecyclerView().getCurrentScrollY());
+ l -> l.getAppsView().getActiveAppsRecyclerView().getCurrentScrollY());
}
case TestProtocol.REQUEST_WIDGETS_SCROLL_Y: {
@@ -163,11 +176,48 @@
.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());
+ });
+
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/testing/TestInformationRequest.java b/src/com/android/launcher3/testing/TestInformationRequest.java
new file mode 100644
index 0000000..272ae56
--- /dev/null
+++ b/src/com/android/launcher3/testing/TestInformationRequest.java
@@ -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 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..e8fd2ff 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,25 @@
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_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 +133,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..a125fbe 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -16,6 +16,7 @@
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;
@@ -26,7 +27,7 @@
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 +286,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;
diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java
index 989a9e4..5aac3f3 100644
--- a/src/com/android/launcher3/touch/AllAppsSwipeController.java
+++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java
@@ -17,6 +17,8 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
+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_SCRIM_FADE;
@@ -94,9 +96,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,17 +106,22 @@
/**
* 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);
}
/**
* Applies Animation config values for transition from home to all apps
*/
- public static void applyNormalToAllAppsAnimConfig(StateAnimationConfig config) {
+ public static void applyNormalToAllAppsAnimConfig(Launcher launcher,
+ StateAnimationConfig config) {
+ boolean isTablet = launcher.getDeviceProfile().isTablet;
config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
- config.setInterpolator(ANIM_ALL_APPS_FADE, ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
+ config.setInterpolator(ANIM_ALL_APPS_FADE, isTablet
+ ? INSTANT : ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
}
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 8d57d69..cd00f15 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
*/
@@ -171,7 +176,8 @@
(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)))
.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,37 @@
}
}
+ 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))));
+ })
+ .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/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index a94ad7c..121088a 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;
@@ -178,18 +179,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 +299,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 +313,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 +329,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 +394,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 +437,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 +483,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..4fcf378 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);
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index ad9f95c..80a8c19 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 {
@@ -180,24 +178,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 +269,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 +304,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 +332,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 +403,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 +518,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 +562,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 +579,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 +591,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 +601,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..8005181 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,17 @@
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;
+ Point expectedS = oldInfo.mPerDisplayBounds.get(newInfo.displayId).first.size;
if (newInfo.supportedBounds.size() != oldInfo.supportedBounds.size()) {
Log.e("b/198965093",
"Inconsistent number of displays"
@@ -268,7 +250,9 @@
+ "\noldInfo.supportedBounds: " + oldInfo.supportedBounds
+ "\nnewInfo.supportedBounds: " + newInfo.supportedBounds);
}
- if (!realSize.equals(expectedSize) && display.getState() == Display.STATE_OFF) {
+ if ((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 +269,105 @@
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;
+ 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);
+ }
+ }
+
+ /**
+ * 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 +395,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..8485371 100644
--- a/src/com/android/launcher3/util/Executors.java
+++ b/src/com/android/launcher3/util/Executors.java
@@ -15,10 +15,17 @@
*/
package com.android.launcher3.util;
+import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
+
+import static java.util.concurrent.Executors.newSingleThreadExecutor;
+
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
@@ -34,6 +41,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, ExecutorService> PACKAGE_EXECUTORS = new ConcurrentHashMap<>();
+
/**
* An {@link ThreadPoolExecutor} to be used with async task with no limit on the queue size.
*/
@@ -76,6 +86,18 @@
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 ExecutorService getPackageExecutor(String packageName) {
+ return PACKAGE_EXECUTORS.computeIfAbsent(
+ packageName,
+ p -> newSingleThreadExecutor(
+ new SimpleThreadFactory(p, THREAD_PRIORITY_BACKGROUND)));
+ }
+
+ /**
* 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/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..c1e4fa8 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);
}
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..a1f31fe 100644
--- a/src/com/android/launcher3/util/UiThreadHelper.java
+++ b/src/com/android/launcher3/util/UiThreadHelper.java
@@ -28,7 +28,6 @@
import android.view.View;
import android.view.inputmethod.InputMethodManager;
-import com.android.launcher3.BaseActivity;
import com.android.launcher3.views.ActivityContext;
/**
@@ -56,7 +55,7 @@
STATS_LOGGER_KEY,
Message.obtain(
HANDLER.get(root.getContext()),
- () -> BaseActivity.fromContext(root.getContext())
+ () -> ActivityContext.lookupContext(root.getContext())
.getStatsLogManager()
.logger()
.log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED)
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..5aaa275
--- /dev/null
+++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java
@@ -0,0 +1,330 @@
+/*
+ * 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.getDimenByName;
+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 = context.getSystemService(DisplayManager.class).getDisplays();
+ 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);
+
+ int bottomNav = isTablet
+ ? 0
+ : (config.screenHeightDp > config.screenWidthDp
+ ? getDimenByName(NAVBAR_HEIGHT, systemRes, 0)
+ : (isGesture
+ ? getDimenByName(NAVBAR_HEIGHT_LANDSCAPE, systemRes, 0)
+ : 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("status_bar_height", systemRes, 0);
+ 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 statusBarHeight = getDimenByName("status_bar_height", systemRes, 0);
+
+ int navBarHeightPortrait, navBarHeightLandscape, navbarWidthLandscape;
+
+ navBarHeightPortrait = isTablet
+ ? (mTaskbarDrawnInProcess
+ ? 0 : systemRes.getDimensionPixelSize(R.dimen.taskbar_size))
+ : getDimenByName(NAVBAR_HEIGHT, systemRes, 0);
+
+ navBarHeightLandscape = isTablet
+ ? (mTaskbarDrawnInProcess
+ ? 0 : systemRes.getDimensionPixelSize(R.dimen.taskbar_size))
+ : (isTabletOrGesture
+ ? getDimenByName(NAVBAR_HEIGHT_LANDSCAPE, systemRes, 0) : 0);
+ navbarWidthLandscape = isTabletOrGesture
+ ? 0
+ : getDimenByName(NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE, systemRes, 0);
+
+ 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;
+ if (tempSize.y > tempSize.x) {
+ navBarHeight = navBarHeightPortrait;
+ navbarWidth = 0;
+ } else {
+ navBarHeight = navBarHeightLandscape;
+ navbarWidth = navbarWidthLandscape;
+ }
+
+ 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;
+ }
+
+ 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();
+ }
+}
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index 8ac40b8..ed31e8d 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,6 +224,7 @@
mOpenCloseAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
+ mOpenCloseAnimator.removeListener(this);
onCloseComplete();
}
});
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..f71aa13 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;
@@ -40,7 +40,6 @@
import android.widget.FrameLayout;
import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.MultiValueAlpha;
@@ -546,14 +545,8 @@
public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
if (Utilities.ATLEAST_Q) {
Insets gestureInsets = insets.getMandatorySystemGestureInsets();
- int gestureInsetBottom = gestureInsets.bottom;
- DeviceProfile dp = mActivity.getDeviceProfile();
- if (dp.isTaskbarPresent) {
- // Ignore taskbar gesture insets to avoid interfering with TouchControllers.
- gestureInsetBottom = Math.max(0, gestureInsetBottom - dp.taskbarSize);
- }
mSystemGestureRegion.set(gestureInsets.left, gestureInsets.top,
- gestureInsets.right, gestureInsetBottom);
+ gestureInsets.right, gestureInsets.bottom);
}
return super.dispatchApplyWindowInsets(insets);
}
diff --git a/src/com/android/launcher3/views/BubbleTextHolder.java b/src/com/android/launcher3/views/BubbleTextHolder.java
index 1cb27e1..76c465c 100644
--- a/src/com/android/launcher3/views/BubbleTextHolder.java
+++ b/src/com/android/launcher3/views/BubbleTextHolder.java
@@ -22,7 +22,7 @@
/**
* Views that contain {@link BubbleTextView} should implement this interface.
*/
-public interface BubbleTextHolder {
+public interface BubbleTextHolder extends IconLabelDotView {
BubbleTextView getBubbleText();
/**
@@ -32,4 +32,14 @@
*/
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..babe607 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;
@@ -83,7 +82,6 @@
private final Launcher mLauncher;
private final boolean mIsRtl;
- private boolean mIsVerticalBarLayout = false;
private boolean mIsOpening;
private IconLoadResult mIconLoadResult;
@@ -151,7 +149,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 +246,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 +272,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 +287,25 @@
// 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
+ synchronized (outIconLoadResult) {
+ outIconLoadResult.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;
+ 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;
}
}
@@ -317,11 +319,11 @@
@UiThread
private void setIcon(@Nullable Drawable drawable, @Nullable Drawable badge,
@Nullable 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 +331,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 +339,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);
@@ -412,8 +412,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 =
@@ -532,8 +531,7 @@
btvIcon = null;
}
- IconLoadResult result = new IconLoadResult(info,
- btvIcon == null ? false : btvIcon.isThemed());
+ IconLoadResult result = new IconLoadResult(info, btvIcon != null && btvIcon.isThemed());
result.btvDrawable = btvIcon;
final long fetchIconId = sFetchIconId++;
@@ -565,7 +563,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 +584,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 +593,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);
}
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..5f6e453 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -43,7 +43,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 +127,7 @@
private String mPopupSectionName;
private Insets mSystemGestureInsets;
- protected BaseRecyclerView mRv;
+ protected FastScrollRecyclerView mRv;
private RecyclerView.OnScrollListener mOnScrollListener;
private int mDownX;
@@ -172,7 +172,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);
}
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 00a0050..b12574f 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -163,9 +163,8 @@
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/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..53c772f 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;
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/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 894c4c9..341cb5c 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);
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListHeader.java b/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
index 932e06d..b0e2ec1 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;
@@ -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..ea62c17 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;
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..8a435c9 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -34,13 +34,6 @@
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);
}
@@ -62,13 +55,28 @@
@Override
public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
- return new ScaleAndTranslation(1f, 0,
- -launcher.getAllAppsController().getShiftRange() * PARALLAX_COEFFICIENT);
+ ScaleAndTranslation scaleAndTranslation =
+ new ScaleAndTranslation(NO_SCALE, NO_OFFSET, NO_OFFSET);
+ if (launcher.getDeviceProfile().isTablet) {
+ scaleAndTranslation.scale = 0.97f;
+ } else {
+ scaleAndTranslation.translationY =
+ -launcher.getAllAppsController().getShiftRange() * PARALLAX_COEFFICIENT;
+ }
+ return scaleAndTranslation;
}
@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 +86,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/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/src/com/android/launcher3/DeviceProfileBaseTest.kt b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
new file mode 100644
index 0000000..f91f1c4
--- /dev/null
+++ b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
@@ -0,0 +1,133 @@
+/*
+ * 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)
+
+ 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)
+
+ 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 }
+ 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/HotseatSizeTest.kt b/tests/src/com/android/launcher3/HotseatSizeTest.kt
new file mode 100644
index 0000000..a44939f
--- /dev/null
+++ b/tests/src/com/android/launcher3/HotseatSizeTest.kt
@@ -0,0 +1,214 @@
+/*
+ * 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
+import org.mockito.ArgumentMatchers
+import org.mockito.Mockito.`when` as whenever
+
+/**
+ * Test for [DeviceProfile]
+ */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class HotseatSizeTest : 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..e00dca8
--- /dev/null
+++ b/tests/src/com/android/launcher3/InlineQsbTest.kt
@@ -0,0 +1,105 @@
+/*
+ * 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 qsbWidth_is_match_parent_for_phones() {
+ initializeVarsForPhone()
+
+ val dp = newDP()
+
+ assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.qsbWidth).isEqualTo(0)
+ }
+
+ @Test
+ fun qsbWidth_is_match_parent_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()
+ assertThat(dp.qsbWidth).isEqualTo(0)
+ }
+
+ @Test
+ fun qsbWidth_has_size_for_tablet_landscape() {
+ initializeVarsForTablet(isLandscape = true)
+ inv = newScalableInvariantDeviceProfile().apply {
+ inlineQsb = booleanArrayOf(
+ false,
+ true, // landscape
+ false,
+ false
+ )
+ }
+
+ val dp = newDP()
+
+ if (dp.hotseatQsbHeight > 0) {
+ assertThat(dp.isQsbInline).isTrue()
+ assertThat(dp.qsbWidth).isGreaterThan(0)
+ } else { // Launcher3 doesn't have QSB height
+ assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.qsbWidth).isEqualTo(0)
+ }
+ }
+
+ /**
+ * This test is to make sure that a tablet doesn't inline the QSB if the layout doesn't support
+ */
+ @Test
+ fun qsbWidth_is_match_parent_for_tablet_landscape_without_inline() {
+ initializeVarsForTablet(isLandscape = true)
+ useTwoPanels = true
+
+ val dp = newDP()
+
+ assertThat(dp.isQsbInline).isFalse()
+ assertThat(dp.qsbWidth).isEqualTo(0)
+ }
+
+}
\ 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/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..9b37741 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();
}
@@ -521,7 +525,7 @@
}
protected int getAllAppsScroll(Launcher launcher) {
- return launcher.getAppsView().getActiveRecyclerView().getCurrentScrollY();
+ return launcher.getAppsView().getActiveAppsRecyclerView().getCurrentScrollY();
}
private void checkLauncherIntegrity(
@@ -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,26 @@
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, 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..f0bef24 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -24,6 +24,9 @@
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,13 +39,18 @@
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.Test;
import org.junit.runner.RunWith;
@@ -50,6 +58,7 @@
@RunWith(AndroidJUnit4.class)
public class TaplTestsLauncher3 extends AbstractLauncherUiTest {
private static final String APP_NAME = "LauncherTestApp";
+ private static final String DUMMY_APP_NAME = "Aardwolf";
@Before
public void setUp() throws Exception {
@@ -100,7 +109,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 +121,7 @@
} finally {
allApps.unfreeze();
}
- mLauncher.pressHome();
+ mLauncher.goHome();
}
public static void runAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) {
@@ -174,6 +183,7 @@
}
@Test
+ @ScreenRecord // b/202433017
public void testWorkspace() throws Exception {
final Workspace workspace = mLauncher.getWorkspace();
@@ -209,7 +219,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 +232,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 +241,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 +273,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 +290,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 +315,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 +326,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 +335,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,28 +365,11 @@
}
}
- 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");
+ final HomeAppIcon playStoreIcon = createShortcutIfNotExist("Play Store", 0, 1);
+ final HomeAppIcon gmailIcon = createShortcutIfNotExist("Gmail", 1, 1);
FolderIcon folderIcon = gmailIcon.dragToIcon(playStoreIcon);
@@ -393,7 +383,7 @@
assertNull("Play Store should be moved to a folder.",
workspace.tryGetWorkspaceAppIcon("Play Store"));
- final AppIcon youTubeIcon = createShortcutIfNotExist("YouTube");
+ final HomeAppIcon youTubeIcon = createShortcutInCenterIfNotExist("YouTube");
folderIcon = youTubeIcon.dragToIcon(folderIcon);
folder = folderIcon.open();
@@ -401,7 +391,6 @@
folder.close();
}
- @Ignore("b/205027405")
@Test
@PortraitLandscape
public void testPressBack() throws Exception {
@@ -410,14 +399,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 +409,88 @@
@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 {
+ final Point dimensions = mLauncher.getWorkspace().getIconGridDimensions();
+
+ Point[] targets = {
+ 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)
+ };
+
+ 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);
+ }
+ }
+
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..13b93d1 100644
--- a/tests/src/com/android/launcher3/ui/WorkProfileTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkProfileTest.java
@@ -26,7 +26,7 @@
import android.view.View;
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;
@@ -41,7 +41,7 @@
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;
@@ -132,10 +132,10 @@
// 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.getActiveAppsRecyclerView()
+ .findViewHolderForAdapterPosition(0).itemView;
workPausedCard.findViewById(R.id.enable_work_apps).performClick();
});
waitForLauncherCondition("Work profile toggle ON failed", launcher -> {
@@ -155,7 +155,7 @@
});
waitForLauncherCondition("Work profile education not shown",
- l -> l.getAppsView().getActiveRecyclerView()
+ l -> l.getAppsView().getActiveAppsRecyclerView()
.findViewHolderForAdapterPosition(0).itemView instanceof WorkEduCard,
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..657f213 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,11 @@
}
dumpCommand("logcat -d -s TestRunner", diagFile(description, "FilteredLogcat", "txt"));
+
+ // Dump bugreport
+ if (launcher.getSystemAnomalyMessage(false, false) != null) {
+ 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/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 7ec5208..45a0196 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -18,17 +18,25 @@
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 {
+
+ protected static final int DEFAULT_DRAG_STEPS = 10;
+
protected final LauncherInstrumentation mLauncher;
protected final UiObject2 mObject;
@@ -45,7 +53,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 +63,108 @@
protected abstract String launchableType();
- private Background launch(BySelector selector) {
+ private LaunchedAppState launch(BySelector selector) {
try (LauncherInstrumentation.Closable c = 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());
+ executeAndWaitForWindowChange(() -> {
+ mLauncher.clickLauncherObject(mObject);
+ expectActivityStartEvents();
+ }, label, "clicking " + launchableType());
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);
+ return assertAppLaunched(label, 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 void executeAndWaitForWindowChange(Runnable command, String label, String action) {
+ mLauncher.executeAndWaitForEvent(
+ command,
+ event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
+ () -> "Launching an app didn't open a new window: " + label,
+ action);
+ }
+
+ protected LaunchedAppState assertAppLaunched(String label, BySelector selector) {
+ mLauncher.assertTrue(
+ "App didn't start: " + label + " (" + selector + ")",
+ TestHelpers.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..2033a42
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
@@ -0,0 +1,170 @@
+/*
+ * 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();
+ final Point endPoint = new Point(displaySize.x / 4, 3 * 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")) {
+ dropDraggedItem(
+ launcher,
+ launchable,
+ expectedNewPackageName,
+ endPoint, downTime,
+ itemVisibleCenter,
+ itemVisibleBounds,
+ itemLabel,
+ expectedExistingPackageName);
+ }
+ }
+ }
+ }
+
+ private static void dropDraggedItem(
+ LauncherInstrumentation launcher, Launchable launchable, String expectedNewPackageName,
+ Point endPoint, long downTime, Point itemVisibleCenter, Rect itemVisibleBounds,
+ String itemLabel, String expectedExistingPackageName) {
+ LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen before drop "
+ + itemVisibleCenter + " in " + itemVisibleBounds);
+
+ launchable.executeAndWaitForWindowChange(() -> {
+ launcher.sendPointer(
+ downTime,
+ SystemClock.uptimeMillis(),
+ MotionEvent.ACTION_UP,
+ endPoint,
+ LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER);
+ LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: after "
+ + "drop");
+ }, itemLabel, "dropping taskbar item");
+
+ try (LauncherInstrumentation.Closable c = launcher.addContextLayer("dropped item")) {
+ launchable.assertAppLaunched(itemLabel, By.pkg(expectedNewPackageName));
+ launcher.checkPackagesVisible(
+ new String[] {expectedNewPackageName, expectedExistingPackageName});
+ }
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 631e8f1..afb4f8d 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;
@@ -83,6 +84,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
@@ -90,6 +92,7 @@
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* The main tapl object. The only object that can be explicitly constructed by the using code. It
@@ -98,18 +101,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 +125,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 +172,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 +227,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 +304,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 +319,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 +355,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 +404,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 +437,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());
@@ -484,18 +501,31 @@
}
}
+ void checkPackagesVisible(String[] expectedVisiblePackages) {
+ Set<String> actualVisiblePackages =
+ getVisiblePackagesStream().collect(Collectors.toSet());
+
+ for (String expectedVisible : expectedVisiblePackages) {
+ assertTrue("Expected package not visible: " + expectedVisible,
+ actualVisiblePackages.contains(expectedVisible));
+ }
+ }
+
private String getVisiblePackages() {
- final String apps = mDevice.findObjects(getAnyObjectSelector())
- .stream()
- .map(LauncherInstrumentation::getApplicationPackageSafe)
- .distinct()
- .filter(pkg -> pkg != null && !SYSTEMUI_PACKAGE.equals(pkg))
- .collect(Collectors.joining(", "));
+ final String apps = getVisiblePackagesStream().collect(Collectors.joining(", "));
return !apps.isEmpty()
? "active app: " + apps
: "the test doesn't see views from any app, including Launcher";
}
+ private Stream<String> getVisiblePackagesStream() {
+ return mDevice.findObjects(getAnyObjectSelector())
+ .stream()
+ .map(LauncherInstrumentation::getApplicationPackageSafe)
+ .distinct()
+ .filter(pkg -> pkg != null && !SYSTEMUI_PACKAGE.equals(pkg));
+ }
+
private static String getApplicationPackageSafe(UiObject2 object) {
try {
return object.getApplicationPackage();
@@ -511,7 +541,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 +733,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 +857,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 +875,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 +904,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 +925,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 +934,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 +965,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 +1013,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 +1057,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 +1157,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 +1330,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 +1342,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 +1372,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 +1454,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,
@@ -1451,7 +1505,8 @@
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) {
@@ -1466,14 +1521,18 @@
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);
+ 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;
}
@@ -1596,9 +1655,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 +1702,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 +1841,4 @@
return ResourceUtils.getBoolByName(
"config_supportsRoundedCornersOnWindows", resources, false);
}
-}
\ No newline at end of file
+}
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/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..fee4490 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,10 +33,14 @@
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.function.Supplier;
@@ -49,6 +55,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 +63,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 +78,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 +88,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,7 +105,7 @@
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
"swiped to all apps")) {
- return new AllApps(mLauncher);
+ return new HomeAllApps(mLauncher);
}
}
}
@@ -110,13 +117,13 @@
* @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 +135,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 +172,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 +217,37 @@
}
@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.
+ * Get the center point of the delete/uninstall icon in the drop target bar.
*/
- private Point getDeleteDropPoint() {
- return mLauncher.waitForObjectInContainer(
- mLauncher.waitForLauncherObject(DROP_BAR_RES_ID),
- DELETE_TARGET_TEXT_ID).getVisibleCenter();
+ 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 +257,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 +328,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,59 +344,79 @@
}
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,
+ () -> 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) {
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;
// Since the destination can be on another page, we need to drag to the edge first
// until we reach the target page
while (targetDest.x > displayX || targetDest.x < 0) {
- int edgeX = targetDest.x > 0 ? displayX : 0;
+ // TODO: b/219919285
+ int edgeX = targetDest.x > 0 ? displayX - 1 : 1;
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;
}
// 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);
+ launcher.movePointer(dragStart, targetDest, DEFAULT_DRAG_STEPS, true,
+ 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 +493,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();
+}