summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-01-07 02:20:53 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-01-07 02:20:53 +0000
commitb0e0f22f629857555e40e7a2d47b8a5536321909 (patch)
treea039eb7a444c66fd6452dd24519742bc0df0fc8c
parente8b6677f888afd363d166a9364765afe0e151f1e (diff)
parentc956023fe65b8deaf126b14aafa8541572b0a404 (diff)
downloadbase-b0e0f22f629857555e40e7a2d47b8a5536321909.tar.gz
Snap for 9463735 from c956023fe65b8deaf126b14aafa8541572b0a404 to tm-qpr2-release
Change-Id: I1b1f0cbb1eed5c29db6b3ce12a6774bcdbe0568b
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java35
-rw-r--r--core/java/android/view/WindowManagerPolicyConstants.java3
-rw-r--r--core/java/android/window/ImeOnBackInvokedDispatcher.java6
-rw-r--r--core/res/res/values-cs/strings.xml2
-rw-r--r--core/res/res/values-de/strings.xml4
-rw-r--r--core/res/res/values-fi/strings.xml16
-rw-r--r--core/res/res/values-sv/strings.xml2
-rw-r--r--core/res/res/values-te/strings.xml2
-rw-r--r--core/res/res/values/config.xml8
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java67
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java18
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java11
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java57
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java5
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java5
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java19
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java3
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldAnimationControllerTest.java10
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt7
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt100
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt15
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt192
-rw-r--r--packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java10
-rw-r--r--packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml5
-rw-r--r--packages/SystemUI/res-keyguard/drawable/unlocked_to_locked.xml145
-rw-r--r--packages/SystemUI/res/values-af/strings.xml2
-rw-r--r--packages/SystemUI/res/values-am/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml5
-rw-r--r--packages/SystemUI/res/values-as/strings.xml2
-rw-r--r--packages/SystemUI/res/values-az/strings.xml2
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml2
-rw-r--r--packages/SystemUI/res/values-be/strings.xml5
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml2
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml2
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml2
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml2
-rw-r--r--packages/SystemUI/res/values-da/strings.xml2
-rw-r--r--packages/SystemUI/res/values-de/strings.xml2
-rw-r--r--packages/SystemUI/res/values-el/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml2
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml2
-rw-r--r--packages/SystemUI/res/values-es/strings.xml2
-rw-r--r--packages/SystemUI/res/values-et/strings.xml2
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml2
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml2
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml4
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml2
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml2
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml2
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml2
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml2
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml2
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml2
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml2
-rw-r--r--packages/SystemUI/res/values-in/strings.xml2
-rw-r--r--packages/SystemUI/res/values-is/strings.xml2
-rw-r--r--packages/SystemUI/res/values-it/strings.xml2
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml2
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml2
-rw-r--r--packages/SystemUI/res/values-km/strings.xml2
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml2
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml2
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml2
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml5
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml2
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml2
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml2
-rw-r--r--packages/SystemUI/res/values-my/strings.xml2
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml2
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml2
-rw-r--r--packages/SystemUI/res/values-or/strings.xml5
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml2
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml2
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml2
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml2
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml2
-rw-r--r--packages/SystemUI/res/values-si/strings.xml5
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml5
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml2
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml5
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml2
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml5
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml2
-rw-r--r--packages/SystemUI/res/values-te/strings.xml2
-rw-r--r--packages/SystemUI/res/values-th/strings.xml2
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml2
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml5
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml2
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml2
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml2
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml2
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml2
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml2
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/LockIconViewController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java57
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt79
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java74
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt113
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt65
-rw-r--r--services/core/java/com/android/server/notification/SnoozeHelper.java14
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java7
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java42
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java1
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java36
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicy.java161
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfiguration.java61
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java120
-rw-r--r--services/core/java/com/android/server/wm/TaskFragment.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java15
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java41
-rw-r--r--services/tests/wmtests/Android.bp4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicyTests.java225
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationDeviceConfigTests.java109
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java73
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java3
147 files changed, 2064 insertions, 323 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 8e09939f6805..4a4ba6371939 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1128,6 +1128,9 @@ public class DevicePolicyManager {
* <p>Use only for device owner provisioning. This extra can be returned by the admin app when
* performing the admin-integrated provisioning flow as a result of the {@link
* #ACTION_GET_PROVISIONING_MODE} activity.
+ *
+ * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*/
public static final String EXTRA_PROVISIONING_TIME_ZONE
= "android.app.extra.PROVISIONING_TIME_ZONE";
@@ -1139,6 +1142,9 @@ public class DevicePolicyManager {
* <p>Use only for device owner provisioning. This extra can be returned by the admin app when
* performing the admin-integrated provisioning flow as a result of the {@link
* #ACTION_GET_PROVISIONING_MODE} activity.
+ *
+ * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*/
public static final String EXTRA_PROVISIONING_LOCAL_TIME
= "android.app.extra.PROVISIONING_LOCAL_TIME";
@@ -1150,6 +1156,9 @@ public class DevicePolicyManager {
* <p>Use only for device owner provisioning. This extra can be returned by the admin app when
* performing the admin-integrated provisioning flow as a result of the {@link
* #ACTION_GET_PROVISIONING_MODE} activity.
+ *
+ * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*/
public static final String EXTRA_PROVISIONING_LOCALE
= "android.app.extra.PROVISIONING_LOCALE";
@@ -1159,7 +1168,7 @@ public class DevicePolicyManager {
* owner provisioning for downloading the mobile device management application.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*/
public static final String EXTRA_PROVISIONING_WIFI_SSID
= "android.app.extra.PROVISIONING_WIFI_SSID";
@@ -1169,7 +1178,7 @@ public class DevicePolicyManager {
* is hidden or not.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*/
public static final String EXTRA_PROVISIONING_WIFI_HIDDEN
= "android.app.extra.PROVISIONING_WIFI_HIDDEN";
@@ -1180,7 +1189,7 @@ public class DevicePolicyManager {
* {@code WEP} or {@code EAP}.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*/
public static final String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE
= "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE";
@@ -1190,7 +1199,7 @@ public class DevicePolicyManager {
* {@link #EXTRA_PROVISIONING_WIFI_SSID}.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*/
public static final String EXTRA_PROVISIONING_WIFI_PASSWORD =
"android.app.extra.PROVISIONING_WIFI_PASSWORD";
@@ -1281,7 +1290,7 @@ public class DevicePolicyManager {
* {@link #EXTRA_PROVISIONING_WIFI_SSID}.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*/
public static final String EXTRA_PROVISIONING_WIFI_PROXY_HOST
= "android.app.extra.PROVISIONING_WIFI_PROXY_HOST";
@@ -1291,7 +1300,7 @@ public class DevicePolicyManager {
* {@link #EXTRA_PROVISIONING_WIFI_SSID}.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*/
public static final String EXTRA_PROVISIONING_WIFI_PROXY_PORT
= "android.app.extra.PROVISIONING_WIFI_PROXY_PORT";
@@ -1301,7 +1310,7 @@ public class DevicePolicyManager {
* {@link #EXTRA_PROVISIONING_WIFI_SSID}.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*/
public static final String EXTRA_PROVISIONING_WIFI_PROXY_BYPASS
= "android.app.extra.PROVISIONING_WIFI_PROXY_BYPASS";
@@ -1311,7 +1320,7 @@ public class DevicePolicyManager {
* {@link #EXTRA_PROVISIONING_WIFI_SSID}.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*/
public static final String EXTRA_PROVISIONING_WIFI_PAC_URL
= "android.app.extra.PROVISIONING_WIFI_PAC_URL";
@@ -1321,7 +1330,7 @@ public class DevicePolicyManager {
* package. When not provided it is assumed that the device admin package is already installed.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION
= "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
@@ -1401,7 +1410,7 @@ public class DevicePolicyManager {
* installed package is less than this version code.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE
= "android.app.extra.PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE";
@@ -1411,7 +1420,7 @@ public class DevicePolicyManager {
* url specified in {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER
= "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
@@ -1426,7 +1435,7 @@ public class DevicePolicyManager {
* be asked to factory reset the device.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*
* <p><strong>Note:</strong> for devices running {@link android.os.Build.VERSION_CODES#LOLLIPOP}
* and {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} only SHA-1 hash is supported.
@@ -1472,7 +1481,7 @@ public class DevicePolicyManager {
* the user will be asked to factory reset the device.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * provisioning via an NFC bump. It can also be used for QR code provisioning.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM
= "android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM";
diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java
index 43d427db2c75..4c49f2c049ee 100644
--- a/core/java/android/view/WindowManagerPolicyConstants.java
+++ b/core/java/android/view/WindowManagerPolicyConstants.java
@@ -169,6 +169,9 @@ public interface WindowManagerPolicyConstants {
case PowerManager.WAKE_REASON_POWER_BUTTON:
case PowerManager.WAKE_REASON_PLUGGED_IN:
case PowerManager.WAKE_REASON_GESTURE:
+ case PowerManager.WAKE_REASON_TAP:
+ case PowerManager.WAKE_REASON_LIFT:
+ case PowerManager.WAKE_REASON_BIOMETRIC:
case PowerManager.WAKE_REASON_CAMERA_LAUNCH:
case PowerManager.WAKE_REASON_WAKE_KEY:
case PowerManager.WAKE_REASON_WAKE_MOTION:
diff --git a/core/java/android/window/ImeOnBackInvokedDispatcher.java b/core/java/android/window/ImeOnBackInvokedDispatcher.java
index 9152e7837b82..a0bd7f70ca58 100644
--- a/core/java/android/window/ImeOnBackInvokedDispatcher.java
+++ b/core/java/android/window/ImeOnBackInvokedDispatcher.java
@@ -220,16 +220,14 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc
* @param previous the previously focused {@link ViewRootImpl}.
* @param current the currently focused {@link ViewRootImpl}.
*/
- // TODO(b/232845902): Add CTS to test IME back behavior when there's root view change while
- // IME is up.
public void switchRootView(ViewRootImpl previous, ViewRootImpl current) {
for (ImeOnBackInvokedCallback imeCallback : mImeCallbacks) {
if (previous != null) {
previous.getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(imeCallback);
}
if (current != null) {
- current.getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
- imeCallback.mPriority, imeCallback);
+ current.getOnBackInvokedDispatcher().registerOnBackInvokedCallbackUnchecked(
+ imeCallback, imeCallback.mPriority);
}
}
}
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index eece25d707c5..ea61feaab93a 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -327,7 +327,7 @@
<string name="permgrouplab_phone" msgid="570318944091926620">"Telefon"</string>
<string name="permgroupdesc_phone" msgid="270048070781478204">"uskutečňování a spravování telefonních hovorů"</string>
<string name="permgrouplab_sensors" msgid="9134046949784064495">"Tělesné senzory"</string>
- <string name="permgroupdesc_sensors" msgid="2610631290633747752">"přístup k datům ze snímačů vašich životních funkcí"</string>
+ <string name="permgroupdesc_sensors" msgid="2610631290633747752">"přístup k datům ze senzorů vašich životních funkcí"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Oznámení"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"zobrazovat oznámení"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Načítat obsah oken"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 64d390e093f1..876d3a17aae3 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1681,13 +1681,13 @@
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Verknüpfung für Bedienungshilfen aktivieren?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Wenn du beide Lautstärketasten einige Sekunden lang gedrückt hältst, aktivierst du die Bedienungshilfen. Dadurch kann sich die Funktionsweise deines Geräts ändern.\n\nAktuelle Funktionen:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nDu kannst ausgewählte Funktionen unter \"Einstellungen\" &gt; \"Bedienungshilfen\" ändern."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
- <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Verknüpfung für <xliff:g id="SERVICE">%1$s</xliff:g> aktivieren?"</string>
+ <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Kurzbefehl für <xliff:g id="SERVICE">%1$s</xliff:g> aktivieren?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Wenn du beide Lautstärketasten einige Sekunden lang gedrückt hältst, aktivierst du die Bedienungshilfe \"<xliff:g id="SERVICE">%1$s</xliff:g>\". Dadurch kann sich die Funktionsweise deines Geräts ändern.\n\nUnter \"Einstellungen &gt; \"Bedienungshilfen\" kannst du dieser Verknüpfung eine andere Funktion zuweisen."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktivieren"</string>
<string name="accessibility_shortcut_off" msgid="3651336255403648739">"Nicht aktivieren"</string>
<string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"AN"</string>
<string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"AUS"</string>
- <string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g> die vollständige Kontrolle über dein Gerät geben?"</string>
+ <string name="accessibility_enable_service_title" msgid="3931558336268541484">"„<xliff:g id="SERVICE">%1$s</xliff:g>“ die vollständige Kontrolle über dein Gerät geben?"</string>
<string name="accessibility_service_warning_description" msgid="291674995220940133">"Die vollständige Kontrolle sollte nur für Apps aktiviert werden, die dir Zugang zu App-Funktionen erleichtern. Das ist in der Regel nur ein kleiner Teil der Apps."</string>
<string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Bildschirm aufrufen und steuern"</string>
<string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Die Funktion kann alle Inhalte auf dem Bildschirm lesen und diese Inhalte über andere Apps anzeigen."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index c4fe972a0b26..c81bf0034a60 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -299,11 +299,11 @@
<string name="user_owner_label" msgid="8628726904184471211">"Vaihda henkilökohtaiseen profiiliin"</string>
<string name="managed_profile_label" msgid="7316778766973512382">"Vaihda työprofiiliin"</string>
<string name="permgrouplab_contacts" msgid="4254143639307316920">"Yhteystiedot"</string>
- <string name="permgroupdesc_contacts" msgid="9163927941244182567">"käyttää yhteystietoja"</string>
+ <string name="permgroupdesc_contacts" msgid="9163927941244182567">"pääsy yhteystietoihin"</string>
<string name="permgrouplab_location" msgid="1858277002233964394">"Sijainti"</string>
- <string name="permgroupdesc_location" msgid="1995955142118450685">"käyttää laitteen sijaintia"</string>
+ <string name="permgroupdesc_location" msgid="1995955142118450685">"pääsy laitteen sijaintiin"</string>
<string name="permgrouplab_calendar" msgid="6426860926123033230">"Kalenteri"</string>
- <string name="permgroupdesc_calendar" msgid="6762751063361489379">"käyttää kalenteria"</string>
+ <string name="permgroupdesc_calendar" msgid="6762751063361489379">"pääsy kalenteriin"</string>
<string name="permgrouplab_sms" msgid="795737735126084874">"Tekstiviestit"</string>
<string name="permgroupdesc_sms" msgid="5726462398070064542">"lähettää ja tarkastella tekstiviestejä"</string>
<string name="permgrouplab_storage" msgid="17339216290379241">"Tiedostot"</string>
@@ -313,7 +313,7 @@
<string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"Valokuvat ja videot"</string>
<string name="permgroupdesc_readMediaVisual" msgid="4080463241903508688">"pääsy laitteen kuviin ja videoihin"</string>
<string name="permgrouplab_microphone" msgid="2480597427667420076">"Mikrofoni"</string>
- <string name="permgroupdesc_microphone" msgid="1047786732792487722">"tallentaa ääntä"</string>
+ <string name="permgroupdesc_microphone" msgid="1047786732792487722">"tallentaa audiota"</string>
<string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"Liikkuminen"</string>
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"nähdä liikkumistietosi"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
@@ -325,7 +325,7 @@
<string name="permgrouplab_phone" msgid="570318944091926620">"Puhelin"</string>
<string name="permgroupdesc_phone" msgid="270048070781478204">"soittaa ja hallinnoida puheluita"</string>
<string name="permgrouplab_sensors" msgid="9134046949784064495">"Kehon anturit"</string>
- <string name="permgroupdesc_sensors" msgid="2610631290633747752">"käyttää anturitietoja elintoiminnoistasi"</string>
+ <string name="permgroupdesc_sensors" msgid="2610631290633747752">"pääsy anturidataan elintoiminnoistasi"</string>
<string name="permgrouplab_notifications" msgid="5472972361980668884">"Ilmoitukset"</string>
<string name="permgroupdesc_notifications" msgid="4608679556801506580">"näyttää ilmoituksia"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Noutaa ikkunan sisältöä"</string>
@@ -448,7 +448,7 @@
<string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"Tällä sovelluksella on pääsy sijaintitietoihin milloin tahansa, myös silloin kun sovellusta ei käytetä."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"muuta ääniasetuksia"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Antaa sovelluksen muokata yleisiä ääniasetuksia, kuten äänenvoimakkuutta ja käytettävää kaiutinta."</string>
- <string name="permlab_recordAudio" msgid="1208457423054219147">"tallentaa ääntä"</string>
+ <string name="permlab_recordAudio" msgid="1208457423054219147">"tallentaa audiota"</string>
<string name="permdesc_recordAudio" msgid="5857246765327514062">"Tämä sovellus voi tallentaa mikrofonilla audiota, kun sovellusta käytetään."</string>
<string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"tallentaa audiota taustalla"</string>
<string name="permdesc_recordBackgroundAudio" msgid="1992623135737407516">"Tämä sovellus voi tallentaa mikrofonilla audiota koska tahansa."</string>
@@ -1173,7 +1173,7 @@
<string name="selected" msgid="6614607926197755875">"valittu"</string>
<string name="not_selected" msgid="410652016565864475">"ei valittu"</string>
<string name="in_progress" msgid="2149208189184319441">"käynnissä"</string>
- <string name="whichApplication" msgid="5432266899591255759">"Tee toiminto käyttäen sovellusta"</string>
+ <string name="whichApplication" msgid="5432266899591255759">"Tee toiminto käyttäen:"</string>
<string name="whichApplicationNamed" msgid="6969946041713975681">"Suorita sovelluksella %1$s"</string>
<string name="whichApplicationLabel" msgid="7852182961472531728">"Suorita toiminto"</string>
<string name="whichViewApplication" msgid="5733194231473132945">"Avaa sovelluksessa"</string>
@@ -1972,7 +1972,7 @@
<string name="pin_specific_target" msgid="7824671240625957415">"Kiinnitä <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Irrota"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"Irrota <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="app_info" msgid="6113278084877079851">"Sovelluksen tiedot"</string>
+ <string name="app_info" msgid="6113278084877079851">"Sovellustiedot"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Aloitetaan esittelyä…"</string>
<string name="demo_restarting_message" msgid="1160053183701746766">"Palautetaan asetuksia…"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 12015ec6d85f..fb9a3132debe 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1173,7 +1173,7 @@
<string name="selected" msgid="6614607926197755875">"valt"</string>
<string name="not_selected" msgid="410652016565864475">"inte valt"</string>
<string name="in_progress" msgid="2149208189184319441">"pågår"</string>
- <string name="whichApplication" msgid="5432266899591255759">"Slutför åtgärd genom att använda"</string>
+ <string name="whichApplication" msgid="5432266899591255759">"Slutför åtgärd med"</string>
<string name="whichApplicationNamed" msgid="6969946041713975681">"Slutför åtgärden med %1$s"</string>
<string name="whichApplicationLabel" msgid="7852182961472531728">"Slutför åtgärd"</string>
<string name="whichViewApplication" msgid="5733194231473132945">"Öppna med"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index f52b714b9563..7cebe2729adb 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -315,7 +315,7 @@
<string name="permgrouplab_microphone" msgid="2480597427667420076">"మైక్రోఫోన్"</string>
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"ఆడియోను రికార్డ్ చేయడానికి"</string>
<string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"ఫిజికల్ యాక్టివిటీ"</string>
- <string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"భౌతిక యాక్టివిటీని యాక్సెస్ చేయండి"</string>
+ <string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ఫిజికల్ యాక్టివిటీని యాక్సెస్ చేయండి"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"కెమెరా"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"చిత్రాలను తీయడానికి మరియు వీడియోను రికార్డ్ చేయడానికి"</string>
<string name="permgrouplab_nearby_devices" msgid="5529147543651181991">"సమీపంలోని పరికరాలు"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f7187c466799..2f5efd12a2ba 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -5213,6 +5213,14 @@
having a separating hinge. -->
<bool name="config_isDisplayHingeAlwaysSeparating">false</bool>
+ <!-- Whether enabling rotation compat policy for immersive apps that prevents auto rotation
+ into non-optimal screen orientation while in fullscreen. This is needed because immersive
+ apps, such as games, are often not optimized for all orientations and can have a poor UX
+ when rotated. Additionally, some games rely on sensors for the gameplay so users can
+ trigger such rotations accidentally when auto rotation is on.
+ Applicable only if ignoreOrientationRequest is enabled. -->
+ <bool name="config_letterboxIsDisplayRotationImmersiveAppCompatPolicyEnabled">false</bool>
+
<!-- Aspect ratio of letterboxing for fixed orientation. Values <= 1.0 will be ignored.
Note: Activity min/max aspect ratio restrictions will still be respected.
Therefore this override can control the maximum screen area that can be occupied by
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 368ef960f938..41281fa0d40f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4441,6 +4441,7 @@
<java-symbol type="dimen" name="controls_thumbnail_image_max_height" />
<java-symbol type="dimen" name="controls_thumbnail_image_max_width" />
+ <java-symbol type="bool" name="config_letterboxIsDisplayRotationImmersiveAppCompatPolicyEnabled" />
<java-symbol type="dimen" name="config_fixedOrientationLetterboxAspectRatio" />
<java-symbol type="dimen" name="config_letterboxBackgroundWallpaperBlurRadius" />
<java-symbol type="integer" name="config_letterboxActivityCornersRadius" />
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
index fb0a9db6a20b..54edd9ec4335 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
@@ -17,9 +17,13 @@
package androidx.window.extensions;
import android.app.ActivityThread;
+import android.app.Application;
import android.content.Context;
+import android.window.TaskFragmentOrganizer;
import androidx.annotation.NonNull;
+import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
+import androidx.window.common.RawFoldingFeatureProducer;
import androidx.window.extensions.area.WindowAreaComponent;
import androidx.window.extensions.area.WindowAreaComponentImpl;
import androidx.window.extensions.embedding.ActivityEmbeddingComponent;
@@ -27,6 +31,8 @@ import androidx.window.extensions.embedding.SplitController;
import androidx.window.extensions.layout.WindowLayoutComponent;
import androidx.window.extensions.layout.WindowLayoutComponentImpl;
+import java.util.Objects;
+
/**
* The reference implementation of {@link WindowExtensions} that implements the initial API version.
@@ -34,7 +40,8 @@ import androidx.window.extensions.layout.WindowLayoutComponentImpl;
public class WindowExtensionsImpl implements WindowExtensions {
private final Object mLock = new Object();
- private volatile WindowLayoutComponent mWindowLayoutComponent;
+ private volatile DeviceStateManagerFoldingFeatureProducer mFoldingFeatureProducer;
+ private volatile WindowLayoutComponentImpl mWindowLayoutComponent;
private volatile SplitController mSplitController;
private volatile WindowAreaComponent mWindowAreaComponent;
@@ -44,6 +51,49 @@ public class WindowExtensionsImpl implements WindowExtensions {
return 1;
}
+ @NonNull
+ private Application getApplication() {
+ return Objects.requireNonNull(ActivityThread.currentApplication());
+ }
+
+ @NonNull
+ private DeviceStateManagerFoldingFeatureProducer getFoldingFeatureProducer() {
+ if (mFoldingFeatureProducer == null) {
+ synchronized (mLock) {
+ if (mFoldingFeatureProducer == null) {
+ Context context = getApplication();
+ RawFoldingFeatureProducer foldingFeatureProducer =
+ new RawFoldingFeatureProducer(context);
+ mFoldingFeatureProducer =
+ new DeviceStateManagerFoldingFeatureProducer(context,
+ foldingFeatureProducer);
+ }
+ }
+ }
+ return mFoldingFeatureProducer;
+ }
+
+ @NonNull
+ private WindowLayoutComponentImpl getWindowLayoutComponentImpl() {
+ if (mWindowLayoutComponent == null) {
+ synchronized (mLock) {
+ if (mWindowLayoutComponent == null) {
+ Context context = getApplication();
+ DeviceStateManagerFoldingFeatureProducer producer =
+ getFoldingFeatureProducer();
+ // TODO(b/263263909) Use the organizer to tell if an Activity is embededed.
+ // Need to improve our Dependency Injection and centralize the logic.
+ TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(command -> {
+ throw new RuntimeException("Not allowed!");
+ });
+ mWindowLayoutComponent = new WindowLayoutComponentImpl(context, organizer,
+ producer);
+ }
+ }
+ }
+ return mWindowLayoutComponent;
+ }
+
/**
* Returns a reference implementation of {@link WindowLayoutComponent} if available,
* {@code null} otherwise. The implementation must match the API level reported in
@@ -52,15 +102,7 @@ public class WindowExtensionsImpl implements WindowExtensions {
*/
@Override
public WindowLayoutComponent getWindowLayoutComponent() {
- if (mWindowLayoutComponent == null) {
- synchronized (mLock) {
- if (mWindowLayoutComponent == null) {
- Context context = ActivityThread.currentApplication();
- mWindowLayoutComponent = new WindowLayoutComponentImpl(context);
- }
- }
- }
- return mWindowLayoutComponent;
+ return getWindowLayoutComponentImpl();
}
/**
@@ -74,7 +116,10 @@ public class WindowExtensionsImpl implements WindowExtensions {
if (mSplitController == null) {
synchronized (mLock) {
if (mSplitController == null) {
- mSplitController = new SplitController();
+ mSplitController = new SplitController(
+ getWindowLayoutComponentImpl(),
+ getFoldingFeatureProducer()
+ );
}
}
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 8da591860c2d..1cd3ea5592e3 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -75,8 +75,8 @@ import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.window.common.CommonFoldingFeature;
+import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
-import androidx.window.extensions.WindowExtensionsProvider;
import androidx.window.extensions.embedding.TransactionManager.TransactionRecord;
import androidx.window.extensions.layout.WindowLayoutComponentImpl;
@@ -145,19 +145,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
private final Handler mHandler;
final Object mLock = new Object();
private final ActivityStartMonitor mActivityStartMonitor;
- @NonNull
- final WindowLayoutComponentImpl mWindowLayoutComponent;
-
- public SplitController() {
- this((WindowLayoutComponentImpl) Objects.requireNonNull(WindowExtensionsProvider
- .getWindowExtensions().getWindowLayoutComponent()));
- }
- @VisibleForTesting
- SplitController(@NonNull WindowLayoutComponentImpl windowLayoutComponent) {
+ public SplitController(@NonNull WindowLayoutComponentImpl windowLayoutComponent,
+ @NonNull DeviceStateManagerFoldingFeatureProducer foldingFeatureProducer) {
final MainThreadExecutor executor = new MainThreadExecutor();
mHandler = executor.mHandler;
- mPresenter = new SplitPresenter(executor, this);
+ mPresenter = new SplitPresenter(executor, windowLayoutComponent, this);
mTransactionManager = new TransactionManager(mPresenter);
final ActivityThread activityThread = ActivityThread.currentActivityThread();
final Application application = activityThread.getApplication();
@@ -168,8 +161,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
mActivityStartMonitor = new ActivityStartMonitor();
instrumentation.addMonitor(mActivityStartMonitor);
- mWindowLayoutComponent = windowLayoutComponent;
- mWindowLayoutComponent.addFoldingStateChangedCallback(new FoldingFeatureListener());
+ foldingFeatureProducer.addDataChangedCallback(new FoldingFeatureListener());
}
private class FoldingFeatureListener implements Consumer<List<CommonFoldingFeature>> {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index 7b2af4933e66..14d244bbb6ce 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -51,6 +51,7 @@ import androidx.window.extensions.embedding.SplitAttributesCalculator.SplitAttri
import androidx.window.extensions.embedding.TaskContainer.TaskProperties;
import androidx.window.extensions.layout.DisplayFeature;
import androidx.window.extensions.layout.FoldingFeature;
+import androidx.window.extensions.layout.WindowLayoutComponentImpl;
import androidx.window.extensions.layout.WindowLayoutInfo;
import com.android.internal.annotations.VisibleForTesting;
@@ -137,10 +138,14 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
.setSplitType(new ExpandContainersSplitType())
.build();
+ private final WindowLayoutComponentImpl mWindowLayoutComponent;
private final SplitController mController;
- SplitPresenter(@NonNull Executor executor, @NonNull SplitController controller) {
+ SplitPresenter(@NonNull Executor executor,
+ @NonNull WindowLayoutComponentImpl windowLayoutComponent,
+ @NonNull SplitController controller) {
super(executor, controller);
+ mWindowLayoutComponent = windowLayoutComponent;
mController = controller;
registerOrganizer();
if (!SplitController.ENABLE_SHELL_TRANSITIONS) {
@@ -556,7 +561,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
return sanitizeSplitAttributes(taskProperties, defaultSplitAttributes,
minDimensionsPair);
}
- final WindowLayoutInfo windowLayoutInfo = mController.mWindowLayoutComponent
+ final WindowLayoutInfo windowLayoutInfo = mWindowLayoutComponent
.getCurrentWindowLayoutInfo(taskProperties.getDisplayId(),
taskConfiguration.windowConfiguration);
final SplitAttributesCalculatorParams params = new SplitAttributesCalculatorParams(
@@ -838,7 +843,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
final int displayId = taskProperties.getDisplayId();
final WindowConfiguration windowConfiguration = taskProperties.getConfiguration()
.windowConfiguration;
- final WindowLayoutInfo info = mController.mWindowLayoutComponent
+ final WindowLayoutInfo info = mWindowLayoutComponent
.getCurrentWindowLayoutInfo(displayId, windowConfiguration);
final List<DisplayFeature> displayFeatures = info.getDisplayFeatures();
if (displayFeatures.isEmpty()) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
index 84b2bfc38559..c9f870005eb9 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
@@ -35,6 +35,8 @@ import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
import android.util.ArrayMap;
+import android.view.WindowManager;
+import android.window.TaskFragmentOrganizer;
import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
@@ -43,13 +45,13 @@ import androidx.annotation.UiContext;
import androidx.window.common.CommonFoldingFeature;
import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
import androidx.window.common.EmptyLifecycleCallbacksAdapter;
-import androidx.window.common.RawFoldingFeatureProducer;
import androidx.window.util.DataProducer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
@@ -80,13 +82,16 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
private final Map<IBinder, ConfigurationChangeListener> mConfigurationChangeListeners =
new ArrayMap<>();
- public WindowLayoutComponentImpl(@NonNull Context context) {
+ private final TaskFragmentOrganizer mTaskFragmentOrganizer;
+
+ public WindowLayoutComponentImpl(@NonNull Context context,
+ @NonNull TaskFragmentOrganizer taskFragmentOrganizer,
+ @NonNull DeviceStateManagerFoldingFeatureProducer foldingFeatureProducer) {
((Application) context.getApplicationContext())
.registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged());
- RawFoldingFeatureProducer foldingFeatureProducer = new RawFoldingFeatureProducer(context);
- mFoldingFeatureProducer = new DeviceStateManagerFoldingFeatureProducer(context,
- foldingFeatureProducer);
+ mFoldingFeatureProducer = foldingFeatureProducer;
mFoldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged);
+ mTaskFragmentOrganizer = taskFragmentOrganizer;
}
/** Registers to listen to {@link CommonFoldingFeature} changes */
@@ -182,7 +187,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
@GuardedBy("mLock")
private boolean isListeningForLayoutChanges(IBinder token) {
- for (Context context: getContextsListeningForLayoutChanges()) {
+ for (Context context : getContextsListeningForLayoutChanges()) {
if (token.equals(Context.getToken(context))) {
return true;
}
@@ -230,8 +235,9 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
/**
* Translates the {@link DisplayFeature} into a {@link WindowLayoutInfo} when a
* valid state is found.
+ *
* @param context a proxy for the {@link android.view.Window} that contains the
- * {@link DisplayFeature}.
+ * {@link DisplayFeature}.
*/
private WindowLayoutInfo getWindowLayoutInfo(@NonNull @UiContext Context context,
List<CommonFoldingFeature> storedFeatures) {
@@ -243,7 +249,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
* Gets the current {@link WindowLayoutInfo} computed with passed {@link WindowConfiguration}.
*
* @return current {@link WindowLayoutInfo} on the default display. Returns
- * empty {@link WindowLayoutInfo} on secondary displays.
+ * empty {@link WindowLayoutInfo} on secondary displays.
*/
@NonNull
public WindowLayoutInfo getCurrentWindowLayoutInfo(int displayId,
@@ -254,7 +260,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
}
}
- /** @see #getWindowLayoutInfo(Context, List) */
+ /** @see #getWindowLayoutInfo(Context, List) */
private WindowLayoutInfo getWindowLayoutInfo(int displayId,
@NonNull WindowConfiguration windowConfiguration,
List<CommonFoldingFeature> storedFeatures) {
@@ -278,7 +284,8 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
*
* @param context a proxy for the {@link android.view.Window} that contains the
* {@link DisplayFeature}.
- * are within the {@link android.view.Window} of the {@link Activity}
+ * @return a {@link List} of {@link DisplayFeature}s that are within the
+ * {@link android.view.Window} of the {@link Activity}
*/
private List<DisplayFeature> getDisplayFeatures(
@NonNull @UiContext Context context, List<CommonFoldingFeature> storedFeatures) {
@@ -317,8 +324,11 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
}
/**
- * Checks whether display features should be reported for the activity.
+ * Calculates if the display features should be reported for the UI Context. The calculation
+ * uses the task information because that is accurate for Activities in ActivityEmbedding mode.
* TODO(b/238948678): Support reporting display features in all windowing modes.
+ *
+ * @return true if the display features should be reported for the UI Context, false otherwise.
*/
private boolean shouldReportDisplayFeatures(@NonNull @UiContext Context context) {
int displayId = context.getDisplay().getDisplayId();
@@ -337,7 +347,27 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
// bounds in this case can't be computed correctly, so we should skip.
return false;
}
- windowingMode = taskConfig.windowConfiguration.getWindowingMode();
+ final Rect taskBounds = taskConfig.windowConfiguration.getBounds();
+ final WindowManager windowManager = Objects.requireNonNull(
+ context.getSystemService(WindowManager.class));
+ final Rect currentBounds = windowManager.getCurrentWindowMetrics().getBounds();
+ final Rect maxBounds = windowManager.getMaximumWindowMetrics().getBounds();
+ boolean isTaskExpanded = maxBounds.equals(taskBounds);
+ boolean isActivityExpanded = maxBounds.equals(currentBounds);
+ /*
+ * We need to proxy being in full screen because when a user enters PiP and exits PiP
+ * the task windowingMode will report multi-window/pinned until the transition is
+ * finished in WM Shell.
+ * maxBounds == taskWindowBounds is a proxy check to verify the window is full screen
+ * For tasks that are letterboxed, we use currentBounds == maxBounds to filter these
+ * out.
+ */
+ // TODO(b/262900133) remove currentBounds check when letterboxed apps report bounds.
+ // currently we don't want to report to letterboxed apps since they do not update the
+ // window bounds when the Activity is moved. An inaccurate fold will be reported so
+ // we skip.
+ return isTaskExpanded && (isActivityExpanded
+ || mTaskFragmentOrganizer.isActivityEmbedded(activityToken));
} else {
// TODO(b/242674941): use task windowing mode for window context that associates with
// activity.
@@ -390,6 +420,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
}
@Override
- public void onLowMemory() {}
+ public void onLowMemory() {
+ }
}
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index 3cc31f9761c1..81c39571bffa 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -90,6 +90,7 @@ import android.window.WindowContainerTransaction;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
import androidx.window.extensions.layout.WindowLayoutComponentImpl;
import androidx.window.extensions.layout.WindowLayoutInfo;
@@ -142,7 +143,9 @@ public class SplitControllerTest {
MockitoAnnotations.initMocks(this);
doReturn(new WindowLayoutInfo(new ArrayList<>())).when(mWindowLayoutComponent)
.getCurrentWindowLayoutInfo(anyInt(), any());
- mSplitController = new SplitController(mWindowLayoutComponent);
+ DeviceStateManagerFoldingFeatureProducer producer =
+ mock(DeviceStateManagerFoldingFeatureProducer.class);
+ mSplitController = new SplitController(mWindowLayoutComponent, producer);
mSplitPresenter = mSplitController.mPresenter;
mSplitInfos = new ArrayList<>();
mEmbeddingCallback = splitInfos -> {
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
index fcd4d621e753..121e81394b2d 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
@@ -75,6 +75,7 @@ import android.window.WindowContainerTransaction;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
import androidx.window.extensions.layout.WindowLayoutComponentImpl;
import androidx.window.extensions.layout.WindowLayoutInfo;
@@ -117,7 +118,9 @@ public class SplitPresenterTest {
MockitoAnnotations.initMocks(this);
doReturn(new WindowLayoutInfo(new ArrayList<>())).when(mWindowLayoutComponent)
.getCurrentWindowLayoutInfo(anyInt(), any());
- mController = new SplitController(mWindowLayoutComponent);
+ DeviceStateManagerFoldingFeatureProducer producer =
+ mock(DeviceStateManagerFoldingFeatureProducer.class);
+ mController = new SplitController(mWindowLayoutComponent, producer);
mPresenter = mController.mPresenter;
spyOn(mController);
spyOn(mPresenter);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
index 98772360a321..7d9d8b0f3a06 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
@@ -45,6 +45,8 @@ import android.window.WindowContainerTransaction;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import androidx.window.common.DeviceStateManagerFoldingFeatureProducer;
+import androidx.window.extensions.layout.WindowLayoutComponentImpl;
import com.google.android.collect.Lists;
@@ -82,7 +84,10 @@ public class TaskFragmentContainerTest {
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mController = new SplitController();
+ DeviceStateManagerFoldingFeatureProducer producer =
+ mock(DeviceStateManagerFoldingFeatureProducer.class);
+ WindowLayoutComponentImpl component = mock(WindowLayoutComponentImpl.class);
+ mController = new SplitController(component, producer);
spyOn(mController);
mActivity = createMockActivity();
mIntent = new Intent();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
index 477bc955212b..95a89b1d23ff 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
@@ -224,16 +224,6 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
mObscuredTouchRegion = obscuredRegion;
}
- private void onLocationChanged(WindowContainerTransaction wct) {
- // Update based on the screen bounds
- getBoundsOnScreen(mTmpRect);
- getRootView().getBoundsOnScreen(mTmpRootRect);
- if (!mTmpRootRect.contains(mTmpRect)) {
- mTmpRect.offsetTo(0, 0);
- }
- wct.setBounds(mTaskToken, mTmpRect);
- }
-
/**
* Call when view position or size has changed. Do not call when animating.
*/
@@ -246,10 +236,15 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
if (isUsingShellTransitions() && mTaskViewTransitions.hasPending()) return;
WindowContainerTransaction wct = new WindowContainerTransaction();
- onLocationChanged(wct);
+ updateWindowBounds(wct);
mSyncQueue.queue(wct);
}
+ private void updateWindowBounds(WindowContainerTransaction wct) {
+ getBoundsOnScreen(mTmpRect);
+ wct.setBounds(mTaskToken, mTmpRect);
+ }
+
/**
* Release this container if it is initialized.
*/
@@ -573,7 +568,7 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
.apply();
// TODO: determine if this is really necessary or not
- onLocationChanged(wct);
+ updateWindowBounds(wct);
} else {
// The surface has already been destroyed before the task has appeared,
// so go ahead and hide the task entirely
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 922472a26113..09dc68a4ccea 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -870,7 +870,8 @@ public class Bubble implements BubbleViewProvider {
pw.print(" desiredHeight: "); pw.println(getDesiredHeightString());
pw.print(" suppressNotif: "); pw.println(shouldSuppressNotification());
pw.print(" autoExpand: "); pw.println(shouldAutoExpand());
- pw.print(" bubbleMetadataFlagListener null: " + (mBubbleMetadataFlagListener == null));
+ pw.print(" isClearable: "); pw.println(mIsClearable);
+ pw.println(" bubbleMetadataFlagListener null: " + (mBubbleMetadataFlagListener == null));
if (mExpandedView != null) {
mExpandedView.dump(pw);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldAnimationControllerTest.java
index 81eefe25704e..8196c5ab08e4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldAnimationControllerTest.java
@@ -224,16 +224,18 @@ public class UnfoldAnimationControllerTest extends ShellTestCase {
mUnfoldAnimationController.onTaskAppeared(taskInfo, mLeash);
assertThat(mTaskAnimator1.mResetTasks).doesNotContain(taskInfo.taskId);
+ mUnfoldAnimationController.onStateChangeStarted();
mUnfoldAnimationController.onTaskVanished(taskInfo);
+ mUnfoldAnimationController.onStateChangeFinished();
assertThat(mTaskAnimator1.mResetTasks).contains(taskInfo.taskId);
}
@Test
- public void testApplicablePinnedTaskDisappeared_doesNotResetSurface() {
- mTaskAnimator1.setTaskMatcher((info) -> info.getWindowingMode() == 2);
+ public void testApplicableTaskDisappeared_noStateChange_doesNotResetSurface() {
+ mTaskAnimator1.setTaskMatcher((info) -> info.getWindowingMode() == 0);
RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
- .setWindowingMode(2).build();
+ .setWindowingMode(0).build();
mUnfoldAnimationController.onTaskAppeared(taskInfo, mLeash);
assertThat(mTaskAnimator1.mResetTasks).doesNotContain(taskInfo.taskId);
@@ -249,7 +251,9 @@ public class UnfoldAnimationControllerTest extends ShellTestCase {
.setWindowingMode(0).build();
mUnfoldAnimationController.onTaskAppeared(taskInfo, mLeash);
+ mUnfoldAnimationController.onStateChangeStarted();
mUnfoldAnimationController.onTaskVanished(taskInfo);
+ mUnfoldAnimationController.onStateChangeFinished();
assertThat(mTaskAnimator1.mResetTasks).doesNotContain(taskInfo.taskId);
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
index 5ac3aad749fc..67159512a701 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
@@ -49,13 +49,16 @@ data class TurbulenceNoiseAnimationConfig(
val opacity: Int = DEFAULT_OPACITY,
val width: Float = 0f,
val height: Float = 0f,
- val duration: Float = DEFAULT_NOISE_DURATION_IN_MILLIS,
+ val maxDuration: Float = DEFAULT_MAX_DURATION_IN_MILLIS,
+ val easeInDuration: Float = DEFAULT_EASING_DURATION_IN_MILLIS,
+ val easeOutDuration: Float = DEFAULT_EASING_DURATION_IN_MILLIS,
val pixelDensity: Float = 1f,
val blendMode: BlendMode = DEFAULT_BLEND_MODE,
val onAnimationEnd: Runnable? = null
) {
companion object {
- const val DEFAULT_NOISE_DURATION_IN_MILLIS = 7500F
+ const val DEFAULT_MAX_DURATION_IN_MILLIS = 7500f
+ const val DEFAULT_EASING_DURATION_IN_MILLIS = 750f
const val DEFAULT_LUMINOSITY_MULTIPLIER = 1f
const val DEFAULT_NOISE_GRID_COUNT = 1.2f
const val DEFAULT_NOISE_SPEED_Z = 0.3f
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt
index 4c7e5f4c7093..b8f4b276dd6a 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt
@@ -15,16 +15,106 @@
*/
package com.android.systemui.surfaceeffects.turbulencenoise
-/** A controller that plays [TurbulenceNoiseView]. */
+import android.view.View
+import androidx.annotation.VisibleForTesting
+import java.util.Random
+
+/** Plays [TurbulenceNoiseView] in ease-in, main (no easing), and ease-out order. */
class TurbulenceNoiseController(private val turbulenceNoiseView: TurbulenceNoiseView) {
+
+ companion object {
+ /**
+ * States of the turbulence noise animation.
+ *
+ * <p>The state is designed to be follow the order below: [AnimationState.EASE_IN],
+ * [AnimationState.MAIN], [AnimationState.EASE_OUT].
+ */
+ enum class AnimationState {
+ EASE_IN,
+ MAIN,
+ EASE_OUT,
+ NOT_PLAYING
+ }
+ }
+
+ private val random = Random()
+
+ /** Current state of the animation. */
+ @VisibleForTesting
+ var state: AnimationState = AnimationState.NOT_PLAYING
+ set(value) {
+ field = value
+ if (state == AnimationState.NOT_PLAYING) {
+ turbulenceNoiseView.visibility = View.INVISIBLE
+ turbulenceNoiseView.clearConfig()
+ } else {
+ turbulenceNoiseView.visibility = View.VISIBLE
+ }
+ }
+
+ init {
+ turbulenceNoiseView.visibility = View.INVISIBLE
+ }
+
/** Updates the color of the noise. */
fun updateNoiseColor(color: Int) {
+ if (state == AnimationState.NOT_PLAYING) {
+ return
+ }
turbulenceNoiseView.updateColor(color)
}
- // TODO: add cancel and/ or pause once design requirements become clear.
- /** Plays [TurbulenceNoiseView] with the given config. */
- fun play(turbulenceNoiseAnimationConfig: TurbulenceNoiseAnimationConfig) {
- turbulenceNoiseView.play(turbulenceNoiseAnimationConfig)
+ /**
+ * Plays [TurbulenceNoiseView] with the given config.
+ *
+ * <p>It plays ease-in, main, and ease-out animations in sequence.
+ */
+ fun play(config: TurbulenceNoiseAnimationConfig) {
+ if (state != AnimationState.NOT_PLAYING) {
+ return // Ignore if any of the animation is playing.
+ }
+
+ turbulenceNoiseView.applyConfig(config)
+ playEaseInAnimation()
+ }
+
+ // TODO(b/237282226): Support force finish.
+ /** Finishes the main animation, which triggers the ease-out animation. */
+ fun finish() {
+ if (state == AnimationState.MAIN) {
+ turbulenceNoiseView.finish(nextAnimation = this::playEaseOutAnimation)
+ }
+ }
+
+ private fun playEaseInAnimation() {
+ if (state != AnimationState.NOT_PLAYING) {
+ return
+ }
+ state = AnimationState.EASE_IN
+
+ // Add offset to avoid repetitive noise.
+ turbulenceNoiseView.playEaseIn(
+ offsetX = random.nextFloat(),
+ offsetY = random.nextFloat(),
+ this::playMainAnimation
+ )
+ }
+
+ private fun playMainAnimation() {
+ if (state != AnimationState.EASE_IN) {
+ return
+ }
+ state = AnimationState.MAIN
+
+ turbulenceNoiseView.play(this::playEaseOutAnimation)
+ }
+
+ private fun playEaseOutAnimation() {
+ if (state != AnimationState.MAIN) {
+ return
+ }
+ state = AnimationState.EASE_OUT
+
+ turbulenceNoiseView.playEaseOut(onAnimationEnd = { state = AnimationState.NOT_PLAYING })
}
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
index 19c114d2693c..7456c4334f0f 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
@@ -114,8 +114,19 @@ class TurbulenceNoiseShader : RuntimeShader(TURBULENCE_NOISE_SHADER) {
setFloatUniform("in_aspectRatio", width / max(height, 0.001f))
}
- /** Sets noise move speed in x, y, and z direction. */
+ /** Current noise movements in x, y, and z axes. */
+ var noiseOffsetX: Float = 0f
+ private set
+ var noiseOffsetY: Float = 0f
+ private set
+ var noiseOffsetZ: Float = 0f
+ private set
+
+ /** Sets noise move offset in x, y, and z direction. */
fun setNoiseMove(x: Float, y: Float, z: Float) {
- setFloatUniform("in_noiseMove", x, y, z)
+ noiseOffsetX = x
+ noiseOffsetY = y
+ noiseOffsetZ = z
+ setFloatUniform("in_noiseMove", noiseOffsetX, noiseOffsetY, noiseOffsetZ)
}
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
index 68712c6cd1de..e1e515d14771 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
@@ -25,75 +25,162 @@ import android.util.AttributeSet
import android.view.View
import androidx.annotation.VisibleForTesting
import androidx.core.graphics.ColorUtils
-import java.util.Random
-import kotlin.math.sin
-/** View that renders turbulence noise effect. */
+/**
+ * View that renders turbulence noise effect.
+ *
+ * <p>Use [TurbulenceNoiseController] to control the turbulence animation. If you want to make some
+ * other turbulence noise effects, either add functionality to [TurbulenceNoiseController] or create
+ * another controller instead of extend or modify the [TurbulenceNoiseView].
+ *
+ * <p>Please keep the [TurbulenceNoiseView] (or View in general) not aware of the state.
+ *
+ * <p>Please avoid inheriting the View if possible. Instead, reconsider adding a controller for a
+ * new case.
+ */
class TurbulenceNoiseView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
companion object {
private const val MS_TO_SEC = 0.001f
- private const val TWO_PI = Math.PI.toFloat() * 2f
}
- @VisibleForTesting val turbulenceNoiseShader = TurbulenceNoiseShader()
+ private val turbulenceNoiseShader = TurbulenceNoiseShader()
private val paint = Paint().apply { this.shader = turbulenceNoiseShader }
- private val random = Random()
- private val animator: ValueAnimator = ValueAnimator.ofFloat(0f, 1f)
- private var config: TurbulenceNoiseAnimationConfig? = null
+ @VisibleForTesting var noiseConfig: TurbulenceNoiseAnimationConfig? = null
+ @VisibleForTesting var currentAnimator: ValueAnimator? = null
- val isPlaying: Boolean
- get() = animator.isRunning
+ override fun onDraw(canvas: Canvas?) {
+ if (canvas == null || !canvas.isHardwareAccelerated) {
+ // Drawing with the turbulence noise shader requires hardware acceleration, so skip
+ // if it's unsupported.
+ return
+ }
- init {
- // Only visible during the animation.
- visibility = INVISIBLE
+ canvas.drawPaint(paint)
}
/** Updates the color during the animation. No-op if there's no animation playing. */
- fun updateColor(color: Int) {
- config?.let {
- it.color = color
- applyConfig(it)
+ internal fun updateColor(color: Int) {
+ noiseConfig?.let {
+ turbulenceNoiseShader.setColor(ColorUtils.setAlphaComponent(color, it.opacity))
}
}
- override fun onDraw(canvas: Canvas?) {
- if (canvas == null || !canvas.isHardwareAccelerated) {
- // Drawing with the turbulence noise shader requires hardware acceleration, so skip
- // if it's unsupported.
+ /** Plays the turbulence noise with no easing. */
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+ fun play(onAnimationEnd: Runnable? = null) {
+ if (noiseConfig == null) {
return
}
+ val config = noiseConfig!!
- canvas.drawPaint(paint)
+ val animator = ValueAnimator.ofFloat(0f, 1f)
+ animator.duration = config.maxDuration.toLong()
+
+ // Animation should start from the initial position to avoid abrupt transition.
+ val initialX = turbulenceNoiseShader.noiseOffsetX
+ val initialY = turbulenceNoiseShader.noiseOffsetY
+ val initialZ = turbulenceNoiseShader.noiseOffsetZ
+
+ animator.addUpdateListener { updateListener ->
+ val timeInSec = updateListener.currentPlayTime * MS_TO_SEC
+ turbulenceNoiseShader.setNoiseMove(
+ initialX + timeInSec * config.noiseMoveSpeedX,
+ initialY + timeInSec * config.noiseMoveSpeedY,
+ initialZ + timeInSec * config.noiseMoveSpeedZ
+ )
+
+ turbulenceNoiseShader.setOpacity(config.luminosityMultiplier)
+
+ invalidate()
+ }
+
+ animator.addListener(
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ currentAnimator = null
+ onAnimationEnd?.run()
+ }
+ }
+ )
+
+ animator.start()
+ currentAnimator = animator
+ }
+
+ /** Plays the turbulence noise with linear ease-in. */
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+ fun playEaseIn(offsetX: Float = 0f, offsetY: Float = 0f, onAnimationEnd: Runnable? = null) {
+ if (noiseConfig == null) {
+ return
+ }
+ val config = noiseConfig!!
+
+ val animator = ValueAnimator.ofFloat(0f, 1f)
+ animator.duration = config.easeInDuration.toLong()
+
+ // Animation should start from the initial position to avoid abrupt transition.
+ val initialX = turbulenceNoiseShader.noiseOffsetX
+ val initialY = turbulenceNoiseShader.noiseOffsetY
+ val initialZ = turbulenceNoiseShader.noiseOffsetZ
+
+ animator.addUpdateListener { updateListener ->
+ val timeInSec = updateListener.currentPlayTime * MS_TO_SEC
+ val progress = updateListener.animatedValue as Float
+
+ turbulenceNoiseShader.setNoiseMove(
+ offsetX + initialX + timeInSec * config.noiseMoveSpeedX,
+ offsetY + initialY + timeInSec * config.noiseMoveSpeedY,
+ initialZ + timeInSec * config.noiseMoveSpeedZ
+ )
+
+ // TODO: Replace it with a better curve.
+ turbulenceNoiseShader.setOpacity(progress * config.luminosityMultiplier)
+
+ invalidate()
+ }
+
+ animator.addListener(
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ currentAnimator = null
+ onAnimationEnd?.run()
+ }
+ }
+ )
+
+ animator.start()
+ currentAnimator = animator
}
- fun play(config: TurbulenceNoiseAnimationConfig) {
- if (isPlaying) {
- return // Ignore if the animation is playing.
+ /** Plays the turbulence noise with linear ease-out. */
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+ fun playEaseOut(onAnimationEnd: Runnable? = null) {
+ if (noiseConfig == null) {
+ return
}
- visibility = VISIBLE
- applyConfig(config)
+ val config = noiseConfig!!
+
+ val animator = ValueAnimator.ofFloat(0f, 1f)
+ animator.duration = config.easeOutDuration.toLong()
- // Add random offset to avoid same patterned noise.
- val offsetX = random.nextFloat()
- val offsetY = random.nextFloat()
+ // Animation should start from the initial position to avoid abrupt transition.
+ val initialX = turbulenceNoiseShader.noiseOffsetX
+ val initialY = turbulenceNoiseShader.noiseOffsetY
+ val initialZ = turbulenceNoiseShader.noiseOffsetZ
- animator.duration = config.duration.toLong()
animator.addUpdateListener { updateListener ->
val timeInSec = updateListener.currentPlayTime * MS_TO_SEC
- // Remap [0,1] to [0, 2*PI]
- val progress = TWO_PI * updateListener.animatedValue as Float
+ val progress = updateListener.animatedValue as Float
turbulenceNoiseShader.setNoiseMove(
- offsetX + timeInSec * config.noiseMoveSpeedX,
- offsetY + timeInSec * config.noiseMoveSpeedY,
- timeInSec * config.noiseMoveSpeedZ
+ initialX + timeInSec * config.noiseMoveSpeedX,
+ initialY + timeInSec * config.noiseMoveSpeedY,
+ initialZ + timeInSec * config.noiseMoveSpeedZ
)
- // Fade in and out the noise as the animation progress.
- // TODO: replace it with a better curve
- turbulenceNoiseShader.setOpacity(sin(TWO_PI - progress) * config.luminosityMultiplier)
+ // TODO: Replace it with a better curve.
+ turbulenceNoiseShader.setOpacity((1f - progress) * config.luminosityMultiplier)
invalidate()
}
@@ -101,16 +188,31 @@ class TurbulenceNoiseView(context: Context?, attrs: AttributeSet?) : View(contex
animator.addListener(
object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
- visibility = INVISIBLE
- config.onAnimationEnd?.run()
+ currentAnimator = null
+ onAnimationEnd?.run()
}
}
)
+
animator.start()
+ currentAnimator = animator
+ }
+
+ /** Finishes the current animation if playing and plays the next animation if given. */
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+ fun finish(nextAnimation: Runnable? = null) {
+ // Calling Animator#end sets the animation state back to the initial state. Using pause to
+ // avoid visual artifacts.
+ currentAnimator?.pause()
+ currentAnimator = null
+
+ nextAnimation?.run()
}
- private fun applyConfig(config: TurbulenceNoiseAnimationConfig) {
- this.config = config
+ /** Applies shader uniforms. Must be called before playing animation. */
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+ fun applyConfig(config: TurbulenceNoiseAnimationConfig) {
+ noiseConfig = config
with(turbulenceNoiseShader) {
setGridCount(config.gridCount)
setColor(ColorUtils.setAlphaComponent(config.color, config.opacity))
@@ -120,4 +222,8 @@ class TurbulenceNoiseView(context: Context?, attrs: AttributeSet?) : View(contex
}
paint.blendMode = config.blendMode
}
+
+ internal fun clearConfig() {
+ noiseConfig = null
+ }
}
diff --git a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
index eac765ab45b2..51f5baa8b45f 100644
--- a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
+++ b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
@@ -40,6 +40,11 @@ import java.util.List;
*/
@ProvidesInterface(action = BcSmartspaceDataPlugin.ACTION, version = BcSmartspaceDataPlugin.VERSION)
public interface BcSmartspaceDataPlugin extends Plugin {
+ String UI_SURFACE_LOCK_SCREEN_AOD = "lockscreen";
+ String UI_SURFACE_HOME_SCREEN = "home";
+ String UI_SURFACE_MEDIA = "media_data_manager";
+ String UI_SURFACE_DREAM = "dream";
+
String ACTION = "com.android.systemui.action.PLUGIN_BC_SMARTSPACE_DATA";
int VERSION = 1;
String TAG = "BcSmartspaceDataPlugin";
@@ -100,6 +105,11 @@ public interface BcSmartspaceDataPlugin extends Plugin {
void setIsDreaming(boolean isDreaming);
/**
+ * Set the UI surface for the cards. Should be called immediately after the view is created.
+ */
+ void setUiSurface(String uiSurface);
+
+ /**
* Range [0.0 - 1.0] when transitioning from Lockscreen to/from AOD
*/
void setDozeAmount(float amount);
diff --git a/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml b/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml
index b3987f1aeeda..951d6fed0a17 100644
--- a/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml
+++ b/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml
@@ -99,4 +99,9 @@
android:fromId="@id/unlocked"
android:toId="@id/locked_aod"
android:drawable="@drawable/unlocked_to_aod_lock" />
+
+ <transition
+ android:fromId="@id/unlocked"
+ android:toId="@id/locked"
+ android:drawable="@drawable/unlocked_to_locked" />
</animated-selector>
diff --git a/packages/SystemUI/res-keyguard/drawable/unlocked_to_locked.xml b/packages/SystemUI/res-keyguard/drawable/unlocked_to_locked.xml
new file mode 100644
index 000000000000..b55abd1fdddc
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/unlocked_to_locked.xml
@@ -0,0 +1,145 @@
+<?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.
+-->
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android">
+ <aapt:attr name="android:drawable">
+ <vector android:height="65dp" android:width="46dp" android:viewportHeight="65" android:viewportWidth="46">
+ <group android:name="_R_G">
+ <group android:name="_R_G_L_2_G_T_1" android:translateX="22.75" android:translateY="22.25" android:scaleX="1.02" android:scaleY="1.02">
+ <group android:name="_R_G_L_2_G" android:translateX="-8.75" android:translateY="-8.75">
+ <path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#FF000000" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M27.19 14.81 C27.19,14.81 27.19,8.3 27.19,8.3 C27.19,4.92 24.44,2.88 21.19,2.75 C17.74,2.62 15,4.74 15,8.11 C15,8.11 15,15 15,15 " />
+ </group>
+ </group>
+ <group android:name="_R_G_L_1_G_N_4_T_1" android:translateX="22.75" android:translateY="22.25" android:scaleX="1.02" android:scaleY="1.02">
+ <group android:name="_R_G_L_1_G_N_4_T_0" android:translateX="-8.75" android:translateY="-8.75">
+ <group android:name="_R_G_L_1_G" android:translateX="8.995" android:translateY="18.431" android:scaleX="0.98039" android:scaleY="0.98039">
+ <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#FF000000" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M11.25 -0.64 C11.25,-0.64 11.25,13.64 11.25,13.64 C11.25,15.22 9.97,16.5 8.39,16.5 C8.39,16.5 -8.39,16.5 -8.39,16.5 C-9.97,16.5 -11.25,15.22 -11.25,13.64 C-11.25,13.64 -11.25,-0.64 -11.25,-0.64 C-11.25,-2.22 -9.97,-3.5 -8.39,-3.5 C-8.39,-3.5 8.39,-3.5 8.39,-3.5 C9.97,-3.5 11.25,-2.22 11.25,-0.64c " />
+ </group>
+ </group>
+ </group>
+ <group android:name="_R_G_L_0_G_N_4_T_1" android:translateX="22.75" android:translateY="22.25" android:scaleX="1.02" android:scaleY="1.02">
+ <group android:name="_R_G_L_0_G_N_4_T_0" android:translateX="-8.75" android:translateY="-8.75">
+ <group android:name="_R_G_L_0_G" android:translateX="8.995000000000001" android:translateY="18.345000000000002" android:pivotX="-0.031" android:pivotY="4.406" android:scaleX="0.98039" android:scaleY="0.98039">
+ <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#FF000000" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-0.09 8.63 C1.2,8.63 2.25,7.57 2.25,6.28 C2.25,4.99 1.2,3.94 -0.09,3.94 C-1.39,3.94 -2.44,4.99 -2.44,6.28 C-2.44,7.57 -1.39,8.63 -0.09,8.63c " />
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+ <target android:name="_R_G_L_2_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="strokeWidth" android:duration="333" android:startOffset="0" android:valueFrom="2" android:valueTo="2" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0.833,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_D_0_P_0">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="pathData" android:duration="83" android:startOffset="0" android:valueFrom="M27.19 14.81 C27.19,14.81 27.19,8.3 27.19,8.3 C27.19,4.92 24.44,2.88 21.19,2.75 C17.74,2.62 15,4.74 15,8.11 C15,8.11 15,15 15,15 " android:valueTo="M27.13 10.19 C27.13,10.19 27.13,3.67 27.13,3.67 C27.13,0.3 24.38,-1.75 21.13,-1.87 C17.68,-2.01 14.94,0.11 14.94,3.49 C14.94,3.49 15,15 15,15 " android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.456,0 0.464,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="133" android:startOffset="83" android:valueFrom="M27.13 10.19 C27.13,10.19 27.13,3.67 27.13,3.67 C27.13,0.3 24.38,-1.75 21.13,-1.87 C17.68,-2.01 14.94,0.11 14.94,3.49 C14.94,3.49 15,15 15,15 " android:valueTo="M2.5 10.38 C2.5,10.38 2.5,3.99 2.5,3.99 C2.5,0.61 5.3,-2.12 8.75,-2.12 C12.2,-2.12 15,0.61 15,3.99 C15,3.99 15,15 15,15 " android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.606,0 0.035,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="pathData" android:duration="117" android:startOffset="217" android:valueFrom="M2.5 10.38 C2.5,10.38 2.5,3.99 2.5,3.99 C2.5,0.61 5.3,-2.12 8.75,-2.12 C12.2,-2.12 15,0.61 15,3.99 C15,3.99 15,15 15,15 " android:valueTo="M2.52 14.65 C2.52,14.65 2.5,8.61 2.5,8.61 C2.5,5.24 5.3,2.5 8.75,2.5 C12.2,2.5 15,5.24 15,8.61 C15,8.61 15.02,14.65 15.02,14.65 " android:valueType="pathType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.511,0 0.409,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_2_G_T_1">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateY" android:duration="333" android:startOffset="0" android:valueFrom="22.25" android:valueTo="22.25" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.535,0 0.426,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateY" android:duration="67" android:startOffset="333" android:valueFrom="22.25" android:valueTo="24.25" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.535,0 0.426,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateY" android:duration="100" android:startOffset="400" android:valueFrom="24.25" android:valueTo="22.25" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.641,0 0.499,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_4_T_1">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateY" android:duration="333" android:startOffset="0" android:valueFrom="22.25" android:valueTo="22.25" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.535,0 0.426,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateY" android:duration="67" android:startOffset="333" android:valueFrom="22.25" android:valueTo="24.25" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.535,0 0.426,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateY" android:duration="100" android:startOffset="400" android:valueFrom="24.25" android:valueTo="22.25" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.641,0 0.499,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_4_T_1">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateY" android:duration="333" android:startOffset="0" android:valueFrom="22.25" android:valueTo="22.25" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.535,0 0.426,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateY" android:duration="67" android:startOffset="333" android:valueFrom="22.25" android:valueTo="24.25" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.535,0 0.426,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator android:propertyName="translateY" android:duration="100" android:startOffset="400" android:valueFrom="24.25" android:valueTo="22.25" android:valueType="floatType">
+ <aapt:attr name="android:interpolator">
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.641,0 0.499,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group">
+ <aapt:attr name="android:animation">
+ <set android:ordering="together">
+ <objectAnimator android:propertyName="translateX" android:duration="850" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" />
+ </set>
+ </aapt:attr>
+ </target>
+</animated-vector>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 35d0981b96e0..c0509a9f7702 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Beweeg nader aan <xliff:g id="DEVICENAME">%1$s</xliff:g> om hier te speel"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Speel tans op <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Iets is fout. Probeer weer."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Onaktief, gaan program na"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nie gekry nie"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrole is nie beskikbaar nie"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index cfb8ad0a8040..d0c5c9040ea8 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"እዚህ ለመጫወት ወደ <xliff:g id="DEVICENAME">%1$s</xliff:g> ቀረብ ይበሉ"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"በ<xliff:g id="DEVICENAME">%1$s</xliff:g> ላይ በማጫወት ላይ"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"የሆነ ችግር ተፈጥሯል። እንደገና ይሞክሩ።"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"ንቁ ያልኾነ፣ መተግበሪያን ይፈትሹ"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"አልተገኘም"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"መቆጣጠሪያ አይገኝም"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 7568eb7942c5..ea5bce12b3db 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"يُرجى الاقتراب من <xliff:g id="DEVICENAME">%1$s</xliff:g> لتشغيل الوسائط هنا."</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"جارٍ تشغيل الوسائط على <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"حدث خطأ. يُرجى إعادة المحاولة."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"غير نشط، تحقّق من التطبيق."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"لم يتم العثور عليه."</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"عنصر التحكّم غير متوفّر"</string>
@@ -1004,8 +1006,7 @@
<string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• تثبيت تطبيق كاميرا"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• إعداد التطبيق"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• توفُّر جهاز واحد على الأقل"</string>
- <!-- no translation found for keyguard_affordance_press_too_short (8145437175134998864) -->
- <skip />
+ <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"انقر مع الاستمرار على الاختصار."</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"إلغاء"</string>
<string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"قلب الجهاز الآن"</string>
<string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"عليك فتح الهاتف لالتقاط صورة ذاتية بشكل أفضل."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index def260793ad6..cbd2bedd3f20 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ইয়াত খেলিবলৈ <xliff:g id="DEVICENAME">%1$s</xliff:g>ৰ আৰু ওচৰলৈ যাওক"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g>ত প্লে কৰি থকা হৈছে"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"কিবা ভুল হ’ল। পুনৰ চেষ্টা কৰক।"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"সক্ৰিয় নহয়, এপ্‌টো পৰীক্ষা কৰক"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"বিচাৰি পোৱা নগ’ল"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"নিয়ন্ত্ৰণটো উপলব্ধ নহয়"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index c3378dde36fb..dd4d5109855d 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Burada oxutmaq üçün <xliff:g id="DEVICENAME">%1$s</xliff:g> cihazına yaxınlaşın"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> cihazında oxudulur"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Xəta oldu. Yenə cəhd edin."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Aktiv deyil, tətbiqi yoxlayın"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Tapılmadı"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Nəzarət əlçatan deyil"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 2b50c3631019..64313896a4ce 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Približite se uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g> da biste na njemu puštali"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Pušta se na uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Došlo je do greške. Probajte ponovo."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno. Vidite aplikaciju"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrola nije dostupna"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 7394df3bef5b..7e7262a057d3 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Падыдзіце бліжэй да прылады \"<xliff:g id="DEVICENAME">%1$s</xliff:g>\", каб прайграць на гэтай"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Прайграецца на прыладзе \"<xliff:g id="DEVICENAME">%1$s</xliff:g>\""</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Нешта пайшло не так. Паўтарыце спробу."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Неактыўна, праверце праграму"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не знойдзена"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Кіраванне недаступнае"</string>
@@ -1004,8 +1006,7 @@
<string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Усталявана праграма \"Камера\"."</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Праграма наладжана."</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Даступная хаця б адна прылада."</string>
- <!-- no translation found for keyguard_affordance_press_too_short (8145437175134998864) -->
- <skip />
+ <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Дакраніцеся і ўтрымлівайце ярлык"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Скасаваць"</string>
<string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Пераключыць"</string>
<string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Каб атрымаць лепшае сэлфі, раскрыйце тэлефон"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 44e4e95dda17..26a154fadc56 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Приближете се до <xliff:g id="DEVICENAME">%1$s</xliff:g> за възпроизвеждане на това устройство"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Възпроизвежда се на <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Нещо се обърка. Опитайте отново."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, проверете прилож."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не е намерено"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Контролата не е налице"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 384b18308468..b6069a4a9361 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"এখান থেকে চালাতে <xliff:g id="DEVICENAME">%1$s</xliff:g>-এর কাছে নিয়ে যান"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g>-এ ভিডিও চালানো হচ্ছে"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"কোনও সমস্যা হয়েছে। আবার চেষ্টা করুন।"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"বন্ধ আছে, অ্যাপ চেক করুন"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"খুঁজে পাওয়া যায়নি"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"কন্ট্রোল উপলভ্য নেই"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index d6217722287b..1ab7594ca0fb 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Približite se uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g> da na njemu reproducirate"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Reproducira se na uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Nešto nije uredu. Pokušajte ponovo."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, vidite aplikaciju"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrola nije dostupna"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 4b77f089b5e0..2f48676a142a 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Acosta\'t a <xliff:g id="DEVICENAME">%1$s</xliff:g> per reproduir el contingut aquí"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"S\'està reproduint a <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"S\'ha produït un error. Torna-ho a provar."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactiu; comprova l\'aplicació"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"No s\'ha trobat"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"El control no està disponible"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 48f6dfe53d14..feeaa32f68a7 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Pokud zde chcete přehrávat média, přibližte se k zařízení <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Přehrávání v zařízení <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Došlo k chybě. Zkuste to znovu."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivní, zkontrolujte aplikaci"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nenalezeno"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Ovládání není k dispozici"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index aa0f20c0b899..f64587e26731 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Ryk tættere på <xliff:g id="DEVICENAME">%1$s</xliff:g> for at afspille her"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Afspilles på <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Noget gik galt. Prøv igen."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Tjek appen"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ikke fundet"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Styringselement ikke tilgængeligt"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index f94c192ec1b0..bd4c5872dfce 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Platziere für die Wiedergabe dein Gerät näher an „<xliff:g id="DEVICENAME">%1$s</xliff:g>“"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Wird auf „<xliff:g id="DEVICENAME">%1$s</xliff:g>“ abgespielt"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Es gab ein Problem. Versuch es noch einmal."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv – sieh in der App nach"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nicht gefunden"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Steuerelement nicht verfügbar"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index ea2f0c97fffa..05cf06cc4ba0 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Μετακινηθείτε πιο κοντά στη συσκευή <xliff:g id="DEVICENAME">%1$s</xliff:g> για αναπαραγωγή εδώ"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Αναπαραγωγή στη συσκευή <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Παρουσιάστηκε κάποιο πρόβλημα. Δοκιμάστε ξανά."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Ανενεργό, έλεγχος εφαρμογής"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Δεν βρέθηκε."</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Μη διαθέσιμο στοιχείο ελέγχου"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index faaefe05b7d9..2c960c62478c 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Move closer to <xliff:g id="DEVICENAME">%1$s</xliff:g> to play here"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Playing on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Something went wrong. Try again."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Control is unavailable"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 7f703df7ec89..d09f71f944d1 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Move closer to <xliff:g id="DEVICENAME">%1$s</xliff:g> to play here"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Playing on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Something went wrong. Try again."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Control is unavailable"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index faaefe05b7d9..2c960c62478c 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Move closer to <xliff:g id="DEVICENAME">%1$s</xliff:g> to play here"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Playing on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Something went wrong. Try again."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Control is unavailable"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index faaefe05b7d9..2c960c62478c 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Move closer to <xliff:g id="DEVICENAME">%1$s</xliff:g> to play here"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Playing on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Something went wrong. Try again."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Control is unavailable"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index e21550f3d140..7b0837d1a77a 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‎‏‏‎‎‎‎‏‏‎‎‏‎‏‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎‎‎‎Move closer to ‎‏‎‎‏‏‎<xliff:g id="DEVICENAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to play here‎‏‎‎‏‎"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎‎‏‏‎‎‎‎‏‎‏‎‎Playing on ‎‏‎‎‏‏‎<xliff:g id="DEVICENAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‏‎‎‎‏‏‎‎‏‎‎‏‏‎‎‎‎‏‏‏‎‎‏‏‏‏‏‎‎‎‎‎‏‎‏‎‏‏‎‏‎‏‏‎‎‏‎‏‏‎Something went wrong. Try again.‎‏‎‎‏‎"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎‏‏‏‏‏‏‎‎Inactive, check app‎‏‎‎‏‎"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎‎‎‏‎‏‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‎‎Not found‎‏‎‎‏‎"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‎‏‎‎‏‎‎‎‎‏‎‎‏‏‎‎‏‎‏‎‎Control is unavailable‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index def72e897a59..55303e8b8f2e 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Acércate a <xliff:g id="DEVICENAME">%1$s</xliff:g> para reproducir aquí"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Reproduciendo en <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Se produjo un error. Vuelve a intentarlo."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Verifica la app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"No se encontró"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"El control no está disponible"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 5146e74bc1fa..c2443daccceb 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Acércate a <xliff:g id="DEVICENAME">%1$s</xliff:g> para jugar aquí"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Reproduciendo en <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Se ha producido un error. Inténtalo de nuevo."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo, comprobar aplicación"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"No se ha encontrado"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Control no disponible"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 7b2bd3e197c4..b31030a42fe3 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Siin esitamiseks liigutage seadmele <xliff:g id="DEVICENAME">%1$s</xliff:g> lähemale"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Esitatakse seadmes <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Midagi läks valesti. Proovige uuesti."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Passiivne, vaadake rakendust"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ei leitud"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Juhtelement pole saadaval"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 3fb9726be8e4..de9c75f45af8 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Gerturatu <xliff:g id="DEVICENAME">%1$s</xliff:g> gailura bertan erreproduzitzen ari dena hemen erreproduzitzeko"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> gailuan erreproduzitzen"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Arazoren bat izan da. Saiatu berriro."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktibo; egiaztatu aplikazioa"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ez da aurkitu"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Ez dago erabilgarri kontrolatzeko aukera"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 161117a423c6..87aed942d05e 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"برای پخش در اینجا، به <xliff:g id="DEVICENAME">%1$s</xliff:g> نزدیک‌تر شوید"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"درحال پخش در <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"مشکلی پیش آمد. دوباره امتحان کنید."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"غیرفعال، برنامه را بررسی کنید"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"پیدا نشد"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"کنترل دردسترس نیست"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 33108eb8445c..f7bb7f701687 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -724,7 +724,7 @@
<string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> on käynnissä"</string>
<string name="instant_apps_message" msgid="6112428971833011754">"Sovellus avattiin ilman asennusta."</string>
<string name="instant_apps_message_with_help" msgid="1816952263531203932">"Sovellus avattiin ilman asennusta. Katso lisätietoja napauttamalla."</string>
- <string name="app_info" msgid="5153758994129963243">"Sovelluksen tiedot"</string>
+ <string name="app_info" msgid="5153758994129963243">"Sovellustiedot"</string>
<string name="go_to_web" msgid="636673528981366511">"Siirry selaimeen"</string>
<string name="mobile_data" msgid="4564407557775397216">"Mobiilidata"</string>
<string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Siirrä <xliff:g id="DEVICENAME">%1$s</xliff:g> lähemmäs toistaaksesi täällä"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Toistetaan: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Jotain meni pieleen. Yritä uudelleen."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Epäaktiivinen, tarkista sovellus"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ei löydy"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Ohjain ei ole käytettävissä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 184b907963e8..be81a9275544 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Rapprochez-vous de <xliff:g id="DEVICENAME">%1$s</xliff:g> pour lire le contenu"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Lecture sur <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Un problème est survenu. Réessayez."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifiez l\'appli"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Introuvable"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"La commande n\'est pas accessible"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 9823ad016c7c..869166321079 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Rapprochez l\'appareil pour transférer la diffusion à votre <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Lecture sur <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Un problème est survenu. Réessayez."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifier l\'appli"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Introuvable"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Commande indisponible"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index b27bd12cd48f..f9738e3b413a 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Achégate ao dispositivo (<xliff:g id="DEVICENAME">%1$s</xliff:g>) para reproducir o contido neste"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Reproducindo contido noutro dispositivo (<xliff:g id="DEVICENAME">%1$s</xliff:g>)"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Produciuse un erro. Téntao de novo."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Comproba a app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Non se atopou"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"O control non está dispoñible"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index e00f8d88be38..dac1403f8dd5 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"આમાં ચલાવવા માટે ડિવાઇસને <xliff:g id="DEVICENAME">%1$s</xliff:g>ની નજીક ખસેડો"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> પર ચલાવવામાં આવી રહ્યું છે"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"કંઈક ખોટું થયું. ફરી પ્રયાસ કરો."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"નિષ્ક્રિય, ઍપને ચેક કરો"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"મળ્યું નથી"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"નિયંત્રણ ઉપલબ્ધ નથી"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 49fb626ab6a6..38d2bffa239a 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"अपने डिवाइस पर मीडिया फ़ाइल ट्रांसफ़र करने के लिए, उसे <xliff:g id="DEVICENAME">%1$s</xliff:g> के पास ले जाएं"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> पर मीडिया चल रहा है"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"कोई गड़बड़ी हुई. फिर से कोशिश करें."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"काम नहीं कर रहा, ऐप जांचें"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"कंट्रोल नहीं है"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"कंट्रोल मौजूद नहीं है"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index e5253bc13a1f..7613317734d1 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Približite se uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g> da biste na njemu reproducirali"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Reproducira se na uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Nešto nije u redu. Pokušajte ponovo."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, provjerite aplik."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrola nije dostupna"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 6263126eb692..c2b94c0b1102 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Menjen közelebb a(z) <xliff:g id="DEVICENAME">%1$s</xliff:g> eszközhöz, hogy itt játszhassa le a tartalmat"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Lejátszás folyamatban a(z) <xliff:g id="DEVICENAME">%1$s</xliff:g> eszközön"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Hiba történt. Próbálkozzon újra."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktív, ellenőrizze az appot"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nem található"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Nem hozzáférhető vezérlő"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index f84530f41579..5623ecfb7f29 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Ավելի մոտեցեք «<xliff:g id="DEVICENAME">%1$s</xliff:g>» սարքին՝ նվագարկումը սկսելու համար"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Նվագարկվում է «<xliff:g id="DEVICENAME">%1$s</xliff:g>» սարքում"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Սխալ առաջացավ։ Նորից փորձեք։"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Ակտիվ չէ, ստուգեք հավելվածը"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Չի գտնվել"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Կառավարման տարրը հասանելի չէ"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 2702f9281463..bf5f8b01848c 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Dekatkan ke <xliff:g id="DEVICENAME">%1$s</xliff:g> untuk memutar di sini"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Diputar di <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Terjadi error. Coba lagi."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Nonaktif, periksa aplikasi"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Tidak ditemukan"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrol tidak tersedia"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 64c76773fa52..f3efb8624333 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Færðu tækið nær <xliff:g id="DEVICENAME">%1$s</xliff:g> til að spila hér"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Í spilun í <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Eitthvað fór úrskeiðis. Reyndu aftur."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Óvirkt, athugaðu forrit"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Fannst ekki"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Stýring er ekki tiltæk"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 89817d19a8fc..e8c6a5b21308 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Avvicinati a <xliff:g id="DEVICENAME">%1$s</xliff:g> per riprodurre i contenuti qui"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"In riproduzione su <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Si è verificato un errore. Riprova."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inattivo, controlla l\'app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Controllo non trovato"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Il controllo non è disponibile"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index ad9ccf13f6fd..690b6b22710c 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"צריך להתקרב אל <xliff:g id="DEVICENAME">%1$s</xliff:g> כדי להפעיל כאן"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"פועלת ב-<xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"משהו השתבש. יש לנסות שוב."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"לא פעיל, יש לבדוק את האפליקציה"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"לא נמצא"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"הפקד לא זמין"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 112db0530716..5bd580ccc603 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ここで再生するには<xliff:g id="DEVICENAME">%1$s</xliff:g>に近づいてください"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g>で再生しています"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"エラーが発生しました。もう一度お試しください。"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"無効: アプリをご確認ください"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"見つかりませんでした"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"コントロールを使用できません"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 22e8a481e6f8..d25daf440ce2 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"მიუახლოვდით <xliff:g id="DEVICENAME">%1$s</xliff:g>-ს მისი მეშვეობით დასაკრავად"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"მიმდინარეობს დაკვრა <xliff:g id="DEVICENAME">%1$s</xliff:g>-ზე"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"რაღაც შეცდომა მოხდა. ცადეთ ხელახლა."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"არააქტიურია, გადაამოწმეთ აპი"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ვერ მოიძებნა"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"კონტროლი მიუწვდომელია"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index d9ce21674ea7..bb24d6af3c0a 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Осы жерде ойнау үшін <xliff:g id="DEVICENAME">%1$s</xliff:g> құрылғысына жақындаңыз"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> құрылғысында ойнатылуда."</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Бірдеңе дұрыс болмады. Қайталап көріңіз."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Өшірулі. Қолданба тексеріңіз."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Табылмады"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Басқару виджеті қолжетімсіз"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 830f2f24bab2..65953058322d 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"រំកិលឱ្យកាន់តែជិត <xliff:g id="DEVICENAME">%1$s</xliff:g> ដើម្បីចាក់នៅទីនេះ"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"កំពុង​ចាក់​​នៅ​លើ <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"មានអ្វីមួយខុសប្រក្រតី។ សូមព្យាយាមម្ដងទៀត។"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"អសកម្ម ពិនិត្យមើល​កម្មវិធី"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"រកមិន​ឃើញទេ"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"មិនអាច​គ្រប់គ្រង​បានទេ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index b142a10c1dfc..81a37f31aa8f 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ಇಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲು <xliff:g id="DEVICENAME">%1$s</xliff:g> ಸಮೀಪಕ್ಕೆ ಹೋಗಿ"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಆಗುತ್ತಿದೆ"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"ಏನೋ ತಪ್ಪಾಗಿದೆ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"ನಿಷ್ಕ್ರಿಯ, ಆ್ಯಪ್ ಪರಿಶೀಲಿಸಿ"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ಕಂಡುಬಂದಿಲ್ಲ"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"ನಿಯಂತ್ರಣ ಲಭ್ಯವಿಲ್ಲ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index f9049f9fa05d..1570a6aa2370 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"현재 기기에서 재생하려면 <xliff:g id="DEVICENAME">%1$s</xliff:g>에 더 가까이 이동합니다."</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g>에서 재생 중"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"문제가 발생했습니다. 다시 시도해 주세요."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"비활성. 앱을 확인하세요."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"찾을 수 없음"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"컨트롤을 사용할 수 없음"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index d579fc2d8c60..b1206840b722 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Бул жерде ойнотуу үчүн <xliff:g id="DEVICENAME">%1$s</xliff:g> түзмөгүнө жакындатыңыз"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> аркылуу ойнотулууда"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Бир жерден ката кетти. Кайра аракет кылыңыз."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Жигерсиз. Колдонмону текшериңиз"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Табылган жок"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Башкара албайсыз"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 628d75e975d3..446deb05cf00 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ກະລຸນາຍ້າຍເຂົ້າໃກ້ <xliff:g id="DEVICENAME">%1$s</xliff:g> ເພື່ອຫຼິ້ນຢູ່ບ່ອນນີ້"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"ກຳລັງຫຼິ້ນຢູ່ <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"ມີບາງຢ່າງຜິດພາດເກີດຂຶ້ນ. ກະລຸນາລອງໃໝ່."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"ບໍ່ເຮັດວຽກ, ກະລຸນາກວດສອບແອັບ"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ບໍ່ພົບ"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"ບໍ່ສາມາດໃຊ້ການຄວບຄຸມໄດ້"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 73a645ef4864..db518c100a0d 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Perkelkite arčiau „<xliff:g id="DEVICENAME">%1$s</xliff:g>“, kad būtų galima leisti čia"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Leidžiama įrenginyje „<xliff:g id="DEVICENAME">%1$s</xliff:g>“"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Kažkas ne taip. Bandykite dar kartą."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktyvu, patikrinkite progr."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nerasta"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Valdiklis nepasiekiamas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 051779cafadc..5ea8da2889d8 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Pārvietojieties tuvāk ierīcei “<xliff:g id="DEVICENAME">%1$s</xliff:g>”, lai atskaņotu šeit"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Notiek atskaņošana ierīcē <xliff:g id="DEVICENAME">%1$s</xliff:g>."</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Radās kļūda. Mēģiniet vēlreiz."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktīva, pārbaudiet lietotni"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Netika atrasta"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Vadīkla nav pieejama"</string>
@@ -1004,8 +1006,7 @@
<string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Ir instalēta kameras lietotne."</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Lietotne ir iestatīta."</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ir pieejama vismaz viena ierīce."</string>
- <!-- no translation found for keyguard_affordance_press_too_short (8145437175134998864) -->
- <skip />
+ <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Pieskarieties saīsnei un turiet."</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Atcelt"</string>
<string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Apvērst tūlīt"</string>
<string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Labākas pašbildes uzņemšana, atlokot tālruni"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 02bfd4f0becb..0575b102e405 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Приближете се до <xliff:g id="DEVICENAME">%1$s</xliff:g> за да пуштите тука"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Пуштено на <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Нешто не е во ред. Обидете се повторно."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивна, провери апликација"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не е најдено"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Контролата не е достапна"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 064927a8bc35..9a2353c6b8ad 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ഇവിടെ പ്ലേ ചെയ്യാൻ <xliff:g id="DEVICENAME">%1$s</xliff:g> എന്നതിന് അടുത്തേക്ക് നീക്കുക"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> എന്നതിൽ പ്ലേ ചെയ്യുന്നു"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"എന്തോ കുഴപ്പമുണ്ടായി. വീണ്ടും ശ്രമിക്കുക."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"നിഷ്‌ക്രിയം, ആപ്പ് പരിശോധിക്കൂ"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"കണ്ടെത്തിയില്ല"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"നിയന്ത്രണം ലഭ്യമല്ല"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 0c36e1df1cf4..08c47b0f4df4 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Энд тоглуулахын тулд <xliff:g id="DEVICENAME">%1$s</xliff:g>-д ойртоно уу"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> дээр тоглуулж байна"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Алдаа гарлаа. Дахин оролдоно уу."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Идэвхгүй байна, аппыг шалгана уу"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Олдсонгүй"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Хяналт боломжгүй байна"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 93978c08f412..103e8d204772 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"येथे प्ले करण्यासाठी <xliff:g id="DEVICENAME">%1$s</xliff:g> च्या जवळ जा"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> वर प्ले केला जात आहे"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"काहीतरी चूक झाली. पुन्हा प्रयत्न करा."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय, ॲप तपासा"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"आढळले नाही"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"नियंत्रण उपलब्ध नाही"</string>
@@ -1004,8 +1006,7 @@
<string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• कॅमेरा अ‍ॅप इंस्टॉल करणे"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• अ‍ॅप सेट करणे"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• किमान एक डिव्हाइस उपलब्ध करणे"</string>
- <!-- no translation found for keyguard_affordance_press_too_short (8145437175134998864) -->
- <skip />
+ <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"स्पर्श करा आणि धरून ठेवा शॉर्टकट"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"रद्द करा"</string>
<string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"आता फ्लिप करा"</string>
<string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"आणखी चांगल्या सेल्फीसाठी फोनबद्दल अधिक जाणून घ्या"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 46aa1cb85bdb..b0b40962123f 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Dekatkan dengan <xliff:g id="DEVICENAME">%1$s</xliff:g> untuk bermain di sini"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Dimainkan pada <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Kesilapan telah berlaku. Cuba lagi."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Tidak aktif, semak apl"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Tidak ditemukan"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kawalan tidak tersedia"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index edfe2e9fd9e5..2014f5c566c5 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ဤနေရာတွင်ဖွင့်ရန် <xliff:g id="DEVICENAME">%1$s</xliff:g> အနီးသို့တိုးပါ"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> တွင် ဖွင့်နေသည်"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"တစ်ခုခုမှားသွားသည်။ ထပ်စမ်းကြည့်ပါ။"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"ရပ်နေသည်၊ အက်ပ်ကို စစ်ဆေးပါ"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"မတွေ့ပါ"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"ထိန်းချုပ်မှု မရနိုင်ပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index eb448aaf2c4d..2b1ebfdb4f27 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Flytt deg nærmere <xliff:g id="DEVICENAME">%1$s</xliff:g> for å spille av her"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Spilles av på <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Noe gikk galt. Prøv på nytt."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Sjekk appen"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ikke funnet"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrollen er utilgjengelig"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index f3db004b264b..3872b0dc26cc 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"तपाईं यहाँ प्ले गर्न चाहनुहुन्छ भने आफ्नो डिभाइसलाई <xliff:g id="DEVICENAME">%1$s</xliff:g> नजिकै लैजानुहोस्"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> मा प्ले गरिँदै छ"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"केही चिज गडबड भयो। फेरि प्रयास गर्नुहोस्।"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय छ, एप जाँच गर्नु…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"फेला परेन"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"नियन्त्रण उपलब्ध छैन"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index da60323ab03a..e49b9fac5ccb 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Ga dichter bij <xliff:g id="DEVICENAME">%1$s</xliff:g> staan om hier af te spelen"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Afspelen op <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Er is iets misgegaan. Probeer het opnieuw."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactief, check de app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Niet gevonden"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Beheeroptie niet beschikbaar"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 8391e249772e..71d0822d078b 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ଏଠାରେ ଚଲାଇବା ପାଇଁ <xliff:g id="DEVICENAME">%1$s</xliff:g>ର ପାଖକୁ ମୁଭ କରନ୍ତୁ"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g>ରେ ଚାଲୁଛି"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"କିଛି ତ୍ରୁଟି ହୋଇଛି। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"ନିଷ୍କ୍ରିୟ ଅଛି, ଆପ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ମିଳିଲା ନାହିଁ"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"ନିୟନ୍ତ୍ରଣ ଉପଲବ୍ଧ ନାହିଁ"</string>
@@ -1004,8 +1006,7 @@
<string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• ଏକ କେମେରା ଆପ ଇନଷ୍ଟଲ କରିବା"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• ଆପ ସେଟ ଅପ କରାଯାଇଛି"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ଅତିକମରେ ଗୋଟିଏ ଡିଭାଇସ ଉପଲବ୍ଧ ଅଛି"</string>
- <!-- no translation found for keyguard_affordance_press_too_short (8145437175134998864) -->
- <skip />
+ <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ସର୍ଟକଟକୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ବାତିଲ କରନ୍ତୁ"</string>
<string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"ବର୍ତ୍ତମାନ ଫ୍ଲିପ କରନ୍ତୁ"</string>
<string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"ଏକ ଉନ୍ନତ ସେଲ୍ଫି ପାଇଁ ଫୋନକୁ ଅନଫୋଲ୍ଡ କରନ୍ତୁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 2a35dfcd8708..f6ad3ad01bac 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ਇੱਥੇ ਚਲਾਉਣ ਲਈ <xliff:g id="DEVICENAME">%1$s</xliff:g> ਦੇ ਨੇੜੇ ਜਾਓ"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> \'ਤੇ ਚਲਾਇਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"ਕੋਈ ਗੜਬੜ ਹੋ ਗਈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"ਅਕਿਰਿਆਸ਼ੀਲ, ਐਪ ਦੀ ਜਾਂਚ ਕਰੋ"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ਨਹੀਂ ਮਿਲਿਆ"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"ਕੰਟਰੋਲ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 0bc0356e5dbc..7cced9e01ba2 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Zbliż do urządzenia <xliff:g id="DEVICENAME">%1$s</xliff:g>, aby na nim odtwarzać"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Odtwarzam na ekranie <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Coś poszło nie tak. Spróbuj ponownie."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Nieaktywny, sprawdź aplikację"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nie znaleziono"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Element jest niedostępny"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index a51ecccd2c21..41925480b3ad 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Aproxime-se do dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g> para abrir a mídia aqui"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Mídia aberta no dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Algo deu errado. Tente novamente."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"O controle está indisponível"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 27786bcb396f..ad93343fd081 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Aproxime-se do dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g> para reproduzir aqui"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"A reproduzir no dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Algo correu mal. Tente novamente."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inativa. Consulte a app."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado."</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"O controlo está indisponível"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index a51ecccd2c21..41925480b3ad 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Aproxime-se do dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g> para abrir a mídia aqui"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Mídia aberta no dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Algo deu errado. Tente novamente."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"O controle está indisponível"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 318b6cff609f..e4a1b0bcf2e0 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Apropie-te de <xliff:g id="DEVICENAME">%1$s</xliff:g> ca să redai acolo"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Se redă pe <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"A apărut o eroare. Încearcă din nou."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactiv, verifică aplicația"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nu s-a găsit"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Comanda este indisponibilă"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9da9c6d21fae..9b4975e712e6 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Для воспроизведения на этом устройстве подойдите ближе к другому (<xliff:g id="DEVICENAME">%1$s</xliff:g>)."</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Воспроизводится на устройстве \"<xliff:g id="DEVICENAME">%1$s</xliff:g>\"."</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Произошла ошибка. Повторите попытку."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Нет ответа. Проверьте приложение."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не найдено."</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Управление недоступно"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index acbc229ed479..91ed10f66e1d 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"මෙහි ක්‍රීඩා කිරීමට <xliff:g id="DEVICENAME">%1$s</xliff:g> වෙත වඩා සමීප වන්න"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> හි වාදනය කරමින්"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"යම් දෙයක් වැරදිණි. නැවත උත්සාහ කරන්න."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"අක්‍රියයි, යෙදුම පරීක්ෂා කරන්න"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"හමු නොවිණි"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"පාලනය ලබා ගත නොහැකිය"</string>
@@ -1004,8 +1006,7 @@
<string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• කැමරා යෙදුමක් ස්ථාපන කරන්න"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• යෙදුම සකසා ඇත"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• අවම වශයෙන් එක උපාංගයක් ලැබේ"</string>
- <!-- no translation found for keyguard_affordance_press_too_short (8145437175134998864) -->
- <skip />
+ <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ස්පර්ශ කර අල්ලා සිටීමේ කෙටිමඟ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"අවලංගු කරන්න"</string>
<string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"දැන් පෙරළන්න"</string>
<string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"වඩා හොඳ සෙල්ෆියක් සඳහා දුරකථනය දිගහරින්න"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 3718a20109f7..4c3d8b816347 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Ak chcete prehrávať v zariadení <xliff:g id="DEVICENAME">%1$s</xliff:g>, priblížte sa k nemu"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Prehráva sa v zariadení <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Niečo sa pokazilo. Skúste to znova."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktívne, preverte aplikáciu"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nenájdené"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Ovládač nie je k dispozícii"</string>
@@ -1004,8 +1006,7 @@
<string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Nainštalujte si aplikáciu kamery"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Aplikácia je nastavená"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• K dispozícii je minimálne jedno zariadenie"</string>
- <!-- no translation found for keyguard_affordance_press_too_short (8145437175134998864) -->
- <skip />
+ <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Pridržte skratku"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Zrušiť"</string>
<string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Prevráťte"</string>
<string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Ak chcete lepšie selfie, rozložte telefón"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 2aee459a43fe..d4996c9f0079 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Približajte napravi <xliff:g id="DEVICENAME">%1$s</xliff:g> za predvajanje v tej napravi"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Predvajanje v napravi <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Prišlo je do napake. Poskusite znova."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, poglejte aplikacijo"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ni mogoče najti"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrolnik ni na voljo"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 06d786fec0d5..ad2e596f849c 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Afrohu te <xliff:g id="DEVICENAME">%1$s</xliff:g> për ta luajtur këtu"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Po luhet në <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Ndodhi një gabim. Provo përsëri."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Joaktive, kontrollo aplikacionin"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nuk u gjet"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrolli është i padisponueshëm"</string>
@@ -1004,8 +1006,7 @@
<string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Të instalosh një aplikacion të kamerës"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Aplikacioni është konfiguruar"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ofrohet të paktën një pajisje"</string>
- <!-- no translation found for keyguard_affordance_press_too_short (8145437175134998864) -->
- <skip />
+ <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Prek dhe mbaj shtypur shkurtoren"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Anulo"</string>
<string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"U kthye tani"</string>
<string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Shpalos telefonin për një selfi më të mirë"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index bc660e13ef11..ef6bb4597104 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Приближите се уређају <xliff:g id="DEVICENAME">%1$s</xliff:g> да бисте на њему пуштали"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Пушта се на уређају <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Дошло је до грешке. Пробајте поново."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно. Видите апликацију"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Није пронађено"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Контрола није доступна"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 381f03238d56..c98273926204 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Flytta dig närmare <xliff:g id="DEVICENAME">%1$s</xliff:g> om du vill spela här"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Spelas upp på <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Något gick fel. Försök igen."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv, kolla appen"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Hittades inte"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Styrning är inte tillgänglig"</string>
@@ -1004,8 +1006,7 @@
<string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• installera en kameraapp"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• appen har konfigurerats"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• minst en enhet är tillgänglig"</string>
- <!-- no translation found for keyguard_affordance_press_too_short (8145437175134998864) -->
- <skip />
+ <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Tryck länge på genvägen"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Avbryt"</string>
<string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Vänd nu"</string>
<string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Vik upp telefonen för att ta en bättre selfie"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 530bfcc2afa1..5e33bf4d82fc 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Sogeza karibu na <xliff:g id="DEVICENAME">%1$s</xliff:g> ili kucheza hapa"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Inacheza kwenye <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Hitilafu fulani imetokea. Jaribu tena."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Haitumiki, angalia programu"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Hakipatikani"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kidhibiti hakipatikani"</string>
@@ -1004,8 +1006,7 @@
<string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Sakinisha programu ya kamera"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Programu hii imewekewa mipangilio"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Angalau kifaa kimoja kinapatikana"</string>
- <!-- no translation found for keyguard_affordance_press_too_short (8145437175134998864) -->
- <skip />
+ <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Gusa na ushikilie njia ya mkato"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Ghairi"</string>
<string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Geuza kifaa sasa"</string>
<string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Kunjua simu ili upige selfi iliyo bora"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 87d20d6848e4..6e14c2630a03 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"இங்கு பிளே செய்ய உங்கள் சாதனத்தை <xliff:g id="DEVICENAME">%1$s</xliff:g> சாதனத்திற்கு அருகில் நகர்த்துங்கள்"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> சாதனத்தில் பிளே ஆகிறது"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"ஏதோ தவறாகிவிட்டது. மீண்டும் முயலவும்."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"செயலில் இல்லை , சரிபார்க்கவும்"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"இல்லை"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"கட்டுப்பாடு இல்லை"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 2afff20bb7ae..d4e458f78e28 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ఇక్కడ ప్లే చేయడానికి <xliff:g id="DEVICENAME">%1$s</xliff:g>కి దగ్గరగా వెళ్లండి"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g>లో ప్లే అవుతోంది"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"ఏదో తప్పు జరిగింది. మళ్లీ ట్రై చేయండి."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"ఇన్‌యాక్టివ్, యాప్ చెక్ చేయండి"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"కనుగొనబడలేదు"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"కంట్రోల్ అందుబాటులో లేదు"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 31a74d13fd72..f8a16bd26483 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ขยับไปใกล้ <xliff:g id="DEVICENAME">%1$s</xliff:g> มากขึ้นเพื่อเล่นที่นี่"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"กำลังเล่นใน <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"เกิดข้อผิดพลาด โปรดลองอีกครั้ง"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"ไม่มีการใช้งาน โปรดตรวจสอบแอป"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ไม่พบ"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"ใช้การควบคุมไม่ได้"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index cc81e719b2f3..3578aa78c96b 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Lumapit sa <xliff:g id="DEVICENAME">%1$s</xliff:g> para mag-play rito"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Nagpe-play sa <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Nagkaproblema. Subukan ulit."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Hindi aktibo, tingnan ang app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Hindi nahanap"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Hindi available ang kontrol"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index a45871d7e488..64431ad25980 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Burada oynatmak için <xliff:g id="DEVICENAME">%1$s</xliff:g> cihazına yaklaşın"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> cihazında oynatılıyor"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Bir sorun oldu. Tekrar deneyin."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Devre dışı, uygulamaya bakın"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Bulunamadı"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrol kullanılamıyor"</string>
@@ -1004,8 +1006,7 @@
<string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Kamera uygulaması yüklenmelidir"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Uygulama kurulmuş olmalıdır"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• En az bir cihaz mevcut olmalıdır"</string>
- <!-- no translation found for keyguard_affordance_press_too_short (8145437175134998864) -->
- <skip />
+ <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Kısayola dokunup basılı tutun"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"İptal"</string>
<string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Şimdi çevirin"</string>
<string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Daha iyi selfie çekmek için telefonu açın"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index f00ac9093eac..9eba61007965 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Наблизьтеся до пристрою <xliff:g id="DEVICENAME">%1$s</xliff:g>, щоб відтворити медіафайли на ньому"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Відтворюється на пристрої <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Сталася помилка. Повторіть спробу."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, перейдіть у додаток"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не знайдено"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Елемент керування недоступний"</string>
@@ -1004,8 +1006,7 @@
<string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Встановлено додаток для камери"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Додаток налаштовано"</string>
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Принаймні один пристрій доступний"</string>
- <!-- no translation found for keyguard_affordance_press_too_short (8145437175134998864) -->
- <skip />
+ <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Натисніть і утримуйте ярлик"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Скасувати"</string>
<string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Перевернути"</string>
<string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Розгорніть телефон, щоб зробити краще селфі"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index d432ff578ab2..cfcdeca3a2c9 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"یہاں چلانے کے ليے <xliff:g id="DEVICENAME">%1$s</xliff:g> کے قریب جائیں"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> پر چل رہا ہے"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"کچھ غلط ہوگیا۔ پھر کوشش کریں۔"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"غیر فعال، ایپ چیک کریں"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"نہیں ملا"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"کنٹرول دستیاب نہیں ہے"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 8c92678c3a4b..83085190c1fa 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Bu yerda ijro qilish uchun <xliff:g id="DEVICENAME">%1$s</xliff:g>qurilmasiga yaqinlashtiring"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> qurilmasida ijro qilinmoqda"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Xatolik yuz berdi. Qayta urining."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Nofaol. Ilovani tekshiring"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Topilmadi"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Boshqarish imkonsiz"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 4e70744fa149..80aa82293e65 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Di chuyển đến gần <xliff:g id="DEVICENAME">%1$s</xliff:g> hơn để phát tại đây"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Đang phát trên <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Đã xảy ra lỗi. Hãy thử lại."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Không hoạt động, hãy kiểm tra ứng dụng"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Không tìm thấy"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Không có chức năng điều khiển"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index f747730eaaf9..a449e9e332cd 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"若要在此设备上播放,请靠近“<xliff:g id="DEVICENAME">%1$s</xliff:g>”"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"正在“<xliff:g id="DEVICENAME">%1$s</xliff:g>”上播放"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"出了点问题,请重试。"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"无效,请检查应用"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"未找到"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"控件不可用"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 01cf0dc557ce..4749e3bc9a97 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"如要在此裝置上播放,請靠近「<xliff:g id="DEVICENAME">%1$s</xliff:g>」"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"正在「<xliff:g id="DEVICENAME">%1$s</xliff:g>」上播放"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"發生錯誤,請再試一次。"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"已停用,請檢查應用程式"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"找不到"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"無法使用控制功能"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 0c9bf9952c3a..4972aee02a80 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"如要在這部裝置上播放,請移到更靠近「<xliff:g id="DEVICENAME">%1$s</xliff:g>」的位置"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"正在「<xliff:g id="DEVICENAME">%1$s</xliff:g>」上播放"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"發生錯誤,請再試一次。"</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"無效,請查看應用程式"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"找不到控制項"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"無法使用控制項"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 029cbb003eee..d9cf44b3fe3d 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -853,6 +853,8 @@
<string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Sondela eduze ne-<xliff:g id="DEVICENAME">%1$s</xliff:g> ukuze udlale lapha"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Idlala ku-<xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Kukhona okungahambanga kahle. Zama futhi."</string>
+ <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Akusebenzi, hlola uhlelo lokusebenza"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ayitholakali"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Ukulawula akutholakali"</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
index 8ee893c14727..359da13a9799 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
@@ -249,7 +249,8 @@ public class RotationButtonController {
}
public void setRotationLockedAtAngle(int rotationSuggestion) {
- RotationPolicy.setRotationLockAtAngle(mContext, true, rotationSuggestion);
+ RotationPolicy.setRotationLockAtAngle(mContext, /* enabled= */ isRotationLocked(),
+ /* rotation= */ rotationSuggestion);
}
public boolean isRotationLocked() {
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index dd6a1bd457b8..1322f16a5a59 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -501,6 +501,17 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
}
@Override
+ public void onBiometricsCleared() {
+ final boolean wasUserUnlockedWithBiometric = mUserUnlockedWithBiometric;
+ mUserUnlockedWithBiometric =
+ mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(
+ KeyguardUpdateMonitor.getCurrentUser());
+ if (wasUserUnlockedWithBiometric != mUserUnlockedWithBiometric) {
+ updateVisibility();
+ }
+ }
+
+ @Override
public void onBiometricRunningStateChanged(boolean running,
BiometricSourceType biometricSourceType) {
final boolean wasRunningFps = mRunningFPS;
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index e40c98892ab5..20ae64cf5985 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -197,6 +197,11 @@ object Flags {
@JvmField
val UNOCCLUSION_TRANSITION = unreleasedFlag(223, "unocclusion_transition", teamfood = false)
+ // flag for controlling auto pin confirmation and material u shapes in bouncer
+ @JvmField
+ val AUTO_PIN_CONFIRMATION =
+ unreleasedFlag(224, "auto_pin_confirmation", "auto_pin_confirmation")
+
// 300 - power menu
// TODO(b/254512600): Tracking Bug
@JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite")
@@ -208,6 +213,10 @@ object Flags {
releasedFlag(401, "smartspace_shared_element_transition_enabled")
val SMARTSPACE = resourceBooleanFlag(402, R.bool.flag_smartspace, "smartspace")
+ // TODO(b/258517050): Clean up after the feature is launched.
+ @JvmField
+ val SMARTSPACE_DATE_WEATHER_DECOUPLED = unreleasedFlag(403, "smartspace_date_weather_decoupled")
+
// 500 - quick settings
// TODO(b/254512321): Tracking Bug
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index 53070a0ab8a7..228320b107cd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -23,6 +23,7 @@ import android.content.Context
import android.graphics.Matrix
import android.graphics.Rect
import android.os.Handler
+import android.os.PowerManager
import android.os.RemoteException
import android.util.Log
import android.view.RemoteAnimationTarget
@@ -145,7 +146,8 @@ class KeyguardUnlockAnimationController @Inject constructor(
private val featureFlags: FeatureFlags,
private val biometricUnlockControllerLazy: Lazy<BiometricUnlockController>,
private val statusBarStateController: SysuiStatusBarStateController,
- private val notificationShadeWindowController: NotificationShadeWindowController
+ private val notificationShadeWindowController: NotificationShadeWindowController,
+ private val powerManager: PowerManager
) : KeyguardStateController.Callback, ISysuiUnlockAnimationController.Stub() {
interface KeyguardUnlockAnimationListener {
@@ -344,7 +346,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
override fun onAnimationEnd(animation: Animator) {
Log.d(TAG, "surfaceBehindEntryAnimator#onAnimationEnd")
playingCannedUnlockAnimation = false
- keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(
+ keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
false /* cancelled */
)
}
@@ -579,7 +581,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
biometricUnlockControllerLazy.get().isWakeAndUnlock -> {
Log.d(TAG, "playCannedUnlockAnimation, isWakeAndUnlock")
setSurfaceBehindAppearAmount(1f)
- keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(
+ keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
false /* cancelled */)
}
@@ -627,7 +629,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
return@postDelayed
}
- keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(
+ keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
false /* cancelled */)
}, CANNED_UNLOCK_START_DELAY)
}
@@ -745,7 +747,8 @@ class KeyguardUnlockAnimationController @Inject constructor(
!keyguardStateController.isFlingingToDismissKeyguardDuringSwipeGesture &&
dismissAmount >= DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD)) {
setSurfaceBehindAppearAmount(1f)
- keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(false /* cancelled */)
+ keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
+ false /* cancelled */)
}
}
@@ -783,10 +786,15 @@ class KeyguardUnlockAnimationController @Inject constructor(
surfaceHeight * SURFACE_BEHIND_SCALE_PIVOT_Y
)
- // If we're snapping the keyguard back, immediately begin fading it out.
- val animationAlpha =
- if (keyguardStateController.isSnappingKeyguardBackAfterSwipe) amount
- else surfaceBehindAlpha
+
+ val animationAlpha = when {
+ // If we're snapping the keyguard back, immediately begin fading it out.
+ keyguardStateController.isSnappingKeyguardBackAfterSwipe -> amount
+ // If the screen has turned back off, the unlock animation is going to be cancelled,
+ // so set the surface alpha to 0f so it's no longer visible.
+ !powerManager.isInteractive -> 0f
+ else -> surfaceBehindAlpha
+ }
// SyncRtSurfaceTransactionApplier cannot apply transaction when the target view is
// unable to draw
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 8aada1f12b0c..bb2141d3fa16 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -144,12 +144,12 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.DeviceConfigProxy;
-import dagger.Lazy;
-
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.concurrent.Executor;
+import dagger.Lazy;
+
/**
* Mediates requests related to the keyguard. This includes queries about the
* state of the keyguard, power management events that effect whether the keyguard
@@ -2725,27 +2725,42 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
}
/**
- * Called if the keyguard exit animation has been cancelled, and we should dismiss to the
- * keyguard.
+ * Called if the keyguard exit animation has been cancelled.
*
* This can happen due to the system cancelling the RemoteAnimation (due to a timeout, a new
- * app transition before finishing the current RemoteAnimation).
+ * app transition before finishing the current RemoteAnimation, or the keyguard being re-shown).
*/
private void handleCancelKeyguardExitAnimation() {
- showSurfaceBehindKeyguard();
- onKeyguardExitRemoteAnimationFinished(true /* cancelled */);
+ if (mPendingLock) {
+ Log.d(TAG, "#handleCancelKeyguardExitAnimation: keyguard exit animation cancelled. "
+ + "There's a pending lock, so we were cancelled because the device was locked "
+ + "again during the unlock sequence. We should end up locked.");
+
+ // A lock is pending, meaning the keyguard exit animation was cancelled because we're
+ // re-locking. We should just end the surface-behind animation without exiting the
+ // keyguard. The pending lock will be handled by onFinishedGoingToSleep().
+ finishSurfaceBehindRemoteAnimation(true);
+ } else {
+ Log.d(TAG, "#handleCancelKeyguardExitAnimation: keyguard exit animation cancelled. "
+ + "No pending lock, we should end up unlocked with the app/launcher visible.");
+
+ // No lock is pending, so the animation was cancelled during the unlock sequence, but
+ // we should end up unlocked. Show the surface and exit the keyguard.
+ showSurfaceBehindKeyguard();
+ exitKeyguardAndFinishSurfaceBehindRemoteAnimation(true /* cancelled */);
+ }
}
/**
- * Called when we're done running the keyguard exit animation.
+ * Called when we're done running the keyguard exit animation, we should now end up unlocked.
*
- * This will call {@link #mSurfaceBehindRemoteAnimationFinishedCallback} to let WM know that
- * we're done with the RemoteAnimation, actually hide the keyguard, and clean up state related
- * to the keyguard exit animation.
+ * This will call {@link #handleCancelKeyguardExitAnimation()} to let WM know that we're done
+ * with the RemoteAnimation, actually hide the keyguard, and clean up state related to the
+ * keyguard exit animation.
*
* @param cancelled {@code true} if the animation was cancelled before it finishes.
*/
- public void onKeyguardExitRemoteAnimationFinished(boolean cancelled) {
+ public void exitKeyguardAndFinishSurfaceBehindRemoteAnimation(boolean cancelled) {
Log.d(TAG, "onKeyguardExitRemoteAnimationFinished");
if (!mSurfaceBehindRemoteAnimationRunning && !mSurfaceBehindRemoteAnimationRequested) {
Log.d(TAG, "skip onKeyguardExitRemoteAnimationFinished cancelled=" + cancelled
@@ -2774,10 +2789,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
}
finishSurfaceBehindRemoteAnimation(cancelled);
- mSurfaceBehindRemoteAnimationRequested = false;
-
- // The remote animation is over, so we're not going away anymore.
- mKeyguardStateController.notifyKeyguardGoingAway(false);
// Dispatch the callback on animation finishes.
mUpdateMonitor.dispatchKeyguardDismissAnimationFinished();
@@ -2836,13 +2847,17 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
return mSurfaceBehindRemoteAnimationRunning;
}
- /** If it's running, finishes the RemoteAnimation on the surface behind the keyguard. */
+ /**
+ * If it's running, finishes the RemoteAnimation on the surface behind the keyguard and resets
+ * related state.
+ *
+ * This does not set keyguard state to either locked or unlocked, it simply ends the remote
+ * animation on the surface behind the keyguard. This can be called by
+ */
void finishSurfaceBehindRemoteAnimation(boolean cancelled) {
- if (!mSurfaceBehindRemoteAnimationRunning) {
- return;
- }
-
+ mSurfaceBehindRemoteAnimationRequested = false;
mSurfaceBehindRemoteAnimationRunning = false;
+ mKeyguardStateController.notifyKeyguardGoingAway(false);
if (mSurfaceBehindRemoteAnimationFinishedCallback != null) {
try {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
index db7a145e2ade..15c34430f455 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
@@ -1070,7 +1070,9 @@ public class MediaControlPanel {
TurbulenceNoiseAnimationConfig.DEFAULT_OPACITY,
/* width= */ mMediaViewHolder.getMultiRippleView().getWidth(),
/* height= */ mMediaViewHolder.getMultiRippleView().getHeight(),
- TurbulenceNoiseAnimationConfig.DEFAULT_NOISE_DURATION_IN_MILLIS,
+ TurbulenceNoiseAnimationConfig.DEFAULT_MAX_DURATION_IN_MILLIS,
+ TurbulenceNoiseAnimationConfig.DEFAULT_EASING_DURATION_IN_MILLIS,
+ TurbulenceNoiseAnimationConfig.DEFAULT_EASING_DURATION_IN_MILLIS,
this.getContext().getResources().getDisplayMetrics().density,
BlendMode.PLUS,
/* onAnimationEnd= */ null
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index 154518dceddf..d6ad7d0fb8cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -238,6 +238,7 @@ class LockscreenSmartspaceController @Inject constructor(
}
val ssView = plugin.getView(parent)
+ ssView.setUiSurface(BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
ssView.registerDataProvider(plugin)
ssView.setIntentStarter(object : BcSmartspaceDataPlugin.IntentStarter {
@@ -281,8 +282,10 @@ class LockscreenSmartspaceController @Inject constructor(
}
val newSession = smartspaceManager.createSmartspaceSession(
- SmartspaceConfig.Builder(context, "lockscreen").build())
- Log.d(TAG, "Starting smartspace session for lockscreen")
+ SmartspaceConfig.Builder(
+ context, BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD).build())
+ Log.d(TAG, "Starting smartspace session for " +
+ BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
newSession.addOnTargetsAvailableListener(uiExecutor, sessionListener)
this.session = newSession
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
index ae8f419d4e64..e4c41a7ed804 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
@@ -68,6 +68,7 @@ import org.mockito.quality.Strictness;
public class LockIconViewControllerBaseTest extends SysuiTestCase {
protected static final String UNLOCKED_LABEL = "unlocked";
+ protected static final String LOCKED_LABEL = "locked";
protected static final int PADDING = 10;
protected MockitoSession mStaticMockSession;
@@ -130,6 +131,7 @@ public class LockIconViewControllerBaseTest extends SysuiTestCase {
Rect windowBounds = new Rect(0, 0, 800, 1200);
when(mWindowManager.getCurrentWindowMetrics().getBounds()).thenReturn(windowBounds);
when(mResources.getString(R.string.accessibility_unlock_button)).thenReturn(UNLOCKED_LABEL);
+ when(mResources.getString(R.string.accessibility_lock_icon)).thenReturn(LOCKED_LABEL);
when(mResources.getDrawable(anyInt(), any())).thenReturn(mIconDrawable);
when(mResources.getDimensionPixelSize(R.dimen.lock_icon_padding)).thenReturn(PADDING);
when(mAuthController.getScaleFactor()).thenReturn(1f);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
index da40595a4f12..b69491ed1096 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
@@ -262,6 +262,26 @@ public class LockIconViewControllerTest extends LockIconViewControllerBaseTest {
// THEN the view is updated to NO translation (no burn-in offsets anymore)
verify(mLockIconView).setTranslationY(0);
verify(mLockIconView).setTranslationX(0);
+ }
+
+ @Test
+ public void lockIconShows_afterBiometricsCleared() {
+ // GIVEN lock icon controller is initialized and view is attached
+ init(/* useMigrationFlag= */false);
+ captureKeyguardUpdateMonitorCallback();
+
+ // GIVEN user has unlocked with a biometric auth (ie: face auth)
+ // and biometric running state changes
+ when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(anyInt())).thenReturn(true);
+ mKeyguardUpdateMonitorCallback.onBiometricRunningStateChanged(false,
+ BiometricSourceType.FACE);
+ reset(mLockIconView);
+
+ // WHEN biometrics are cleared
+ when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(anyInt())).thenReturn(false);
+ mKeyguardUpdateMonitorCallback.onBiometricsCleared();
+ // THEN the lock icon is shown
+ verify(mLockIconView).setContentDescription(LOCKED_LABEL);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
index a78c902a1f30..2c81e82f34df 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
@@ -4,6 +4,7 @@ import android.app.ActivityManager
import android.app.WindowConfiguration
import android.graphics.Point
import android.graphics.Rect
+import android.os.PowerManager
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import android.view.RemoteAnimationTarget
@@ -19,15 +20,16 @@ import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.mockito.whenever
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor.forClass
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
@@ -56,6 +58,8 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
private lateinit var statusBarStateController: SysuiStatusBarStateController
@Mock
private lateinit var notificationShadeWindowController: NotificationShadeWindowController
+ @Mock
+ private lateinit var powerManager: PowerManager
@Mock
private lateinit var launcherUnlockAnimationController: ILauncherUnlockAnimationController.Stub
@@ -79,12 +83,13 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
keyguardUnlockAnimationController = KeyguardUnlockAnimationController(
context, keyguardStateController, { keyguardViewMediator }, keyguardViewController,
featureFlags, { biometricUnlockController }, statusBarStateController,
- notificationShadeWindowController
+ notificationShadeWindowController, powerManager
)
keyguardUnlockAnimationController.setLauncherUnlockController(
launcherUnlockAnimationController)
- `when`(keyguardViewController.viewRootImpl).thenReturn(mock(ViewRootImpl::class.java))
+ whenever(keyguardViewController.viewRootImpl).thenReturn(mock(ViewRootImpl::class.java))
+ whenever(powerManager.isInteractive).thenReturn(true)
// All of these fields are final, so we can't mock them, but are needed so that the surface
// appear amount setter doesn't short circuit.
@@ -96,6 +101,12 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
keyguardUnlockAnimationController.surfaceTransactionApplier = surfaceTransactionApplier
}
+ @After
+ fun tearDown() {
+ keyguardUnlockAnimationController.surfaceBehindEntryAnimator.cancel()
+ keyguardUnlockAnimationController.surfaceBehindAlphaAnimator.cancel()
+ }
+
/**
* If we're wake and unlocking, we are animating from the black/AOD screen to the app/launcher
* underneath. The LightRevealScrim will animate circularly from the fingerprint reader,
@@ -104,7 +115,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
*/
@Test
fun noSurfaceAnimation_ifWakeAndUnlocking() {
- `when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
+ whenever(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
remoteAnimationTargets,
@@ -124,7 +135,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
// Also expect we've immediately asked the keyguard view mediator to finish the remote
// animation.
- verify(keyguardViewMediator, times(1)).onKeyguardExitRemoteAnimationFinished(
+ verify(keyguardViewMediator, times(1)).exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
false /* cancelled */)
verifyNoMoreInteractions(surfaceTransactionApplier)
@@ -135,7 +146,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
*/
@Test
fun surfaceAnimation_ifNotWakeAndUnlocking() {
- `when`(biometricUnlockController.isWakeAndUnlock).thenReturn(false)
+ whenever(biometricUnlockController.isWakeAndUnlock).thenReturn(false)
keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
remoteAnimationTargets,
@@ -144,7 +155,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
)
// Since the animation is running, we should not have finished the remote animation.
- verify(keyguardViewMediator, times(0)).onKeyguardExitRemoteAnimationFinished(
+ verify(keyguardViewMediator, times(0)).exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
false /* cancelled */)
}
@@ -159,7 +170,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
*/
@Test
fun fadeInSurfaceBehind_ifRequestedShowSurface_butNotFlinging() {
- `when`(keyguardStateController.isFlingingToDismissKeyguard).thenReturn(false)
+ whenever(keyguardStateController.isFlingingToDismissKeyguard).thenReturn(false)
keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
remoteAnimationTargets,
@@ -181,7 +192,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
*/
@Test
fun playCannedUnlockAnimation_ifRequestedShowSurface_andFlinging() {
- `when`(keyguardStateController.isFlingingToDismissKeyguard).thenReturn(true)
+ whenever(keyguardStateController.isFlingingToDismissKeyguard).thenReturn(true)
keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
remoteAnimationTargets,
@@ -215,7 +226,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
@Test
fun doNotPlayCannedUnlockAnimation_ifLaunchingApp() {
- `when`(notificationShadeWindowController.isLaunchingActivity).thenReturn(true)
+ whenever(notificationShadeWindowController.isLaunchingActivity).thenReturn(true)
keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
remoteAnimationTargets,
@@ -272,7 +283,53 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
assertTrue(remainingTargets.isEmpty())
// Since the animation is running, we should not have finished the remote animation.
- verify(keyguardViewMediator, times(0)).onKeyguardExitRemoteAnimationFinished(
+ verify(keyguardViewMediator, times(0)).exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
false /* cancelled */)
}
+
+ @Test
+ fun surfaceBehindAlphaOverriddenTo0_ifNotInteractive() {
+ whenever(powerManager.isInteractive).thenReturn(false)
+
+ keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
+ remoteAnimationTargets,
+ 0 /* startTime */,
+ false /* requestedShowSurfaceBehindKeyguard */
+ )
+
+ keyguardUnlockAnimationController.setSurfaceBehindAppearAmount(1f)
+
+ val captor = forClass(SyncRtSurfaceTransactionApplier.SurfaceParams::class.java)
+ verify(surfaceTransactionApplier, times(1)).scheduleApply(captor.capture())
+
+ val params = captor.value
+
+ // We expect that we've set the surface behind to alpha = 0f since we're not interactive.
+ assertEquals(params.alpha, 0f)
+ assertTrue(params.matrix.isIdentity)
+
+ verifyNoMoreInteractions(surfaceTransactionApplier)
+ }
+
+ @Test
+ fun surfaceBehindAlphaNotOverriddenTo0_ifInteractive() {
+ whenever(powerManager.isInteractive).thenReturn(true)
+
+ keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
+ remoteAnimationTargets,
+ 0 /* startTime */,
+ false /* requestedShowSurfaceBehindKeyguard */
+ )
+
+ keyguardUnlockAnimationController.setSurfaceBehindAppearAmount(1f)
+
+ val captor = forClass(SyncRtSurfaceTransactionApplier.SurfaceParams::class.java)
+ verify(surfaceTransactionApplier, times(1)).scheduleApply(captor.capture())
+
+ val params = captor.value
+ assertEquals(params.alpha, 1f)
+ assertTrue(params.matrix.isIdentity)
+
+ verifyNoMoreInteractions(surfaceTransactionApplier)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index c38e27aa76bb..5196f4962a6c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -57,6 +57,7 @@ import com.android.keyguard.KeyguardDisplayManager;
import com.android.keyguard.KeyguardSecurityView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.mediator.ScreenOnCoordinator;
+import com.android.systemui.DejankUtils;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.biometrics.AuthController;
@@ -160,6 +161,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
mScreenOffAnimationController, mAuthController, mShadeExpansionStateManager,
mShadeWindowLogger);
+ DejankUtils.setImmediate(true);
+
createAndStartViewMediator();
}
@@ -357,7 +360,67 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
@Test
@TestableLooper.RunWithLooper(setAsMainLooper = true)
+ public void testCancelKeyguardExitAnimation_noPendingLock_keyguardWillNotBeShowing() {
+ startMockKeyguardExitAnimation();
+ cancelMockKeyguardExitAnimation();
+
+ // There should not be a pending lock, but try to handle it anyway to ensure one isn't set.
+ mViewMediator.maybeHandlePendingLock();
+ TestableLooper.get(this).processAllMessages();
+
+ assertFalse(mViewMediator.isShowingAndNotOccluded());
+ }
+
+ @Test
+ @TestableLooper.RunWithLooper(setAsMainLooper = true)
+ public void testCancelKeyguardExitAnimationDueToSleep_withPendingLock_keyguardWillBeShowing() {
+ startMockKeyguardExitAnimation();
+
+ mViewMediator.onStartedGoingToSleep(PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
+ mViewMediator.onFinishedGoingToSleep(PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, false);
+
+ cancelMockKeyguardExitAnimation();
+
+ mViewMediator.maybeHandlePendingLock();
+ TestableLooper.get(this).processAllMessages();
+
+ assertTrue(mViewMediator.isShowingAndNotOccluded());
+ }
+
+ @Test
+ @TestableLooper.RunWithLooper(setAsMainLooper = true)
+ public void testCancelKeyguardExitAnimationThenSleep_withPendingLock_keyguardWillBeShowing() {
+ startMockKeyguardExitAnimation();
+ cancelMockKeyguardExitAnimation();
+
+ mViewMediator.maybeHandlePendingLock();
+ TestableLooper.get(this).processAllMessages();
+
+ mViewMediator.onStartedGoingToSleep(PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
+ mViewMediator.onFinishedGoingToSleep(PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, false);
+
+ mViewMediator.maybeHandlePendingLock();
+ TestableLooper.get(this).processAllMessages();
+
+ assertTrue(mViewMediator.isShowingAndNotOccluded());
+ }
+
+ @Test
+ @TestableLooper.RunWithLooper(setAsMainLooper = true)
public void testStartKeyguardExitAnimation_expectSurfaceBehindRemoteAnimation() {
+ startMockKeyguardExitAnimation();
+ assertTrue(mViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind());
+ }
+
+ /**
+ * Configures mocks appropriately, then starts the keyguard exit animation.
+ */
+ private void startMockKeyguardExitAnimation() {
+ mViewMediator.onSystemReady();
+ TestableLooper.get(this).processAllMessages();
+
+ mViewMediator.setShowingLocked(true);
+
RemoteAnimationTarget[] apps = new RemoteAnimationTarget[]{
mock(RemoteAnimationTarget.class)
};
@@ -366,10 +429,19 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
};
IRemoteAnimationFinishedCallback callback = mock(IRemoteAnimationFinishedCallback.class);
+ when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true);
mViewMediator.startKeyguardExitAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY, apps, wallpapers,
null, callback);
TestableLooper.get(this).processAllMessages();
- assertTrue(mViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind());
+ }
+
+ /**
+ * Configures mocks appropriately, then cancels the keyguard exit animation.
+ */
+ private void cancelMockKeyguardExitAnimation() {
+ when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(false);
+ mViewMediator.cancelKeyguardExitAnimation();
+ TestableLooper.get(this).processAllMessages();
}
private void createAndStartViewMediator() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
index 37f96c8d7023..001e1f4d8086 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
@@ -98,6 +98,8 @@ class DreamSmartspaceControllerTest : SysuiTestCase() {
override fun setIsDreaming(isDreaming: Boolean) {}
+ override fun setUiSurface(uiSurface: String) {}
+
override fun setDozeAmount(amount: Float) {}
override fun setIntentStarter(intentStarter: BcSmartspaceDataPlugin.IntentStarter?) {}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
index 790865bb496f..ddcf59ec001f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
@@ -55,21 +55,21 @@ import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.settings.SecureSettings
import com.android.systemui.util.time.FakeSystemClock
-import java.util.Optional
-import java.util.concurrent.Executor
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
+import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
+import java.util.Optional
+import java.util.concurrent.Executor
@SmallTest
class LockscreenSmartspaceControllerTest : SysuiTestCase() {
@@ -518,6 +518,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
// THEN the existing session is reused and views are registered
verify(smartspaceManager, never()).createSmartspaceSession(any())
+ verify(smartspaceView2).setUiSurface(BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
verify(smartspaceView2).registerDataProvider(plugin)
}
@@ -554,6 +555,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
controller.stateChangeListener.onViewAttachedToWindow(view)
+ verify(smartspaceView).setUiSurface(BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
verify(smartspaceView).registerDataProvider(plugin)
verify(smartspaceSession)
.addOnTargetsAvailableListener(any(), capture(sessionListenerCaptor))
@@ -642,6 +644,9 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
override fun setIsDreaming(isDreaming: Boolean) {
}
+ override fun setUiSurface(uiSurface: String) {
+ }
+
override fun setDozeAmount(amount: Float) {
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt
index d25c8c1a5899..614261d476c6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt
@@ -17,8 +17,14 @@ package com.android.systemui.surfaceeffects.turbulencenoise
import android.graphics.Color
import android.testing.AndroidTestingRunner
+import android.view.View.INVISIBLE
+import android.view.View.VISIBLE
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController.Companion.AnimationState.EASE_IN
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController.Companion.AnimationState.EASE_OUT
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController.Companion.AnimationState.MAIN
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController.Companion.AnimationState.NOT_PLAYING
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -33,26 +39,117 @@ class TurbulenceNoiseControllerTest : SysuiTestCase() {
private val fakeExecutor = FakeExecutor(fakeSystemClock)
@Test
- fun play_playsTurbulenceNoise() {
- val config = TurbulenceNoiseAnimationConfig(duration = 1000f)
+ fun play_playsTurbulenceNoiseInOrder() {
+ val config = TurbulenceNoiseAnimationConfig(maxDuration = 1000f)
val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+ val turbulenceNoiseController = TurbulenceNoiseController(turbulenceNoiseView)
+
+ assertThat(turbulenceNoiseController.state).isEqualTo(NOT_PLAYING)
+
+ fakeExecutor.execute {
+ turbulenceNoiseController.play(config)
+
+ assertThat(turbulenceNoiseController.state).isEqualTo(EASE_IN)
+
+ fakeSystemClock.advanceTime(config.easeInDuration.toLong())
+
+ assertThat(turbulenceNoiseController.state).isEqualTo(MAIN)
+
+ fakeSystemClock.advanceTime(config.maxDuration.toLong())
+
+ assertThat(turbulenceNoiseController.state).isEqualTo(EASE_OUT)
+
+ fakeSystemClock.advanceTime(config.easeOutDuration.toLong())
+
+ assertThat(turbulenceNoiseController.state).isEqualTo(NOT_PLAYING)
+ }
+ }
+
+ @Test
+ fun play_alreadyPlaying_ignoresNewAnimationRequest() {
+ val config = TurbulenceNoiseAnimationConfig(maxDuration = 1000f)
+ val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+ // Currently playing the main animation.
+ val turbulenceNoiseController =
+ TurbulenceNoiseController(turbulenceNoiseView).also { it.state = MAIN }
+
+ fakeExecutor.execute {
+ // Request another animation
+ turbulenceNoiseController.play(config)
+
+ assertThat(turbulenceNoiseController.state).isEqualTo(MAIN)
+ }
+ }
+
+ @Test
+ fun finish_mainAnimationPlaying_playsEaseOutAnimation() {
+ val config = TurbulenceNoiseAnimationConfig(maxDuration = 1000f)
+ val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+ val turbulenceNoiseController =
+ TurbulenceNoiseController(turbulenceNoiseView).also { it.state = MAIN }
+
+ fakeExecutor.execute {
+ turbulenceNoiseController.play(config)
+
+ fakeSystemClock.advanceTime(config.maxDuration.toLong() / 2)
+
+ turbulenceNoiseController.finish()
+
+ assertThat(turbulenceNoiseController.state).isEqualTo(EASE_OUT)
+ }
+ }
+
+ @Test
+ fun finish_nonMainAnimationPlaying_doesNotFinishAnimation() {
+ val config = TurbulenceNoiseAnimationConfig(maxDuration = 1000f)
+ val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+ val turbulenceNoiseController =
+ TurbulenceNoiseController(turbulenceNoiseView).also { it.state = EASE_IN }
+
+ fakeExecutor.execute {
+ turbulenceNoiseController.play(config)
+
+ fakeSystemClock.advanceTime(config.maxDuration.toLong() / 2)
+
+ turbulenceNoiseController.finish()
+ assertThat(turbulenceNoiseController.state).isEqualTo(EASE_IN)
+ }
+ }
+
+ @Test
+ fun onAnimationFinished_resetsStateCorrectly() {
+ val config = TurbulenceNoiseAnimationConfig(maxDuration = 1000f)
+ val turbulenceNoiseView = TurbulenceNoiseView(context, null)
val turbulenceNoiseController = TurbulenceNoiseController(turbulenceNoiseView)
+ assertThat(turbulenceNoiseController.state).isEqualTo(NOT_PLAYING)
+ assertThat(turbulenceNoiseView.visibility).isEqualTo(INVISIBLE)
+ assertThat(turbulenceNoiseView.noiseConfig).isNull()
+
fakeExecutor.execute {
turbulenceNoiseController.play(config)
- assertThat(turbulenceNoiseView.isPlaying).isTrue()
+ assertThat(turbulenceNoiseController.state).isEqualTo(EASE_IN)
+ assertThat(turbulenceNoiseView.visibility).isEqualTo(VISIBLE)
+ assertThat(turbulenceNoiseView.noiseConfig).isEqualTo(config)
- fakeSystemClock.advanceTime(config.duration.toLong())
+ // Play all the animations.
+ fakeSystemClock.advanceTime(
+ config.easeInDuration.toLong() +
+ config.maxDuration.toLong() +
+ config.easeOutDuration.toLong()
+ )
- assertThat(turbulenceNoiseView.isPlaying).isFalse()
+ assertThat(turbulenceNoiseController.state).isEqualTo(NOT_PLAYING)
+ assertThat(turbulenceNoiseView.visibility).isEqualTo(INVISIBLE)
+ assertThat(turbulenceNoiseView.noiseConfig).isNull()
}
}
@Test
fun updateColor_updatesCorrectColor() {
- val config = TurbulenceNoiseAnimationConfig(duration = 1000f, color = Color.WHITE)
+ val config = TurbulenceNoiseAnimationConfig(maxDuration = 1000f, color = Color.WHITE)
val turbulenceNoiseView = TurbulenceNoiseView(context, null)
val expectedColor = Color.RED
@@ -61,9 +158,9 @@ class TurbulenceNoiseControllerTest : SysuiTestCase() {
fakeExecutor.execute {
turbulenceNoiseController.play(config)
- turbulenceNoiseView.updateColor(expectedColor)
+ turbulenceNoiseController.updateNoiseColor(expectedColor)
- fakeSystemClock.advanceTime(config.duration.toLong())
+ fakeSystemClock.advanceTime(config.maxDuration.toLong())
assertThat(config.color).isEqualTo(expectedColor)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt
index 633aac076502..ce7f2f4eb6ea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt
@@ -16,7 +16,6 @@
package com.android.systemui.surfaceeffects.turbulencenoise
import android.testing.AndroidTestingRunner
-import android.view.View
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.concurrency.FakeExecutor
@@ -34,53 +33,65 @@ class TurbulenceNoiseViewTest : SysuiTestCase() {
private val fakeExecutor = FakeExecutor(fakeSystemClock)
@Test
- fun play_viewHasCorrectVisibility() {
- val config = TurbulenceNoiseAnimationConfig(duration = 1000f)
- val turbulenceNoiseView = TurbulenceNoiseView(context, null)
-
- assertThat(turbulenceNoiseView.visibility).isEqualTo(View.INVISIBLE)
+ fun play_playsAnimation() {
+ val config = TurbulenceNoiseAnimationConfig()
+ val turbulenceNoiseView = TurbulenceNoiseView(context, null).also { it.applyConfig(config) }
+ var onAnimationEndCalled = false
fakeExecutor.execute {
- turbulenceNoiseView.play(config)
+ turbulenceNoiseView.play(onAnimationEnd = { onAnimationEndCalled = true })
+
+ fakeSystemClock.advanceTime(config.maxDuration.toLong())
- assertThat(turbulenceNoiseView.visibility).isEqualTo(View.VISIBLE)
+ assertThat(onAnimationEndCalled).isTrue()
+ }
+ }
- fakeSystemClock.advanceTime(config.duration.toLong())
+ @Test
+ fun playEaseIn_playsEaseInAnimation() {
+ val config = TurbulenceNoiseAnimationConfig()
+ val turbulenceNoiseView = TurbulenceNoiseView(context, null).also { it.applyConfig(config) }
+ var onAnimationEndCalled = false
- assertThat(turbulenceNoiseView.visibility).isEqualTo(View.INVISIBLE)
+ fakeExecutor.execute {
+ turbulenceNoiseView.playEaseIn(onAnimationEnd = { onAnimationEndCalled = true })
+
+ fakeSystemClock.advanceTime(config.easeInDuration.toLong())
+
+ assertThat(onAnimationEndCalled).isTrue()
}
}
@Test
- fun play_playsAnimation() {
- val config = TurbulenceNoiseAnimationConfig(duration = 1000f)
- val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+ fun playEaseOut_playsEaseOutAnimation() {
+ val config = TurbulenceNoiseAnimationConfig()
+ val turbulenceNoiseView = TurbulenceNoiseView(context, null).also { it.applyConfig(config) }
+ var onAnimationEndCalled = false
fakeExecutor.execute {
- turbulenceNoiseView.play(config)
+ turbulenceNoiseView.playEaseOut(onAnimationEnd = { onAnimationEndCalled = true })
+
+ fakeSystemClock.advanceTime(config.easeOutDuration.toLong())
- assertThat(turbulenceNoiseView.isPlaying).isTrue()
+ assertThat(onAnimationEndCalled).isTrue()
}
}
@Test
- fun play_onEnd_triggersOnAnimationEnd() {
- var animationEnd = false
- val config =
- TurbulenceNoiseAnimationConfig(
- duration = 1000f,
- onAnimationEnd = { animationEnd = true }
- )
- val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+ fun finish_animationPlaying_finishesAnimation() {
+ val config = TurbulenceNoiseAnimationConfig()
+ val turbulenceNoiseView = TurbulenceNoiseView(context, null).also { it.applyConfig(config) }
+ var onAnimationEndCalled = false
fakeExecutor.execute {
- turbulenceNoiseView.play(config)
+ turbulenceNoiseView.play(onAnimationEnd = { onAnimationEndCalled = true })
- assertThat(turbulenceNoiseView.isPlaying).isTrue()
+ assertThat(turbulenceNoiseView.currentAnimator).isNotNull()
- fakeSystemClock.advanceTime(config.duration.toLong())
+ turbulenceNoiseView.finish()
- assertThat(animationEnd).isTrue()
+ assertThat(onAnimationEndCalled).isTrue()
+ assertThat(turbulenceNoiseView.currentAnimator).isNull()
}
}
}
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index babe4eafd8f3..12c16fc43bd3 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -129,7 +129,7 @@ public final class SnoozeHelper {
protected Long getSnoozeTimeForUnpostedNotification(int userId, String pkg, String key) {
Long time = null;
synchronized (mLock) {
- time = mPersistedSnoozedNotifications.get(key);
+ time = mPersistedSnoozedNotifications.get(getTrimmedString(key));
}
if (time == null) {
time = 0L;
@@ -139,7 +139,7 @@ public final class SnoozeHelper {
protected String getSnoozeContextForUnpostedNotification(int userId, String pkg, String key) {
synchronized (mLock) {
- return mPersistedSnoozedNotificationsWithContext.get(key);
+ return mPersistedSnoozedNotificationsWithContext.get(getTrimmedString(key));
}
}
@@ -364,8 +364,9 @@ public final class SnoozeHelper {
final NotificationRecord record = mSnoozedNotifications.valueAt(i);
if (record.getUserId() == userId && record.getSbn().getPackageName().equals(pkg)) {
mSnoozedNotifications.removeAt(i);
- mPersistedSnoozedNotificationsWithContext.remove(record.getKey());
- mPersistedSnoozedNotifications.remove(record.getKey());
+ String trimmedKey = getTrimmedString(record.getKey());
+ mPersistedSnoozedNotificationsWithContext.remove(trimmedKey);
+ mPersistedSnoozedNotifications.remove(trimmedKey);
Runnable runnable = () -> {
final PendingIntent pi = createPendingIntent(record.getKey());
mAm.cancel(pi);
@@ -386,8 +387,9 @@ public final class SnoozeHelper {
final NotificationRecord record = mSnoozedNotifications.valueAt(i);
if (record.getUserId() == userId) {
mSnoozedNotifications.removeAt(i);
- mPersistedSnoozedNotificationsWithContext.remove(record.getKey());
- mPersistedSnoozedNotifications.remove(record.getKey());
+ String trimmedKey = getTrimmedString(record.getKey());
+ mPersistedSnoozedNotificationsWithContext.remove(trimmedKey);
+ mPersistedSnoozedNotifications.remove(trimmedKey);
Runnable runnable = () -> {
final PendingIntent pi = createPendingIntent(record.getKey());
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index de0d1f8f76af..5285f63dcc44 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1077,10 +1077,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// a tendency to hit the power button immediately when they pick up their device, and we
// don't want to put the device back to sleep in those cases.
final PowerManager.WakeData lastWakeUp = mPowerManagerInternal.getLastWakeup();
- if (lastWakeUp != null && lastWakeUp.wakeReason == PowerManager.WAKE_REASON_GESTURE) {
- final int gestureDelayMillis = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.POWER_BUTTON_SUPPRESSION_DELAY_AFTER_GESTURE_WAKE,
- POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS);
+ if (lastWakeUp != null && (lastWakeUp.wakeReason == PowerManager.WAKE_REASON_GESTURE
+ || lastWakeUp.wakeReason == PowerManager.WAKE_REASON_LIFT
+ || lastWakeUp.wakeReason == PowerManager.WAKE_REASON_BIOMETRIC)) {
final long now = SystemClock.uptimeMillis();
if (mPowerButtonSuppressionDelayMillis > 0
&& (now < lastWakeUp.wakeTime + mPowerButtonSuppressionDelayMillis)) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 9215cabad25a..6b01a7726a43 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -7938,6 +7938,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// The smallest screen width is the short side of screen bounds. Because the bounds
// and density won't be changed, smallestScreenWidthDp is also fixed.
overrideConfig.smallestScreenWidthDp = fullConfig.smallestScreenWidthDp;
+ // TODO(b/264276741): Check whether the runtime orietnation request is fixed rather than
+ // the manifest orientation which may be obsolete.
if (info.isFixedOrientation()) {
// lock rotation too. When in size-compat, onConfigurationChanged will watch for and
// apply runtime rotation changes.
@@ -8051,8 +8053,24 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
updateResolvedBoundsPosition(newParentConfiguration);
}
- if (mVisibleRequested) {
- updateCompatDisplayInsets();
+ boolean isIgnoreOrientationRequest = mDisplayContent != null
+ && mDisplayContent.getIgnoreOrientationRequest();
+ if (mCompatDisplayInsets == null // for size compat mode set in updateCompatDisplayInsets
+ // Fixed orientation letterboxing is possible on both large screen devices
+ // with ignoreOrientationRequest enabled and on phones in split screen even with
+ // ignoreOrientationRequest disabled.
+ && (mLetterboxBoundsForFixedOrientationAndAspectRatio != null
+ // Limiting check for aspect ratio letterboxing to devices with enabled
+ // ignoreOrientationRequest. This avoids affecting phones where apps may
+ // not expect the change of smallestScreenWidthDp after rotation which is
+ // possible with this logic. Not having smallestScreenWidthDp completely
+ // accurate on phones shouldn't make the big difference and is expected
+ // to be already well-tested by apps.
+ || (isIgnoreOrientationRequest && mIsAspectRatioApplied))) {
+ // TODO(b/264034555): Use mDisplayContent to calculate smallestScreenWidthDp from all
+ // rotations and only re-calculate if parent bounds have non-orientation size change.
+ resolvedConfig.smallestScreenWidthDp =
+ Math.min(resolvedConfig.screenWidthDp, resolvedConfig.screenHeightDp);
}
// Assign configuration sequence number into hierarchy because there is a different way than
@@ -8440,7 +8458,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Calculate app bounds using fixed orientation bounds because they will be needed later
// for comparison with size compat app bounds in {@link resolveSizeCompatModeConfiguration}.
getTaskFragment().computeConfigResourceOverrides(getResolvedOverrideConfiguration(),
- newParentConfig);
+ newParentConfig, mCompatDisplayInsets);
mLetterboxBoundsForFixedOrientationAndAspectRatio = new Rect(resolvedBounds);
}
@@ -9119,6 +9137,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mLastReportedDisplayId = newDisplayId;
}
+ // Calling from here rather than from onConfigurationChanged because it's possible that
+ // onConfigurationChanged was called before mVisibleRequested became true and
+ // mCompatDisplayInsets may not be called again when mVisibleRequested changes. And we
+ // don't want to save mCompatDisplayInsets in onConfigurationChanged without visibility
+ // check to avoid remembering obsolete configuration which can lead to unnecessary
+ // size-compat mode.
+ if (mVisibleRequested) {
+ // Calling from here rather than resolveOverrideConfiguration to ensure that this is
+ // called after full config is updated in ConfigurationContainer#onConfigurationChanged.
+ updateCompatDisplayInsets();
+ }
+
// Short circuit: if the two full configurations are equal (the common case), then there is
// nothing to do. We test the full configuration instead of the global and merged override
// configurations because there are cases (like moving a task to the root pinned task) where
@@ -9127,12 +9157,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (getConfiguration().equals(mTmpConfig) && !forceNewConfig && !displayChanged) {
ProtoLog.v(WM_DEBUG_CONFIGURATION, "Configuration & display "
+ "unchanged in %s", this);
- // It's possible that resolveOverrideConfiguration was called before mVisibleRequested
- // became true and mCompatDisplayInsets may not have been created so ensure
- // that mCompatDisplayInsets is created here.
- if (mVisibleRequested) {
- updateCompatDisplayInsets();
- }
return true;
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 36f86d10e2c5..75d84eabd146 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -5948,6 +5948,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
}
+ @Nullable
ActivityRecord topRunningActivity() {
return topRunningActivity(false /* considerKeyguardState */);
}
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index cf3a6880e712..e6d8b3db4564 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -100,6 +100,8 @@ public class DisplayRotation {
private final DisplayWindowSettings mDisplayWindowSettings;
private final Context mContext;
private final Object mLock;
+ @Nullable
+ private final DisplayRotationImmersiveAppCompatPolicy mCompatPolicyForImmersiveApps;
public final boolean isDefaultDisplay;
private final boolean mSupportAutoRotation;
@@ -205,7 +207,7 @@ public class DisplayRotation {
/**
* A flag to indicate if the display rotation should be fixed to user specified rotation
- * regardless of all other states (including app requrested orientation). {@code true} the
+ * regardless of all other states (including app requested orientation). {@code true} the
* display rotation should be fixed to user specified rotation, {@code false} otherwise.
*/
private int mFixedToUserRotation = IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT;
@@ -232,6 +234,7 @@ public class DisplayRotation {
mContext = context;
mLock = lock;
isDefaultDisplay = displayContent.isDefaultDisplay;
+ mCompatPolicyForImmersiveApps = initImmersiveAppCompatPolicy(service, displayContent);
mSupportAutoRotation =
mContext.getResources().getBoolean(R.bool.config_supportAutoRotation);
@@ -255,6 +258,14 @@ public class DisplayRotation {
}
}
+ @VisibleForTesting
+ @Nullable
+ DisplayRotationImmersiveAppCompatPolicy initImmersiveAppCompatPolicy(
+ WindowManagerService service, DisplayContent displayContent) {
+ return DisplayRotationImmersiveAppCompatPolicy.createIfNeeded(
+ service.mLetterboxConfiguration, this, displayContent);
+ }
+
// Change the default value to the value specified in the sysprop
// ro.bootanim.set_orientation_<display_id>. Four values are supported: ORIENTATION_0,
// ORIENTATION_90, ORIENTATION_180 and ORIENTATION_270.
@@ -1305,11 +1316,11 @@ public class DisplayRotation {
return mAllowAllRotations;
}
- private boolean isLandscapeOrSeascape(int rotation) {
+ boolean isLandscapeOrSeascape(@Surface.Rotation final int rotation) {
return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
}
- private boolean isAnyPortrait(int rotation) {
+ boolean isAnyPortrait(@Surface.Rotation final int rotation) {
return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
}
@@ -1348,9 +1359,16 @@ public class DisplayRotation {
return mFoldController != null && mFoldController.overrideFrozenRotation();
}
- private boolean isRotationChoicePossible(int orientation) {
- // Rotation choice is only shown when the user is in locked mode.
- if (mUserRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) return false;
+ private boolean isRotationChoiceAllowed(@Surface.Rotation final int proposedRotation) {
+ final boolean isRotationLockEnforced = mCompatPolicyForImmersiveApps != null
+ && mCompatPolicyForImmersiveApps.isRotationLockEnforced(proposedRotation);
+
+ // Don't show rotation choice button if
+ if (!isRotationLockEnforced // not enforcing locked rotation
+ // and the screen rotation is not locked by the user.
+ && mUserRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) {
+ return false;
+ }
// Don't show rotation choice if we are in tabletop or book modes.
if (isTabletopAutoRotateOverrideEnabled()) return false;
@@ -1402,7 +1420,7 @@ public class DisplayRotation {
}
// Ensure that some rotation choice is possible for the given orientation.
- switch (orientation) {
+ switch (mCurrentAppOrientation) {
case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
case ActivityInfo.SCREEN_ORIENTATION_USER:
case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
@@ -1719,11 +1737,11 @@ public class DisplayRotation {
@Override
- public void onProposedRotationChanged(int rotation) {
+ public void onProposedRotationChanged(@Surface.Rotation int rotation) {
ProtoLog.v(WM_DEBUG_ORIENTATION, "onProposedRotationChanged, rotation=%d", rotation);
// Send interaction power boost to improve redraw performance.
mService.mPowerManagerInternal.setPowerBoost(Boost.INTERACTION, 0);
- if (isRotationChoicePossible(mCurrentAppOrientation)) {
+ if (isRotationChoiceAllowed(rotation)) {
final boolean isValid = isValidRotationChoice(rotation);
sendProposedRotationChangeToStatusBarInternal(rotation, isValid);
} else {
diff --git a/services/core/java/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicy.java
new file mode 100644
index 000000000000..4dad2b23d3c7
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicy.java
@@ -0,0 +1,161 @@
+/*
+ * 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.server.wm;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
+import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.ITYPE_STATUS_BAR;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.Configuration.Orientation;
+import android.view.InsetsVisibilities;
+import android.view.Surface;
+
+/**
+ * Policy to decide whether to enforce screen rotation lock for optimisation of the screen rotation
+ * user experience for immersive applications for compatibility when ignoring orientation request.
+ *
+ * <p>This is needed because immersive apps, such as games, are often not optimized for all
+ * orientations and can have a poor UX when rotated (e.g., state loss or entering size-compat mode).
+ * Additionally, some games rely on sensors for the gameplay so users can trigger such rotations
+ * accidentally when auto rotation is on.
+ */
+final class DisplayRotationImmersiveAppCompatPolicy {
+
+ @Nullable
+ static DisplayRotationImmersiveAppCompatPolicy createIfNeeded(
+ @NonNull final LetterboxConfiguration letterboxConfiguration,
+ @NonNull final DisplayRotation displayRotation,
+ @NonNull final DisplayContent displayContent) {
+ if (!letterboxConfiguration
+ .isDisplayRotationImmersiveAppCompatPolicyEnabled(/* checkDeviceConfig */ false)) {
+ return null;
+ }
+
+ return new DisplayRotationImmersiveAppCompatPolicy(
+ letterboxConfiguration, displayRotation, displayContent);
+ }
+
+ private final DisplayRotation mDisplayRotation;
+ private final LetterboxConfiguration mLetterboxConfiguration;
+ private final DisplayContent mDisplayContent;
+
+ private DisplayRotationImmersiveAppCompatPolicy(
+ @NonNull final LetterboxConfiguration letterboxConfiguration,
+ @NonNull final DisplayRotation displayRotation,
+ @NonNull final DisplayContent displayContent) {
+ mDisplayRotation = displayRotation;
+ mLetterboxConfiguration = letterboxConfiguration;
+ mDisplayContent = displayContent;
+ }
+
+ /**
+ * Decides whether it is necessary to lock screen rotation, preventing auto rotation, based on
+ * the top activity configuration and proposed screen rotation.
+ *
+ * <p>This is needed because immersive apps, such as games, are often not optimized for all
+ * orientations and can have a poor UX when rotated. Additionally, some games rely on sensors
+ * for the gameplay so users can trigger such rotations accidentally when auto rotation is on.
+ *
+ * <p>Screen rotation is locked when the following conditions are met:
+ * <ul>
+ * <li>Top activity requests to hide status and navigation bars
+ * <li>Top activity is fullscreen and in optimal orientation (without letterboxing)
+ * <li>Rotation will lead to letterboxing due to fixed orientation.
+ * <li>{@link DisplayContent#getIgnoreOrientationRequest} is {@code true}
+ * <li>This policy is enabled on the device, for details see
+ * {@link LetterboxConfiguration#isDisplayRotationImmersiveAppCompatPolicyEnabled}
+ * </ul>
+ *
+ * @param proposedRotation new proposed {@link Surface.Rotation} for the screen.
+ * @return {@code true}, if there is a need to lock screen rotation, {@code false} otherwise.
+ */
+ boolean isRotationLockEnforced(@Surface.Rotation final int proposedRotation) {
+ if (!mLetterboxConfiguration.isDisplayRotationImmersiveAppCompatPolicyEnabled(
+ /* checkDeviceConfig */ true)) {
+ return false;
+ }
+ synchronized (mDisplayContent.mWmService.mGlobalLock) {
+ return isRotationLockEnforcedLocked(proposedRotation);
+ }
+ }
+
+ private boolean isRotationLockEnforcedLocked(@Surface.Rotation final int proposedRotation) {
+ if (!mDisplayContent.getIgnoreOrientationRequest()) {
+ return false;
+ }
+
+ final ActivityRecord activityRecord = mDisplayContent.topRunningActivity();
+ if (activityRecord == null) {
+ return false;
+ }
+
+ // Don't lock screen rotation if an activity hasn't requested to hide system bars.
+ if (!hasRequestedToHideStatusAndNavBars(activityRecord)) {
+ return false;
+ }
+
+ // Don't lock screen rotation if activity is not in fullscreen. Checking windowing mode
+ // for a task rather than an activity to exclude activity embedding scenario.
+ if (activityRecord.getTask() == null
+ || activityRecord.getTask().getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+ return false;
+ }
+
+ // Don't lock screen rotation if activity is letterboxed.
+ if (activityRecord.areBoundsLetterboxed()) {
+ return false;
+ }
+
+ if (activityRecord.getRequestedConfigurationOrientation() == ORIENTATION_UNDEFINED) {
+ return false;
+ }
+
+ // Lock screen rotation only if, after rotation the activity's orientation won't match
+ // the screen orientation, forcing the activity to enter letterbox mode after rotation.
+ return activityRecord.getRequestedConfigurationOrientation()
+ != surfaceRotationToConfigurationOrientation(proposedRotation);
+ }
+
+ /**
+ * Checks whether activity has requested to hide status and navigation bars.
+ */
+ private boolean hasRequestedToHideStatusAndNavBars(@NonNull ActivityRecord activity) {
+ WindowState mainWindow = activity.findMainWindow();
+ if (mainWindow == null) {
+ return false;
+ }
+ InsetsVisibilities insetsVisibilities = mainWindow.getRequestedVisibilities();
+ return !insetsVisibilities.getVisibility(ITYPE_STATUS_BAR)
+ && !insetsVisibilities.getVisibility(ITYPE_NAVIGATION_BAR);
+ }
+
+ @Orientation
+ private int surfaceRotationToConfigurationOrientation(@Surface.Rotation final int rotation) {
+ if (mDisplayRotation.isAnyPortrait(rotation)) {
+ return ORIENTATION_PORTRAIT;
+ } else if (mDisplayRotation.isLandscapeOrSeascape(rotation)) {
+ return ORIENTATION_LANDSCAPE;
+ } else {
+ return ORIENTATION_UNDEFINED;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index 5e4f2aeb37e4..f916ee40d538 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -18,6 +18,7 @@ package com.android.server.wm;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -227,23 +228,35 @@ final class LetterboxConfiguration {
// LetterboxUiController#shouldIgnoreRequestedOrientation for details.
private final boolean mIsPolicyForIgnoringRequestedOrientationEnabled;
- LetterboxConfiguration(Context systemUiContext) {
- this(systemUiContext, new LetterboxConfigurationPersister(systemUiContext,
- () -> readLetterboxHorizontalReachabilityPositionFromConfig(systemUiContext,
- /* forBookMode */ false),
- () -> readLetterboxVerticalReachabilityPositionFromConfig(systemUiContext,
- /* forTabletopMode */ false),
- () -> readLetterboxHorizontalReachabilityPositionFromConfig(systemUiContext,
- /* forBookMode */ true),
- () -> readLetterboxVerticalReachabilityPositionFromConfig(systemUiContext,
- /* forTabletopMode */ true)
- ));
+ // Whether enabling rotation compat policy for immersive apps that prevents auto rotation
+ // into non-optimal screen orientation while in fullscreen. This is needed because immersive
+ // apps, such as games, are often not optimized for all orientations and can have a poor UX
+ // when rotated. Additionally, some games rely on sensors for the gameplay so users can trigger
+ // such rotations accidentally when auto rotation is on.
+ private final boolean mIsDisplayRotationImmersiveAppCompatPolicyEnabled;
+
+ // Flags dynamically updated with {@link android.provider.DeviceConfig}.
+ @NonNull private final LetterboxConfigurationDeviceConfig mDeviceConfig;
+
+ LetterboxConfiguration(@NonNull final Context systemUiContext) {
+ this(systemUiContext,
+ new LetterboxConfigurationPersister(systemUiContext,
+ () -> readLetterboxHorizontalReachabilityPositionFromConfig(
+ systemUiContext, /* forBookMode */ false),
+ () -> readLetterboxVerticalReachabilityPositionFromConfig(
+ systemUiContext, /* forTabletopMode */ false),
+ () -> readLetterboxHorizontalReachabilityPositionFromConfig(
+ systemUiContext, /* forBookMode */ true),
+ () -> readLetterboxVerticalReachabilityPositionFromConfig(
+ systemUiContext, /* forTabletopMode */ true)));
}
@VisibleForTesting
- LetterboxConfiguration(Context systemUiContext,
- LetterboxConfigurationPersister letterboxConfigurationPersister) {
+ LetterboxConfiguration(@NonNull final Context systemUiContext,
+ @NonNull final LetterboxConfigurationPersister letterboxConfigurationPersister) {
mContext = systemUiContext;
+ mDeviceConfig = new LetterboxConfigurationDeviceConfig(systemUiContext.getMainExecutor());
+
mFixedOrientationLetterboxAspectRatio = mContext.getResources().getFloat(
R.dimen.config_fixedOrientationLetterboxAspectRatio);
mLetterboxActivityCornersRadius = mContext.getResources().getInteger(
@@ -284,6 +297,12 @@ final class LetterboxConfiguration {
mIsPolicyForIgnoringRequestedOrientationEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled);
+ mIsDisplayRotationImmersiveAppCompatPolicyEnabled = mContext.getResources().getBoolean(
+ R.bool.config_letterboxIsDisplayRotationImmersiveAppCompatPolicyEnabled);
+ mDeviceConfig.updateFlagActiveStatus(
+ /* isActive */ mIsDisplayRotationImmersiveAppCompatPolicyEnabled,
+ /* key */ KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY);
+
mLetterboxConfigurationPersister = letterboxConfigurationPersister;
mLetterboxConfigurationPersister.start();
}
@@ -1105,4 +1124,20 @@ final class LetterboxConfiguration {
mIsCameraCompatRefreshCycleThroughStopEnabled = true;
}
+ /**
+ * Checks whether rotation compat policy for immersive apps that prevents auto rotation
+ * into non-optimal screen orientation while in fullscreen is enabled.
+ *
+ * <p>This is needed because immersive apps, such as games, are often not optimized for all
+ * orientations and can have a poor UX when rotated. Additionally, some games rely on sensors
+ * for the gameplay so users can trigger such rotations accidentally when auto rotation is on.
+ *
+ * @param checkDeviceConfig whether should check both static config and a dynamic property
+ * from {@link DeviceConfig} or only static value.
+ */
+ boolean isDisplayRotationImmersiveAppCompatPolicyEnabled(final boolean checkDeviceConfig) {
+ return mIsDisplayRotationImmersiveAppCompatPolicyEnabled && (!checkDeviceConfig
+ || mDeviceConfig.getFlag(KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY));
+ }
+
}
diff --git a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
new file mode 100644
index 000000000000..cf123a1f9ace
--- /dev/null
+++ b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.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.server.wm;
+
+import android.annotation.NonNull;
+import android.provider.DeviceConfig;
+import android.util.ArraySet;
+
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Map;
+import java.util.concurrent.Executor;
+
+/**
+ * Utility class that caches {@link DeviceConfig} flags for app compat features and listens
+ * to updates by implementing {@link DeviceConfig.OnPropertiesChangedListener}.
+ */
+final class LetterboxConfigurationDeviceConfig
+ implements DeviceConfig.OnPropertiesChangedListener {
+
+ static final String KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY =
+ "enable_display_rotation_immersive_app_compat_policy";
+ private static final boolean DEFAULT_VALUE_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY =
+ true;
+
+ @VisibleForTesting
+ static final Map<String, Boolean> sKeyToDefaultValueMap = Map.of(
+ KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY,
+ DEFAULT_VALUE_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY
+ );
+
+ // Whether enabling rotation compat policy for immersive apps that prevents auto rotation
+ // into non-optimal screen orientation while in fullscreen. This is needed because immersive
+ // apps, such as games, are often not optimized for all orientations and can have a poor UX
+ // when rotated. Additionally, some games rely on sensors for the gameplay so users can trigger
+ // such rotations accidentally when auto rotation is on.
+ private boolean mIsDisplayRotationImmersiveAppCompatPolicyEnabled =
+ DEFAULT_VALUE_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY;
+
+ // Set of active device configs that need to be updated in
+ // DeviceConfig.OnPropertiesChangedListener#onPropertiesChanged.
+ private final ArraySet<String> mActiveDeviceConfigsSet = new ArraySet<>();
+
+ LetterboxConfigurationDeviceConfig(@NonNull final Executor executor) {
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ executor, /* onPropertiesChangedListener */ this);
+ }
+
+ @Override
+ public void onPropertiesChanged(@NonNull final DeviceConfig.Properties properties) {
+ for (int i = mActiveDeviceConfigsSet.size() - 1; i >= 0; i--) {
+ String key = mActiveDeviceConfigsSet.valueAt(i);
+ // Reads the new configuration, if the device config properties contain the key.
+ if (properties.getKeyset().contains(key)) {
+ readAndSaveValueFromDeviceConfig(key);
+ }
+ }
+ }
+
+ /**
+ * Adds {@code key} to a set of flags that can be updated from the server if
+ * {@code isActive} is {@code true} and read it's current value from {@link DeviceConfig}.
+ */
+ void updateFlagActiveStatus(boolean isActive, String key) {
+ if (!isActive) {
+ return;
+ }
+ mActiveDeviceConfigsSet.add(key);
+ readAndSaveValueFromDeviceConfig(key);
+ }
+
+ /**
+ * Returns values of the {@code key} flag.
+ *
+ * @throws AssertionError {@code key} isn't recognised.
+ */
+ boolean getFlag(String key) {
+ switch (key) {
+ case KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY:
+ return mIsDisplayRotationImmersiveAppCompatPolicyEnabled;
+ default:
+ throw new AssertionError("Unexpected flag name: " + key);
+ }
+ }
+
+ private void readAndSaveValueFromDeviceConfig(String key) {
+ Boolean defaultValue = sKeyToDefaultValueMap.get(key);
+ if (defaultValue == null) {
+ throw new AssertionError("Haven't found default value for flag: " + key);
+ }
+ switch (key) {
+ case KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY:
+ mIsDisplayRotationImmersiveAppCompatPolicyEnabled =
+ getDeviceConfig(key, defaultValue);
+ break;
+ default:
+ throw new AssertionError("Unexpected flag name: " + key);
+ }
+ }
+
+ private boolean getDeviceConfig(String key, boolean defaultValue) {
+ return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ key, defaultValue);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 689cae5777cd..22da56ad4d3b 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -2138,7 +2138,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
final Rect resolvedBounds = inOutConfig.windowConfiguration.getBounds();
- if (resolvedBounds == null || resolvedBounds.isEmpty()) {
+ if (resolvedBounds.isEmpty()) {
mTmpFullBounds.set(parentBounds);
insideParentBounds = true;
} else {
@@ -2227,6 +2227,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
: overrideScreenHeightDp;
}
+ // TODO(b/238331848): Consider simplifying logic that computes smallestScreenWidthDp.
if (inOutConfig.smallestScreenWidthDp
== Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
// When entering to or exiting from Pip, the PipTaskOrganizer will set the
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 700016be62f8..fb584feeaf04 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -3759,7 +3759,6 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
if (mSyncState == SYNC_STATE_NONE) return false;
mSyncState = SYNC_STATE_READY;
mSyncMethodOverride = BLASTSyncEngine.METHOD_UNDEFINED;
- mWmService.mWindowPlacerLocked.requestTraversal();
ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "onSyncFinishedDrawing %s", this);
return true;
}
@@ -3829,8 +3828,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
/**
* Checks if the subtree rooted at this container is finished syncing (everything is ready or
- * not visible). NOTE, this is not const: it will cancel/prepare itself depending on its state
- * in the hierarchy.
+ * not visible). NOTE, this is not const: it may cancel/prepare/complete itself depending on
+ * its state in the hierarchy.
*
* @return {@code true} if this subtree is finished waiting for sync participants.
*/
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b3a7754bc2d5..4e32a7ca3bf4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2587,12 +2587,6 @@ public class WindowManagerService extends IWindowManager.Stub
&& win.mSyncSeqId > lastSyncSeqId) {
maybeSyncSeqId = win.shouldSyncWithBuffers() ? win.mSyncSeqId : -1;
win.markRedrawForSyncReported();
- if (win.mSyncState == WindowContainer.SYNC_STATE_WAITING_FOR_DRAW
- && winAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN
- && maybeSyncSeqId < 0) {
- // Do not wait for a drawn window which won't report draw.
- win.onSyncFinishedDrawing();
- }
} else {
maybeSyncSeqId = -1;
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 2f55d1824c07..04699619bfc8 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -6004,12 +6004,16 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
@Override
boolean isSyncFinished() {
- if (mSyncState == SYNC_STATE_WAITING_FOR_DRAW && mViewVisibility != View.VISIBLE
- && !isVisibleRequested()) {
+ if (!isVisibleRequested()) {
// Don't wait for invisible windows. However, we don't alter the state in case the
// window becomes visible while the sync group is still active.
return true;
}
+ if (mSyncState == SYNC_STATE_WAITING_FOR_DRAW && mWinAnimator.mDrawState == HAS_DRAWN
+ && !mRedrawForSyncReported && !mWmService.mResizingWindows.contains(this)) {
+ // Complete the sync state immediately for a drawn window that doesn't need to redraw.
+ onSyncFinishedDrawing();
+ }
return super.isSyncFinished();
}
@@ -6060,6 +6064,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
final boolean hasSyncHandlers = executeDrawHandlers(postDrawTransaction, syncSeqId);
boolean skipLayout = false;
+ boolean layoutNeeded = false;
// Control the timing to switch the appearance of window with different rotations.
final AsyncRotationController asyncRotationController =
mDisplayContent.getAsyncRotationController();
@@ -6072,7 +6077,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
} else if (syncActive) {
// Currently in a Sync that is using BLAST.
if (!syncStillPending) {
- onSyncFinishedDrawing();
+ layoutNeeded = onSyncFinishedDrawing();
}
if (postDrawTransaction != null) {
mSyncTransaction.merge(postDrawTransaction);
@@ -6081,10 +6086,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
} else if (useBLASTSync()) {
// Sync that is not using BLAST
- onSyncFinishedDrawing();
+ layoutNeeded = onSyncFinishedDrawing();
}
- final boolean layoutNeeded =
+ layoutNeeded |=
mWinAnimator.finishDrawingLocked(postDrawTransaction, mClientWasDrawingForSync);
mClientWasDrawingForSync = false;
// We always want to force a traversal after a finish draw for blast sync.
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
index 1f117b3697c9..9c3d5a7fb6d9 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
@@ -234,7 +234,7 @@ public class SnoozeHelperTest extends UiServiceTestCase {
}
@Test
- public void testScheduleRepostsForLongTagPersistedNotification() throws Exception {
+ public void testLongTagPersistedNotification() throws Exception {
String longTag = "A".repeat(66000);
NotificationRecord r = getNotificationRecord("pkg", 1, longTag, UserHandle.SYSTEM);
mSnoozeHelper.snooze(r, 0);
@@ -612,7 +612,8 @@ public class SnoozeHelperTest extends UiServiceTestCase {
public void testClearData_userPackage() {
// snooze 2 from same package
NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
- NotificationRecord r2 = getNotificationRecord("pkg", 2, "two", UserHandle.SYSTEM);
+ NotificationRecord r2 = getNotificationRecord("pkg", 2, "two" + "2".repeat(66000),
+ UserHandle.SYSTEM); // include notif with very long tag
mSnoozeHelper.snooze(r, 1000);
mSnoozeHelper.snooze(r2, 1000);
assertTrue(mSnoozeHelper.isSnoozed(
@@ -634,11 +635,14 @@ public class SnoozeHelperTest extends UiServiceTestCase {
@Test
public void testClearData_user() {
- // snooze 2 from same package
+ // snooze 2 from same package, including notifs with long tag
NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
- NotificationRecord r2 = getNotificationRecord("pkg2", 2, "two", UserHandle.SYSTEM);
- NotificationRecord r3 = getNotificationRecord("pkg2", 3, "three", UserHandle.SYSTEM);
- NotificationRecord r4 = getNotificationRecord("pkg", 2, "two", UserHandle.ALL);
+ NotificationRecord r2 = getNotificationRecord("pkg2", 2, "two" + "2".repeat(66000),
+ UserHandle.SYSTEM);
+ NotificationRecord r3 = getNotificationRecord("pkg2", 3, "three",
+ UserHandle.SYSTEM);
+ NotificationRecord r4 = getNotificationRecord("pkg", 2, "two" + "2".repeat(66000),
+ UserHandle.ALL);
mSnoozeHelper.snooze(r, 1000);
mSnoozeHelper.snooze(r2, 1000);
mSnoozeHelper.snooze(r3, "until");
@@ -653,6 +657,19 @@ public class SnoozeHelperTest extends UiServiceTestCase {
assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_ALL, r4.getSbn().getPackageName(), r4.getKey()));
+ assertFalse(0L == mSnoozeHelper.getSnoozeTimeForUnpostedNotification(
+ r.getUser().getIdentifier(), r.getSbn().getPackageName(),
+ r.getSbn().getKey()));
+ assertFalse(0L == mSnoozeHelper.getSnoozeTimeForUnpostedNotification(
+ r2.getUser().getIdentifier(), r2.getSbn().getPackageName(),
+ r2.getSbn().getKey()));
+ assertNotNull(mSnoozeHelper.getSnoozeContextForUnpostedNotification(
+ r3.getUser().getIdentifier(), r3.getSbn().getPackageName(),
+ r3.getSbn().getKey()));
+ assertNotNull(mSnoozeHelper.getSnoozeContextForUnpostedNotification(
+ r4.getUser().getIdentifier(), r4.getSbn().getPackageName(),
+ r4.getSbn().getKey()));
+
// clear data
mSnoozeHelper.clearData(UserHandle.USER_SYSTEM);
@@ -666,18 +683,18 @@ public class SnoozeHelperTest extends UiServiceTestCase {
assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r4.getSbn().getPackageName(), r4.getKey()));
- assertNull(mSnoozeHelper.getSnoozeContextForUnpostedNotification(
- r3.getUser().getIdentifier(), r3.getSbn().getPackageName(),
- r3.getSbn().getKey()));
- assertNotNull(mSnoozeHelper.getSnoozeContextForUnpostedNotification(
- r4.getUser().getIdentifier(), r4.getSbn().getPackageName(),
- r4.getSbn().getKey()));
assertEquals(0L, mSnoozeHelper.getSnoozeTimeForUnpostedNotification(
r.getUser().getIdentifier(), r.getSbn().getPackageName(),
r.getSbn().getKey()).longValue());
assertEquals(0L, mSnoozeHelper.getSnoozeTimeForUnpostedNotification(
r2.getUser().getIdentifier(), r2.getSbn().getPackageName(),
r2.getSbn().getKey()).longValue());
+ assertNull(mSnoozeHelper.getSnoozeContextForUnpostedNotification(
+ r3.getUser().getIdentifier(), r3.getSbn().getPackageName(),
+ r3.getSbn().getKey()));
+ assertNotNull(mSnoozeHelper.getSnoozeContextForUnpostedNotification(
+ r4.getUser().getIdentifier(), r4.getSbn().getPackageName(),
+ r4.getSbn().getKey()));
// 2 for initial timed-snoozes, once each for canceling the USER_SYSTEM snoozes
verify(mAm, times(5)).cancel(any(PendingIntent.class));
diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp
index 079d765868fd..2ce7cea08a3d 100644
--- a/services/tests/wmtests/Android.bp
+++ b/services/tests/wmtests/Android.bp
@@ -68,6 +68,10 @@ android_test {
"android.test.runner",
],
+ defaults: [
+ "modules-utils-testable-device-config-defaults",
+ ],
+
// These are not normally accessible from apps so they must be explicitly included.
jni_libs: [
"libdexmakerjvmtiagent",
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicyTests.java
new file mode 100644
index 000000000000..def4b88701af
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationImmersiveAppCompatPolicyTests.java
@@ -0,0 +1,225 @@
+/*
+ * 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.server.wm;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
+import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.ITYPE_STATUS_BAR;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+
+import android.platform.test.annotations.Presubmit;
+import android.view.InsetsVisibilities;
+import android.view.Surface;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test class for {@link DisplayRotationImmersiveAppCompatPolicy}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:DisplayRotationImmersiveAppCompatPolicyTests
+ */
+@SmallTest
+@Presubmit
+@RunWith(WindowTestRunner.class)
+public class DisplayRotationImmersiveAppCompatPolicyTests extends WindowTestsBase {
+
+ private DisplayRotationImmersiveAppCompatPolicy mPolicy;
+
+ private LetterboxConfiguration mMockLetterboxConfiguration;
+ private ActivityRecord mMockActivityRecord;
+ private Task mMockTask;
+ private InsetsVisibilities mMockInsetsVisibilities;
+
+ @Before
+ public void setUp() throws Exception {
+ mMockActivityRecord = mock(ActivityRecord.class);
+ mMockTask = mock(Task.class);
+ when(mMockTask.getWindowingMode()).thenReturn(WINDOWING_MODE_FULLSCREEN);
+ when(mMockActivityRecord.getTask()).thenReturn(mMockTask);
+ when(mMockActivityRecord.areBoundsLetterboxed()).thenReturn(false);
+ when(mMockActivityRecord.getRequestedConfigurationOrientation()).thenReturn(
+ ORIENTATION_LANDSCAPE);
+ WindowState mockWindowState = mock(WindowState.class);
+ mMockInsetsVisibilities = mock(InsetsVisibilities.class);
+ when(mMockInsetsVisibilities.getVisibility(eq(ITYPE_STATUS_BAR))).thenReturn(false);
+ when(mMockInsetsVisibilities.getVisibility(eq(ITYPE_NAVIGATION_BAR))).thenReturn(false);
+ when(mockWindowState.getRequestedVisibilities()).thenReturn(mMockInsetsVisibilities);
+ when(mMockActivityRecord.findMainWindow()).thenReturn(mockWindowState);
+
+ spy(mDisplayContent);
+ doReturn(mMockActivityRecord).when(mDisplayContent).topRunningActivity();
+ when(mDisplayContent.getIgnoreOrientationRequest()).thenReturn(true);
+
+ mMockLetterboxConfiguration = mock(LetterboxConfiguration.class);
+ when(mMockLetterboxConfiguration.isDisplayRotationImmersiveAppCompatPolicyEnabled(
+ /* checkDeviceConfig */ anyBoolean())).thenReturn(true);
+
+ mPolicy = DisplayRotationImmersiveAppCompatPolicy.createIfNeeded(
+ mMockLetterboxConfiguration, createDisplayRotationMock(),
+ mDisplayContent);
+ }
+
+ private DisplayRotation createDisplayRotationMock() {
+ DisplayRotation mockDisplayRotation = mock(DisplayRotation.class);
+
+ when(mockDisplayRotation.isAnyPortrait(Surface.ROTATION_0)).thenReturn(true);
+ when(mockDisplayRotation.isAnyPortrait(Surface.ROTATION_90)).thenReturn(false);
+ when(mockDisplayRotation.isAnyPortrait(Surface.ROTATION_180)).thenReturn(true);
+ when(mockDisplayRotation.isAnyPortrait(Surface.ROTATION_270)).thenReturn(false);
+ when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_0)).thenReturn(false);
+ when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_90)).thenReturn(true);
+ when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_180)).thenReturn(false);
+ when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_270)).thenReturn(true);
+
+ return mockDisplayRotation;
+ }
+
+ @Test
+ public void testIsRotationLockEnforced_landscapeActivity_lockedWhenRotatingToPortrait() {
+ // Base case: App is optimal in Landscape.
+
+ // ROTATION_* is the target display orientation counted from the natural display
+ // orientation. Outside of test environment, ROTATION_0 means that proposed display
+ // rotation is the natural device orientation.
+ // DisplayRotationImmersiveAppCompatPolicy assesses whether the proposed target
+ // orientation ROTATION_* is optimal for the top fullscreen activity or not.
+ // For instance, ROTATION_0 means portrait screen orientation (see
+ // createDisplayRotationMock) which isn't optimal for a landscape-only activity so
+ // we should show a rotation suggestion button instead of rotating directly.
+
+ // Rotation to portrait
+ assertTrue(mPolicy.isRotationLockEnforced(Surface.ROTATION_0));
+ // Rotation to landscape
+ assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_90));
+ // Rotation to portrait
+ assertTrue(mPolicy.isRotationLockEnforced(Surface.ROTATION_180));
+ // Rotation to landscape
+ assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_270));
+ }
+
+ @Test
+ public void testIsRotationLockEnforced_portraitActivity_lockedWhenRotatingToLandscape() {
+ when(mMockActivityRecord.getRequestedConfigurationOrientation()).thenReturn(
+ ORIENTATION_PORTRAIT);
+
+ // Rotation to portrait
+ assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_0));
+ // Rotation to landscape
+ assertTrue(mPolicy.isRotationLockEnforced(Surface.ROTATION_90));
+ // Rotation to portrait
+ assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_180));
+ // Rotation to landscape
+ assertTrue(mPolicy.isRotationLockEnforced(Surface.ROTATION_270));
+ }
+
+ @Test
+ public void testIsRotationLockEnforced_responsiveActivity_lockNotEnforced() {
+ // Do not fix screen orientation
+ when(mMockActivityRecord.getRequestedConfigurationOrientation()).thenReturn(
+ ORIENTATION_UNDEFINED);
+
+ assertIsRotationLockEnforcedReturnsFalseForAllRotations();
+ }
+
+ @Test
+ public void testIsRotationLockEnforced_statusBarVisible_lockNotEnforced() {
+ // Some system bars are visible
+ when(mMockInsetsVisibilities.getVisibility(eq(ITYPE_STATUS_BAR))).thenReturn(true);
+
+ assertIsRotationLockEnforcedReturnsFalseForAllRotations();
+ }
+
+ @Test
+ public void testIsRotationLockEnforced_navBarVisible_lockNotEnforced() {
+ // Some system bars are visible
+ when(mMockInsetsVisibilities.getVisibility(eq(ITYPE_NAVIGATION_BAR))).thenReturn(true);
+
+ assertIsRotationLockEnforcedReturnsFalseForAllRotations();
+ }
+
+ @Test
+ public void testIsRotationLockEnforced_activityIsLetterboxed_lockNotEnforced() {
+ // Activity is letterboxed
+ when(mMockActivityRecord.areBoundsLetterboxed()).thenReturn(true);
+
+ assertIsRotationLockEnforcedReturnsFalseForAllRotations();
+ }
+
+ @Test
+ public void testIsRotationLockEnforced_notFullscreen_lockNotEnforced() {
+ when(mMockTask.getWindowingMode()).thenReturn(WINDOWING_MODE_MULTI_WINDOW);
+
+ assertIsRotationLockEnforcedReturnsFalseForAllRotations();
+
+ when(mMockTask.getWindowingMode()).thenReturn(WINDOWING_MODE_PINNED);
+
+ assertIsRotationLockEnforcedReturnsFalseForAllRotations();
+
+ when(mMockTask.getWindowingMode()).thenReturn(WINDOWING_MODE_FREEFORM);
+
+ assertIsRotationLockEnforcedReturnsFalseForAllRotations();
+ }
+
+ @Test
+ public void testIsRotationLockEnforced_ignoreOrientationRequestDisabled_lockNotEnforced() {
+ when(mDisplayContent.getIgnoreOrientationRequest()).thenReturn(false);
+
+ assertIsRotationLockEnforcedReturnsFalseForAllRotations();
+ }
+
+ @Test
+ public void testRotationChoiceEnforcedOnly_nullTopRunningActivity_lockNotEnforced() {
+ when(mDisplayContent.topRunningActivity()).thenReturn(null);
+
+ assertIsRotationLockEnforcedReturnsFalseForAllRotations();
+ }
+
+ @Test
+ public void testRotationChoiceEnforcedOnly_featureFlagDisabled_lockNotEnforced() {
+ when(mMockLetterboxConfiguration.isDisplayRotationImmersiveAppCompatPolicyEnabled(
+ /* checkDeviceConfig */ true)).thenReturn(false);
+
+ assertIsRotationLockEnforcedReturnsFalseForAllRotations();
+ }
+
+ private void assertIsRotationLockEnforcedReturnsFalseForAllRotations() {
+ assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_0));
+ assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_90));
+ assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_180));
+ assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_270));
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 491f876dceed..4ce43e1fc469 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -1096,8 +1096,16 @@ public class DisplayRotationTests {
mMockDisplayAddress = mock(DisplayAddress.class);
mMockDisplayWindowSettings = mock(DisplayWindowSettings.class);
+
mTarget = new DisplayRotation(sMockWm, mMockDisplayContent, mMockDisplayAddress,
- mMockDisplayPolicy, mMockDisplayWindowSettings, mMockContext, new Object());
+ mMockDisplayPolicy, mMockDisplayWindowSettings, mMockContext, new Object()) {
+ @Override
+ DisplayRotationImmersiveAppCompatPolicy initImmersiveAppCompatPolicy(
+ WindowManagerService service, DisplayContent displayContent) {
+ return null;
+ }
+ };
+
reset(sMockWm);
captureObservers();
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationDeviceConfigTests.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationDeviceConfigTests.java
new file mode 100644
index 000000000000..2b7a06bd35f3
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationDeviceConfigTests.java
@@ -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.server.wm;
+
+import static com.android.server.wm.LetterboxConfigurationDeviceConfig.sKeyToDefaultValueMap;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.Presubmit;
+import android.provider.DeviceConfig;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.modules.utils.testing.TestableDeviceConfig;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.Map;
+
+/**
+ * Test class for {@link LetterboxConfigurationDeviceConfig}.
+ *
+ * atest WmTests:LetterboxConfigurationDeviceConfigTests
+ */
+@SmallTest
+@Presubmit
+public class LetterboxConfigurationDeviceConfigTests {
+
+ private LetterboxConfigurationDeviceConfig mDeviceConfig;
+
+ @Rule
+ public final TestableDeviceConfig.TestableDeviceConfigRule
+ mDeviceConfigRule = new TestableDeviceConfig.TestableDeviceConfigRule();
+
+ @Before
+ public void setUp() {
+ mDeviceConfig = new LetterboxConfigurationDeviceConfig(/* executor */ Runnable::run);
+ }
+
+ @Test
+ public void testGetFlag_flagIsActive_flagChanges() throws Throwable {
+ for (Map.Entry<String, Boolean> entry : sKeyToDefaultValueMap.entrySet()) {
+ testGetFlagForKey_flagIsActive_flagChanges(entry.getKey(), entry.getValue());
+ }
+ }
+
+ private void testGetFlagForKey_flagIsActive_flagChanges(final String key, boolean defaultValue)
+ throws InterruptedException {
+ mDeviceConfig.updateFlagActiveStatus(/* isActive */ true, key);
+
+ assertEquals("Unexpected default value for " + key,
+ mDeviceConfig.getFlag(key), defaultValue);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER, key,
+ /* value */ Boolean.TRUE.toString(), /* makeDefault */ false);
+
+ assertTrue("Flag " + key + "is not true after change", mDeviceConfig.getFlag(key));
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER, key,
+ /* value */ Boolean.FALSE.toString(), /* makeDefault */ false);
+
+ assertFalse("Flag " + key + "is not false after change", mDeviceConfig.getFlag(key));
+ }
+
+ @Test
+ public void testGetFlag_flagIsNotActive_alwaysReturnDefaultValue() throws Throwable {
+ for (Map.Entry<String, Boolean> entry : sKeyToDefaultValueMap.entrySet()) {
+ testGetFlagForKey_flagIsNotActive_alwaysReturnDefaultValue(
+ entry.getKey(), entry.getValue());
+ }
+ }
+
+ private void testGetFlagForKey_flagIsNotActive_alwaysReturnDefaultValue(final String key,
+ boolean defaultValue) throws InterruptedException {
+ assertEquals("Unexpected default value for " + key,
+ mDeviceConfig.getFlag(key), defaultValue);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER, key,
+ /* value */ Boolean.TRUE.toString(), /* makeDefault */ false);
+
+ assertEquals("Flag " + key + "is not set to default after change",
+ mDeviceConfig.getFlag(key), defaultValue);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER, key,
+ /* value */ Boolean.FALSE.toString(), /* makeDefault */ false);
+
+ assertEquals("Flag " + key + "is not set to default after change",
+ mDeviceConfig.getFlag(key), defaultValue);
+ }
+
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index e9080ab78fbc..a8e91980014e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -1617,6 +1617,79 @@ public class SizeCompatTests extends WindowTestsBase {
}
@Test
+ public void testComputeConfigResourceOverrides_unresizableApp() {
+ // Set up a display in landscape and ignoring orientation request.
+ setUpDisplaySizeWithApp(2800, 1400);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+
+ final Rect activityBounds = new Rect(mActivity.getBounds());
+
+ int originalScreenWidthDp = mActivity.getConfiguration().screenWidthDp;
+ int originalScreenHeighthDp = mActivity.getConfiguration().screenHeightDp;
+
+ // App should launch in fixed orientation letterbox.
+ // Activity bounds should be 700x1400 with the ratio as the display.
+ assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFitted();
+ assertEquals(originalScreenWidthDp, mActivity.getConfiguration().smallestScreenWidthDp);
+ assertTrue(originalScreenWidthDp < originalScreenHeighthDp);
+
+ // Rotate display to portrait.
+ rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
+
+ // After we rotate, the activity should go in the size-compat mode and report the same
+ // configuration values.
+ assertScaled();
+ assertEquals(originalScreenWidthDp, mActivity.getConfiguration().smallestScreenWidthDp);
+ assertEquals(originalScreenWidthDp, mActivity.getConfiguration().screenWidthDp);
+ assertEquals(originalScreenHeighthDp, mActivity.getConfiguration().screenHeightDp);
+
+ // Restart activity
+ mActivity.restartProcessIfVisible();
+
+ // Now configuration should be updated
+ assertFitted();
+ assertNotEquals(originalScreenWidthDp, mActivity.getConfiguration().screenWidthDp);
+ assertNotEquals(originalScreenHeighthDp, mActivity.getConfiguration().screenHeightDp);
+ assertEquals(mActivity.getConfiguration().screenWidthDp,
+ mActivity.getConfiguration().smallestScreenWidthDp);
+ }
+
+ @Test
+ public void testComputeConfigResourceOverrides_resizableFixedOrientationActivity() {
+ // Set up a display in landscape and ignoring orientation request.
+ setUpDisplaySizeWithApp(2800, 1400);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+ // Portrait fixed app without max aspect.
+ prepareLimitedBounds(mActivity, SCREEN_ORIENTATION_PORTRAIT, false /* isUnresizable */);
+
+ final Rect activityBounds = new Rect(mActivity.getBounds());
+
+ int originalScreenWidthDp = mActivity.getConfiguration().screenWidthDp;
+ int originalScreenHeighthDp = mActivity.getConfiguration().screenHeightDp;
+
+ // App should launch in fixed orientation letterbox.
+ // Activity bounds should be 700x1400 with the ratio as the display.
+ assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFitted();
+ assertEquals(originalScreenWidthDp, mActivity.getConfiguration().smallestScreenWidthDp);
+ assertTrue(originalScreenWidthDp < originalScreenHeighthDp);
+
+ // Rotate display to portrait.
+ rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
+
+ // Now configuration should be updated
+ assertFitted();
+ assertNotEquals(originalScreenWidthDp, mActivity.getConfiguration().screenWidthDp);
+ assertNotEquals(originalScreenHeighthDp, mActivity.getConfiguration().screenHeightDp);
+ assertEquals(mActivity.getConfiguration().screenWidthDp,
+ mActivity.getConfiguration().smallestScreenWidthDp);
+ }
+
+ @Test
public void testSplitAspectRatioForUnresizablePortraitApps() {
// Set up a display in landscape and ignoring orientation request.
int screenWidth = 1600;
diff --git a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
index df7b3cdebe28..aff9c1a9372a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
@@ -31,6 +31,7 @@ import static com.android.server.wm.WindowState.BLAST_TIMEOUT_DURATION;
import static org.junit.Assert.assertEquals;
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.ArgumentMatchers.eq;
@@ -108,9 +109,7 @@ public class SyncEngineTests extends WindowTestsBase {
bse.onSurfacePlacement();
verify(listener, times(0)).onTransactionReady(anyInt(), any());
- mockWC.onSyncFinishedDrawing();
- // Make sure the second traversal is requested.
- verify(mWm.mWindowPlacerLocked, times(2)).requestTraversal();
+ assertTrue(mockWC.onSyncFinishedDrawing());
bse.onSurfacePlacement();
verify(listener, times(1)).onTransactionReady(eq(id), notNull());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index df3b306d6739..fa98537f8909 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -1240,7 +1240,8 @@ public class WindowOrganizerTests extends WindowTestsBase {
assertTrue(w1.useBLASTSync());
assertTrue(w2.useBLASTSync());
- w1.immediatelyNotifyBlastSync();
+ // A drawn window can complete the sync state automatically.
+ w1.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
mWm.mSyncEngine.onSurfacePlacement();
verify(mockCallback).onTransactionReady(anyInt(), any());
assertFalse(w1.useBLASTSync());