summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java4
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobNotificationCoordinator.java13
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java317
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java19
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java32
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java6
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java97
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java8
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java2
-rw-r--r--core/java/android/animation/AnimatorInflater.java24
-rw-r--r--core/java/android/app/IActivityManager.aidl1
-rw-r--r--core/java/android/app/TaskInfo.java10
-rw-r--r--core/java/android/app/UiAutomationConnection.java12
-rw-r--r--core/java/android/app/WallpaperManager.java143
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java3
-rw-r--r--core/java/android/app/admin/WifiSsidPolicy.java7
-rw-r--r--core/java/android/content/pm/PackageParser.java18
-rw-r--r--core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java33
-rw-r--r--core/java/android/content/res/ConfigurationBoundResourceCache.java12
-rw-r--r--core/java/android/content/res/DrawableCache.java24
-rw-r--r--core/java/android/content/res/ResourcesImpl.java27
-rw-r--r--core/java/android/content/res/ThemedResourceCache.java41
-rw-r--r--core/java/android/os/PowerManager.java3
-rw-r--r--core/java/android/service/dreams/DreamOverlayService.java25
-rw-r--r--core/java/android/service/dreams/DreamService.java8
-rw-r--r--core/java/android/service/dreams/IDreamOverlayCallback.aidl3
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java8
-rw-r--r--core/java/android/util/FeatureFlagUtils.java2
-rw-r--r--core/java/android/view/InsetsState.java3
-rw-r--r--core/java/android/view/ViewRootImpl.java14
-rw-r--r--core/java/android/view/autofill/AutofillManager.java17
-rw-r--r--core/java/android/webkit/SslErrorHandler.java40
-rw-r--r--core/java/android/webkit/WebViewClient.java48
-rw-r--r--core/java/android/window/ScreenCapture.java69
-rw-r--r--core/java/com/android/internal/app/PlatLogoActivity.java594
-rw-r--r--core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java3
-rw-r--r--core/java/com/android/internal/policy/DecorView.java10
-rw-r--r--core/jni/android_window_ScreenCapture.cpp22
-rw-r--r--core/res/res/drawable-nodpi/platlogo.xml211
-rw-r--r--core/res/res/values-af/strings.xml2
-rw-r--r--core/res/res/values-am/strings.xml2
-rw-r--r--core/res/res/values-ar/strings.xml2
-rw-r--r--core/res/res/values-as/strings.xml2
-rw-r--r--core/res/res/values-az/strings.xml2
-rw-r--r--core/res/res/values-b+sr+Latn/strings.xml6
-rw-r--r--core/res/res/values-be/strings.xml6
-rw-r--r--core/res/res/values-bg/strings.xml2
-rw-r--r--core/res/res/values-bn/strings.xml2
-rw-r--r--core/res/res/values-bs/strings.xml4
-rw-r--r--core/res/res/values-ca/strings.xml2
-rw-r--r--core/res/res/values-cs/strings.xml2
-rw-r--r--core/res/res/values-da/strings.xml2
-rw-r--r--core/res/res/values-de/strings.xml2
-rw-r--r--core/res/res/values-el/strings.xml4
-rw-r--r--core/res/res/values-en-rAU/strings.xml2
-rw-r--r--core/res/res/values-en-rCA/strings.xml2
-rw-r--r--core/res/res/values-en-rGB/strings.xml2
-rw-r--r--core/res/res/values-en-rIN/strings.xml2
-rw-r--r--core/res/res/values-en-rXC/strings.xml2
-rw-r--r--core/res/res/values-es-rUS/strings.xml4
-rw-r--r--core/res/res/values-es/strings.xml4
-rw-r--r--core/res/res/values-et/strings.xml2
-rw-r--r--core/res/res/values-eu/strings.xml2
-rw-r--r--core/res/res/values-fa/strings.xml2
-rw-r--r--core/res/res/values-fi/strings.xml2
-rw-r--r--core/res/res/values-fr-rCA/strings.xml2
-rw-r--r--core/res/res/values-fr/strings.xml2
-rw-r--r--core/res/res/values-gl/strings.xml2
-rw-r--r--core/res/res/values-gu/strings.xml2
-rw-r--r--core/res/res/values-hi/strings.xml4
-rw-r--r--core/res/res/values-hr/strings.xml4
-rw-r--r--core/res/res/values-hu/strings.xml2
-rw-r--r--core/res/res/values-hy/strings.xml2
-rw-r--r--core/res/res/values-in/strings.xml2
-rw-r--r--core/res/res/values-is/strings.xml2
-rw-r--r--core/res/res/values-it/strings.xml2
-rw-r--r--core/res/res/values-iw/strings.xml2
-rw-r--r--core/res/res/values-ja/strings.xml6
-rw-r--r--core/res/res/values-ka/strings.xml2
-rw-r--r--core/res/res/values-kk/strings.xml6
-rw-r--r--core/res/res/values-km/strings.xml4
-rw-r--r--core/res/res/values-kn/strings.xml6
-rw-r--r--core/res/res/values-ko/strings.xml4
-rw-r--r--core/res/res/values-ky/strings.xml2
-rw-r--r--core/res/res/values-lo/strings.xml2
-rw-r--r--core/res/res/values-lt/strings.xml2
-rw-r--r--core/res/res/values-lv/strings.xml2
-rw-r--r--core/res/res/values-mk/strings.xml2
-rw-r--r--core/res/res/values-ml/strings.xml2
-rw-r--r--core/res/res/values-mn/strings.xml2
-rw-r--r--core/res/res/values-mr/strings.xml2
-rw-r--r--core/res/res/values-ms/strings.xml2
-rw-r--r--core/res/res/values-my/strings.xml4
-rw-r--r--core/res/res/values-nb/strings.xml2
-rw-r--r--core/res/res/values-ne/strings.xml60
-rw-r--r--core/res/res/values-nl/strings.xml2
-rw-r--r--core/res/res/values-or/strings.xml4
-rw-r--r--core/res/res/values-pa/strings.xml6
-rw-r--r--core/res/res/values-pl/strings.xml2
-rw-r--r--core/res/res/values-pt-rBR/strings.xml4
-rw-r--r--core/res/res/values-pt-rPT/strings.xml4
-rw-r--r--core/res/res/values-pt/strings.xml4
-rw-r--r--core/res/res/values-ro/strings.xml2
-rw-r--r--core/res/res/values-ru/strings.xml6
-rw-r--r--core/res/res/values-si/strings.xml2
-rw-r--r--core/res/res/values-sk/strings.xml2
-rw-r--r--core/res/res/values-sl/strings.xml2
-rw-r--r--core/res/res/values-sq/strings.xml2
-rw-r--r--core/res/res/values-sr/strings.xml6
-rw-r--r--core/res/res/values-sv/strings.xml2
-rw-r--r--core/res/res/values-sw/strings.xml2
-rw-r--r--core/res/res/values-ta/strings.xml2
-rw-r--r--core/res/res/values-te/strings.xml8
-rw-r--r--core/res/res/values-th/strings.xml4
-rw-r--r--core/res/res/values-tl/strings.xml2
-rw-r--r--core/res/res/values-tr/strings.xml2
-rw-r--r--core/res/res/values-uk/strings.xml2
-rw-r--r--core/res/res/values-ur/strings.xml2
-rw-r--r--core/res/res/values-uz/strings.xml2
-rw-r--r--core/res/res/values-vi/strings.xml2
-rw-r--r--core/res/res/values-zh-rCN/strings.xml2
-rw-r--r--core/res/res/values-zh-rHK/strings.xml2
-rw-r--r--core/res/res/values-zh-rTW/strings.xml2
-rw-r--r--core/res/res/values-zu/strings.xml2
-rw-r--r--core/res/res/values/config.xml10
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java46
-rw-r--r--data/keyboards/Vendor_0957_Product_0001.kl3
-rw-r--r--graphics/java/android/graphics/Bitmap.java51
-rw-r--r--graphics/java/android/graphics/Gainmap.java11
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java42
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java28
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java56
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java96
-rw-r--r--libs/WindowManager/Shell/res/values/styles.xml52
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java26
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java43
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java43
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeSettingsObserver.java92
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java436
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java48
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java56
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java72
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java49
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java38
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java135
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java55
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java90
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java23
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java9
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipFromSplitScreenOnGoToHomeTest.kt200
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java16
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java163
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java209
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java23
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionsTest.java35
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java10
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/StubTransaction.java313
-rw-r--r--libs/hwui/jni/Gainmap.cpp11
-rw-r--r--media/java/android/media/MediaCodec.java8
-rw-r--r--packages/CompanionDeviceManager/res/values-it/strings.xml2
-rw-r--r--packages/PackageInstaller/res/values-kn/strings.xml2
-rw-r--r--packages/PackageInstaller/res/values-or/strings.xml2
-rw-r--r--packages/SettingsLib/BannerMessagePreference/res/values-te/strings.xml2
-rw-r--r--packages/SettingsLib/FooterPreference/res/values-kk/strings.xml2
-rw-r--r--packages/SettingsLib/SelectorWithWidgetPreference/res/values-or/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-be/strings.xml9
-rw-r--r--packages/SettingsLib/res/values-de/strings.xml9
-rw-r--r--packages/SettingsLib/res/values-ja/strings.xml9
-rw-r--r--packages/SettingsLib/res/values-kn/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ky/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-mk/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ne/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-zh-rCN/strings.xml4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java14
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java87
-rw-r--r--packages/Shell/AndroidManifest.xml2
-rw-r--r--packages/Shell/src/com/android/shell/Screenshooter.java10
-rw-r--r--packages/SoundPicker/res/values-kn/strings.xml2
-rw-r--r--packages/SystemUI/AndroidManifest.xml2
-rw-r--r--packages/SystemUI/accessibility/accessibilitymenu/res/values-es/strings.xml2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt42
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt3
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt3
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml4
-rw-r--r--packages/SystemUI/res-keyguard/values-ne/strings.xml6
-rw-r--r--packages/SystemUI/res-keyguard/values-sw600dp-land/integers.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values/dimens.xml5
-rw-r--r--packages/SystemUI/res-keyguard/values/ids.xml14
-rw-r--r--packages/SystemUI/res-keyguard/values/strings.xml18
-rw-r--r--packages/SystemUI/res/layout/media_output_list_item_advanced.xml4
-rw-r--r--packages/SystemUI/res/values-af/strings.xml25
-rw-r--r--packages/SystemUI/res/values-am/strings.xml25
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml25
-rw-r--r--packages/SystemUI/res/values-as/strings.xml25
-rw-r--r--packages/SystemUI/res/values-az/strings.xml25
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml25
-rw-r--r--packages/SystemUI/res/values-be/strings.xml25
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml25
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml25
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml19
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml25
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml31
-rw-r--r--packages/SystemUI/res/values-da/strings.xml25
-rw-r--r--packages/SystemUI/res/values-de/strings.xml29
-rw-r--r--packages/SystemUI/res/values-el/strings.xml25
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml29
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml22
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml29
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml29
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml16
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml21
-rw-r--r--packages/SystemUI/res/values-es/strings.xml25
-rw-r--r--packages/SystemUI/res/values-et/strings.xml25
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml25
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml19
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml25
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml25
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml19
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml27
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml19
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml16
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml21
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml19
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml35
-rw-r--r--packages/SystemUI/res/values-in/strings.xml25
-rw-r--r--packages/SystemUI/res/values-is/strings.xml25
-rw-r--r--packages/SystemUI/res/values-it/strings.xml21
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml19
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml19
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml19
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml25
-rw-r--r--packages/SystemUI/res/values-km/strings.xml19
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml25
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml25
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml25
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml25
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml25
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml25
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml27
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml19
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml25
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml19
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml19
-rw-r--r--packages/SystemUI/res/values-my/strings.xml21
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml25
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml25
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml19
-rw-r--r--packages/SystemUI/res/values-or/strings.xml25
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml25
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml25
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml21
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml19
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml21
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml19
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml25
-rw-r--r--packages/SystemUI/res/values-si/strings.xml25
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml25
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml19
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml25
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml25
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml25
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml19
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml25
-rw-r--r--packages/SystemUI/res/values-te/strings.xml21
-rw-r--r--packages/SystemUI/res/values-th/strings.xml19
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml19
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml25
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml25
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml25
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml19
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml25
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml21
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml25
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml31
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml19
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt15
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java78
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java14
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusAreaView.kt118
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java6
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/LockIconViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/SwipeHelper.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java88
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java111
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt33
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt39
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt34
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt55
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskRoleManagerExt.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordingAdapter.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ImageCaptureImpl.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java61
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java29
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java15
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt44
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/TestScopeProvider.kt25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractorImplTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt44
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt59
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java44
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/multishade/domain/interactor/MultiShadeMotionEventInteractorTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt43
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt32
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperServiceTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQuickSettingsContainerTest.kt97
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt27
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt110
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java49
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java90
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt4
-rw-r--r--packages/overlays/NotesRoleEnabledOverlay/Android.bp1
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerService.java418
-rw-r--r--services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java8
-rw-r--r--services/core/java/com/android/server/VcnManagementService.java15
-rw-r--r--services/core/java/com/android/server/VpnManagerService.java3
-rw-r--r--services/core/java/com/android/server/WallpaperUpdateReceiver.java2
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java75
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerConstants.java6
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java90
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerShellCommand.java45
-rw-r--r--services/core/java/com/android/server/am/BroadcastProcessQueue.java6
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueueImpl.java28
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueueModernImpl.java101
-rw-r--r--services/core/java/com/android/server/am/BroadcastRecord.java19
-rw-r--r--services/core/java/com/android/server/am/ContentProviderHelper.java18
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java8
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java13
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java24
-rw-r--r--services/core/java/com/android/server/am/StackTracesDumpHelper.java4
-rw-r--r--services/core/java/com/android/server/am/UidObserverController.java75
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java17
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java26
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java1
-rw-r--r--services/core/java/com/android/server/audio/BtHelper.java4
-rw-r--r--services/core/java/com/android/server/audio/PlaybackActivityMonitor.java3
-rw-r--r--services/core/java/com/android/server/dreams/DreamManagerService.java11
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java5
-rw-r--r--services/core/java/com/android/server/pm/Settings.java9
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java5
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java19
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java4
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperData.java16
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java50
-rw-r--r--services/core/java/com/android/server/wm/AsyncRotationController.java2
-rw-r--r--services/core/java/com/android/server/wm/DeviceStateController.java30
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java7
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java3
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java8
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfiguration.java3
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java24
-rw-r--r--services/core/java/com/android/server/wm/SplashScreenExceptionList.java4
-rw-r--r--services/core/java/com/android/server/wm/Task.java1
-rw-r--r--services/core/java/com/android/server/wm/Transition.java82
-rw-r--r--services/core/java/com/android/server/wm/TransitionController.java5
-rw-r--r--services/core/java/com/android/server/wm/WallpaperController.java40
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java13
-rw-r--r--services/credentials/java/com/android/server/credentials/CredentialManagerService.java15
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java225
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java49
-rw-r--r--services/tests/PackageManagerServiceTests/server/res/raw/install_app1_cert5bin12760 -> 12756 bytes
-rw-r--r--services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java13
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java47
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java53
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java4
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java6
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java568
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java5
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java37
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java4
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java3
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java31
-rw-r--r--services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java4
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java20
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DeviceStateControllerTests.java28
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java11
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java66
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SplashScreenExceptionListTest.java22
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java26
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java2
-rw-r--r--tests/SilkFX/res/layout/gainmap_transform_test.xml122
-rw-r--r--tests/SilkFX/src/com/android/test/silkfx/Main.kt4
-rw-r--r--tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt28
-rw-r--r--tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapTransformsTest.kt116
-rw-r--r--tests/vcn/java/com/android/server/VcnManagementServiceTest.java8
479 files changed, 8077 insertions, 4181 deletions
diff --git a/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java b/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java
index fd8ddbcf3809..6c8af39015f5 100644
--- a/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java
@@ -59,6 +59,10 @@ public interface JobSchedulerInternal {
*/
void reportAppUsage(String packageName, int userId);
+ /** @return {@code true} if the app is considered buggy from JobScheduler's perspective. */
+ boolean isAppConsideredBuggy(int callingUserId, @NonNull String callingPackageName,
+ int timeoutBlameUserId, @NonNull String timeoutBlamePackageName);
+
/**
* @return {@code true} if the given notification is associated with any user-initiated jobs.
*/
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobNotificationCoordinator.java b/apex/jobscheduler/service/java/com/android/server/job/JobNotificationCoordinator.java
index 8a5d09404ebb..071707059f2d 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobNotificationCoordinator.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobNotificationCoordinator.java
@@ -123,21 +123,21 @@ class JobNotificationCoordinator {
if (oldDetails == null) {
if (jobStatus.startedAsUserInitiatedJob) {
Counter.logIncrementWithUid(
- "job_scheduler.value_cntr_w_uid_initial_setNotification_call_required",
+ "job_scheduler.value_cntr_w_uid_initial_set_notification_call_required",
jobStatus.getUid());
} else {
Counter.logIncrementWithUid(
- "job_scheduler.value_cntr_w_uid_initial_setNotification_call_optional",
+ "job_scheduler.value_cntr_w_uid_initial_set_notification_call_optional",
jobStatus.getUid());
}
} else {
if (jobStatus.startedAsUserInitiatedJob) {
Counter.logIncrementWithUid(
- "job_scheduler.value_cntr_w_uid_subsequent_setNotification_call_required",
+ "job_scheduler.value_cntr_w_uid_subsequent_set_notification_call_required",
jobStatus.getUid());
} else {
Counter.logIncrementWithUid(
- "job_scheduler.value_cntr_w_uid_subsequent_setNotification_call_optional",
+ "job_scheduler.value_cntr_w_uid_subsequent_set_notification_call_optional",
jobStatus.getUid());
}
if (oldDetails.notificationId != notificationId) {
@@ -145,7 +145,7 @@ class JobNotificationCoordinator {
removeNotificationAssociation(hostingContext, JobParameters.STOP_REASON_UNDEFINED,
jobStatus);
Counter.logIncrementWithUid(
- "job_scheduler.value_cntr_w_uid_setNotification_changed_notification_ids",
+ "job_scheduler.value_cntr_w_uid_set_notification_changed_notification_ids",
jobStatus.getUid());
}
}
@@ -200,7 +200,10 @@ class JobNotificationCoordinator {
// No more jobs using this notification. Apply the final job stop policy.
// If the user attempted to stop the job/app, then always remove the notification
// so the user doesn't get confused about the app state.
+ // Similarly, if the user background restricted the app, remove the notification so
+ // the user doesn't think the app is continuing to run in the background.
if (details.jobEndNotificationPolicy == JOB_END_NOTIFICATION_POLICY_REMOVE
+ || stopReason == JobParameters.STOP_REASON_BACKGROUND_RESTRICTION
|| stopReason == JobParameters.STOP_REASON_USER) {
mNotificationManagerInternal.cancelNotification(
packageName, packageName, details.appUid, details.appPid, /* tag */ null,
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index cbc9263a2c3d..f99bcf144b91 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -322,16 +322,25 @@ public class JobSchedulerService extends com.android.server.SystemService
private static final String QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG = ".schedulePersisted()";
private static final String QUOTA_TRACKER_SCHEDULE_LOGGED =
".schedulePersisted out-of-quota logged";
+ private static final String QUOTA_TRACKER_TIMEOUT_UIJ_TAG = "timeout-uij";
+ private static final String QUOTA_TRACKER_TIMEOUT_EJ_TAG = "timeout-ej";
+ private static final String QUOTA_TRACKER_TIMEOUT_REG_TAG = "timeout-reg";
+ private static final String QUOTA_TRACKER_TIMEOUT_TOTAL_TAG = "timeout-total";
+ private static final String QUOTA_TRACKER_ANR_TAG = "anr";
private static final Category QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED = new Category(
".schedulePersisted()");
private static final Category QUOTA_TRACKER_CATEGORY_SCHEDULE_LOGGED = new Category(
".schedulePersisted out-of-quota logged");
- private static final Categorizer QUOTA_CATEGORIZER = (userId, packageName, tag) -> {
- if (QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG.equals(tag)) {
- return QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED;
- }
- return QUOTA_TRACKER_CATEGORY_SCHEDULE_LOGGED;
- };
+ private static final Category QUOTA_TRACKER_CATEGORY_TIMEOUT_UIJ =
+ new Category(QUOTA_TRACKER_TIMEOUT_UIJ_TAG);
+ private static final Category QUOTA_TRACKER_CATEGORY_TIMEOUT_EJ =
+ new Category(QUOTA_TRACKER_TIMEOUT_EJ_TAG);
+ private static final Category QUOTA_TRACKER_CATEGORY_TIMEOUT_REG =
+ new Category(QUOTA_TRACKER_TIMEOUT_REG_TAG);
+ private static final Category QUOTA_TRACKER_CATEGORY_TIMEOUT_TOTAL =
+ new Category(QUOTA_TRACKER_TIMEOUT_TOTAL_TAG);
+ private static final Category QUOTA_TRACKER_CATEGORY_ANR = new Category(QUOTA_TRACKER_ANR_TAG);
+ private static final Category QUOTA_TRACKER_CATEGORY_DISABLED = new Category("disabled");
/**
* Queue of pending jobs. The JobServiceContext class will receive jobs from this list
@@ -493,10 +502,18 @@ public class JobSchedulerService extends com.android.server.SystemService
}
switch (name) {
case Constants.KEY_ENABLE_API_QUOTAS:
+ case Constants.KEY_ENABLE_EXECUTION_SAFEGUARDS_UDC:
case Constants.KEY_API_QUOTA_SCHEDULE_COUNT:
case Constants.KEY_API_QUOTA_SCHEDULE_WINDOW_MS:
case Constants.KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT:
case Constants.KEY_API_QUOTA_SCHEDULE_THROW_EXCEPTION:
+ case Constants.KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT:
+ case Constants.KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT:
+ case Constants.KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT:
+ case Constants.KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT:
+ case Constants.KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS:
+ case Constants.KEY_EXECUTION_SAFEGUARDS_UDC_ANR_COUNT:
+ case Constants.KEY_EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS:
if (!apiQuotaScheduleUpdated) {
mConstants.updateApiQuotaConstantsLocked();
updateQuotaTracker();
@@ -583,10 +600,26 @@ public class JobSchedulerService extends com.android.server.SystemService
@VisibleForTesting
void updateQuotaTracker() {
- mQuotaTracker.setEnabled(mConstants.ENABLE_API_QUOTAS);
+ mQuotaTracker.setEnabled(
+ mConstants.ENABLE_API_QUOTAS || mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC);
mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED,
mConstants.API_QUOTA_SCHEDULE_COUNT,
mConstants.API_QUOTA_SCHEDULE_WINDOW_MS);
+ mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_TIMEOUT_UIJ,
+ mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT,
+ mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS);
+ mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_TIMEOUT_EJ,
+ mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT,
+ mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS);
+ mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_TIMEOUT_REG,
+ mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT,
+ mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS);
+ mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_TIMEOUT_TOTAL,
+ mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT,
+ mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS);
+ mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_ANR,
+ mConstants.EXECUTION_SAFEGUARDS_UDC_ANR_COUNT,
+ mConstants.EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS);
}
/**
@@ -616,6 +649,8 @@ public class JobSchedulerService extends com.android.server.SystemService
"conn_low_signal_strength_relax_frac";
private static final String KEY_PREFETCH_FORCE_BATCH_RELAX_THRESHOLD_MS =
"prefetch_force_batch_relax_threshold_ms";
+ // This has been enabled for 3+ full releases. We're unlikely to disable it.
+ // TODO(141645789): remove this flag
private static final String KEY_ENABLE_API_QUOTAS = "enable_api_quotas";
private static final String KEY_API_QUOTA_SCHEDULE_COUNT = "aq_schedule_count";
private static final String KEY_API_QUOTA_SCHEDULE_WINDOW_MS = "aq_schedule_window_ms";
@@ -623,6 +658,22 @@ public class JobSchedulerService extends com.android.server.SystemService
"aq_schedule_throw_exception";
private static final String KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT =
"aq_schedule_return_failure";
+ private static final String KEY_ENABLE_EXECUTION_SAFEGUARDS_UDC =
+ "enable_execution_safeguards_udc";
+ private static final String KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT =
+ "es_u_timeout_uij_count";
+ private static final String KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT =
+ "es_u_timeout_ej_count";
+ private static final String KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT =
+ "es_u_timeout_reg_count";
+ private static final String KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT =
+ "es_u_timeout_total_count";
+ private static final String KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS =
+ "es_u_timeout_window_ms";
+ private static final String KEY_EXECUTION_SAFEGUARDS_UDC_ANR_COUNT =
+ "es_u_anr_count";
+ private static final String KEY_EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS =
+ "es_u_anr_window_ms";
private static final String KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS =
"runtime_free_quota_max_limit_ms";
@@ -662,6 +713,17 @@ public class JobSchedulerService extends com.android.server.SystemService
private static final long DEFAULT_API_QUOTA_SCHEDULE_WINDOW_MS = MINUTE_IN_MILLIS;
private static final boolean DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION = true;
private static final boolean DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = false;
+ private static final boolean DEFAULT_ENABLE_EXECUTION_SAFEGUARDS_UDC = true;
+ private static final int DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT = 2;
+ // EJs have a shorter timeout, so set a higher limit for them to start with.
+ private static final int DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT = 5;
+ private static final int DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT = 3;
+ private static final int DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT = 10;
+ private static final long DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS =
+ 24 * HOUR_IN_MILLIS;
+ private static final int DEFAULT_EXECUTION_SAFEGUARDS_UDC_ANR_COUNT = 3;
+ private static final long DEFAULT_EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS =
+ 6 * HOUR_IN_MILLIS;
@VisibleForTesting
public static final long DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS = 30 * MINUTE_IN_MILLIS;
@VisibleForTesting
@@ -774,6 +836,55 @@ public class JobSchedulerService extends com.android.server.SystemService
public boolean API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT =
DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT;
+ /**
+ * Whether to enable the execution safeguards added in UDC.
+ */
+ public boolean ENABLE_EXECUTION_SAFEGUARDS_UDC = DEFAULT_ENABLE_EXECUTION_SAFEGUARDS_UDC;
+ /**
+ * The maximum number of times an app can have a user-iniated job time out before the system
+ * begins removing some of the app's privileges.
+ */
+ public int EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT =
+ DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT;
+ /**
+ * The maximum number of times an app can have an expedited job time out before the system
+ * begins removing some of the app's privileges.
+ */
+ public int EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT =
+ DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT;
+ /**
+ * The maximum number of times an app can have a regular job time out before the system
+ * begins removing some of the app's privileges.
+ */
+ public int EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT =
+ DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT;
+ /**
+ * The maximum number of times an app can have jobs time out before the system
+ * attempts to restrict most of the app's privileges.
+ */
+ public int EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT =
+ DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT;
+ /**
+ * The time window that {@link #EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT},
+ * {@link #EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT},
+ * {@link #EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT}, and
+ * {@link #EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT} should be evaluated over.
+ */
+ public long EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS =
+ DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS;
+
+ /**
+ * The maximum number of times an app can ANR from JobScheduler's perspective before
+ * JobScheduler will attempt to restrict the app.
+ */
+ public int EXECUTION_SAFEGUARDS_UDC_ANR_COUNT = DEFAULT_EXECUTION_SAFEGUARDS_UDC_ANR_COUNT;
+ /**
+ * The time window that {@link #EXECUTION_SAFEGUARDS_UDC_ANR_COUNT}
+ * should be evaluated over.
+ */
+ public long EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS =
+ DEFAULT_EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS;
+
/** The maximum amount of time we will let a job run for when quota is "free". */
public long RUNTIME_FREE_QUOTA_MAX_LIMIT_MS = DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
@@ -915,6 +1026,9 @@ public class JobSchedulerService extends com.android.server.SystemService
private void updateApiQuotaConstantsLocked() {
ENABLE_API_QUOTAS = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
KEY_ENABLE_API_QUOTAS, DEFAULT_ENABLE_API_QUOTAS);
+ ENABLE_EXECUTION_SAFEGUARDS_UDC = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_ENABLE_EXECUTION_SAFEGUARDS_UDC, DEFAULT_ENABLE_EXECUTION_SAFEGUARDS_UDC);
// Set a minimum value on the quota limit so it's not so low that it interferes with
// legitimate use cases.
API_QUOTA_SCHEDULE_COUNT = Math.max(250,
@@ -931,6 +1045,40 @@ public class JobSchedulerService extends com.android.server.SystemService
DeviceConfig.NAMESPACE_JOB_SCHEDULER,
KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT,
DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT);
+
+ // Set a minimum value on the timeout limit so it's not so low that it interferes with
+ // legitimate use cases.
+ EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT = Math.max(2,
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT,
+ DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT));
+ EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT = Math.max(2,
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT,
+ DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT));
+ EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT = Math.max(2,
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT,
+ DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT));
+ final int highestTimeoutCount = Math.max(EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT,
+ Math.max(EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT,
+ EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT));
+ EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT = Math.max(highestTimeoutCount,
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT,
+ DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT));
+ EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS = DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS,
+ DEFAULT_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS);
+ EXECUTION_SAFEGUARDS_UDC_ANR_COUNT = Math.max(1,
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_EXECUTION_SAFEGUARDS_UDC_ANR_COUNT,
+ DEFAULT_EXECUTION_SAFEGUARDS_UDC_ANR_COUNT));
+ EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS = DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS,
+ DEFAULT_EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS);
}
private void updateRuntimeConstantsLocked() {
@@ -1029,6 +1177,23 @@ public class JobSchedulerService extends com.android.server.SystemService
pw.print(KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT,
API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT).println();
+ pw.print(KEY_ENABLE_EXECUTION_SAFEGUARDS_UDC, ENABLE_EXECUTION_SAFEGUARDS_UDC)
+ .println();
+ pw.print(KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT,
+ EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT).println();
+ pw.print(KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT,
+ EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT).println();
+ pw.print(KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT,
+ EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT).println();
+ pw.print(KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT,
+ EXECUTION_SAFEGUARDS_UDC_TIMEOUT_TOTAL_COUNT).println();
+ pw.print(KEY_EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS,
+ EXECUTION_SAFEGUARDS_UDC_TIMEOUT_WINDOW_MS).println();
+ pw.print(KEY_EXECUTION_SAFEGUARDS_UDC_ANR_COUNT,
+ EXECUTION_SAFEGUARDS_UDC_ANR_COUNT).println();
+ pw.print(KEY_EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS,
+ EXECUTION_SAFEGUARDS_UDC_ANR_WINDOW_MS).println();
+
pw.print(KEY_RUNTIME_MIN_GUARANTEE_MS, RUNTIME_MIN_GUARANTEE_MS).println();
pw.print(KEY_RUNTIME_MIN_EJ_GUARANTEE_MS, RUNTIME_MIN_EJ_GUARANTEE_MS).println();
pw.print(KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS, RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
@@ -2252,12 +2417,52 @@ public class JobSchedulerService extends com.android.server.SystemService
// Set up the app standby bucketing tracker
mStandbyTracker = new StandbyTracker();
mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
- mQuotaTracker = new CountQuotaTracker(context, QUOTA_CATEGORIZER);
- mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED,
- mConstants.API_QUOTA_SCHEDULE_COUNT,
- mConstants.API_QUOTA_SCHEDULE_WINDOW_MS);
+
+ final Categorizer quotaCategorizer = (userId, packageName, tag) -> {
+ if (QUOTA_TRACKER_TIMEOUT_UIJ_TAG.equals(tag)) {
+ return mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC
+ ? QUOTA_TRACKER_CATEGORY_TIMEOUT_UIJ
+ : QUOTA_TRACKER_CATEGORY_DISABLED;
+ }
+ if (QUOTA_TRACKER_TIMEOUT_EJ_TAG.equals(tag)) {
+ return mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC
+ ? QUOTA_TRACKER_CATEGORY_TIMEOUT_EJ
+ : QUOTA_TRACKER_CATEGORY_DISABLED;
+ }
+ if (QUOTA_TRACKER_TIMEOUT_REG_TAG.equals(tag)) {
+ return mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC
+ ? QUOTA_TRACKER_CATEGORY_TIMEOUT_REG
+ : QUOTA_TRACKER_CATEGORY_DISABLED;
+ }
+ if (QUOTA_TRACKER_TIMEOUT_TOTAL_TAG.equals(tag)) {
+ return mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC
+ ? QUOTA_TRACKER_CATEGORY_TIMEOUT_TOTAL
+ : QUOTA_TRACKER_CATEGORY_DISABLED;
+ }
+ if (QUOTA_TRACKER_ANR_TAG.equals(tag)) {
+ return mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC
+ ? QUOTA_TRACKER_CATEGORY_ANR
+ : QUOTA_TRACKER_CATEGORY_DISABLED;
+ }
+ if (QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG.equals(tag)) {
+ return mConstants.ENABLE_API_QUOTAS
+ ? QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED
+ : QUOTA_TRACKER_CATEGORY_DISABLED;
+ }
+ if (QUOTA_TRACKER_SCHEDULE_LOGGED.equals(tag)) {
+ return mConstants.ENABLE_API_QUOTAS
+ ? QUOTA_TRACKER_CATEGORY_SCHEDULE_LOGGED
+ : QUOTA_TRACKER_CATEGORY_DISABLED;
+ }
+ Slog.wtf(TAG, "Unexpected category tag: " + tag);
+ return QUOTA_TRACKER_CATEGORY_DISABLED;
+ };
+ mQuotaTracker = new CountQuotaTracker(context, quotaCategorizer);
+ updateQuotaTracker();
// Log at most once per minute.
+ // Set outside updateQuotaTracker() since this is intentionally not configurable.
mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_SCHEDULE_LOGGED, 1, 60_000);
+ mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_DISABLED, Integer.MAX_VALUE, 60_000);
mAppStandbyInternal = LocalServices.getService(AppStandbyInternal.class);
mAppStandbyInternal.addListener(mStandbyTracker);
@@ -2762,6 +2967,48 @@ public class JobSchedulerService extends com.android.server.SystemService
0 /* Reset cumulativeExecutionTime because of successful execution */);
}
+ @VisibleForTesting
+ void maybeProcessBuggyJob(@NonNull JobStatus jobStatus, int debugStopReason) {
+ boolean jobTimedOut = debugStopReason == JobParameters.INTERNAL_STOP_REASON_TIMEOUT;
+ // If madeActive = 0, the job never actually started.
+ if (!jobTimedOut && jobStatus.madeActive > 0) {
+ final long executionDurationMs = sUptimeMillisClock.millis() - jobStatus.madeActive;
+ // The debug reason may be different if we stopped the job for some other reason
+ // (eg. constraints), so look at total execution time to be safe.
+ if (jobStatus.startedAsUserInitiatedJob) {
+ // TODO: factor in different min guarantees for different UI job types
+ jobTimedOut = executionDurationMs >= mConstants.RUNTIME_MIN_UI_GUARANTEE_MS;
+ } else if (jobStatus.startedAsExpeditedJob) {
+ jobTimedOut = executionDurationMs >= mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS;
+ } else {
+ jobTimedOut = executionDurationMs >= mConstants.RUNTIME_MIN_GUARANTEE_MS;
+ }
+ }
+ if (jobTimedOut) {
+ final int userId = jobStatus.getTimeoutBlameUserId();
+ final String pkg = jobStatus.getTimeoutBlamePackageName();
+ mQuotaTracker.noteEvent(userId, pkg,
+ jobStatus.startedAsUserInitiatedJob
+ ? QUOTA_TRACKER_TIMEOUT_UIJ_TAG
+ : (jobStatus.startedAsExpeditedJob
+ ? QUOTA_TRACKER_TIMEOUT_EJ_TAG
+ : QUOTA_TRACKER_TIMEOUT_REG_TAG));
+ if (!mQuotaTracker.noteEvent(userId, pkg, QUOTA_TRACKER_TIMEOUT_TOTAL_TAG)) {
+ mAppStandbyInternal.restrictApp(
+ pkg, userId, UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY);
+ }
+ }
+
+ if (debugStopReason == JobParameters.INTERNAL_STOP_REASON_ANR) {
+ final int callingUserId = jobStatus.getUserId();
+ final String callingPkg = jobStatus.getServiceComponent().getPackageName();
+ if (!mQuotaTracker.noteEvent(callingUserId, callingPkg, QUOTA_TRACKER_ANR_TAG)) {
+ mAppStandbyInternal.restrictApp(callingPkg, callingUserId,
+ UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY);
+ }
+ }
+ }
+
// JobCompletedListener implementations.
/**
@@ -2784,6 +3031,8 @@ public class JobSchedulerService extends com.android.server.SystemService
mLastCompletedJobTimeElapsed[mLastCompletedJobIndex] = sElapsedRealtimeClock.millis();
mLastCompletedJobIndex = (mLastCompletedJobIndex + 1) % NUM_COMPLETED_JOB_HISTORY;
+ maybeProcessBuggyJob(jobStatus, debugStopReason);
+
if (debugStopReason == JobParameters.INTERNAL_STOP_REASON_UNINSTALL
|| debugStopReason == JobParameters.INTERNAL_STOP_REASON_DATA_CLEARED) {
// The job should have already been cleared from the rest of the JS tracking. No need
@@ -3511,26 +3760,36 @@ public class JobSchedulerService extends com.android.server.SystemService
if (job.shouldTreatAsUserInitiatedJob()
&& checkRunUserInitiatedJobsPermission(
job.getSourceUid(), job.getSourcePackageName())) {
+ // The calling package is the one doing the work, so use it in the
+ // timeout quota checks.
+ final boolean isWithinTimeoutQuota = mQuotaTracker.isWithinQuota(
+ job.getTimeoutBlameUserId(), job.getTimeoutBlamePackageName(),
+ QUOTA_TRACKER_TIMEOUT_UIJ_TAG);
+ final long upperLimitMs = isWithinTimeoutQuota
+ ? mConstants.RUNTIME_UI_LIMIT_MS
+ : mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
if (job.getJob().getRequiredNetwork() != null) {
// User-initiated data transfers.
if (mConstants.RUNTIME_USE_DATA_ESTIMATES_FOR_LIMITS) {
final long estimatedTransferTimeMs =
mConnectivityController.getEstimatedTransferTimeMs(job);
if (estimatedTransferTimeMs == ConnectivityController.UNKNOWN_TIME) {
- return mConstants.RUNTIME_MIN_UI_DATA_TRANSFER_GUARANTEE_MS;
+ return Math.min(upperLimitMs,
+ mConstants.RUNTIME_MIN_UI_DATA_TRANSFER_GUARANTEE_MS);
}
// Try to give the job at least as much time as we think the transfer
// will take, but cap it at the maximum limit.
final long factoredTransferTimeMs = (long) (estimatedTransferTimeMs
* mConstants.RUNTIME_MIN_UI_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR);
- return Math.min(mConstants.RUNTIME_UI_LIMIT_MS,
+ return Math.min(upperLimitMs,
Math.max(factoredTransferTimeMs,
mConstants.RUNTIME_MIN_UI_DATA_TRANSFER_GUARANTEE_MS));
}
- return Math.max(mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
- mConstants.RUNTIME_MIN_UI_DATA_TRANSFER_GUARANTEE_MS);
+ return Math.min(upperLimitMs,
+ Math.max(mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+ mConstants.RUNTIME_MIN_UI_DATA_TRANSFER_GUARANTEE_MS));
}
- return mConstants.RUNTIME_MIN_UI_GUARANTEE_MS;
+ return Math.min(upperLimitMs, mConstants.RUNTIME_MIN_UI_GUARANTEE_MS);
} else if (job.shouldTreatAsExpeditedJob()) {
// Don't guarantee RESTRICTED jobs more than 5 minutes.
return job.getEffectiveStandbyBucket() != RESTRICTED_INDEX
@@ -3547,13 +3806,24 @@ public class JobSchedulerService extends com.android.server.SystemService
synchronized (mLock) {
if (job.shouldTreatAsUserInitiatedJob()
&& checkRunUserInitiatedJobsPermission(
- job.getSourceUid(), job.getSourcePackageName())) {
+ job.getSourceUid(), job.getSourcePackageName())
+ && mQuotaTracker.isWithinQuota(job.getTimeoutBlameUserId(),
+ job.getTimeoutBlamePackageName(),
+ QUOTA_TRACKER_TIMEOUT_UIJ_TAG)) {
return mConstants.RUNTIME_UI_LIMIT_MS;
}
if (job.shouldTreatAsUserInitiatedJob()) {
return mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
}
- return Math.min(mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ // Only let the app use the higher runtime if it hasn't repeatedly timed out.
+ final String timeoutTag = job.shouldTreatAsExpeditedJob()
+ ? QUOTA_TRACKER_TIMEOUT_EJ_TAG : QUOTA_TRACKER_TIMEOUT_REG_TAG;
+ final long upperLimitMs =
+ mQuotaTracker.isWithinQuota(job.getTimeoutBlameUserId(),
+ job.getTimeoutBlamePackageName(), timeoutTag)
+ ? mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS
+ : mConstants.RUNTIME_MIN_GUARANTEE_MS;
+ return Math.min(upperLimitMs,
mConstants.USE_TARE_POLICY
? mTareController.getMaxJobExecutionTimeMsLocked(job)
: mQuotaController.getMaxJobExecutionTimeMsLocked(job));
@@ -3797,6 +4067,17 @@ public class JobSchedulerService extends com.android.server.SystemService
}
@Override
+ public boolean isAppConsideredBuggy(int callingUserId, @NonNull String callingPackageName,
+ int timeoutBlameUserId, @NonNull String timeoutBlamePackageName) {
+ return !mQuotaTracker.isWithinQuota(callingUserId, callingPackageName,
+ QUOTA_TRACKER_ANR_TAG)
+ || !mQuotaTracker.isWithinQuota(callingUserId, callingPackageName,
+ QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG)
+ || !mQuotaTracker.isWithinQuota(timeoutBlameUserId, timeoutBlamePackageName,
+ QUOTA_TRACKER_TIMEOUT_TOTAL_TAG);
+ }
+
+ @Override
public boolean isNotificationAssociatedWithAnyUserInitiatedJobs(int notificationId,
int userId, @NonNull String packageName) {
if (packageName == null) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index 0b08b6faf971..109686d76b2f 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -413,16 +413,22 @@ public final class JobServiceContext implements ServiceConnection {
final Intent intent = new Intent().setComponent(job.getServiceComponent())
.setFlags(Intent.FLAG_FROM_BACKGROUND);
boolean binding = false;
+ boolean startedWithForegroundFlag = false;
try {
final Context.BindServiceFlags bindFlags;
- if (job.shouldTreatAsUserInitiatedJob()) {
+ if (job.shouldTreatAsUserInitiatedJob() && !job.isUserBgRestricted()) {
+ // If the user has bg restricted the app, don't give the job FG privileges
+ // such as bypassing data saver or getting the higher foreground proc state.
+ // If we've gotten to this point, the app is most likely in the foreground,
+ // so the job will run just fine while the user keeps the app in the foreground.
bindFlags = Context.BindServiceFlags.of(
Context.BIND_AUTO_CREATE
| Context.BIND_ALMOST_PERCEPTIBLE
| Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS
| Context.BIND_BYPASS_USER_NETWORK_RESTRICTIONS
| Context.BIND_NOT_APP_COMPONENT_USAGE);
- } else if (job.shouldTreatAsExpeditedJob()) {
+ startedWithForegroundFlag = true;
+ } else if (job.shouldTreatAsExpeditedJob() || job.shouldTreatAsUserInitiatedJob()) {
bindFlags = Context.BindServiceFlags.of(
Context.BIND_AUTO_CREATE
| Context.BIND_NOT_FOREGROUND
@@ -535,8 +541,11 @@ public final class JobServiceContext implements ServiceConnection {
mAvailable = false;
mStoppedReason = null;
mStoppedTime = 0;
+ // Wait until after bindService() returns a success value to set these so we don't
+ // have JobStatus objects that aren't running but have these set to true.
job.startedAsExpeditedJob = job.shouldTreatAsExpeditedJob();
job.startedAsUserInitiatedJob = job.shouldTreatAsUserInitiatedJob();
+ job.startedWithForegroundFlag = startedWithForegroundFlag;
return true;
}
}
@@ -1331,7 +1340,7 @@ public final class JobServiceContext implements ServiceConnection {
// FINISHED/NO-RETRY.
onSlowAppResponseLocked(/* reschedule */ false, /* updateStopReasons */ true,
/* texCounterMetricId */
- "job_scheduler.value_cntr_w_uid_slow_app_response_onStartJob",
+ "job_scheduler.value_cntr_w_uid_slow_app_response_on_start_job",
/* debugReason */ "timed out while starting",
/* anrMessage */ "No response to onStartJob",
CompatChanges.isChangeEnabled(ANR_PRE_UDC_APIS_ON_SLOW_RESPONSES,
@@ -1343,7 +1352,7 @@ public final class JobServiceContext implements ServiceConnection {
// other reason.
onSlowAppResponseLocked(/* reschedule */ true, /* updateStopReasons */ false,
/* texCounterMetricId */
- "job_scheduler.value_cntr_w_uid_slow_app_response_onStopJob",
+ "job_scheduler.value_cntr_w_uid_slow_app_response_on_stop_job",
/* debugReason */ "timed out while stopping",
/* anrMessage */ "No response to onStopJob",
CompatChanges.isChangeEnabled(ANR_PRE_UDC_APIS_ON_SLOW_RESPONSES,
@@ -1400,7 +1409,7 @@ public final class JobServiceContext implements ServiceConnection {
} else if (mAwaitingNotification) {
onSlowAppResponseLocked(/* reschedule */ true, /* updateStopReasons */ true,
/* texCounterMetricId */
- "job_scheduler.value_cntr_w_uid_slow_app_response_setNotification",
+ "job_scheduler.value_cntr_w_uid_slow_app_response_set_notification",
/* debugReason */ "timed out while stopping",
/* anrMessage */ "required notification not provided",
/* triggerAnr */ true);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
index ecee10a13c1d..25b3421a55f0 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -19,6 +19,7 @@ package com.android.server.job.controllers;
import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -205,8 +206,32 @@ public final class BackgroundJobsController extends StateController {
final int uid = jobStatus.getSourceUid();
final String packageName = jobStatus.getSourcePackageName();
- final boolean canRun = !mAppStateTracker.areJobsRestricted(uid, packageName,
- jobStatus.canRunInBatterySaver());
+ final boolean isUserBgRestricted =
+ !mActivityManagerInternal.isBgAutoRestrictedBucketFeatureFlagEnabled()
+ && !mAppStateTracker.isRunAnyInBackgroundAppOpsAllowed(uid, packageName);
+ // If a job started with the foreground flag, it'll cause the UID to stay active
+ // and thus cause areJobsRestricted() to always return false, so if
+ // areJobsRestricted() returns false and the app is BG restricted and not TOP,
+ // we need to stop any jobs that started with the foreground flag so they don't
+ // keep the app in an elevated proc state. If we were to get in this situation,
+ // then the user restricted the app after the job started, so it's best to stop
+ // the job as soon as possible, especially since the job would be visible to the
+ // user (with a notification and in Task Manager).
+ // There are several other reasons that uidActive can be true for an app even if its
+ // proc state is less important than BFGS.
+ // JobScheduler has historically (at least up through UDC) allowed the app's jobs to run
+ // when its UID was active, even if it's background restricted. This has been fine because
+ // JobScheduler stops the job as soon as the UID becomes inactive and the jobs themselves
+ // will not keep the UID active. The logic here is to ensure that special jobs
+ // (e.g. user-initiated jobs) themselves do not keep the UID active when the app is
+ // background restricted.
+ final boolean shouldStopImmediately = jobStatus.startedWithForegroundFlag
+ && isUserBgRestricted
+ && mService.getUidProcState(uid)
+ > ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ final boolean canRun = !shouldStopImmediately
+ && !mAppStateTracker.areJobsRestricted(
+ uid, packageName, jobStatus.canRunInBatterySaver());
final boolean isActive;
if (activeState == UNKNOWN) {
@@ -219,8 +244,7 @@ public final class BackgroundJobsController extends StateController {
}
boolean didChange =
jobStatus.setBackgroundNotRestrictedConstraintSatisfied(nowElapsed, canRun,
- !mActivityManagerInternal.isBgAutoRestrictedBucketFeatureFlagEnabled()
- && !mAppStateTracker.isRunAnyInBackgroundAppOpsAllowed(uid, packageName));
+ isUserBgRestricted);
didChange |= jobStatus.setUidActive(isActive);
return didChange;
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index f6bdb9303a04..6d938debde10 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -1774,6 +1774,12 @@ public final class ConnectivityController extends RestrictingController implemen
}
pw.println();
+ if (mBackgroundMeteredAllowed.size() > 0) {
+ pw.print("Background metered allowed: ");
+ pw.println(mBackgroundMeteredAllowed);
+ pw.println();
+ }
+
pw.println("Current default network callbacks:");
pw.increaseIndent();
for (int i = 0; i < mCurrentDefaultNetworkCallbacks.size(); i++) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index edd531d13965..13903acc0439 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -430,6 +430,13 @@ public final class JobStatus {
* when it started running. This isn't copied over when a job is rescheduled.
*/
public boolean startedAsUserInitiatedJob = false;
+ /**
+ * Whether this particular JobStatus instance started with the foreground flag
+ * (or more accurately, did <b>not</b> have the
+ * {@link android.content.Context#BIND_NOT_FOREGROUND} flag
+ * included in its binding flags when started).
+ */
+ public boolean startedWithForegroundFlag = false;
public boolean startedWithImmediacyPrivilege = false;
@@ -1088,13 +1095,77 @@ public final class JobStatus {
return UserHandle.getUserId(callingUid);
}
+ private boolean shouldBlameSourceForTimeout() {
+ // If the system scheduled the job on behalf of an app, assume the app is the one
+ // doing the work and blame the app directly. This is the case with things like
+ // syncs via SyncManager.
+ // If the system didn't schedule the job on behalf of an app, then
+ // blame the app doing the actual work. Proxied jobs are a little tricky.
+ // Proxied jobs scheduled by built-in system apps like DownloadManager may be fine
+ // and we could consider exempting those jobs. For example, in DownloadManager's
+ // case, all it does is download files and the code is vetted. A timeout likely
+ // means it's downloading a large file, which isn't an error. For now, DownloadManager
+ // is an exempted app, so this shouldn't be an issue.
+ // However, proxied jobs coming from other system apps (such as those that can
+ // be updated separately from an OTA) may not be fine and we would want to apply
+ // this policy to those jobs/apps.
+ // TODO(284512488): consider exempting DownloadManager or other system apps
+ return UserHandle.isCore(callingUid);
+ }
+
+ /**
+ * Returns the package name that should most likely be blamed for the job timing out.
+ */
+ public String getTimeoutBlamePackageName() {
+ if (shouldBlameSourceForTimeout()) {
+ return sourcePackageName;
+ }
+ return getServiceComponent().getPackageName();
+ }
+
+ /**
+ * Returns the UID that should most likely be blamed for the job timing out.
+ */
+ public int getTimeoutBlameUid() {
+ if (shouldBlameSourceForTimeout()) {
+ return sourceUid;
+ }
+ return callingUid;
+ }
+
+ /**
+ * Returns the userId that should most likely be blamed for the job timing out.
+ */
+ public int getTimeoutBlameUserId() {
+ if (shouldBlameSourceForTimeout()) {
+ return sourceUserId;
+ }
+ return UserHandle.getUserId(callingUid);
+ }
+
/**
* Returns an appropriate standby bucket for the job, taking into account any standby
* exemptions.
*/
public int getEffectiveStandbyBucket() {
+ final JobSchedulerInternal jsi = LocalServices.getService(JobSchedulerInternal.class);
+ final boolean isBuggy = jsi.isAppConsideredBuggy(
+ getUserId(), getServiceComponent().getPackageName(),
+ getTimeoutBlameUserId(), getTimeoutBlamePackageName());
+
final int actualBucket = getStandbyBucket();
if (actualBucket == EXEMPTED_INDEX) {
+ // EXEMPTED apps always have their jobs exempted, even if they're buggy, because the
+ // user has explicitly told the system to avoid restricting the app for power reasons.
+ if (isBuggy) {
+ final String pkg;
+ if (getServiceComponent().getPackageName().equals(sourcePackageName)) {
+ pkg = sourcePackageName;
+ } else {
+ pkg = getServiceComponent().getPackageName() + "/" + sourcePackageName;
+ }
+ Slog.w(TAG, "Exempted app " + pkg + " considered buggy");
+ }
return actualBucket;
}
if (uidActive || getJob().isExemptedFromAppStandby()) {
@@ -1102,13 +1173,18 @@ public final class JobStatus {
// like other ACTIVE apps.
return ACTIVE_INDEX;
}
+ // If the app is considered buggy, but hasn't yet been put in the RESTRICTED bucket
+ // (potentially because it's used frequently by the user), limit its effective bucket
+ // so that it doesn't get to run as much as a normal ACTIVE app.
+ final int highestBucket = isBuggy ? WORKING_INDEX : ACTIVE_INDEX;
if (actualBucket != RESTRICTED_INDEX && actualBucket != NEVER_INDEX
&& mHasMediaBackupExemption) {
- // Cap it at WORKING_INDEX as media back up jobs are important to the user, and the
+ // Treat it as if it's at least WORKING_INDEX since media backup jobs are important
+ // to the user, and the
// source package may not have been used directly in a while.
- return Math.min(WORKING_INDEX, actualBucket);
+ return Math.max(highestBucket, Math.min(WORKING_INDEX, actualBucket));
}
- return actualBucket;
+ return Math.max(highestBucket, actualBucket);
}
/** Returns the real standby bucket of the job. */
@@ -1537,6 +1613,10 @@ public final class JobStatus {
* for any reason.
*/
public boolean shouldTreatAsUserInitiatedJob() {
+ // isUserBgRestricted is intentionally excluded from this method. It should be fine to
+ // treat the job as a UI job while the app is TOP, but just not in the background.
+ // Instead of adding a proc state check here, the parts of JS that can make the distinction
+ // and care about the distinction can do the check.
return getJob().isUserInitiated()
&& (getInternalFlags() & INTERNAL_FLAG_DEMOTED_BY_USER) == 0
&& (getInternalFlags() & INTERNAL_FLAG_DEMOTED_BY_SYSTEM_UIJ) == 0;
@@ -1584,6 +1664,11 @@ public final class JobStatus {
&& (mDynamicConstraints & CONSTRAINT_BACKGROUND_NOT_RESTRICTED) == 0);
}
+ /** Returns whether or not the app is background restricted by the user (FAS). */
+ public boolean isUserBgRestricted() {
+ return mIsUserBgRestricted;
+ }
+
/** @return true if the constraint was changed, false otherwise. */
boolean setChargingConstraintSatisfied(final long nowElapsed, boolean state) {
return setConstraintSatisfied(CONSTRAINT_CHARGING, nowElapsed, state);
@@ -2733,6 +2818,12 @@ public final class JobStatus {
}
pw.decreaseIndent();
+ pw.print("Started with foreground flag: ");
+ pw.println(startedWithForegroundFlag);
+ if (mIsUserBgRestricted) {
+ pw.println("User BG restricted");
+ }
+
if (changedAuthorities != null) {
pw.println("Changed authorities:");
pw.increaseIndent();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 07958dd0fef5..1c29982dbd48 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -773,6 +773,14 @@ public final class QuotaController extends StateController {
// If quota is currently "free", then the job can run for the full amount of time,
// regardless of bucket (hence using charging instead of isQuotaFreeLocked()).
if (mService.isBatteryCharging()
+ // The top and foreground cases here were added because apps in those states
+ // aren't really restricted and the work could be something the user is
+ // waiting for. Now that user-initiated jobs are a defined concept, we may
+ // not need these exemptions as much. However, UIJs are currently limited
+ // (as of UDC) to data transfer work. There may be other work that could
+ // rely on this exception. Once we add more UIJ types, we can re-evaluate
+ // the need for these exceptions.
+ // TODO: re-evaluate the need for these exceptions
|| mTopAppCache.get(jobStatus.getSourceUid())
|| isTopStartedJobLocked(jobStatus)
|| isUidInForeground(jobStatus.getSourceUid())) {
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 55e681521048..7d3837786be9 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -3025,7 +3025,7 @@ public class AppStandbyController
public static final long DEFAULT_INITIAL_FOREGROUND_SERVICE_START_TIMEOUT =
COMPRESS_TIME ? ONE_MINUTE : 30 * ONE_MINUTE;
public static final long DEFAULT_AUTO_RESTRICTED_BUCKET_DELAY_MS =
- COMPRESS_TIME ? ONE_MINUTE : ONE_DAY;
+ COMPRESS_TIME ? ONE_MINUTE : ONE_HOUR;
public static final boolean DEFAULT_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS = true;
public static final long DEFAULT_BROADCAST_RESPONSE_WINDOW_DURATION_MS =
2 * ONE_MINUTE;
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 2198fcd70637..f67c68eb044d 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -111,20 +111,20 @@ public class AnimatorInflater {
float pathErrorScale) throws NotFoundException {
final ConfigurationBoundResourceCache<Animator> animatorCache = resources
.getAnimatorCache();
- ConfigurationBoundResourceCache.Entry<Animator> animatorEntry =
- animatorCache.getInstance(id, resources, theme);
- if (animatorEntry.hasValue()) {
+ Animator animator = animatorCache.getInstance(id, resources, theme);
+ if (animator != null) {
if (DBG_ANIMATOR_INFLATER) {
Log.d(TAG, "loaded animator from cache, " + resources.getResourceName(id));
}
- return animatorEntry.getValue();
+ return animator;
} else if (DBG_ANIMATOR_INFLATER) {
Log.d(TAG, "cache miss for animator " + resources.getResourceName(id));
}
+ int cacheGeneration = animatorCache.getGeneration();
XmlResourceParser parser = null;
try {
parser = resources.getAnimation(id);
- Animator animator = createAnimatorFromXml(resources, theme, parser, pathErrorScale);
+ animator = createAnimatorFromXml(resources, theme, parser, pathErrorScale);
if (animator != null) {
animator.appendChangingConfigurations(getChangingConfigs(resources, id));
final ConstantState<Animator> constantState = animator.createConstantState();
@@ -132,7 +132,7 @@ public class AnimatorInflater {
if (DBG_ANIMATOR_INFLATER) {
Log.d(TAG, "caching animator for res " + resources.getResourceName(id));
}
- animatorCache.put(id, theme, constantState, animatorEntry.getGeneration());
+ animatorCache.put(id, theme, constantState, cacheGeneration);
// create a new animator so that cached version is never used by the user
animator = constantState.newInstance(resources, theme);
}
@@ -161,22 +161,22 @@ public class AnimatorInflater {
final ConfigurationBoundResourceCache<StateListAnimator> cache = resources
.getStateListAnimatorCache();
final Theme theme = context.getTheme();
- ConfigurationBoundResourceCache.Entry<StateListAnimator> animatorEntry =
- cache.getInstance(id, resources, theme);
- if (animatorEntry.hasValue()) {
- return animatorEntry.getValue();
+ StateListAnimator animator = cache.getInstance(id, resources, theme);
+ if (animator != null) {
+ return animator;
}
+ int cacheGeneration = cache.getGeneration();
XmlResourceParser parser = null;
try {
parser = resources.getAnimation(id);
- StateListAnimator animator =
+ animator =
createStateListAnimatorFromXml(context, parser, Xml.asAttributeSet(parser));
if (animator != null) {
animator.appendChangingConfigurations(getChangingConfigs(resources, id));
final ConstantState<StateListAnimator> constantState = animator
.createConstantState();
if (constantState != null) {
- cache.put(id, theme, constantState, animatorEntry.getGeneration());
+ cache.put(id, theme, constantState, cacheGeneration);
// return a clone so that the animator in constant state is never used.
animator = constantState.newInstance(resources, theme);
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 0ec3847d29f4..46260ea5e658 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -607,6 +607,7 @@ interface IActivityManager {
void killPackageDependents(in String packageName, int userId);
void makePackageIdle(String packageName, int userId);
+ void setDeterministicUidIdle(boolean deterministic);
int getMemoryTrimLevel();
boolean isVrModePackageEnabled(in ComponentName packageName);
void notifyLockedProfile(int userId);
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index 4b8cfd5d3215..c4e49954f745 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -334,6 +334,12 @@ public class TaskInfo {
public boolean isVisible;
/**
+ * Whether this task is request visible.
+ * @hide
+ */
+ public boolean isVisibleRequested;
+
+ /**
* Whether this task is sleeping due to sleeping display.
* @hide
*/
@@ -518,6 +524,7 @@ public class TaskInfo {
&& Objects.equals(taskDescription, that.taskDescription)
&& isFocused == that.isFocused
&& isVisible == that.isVisible
+ && isVisibleRequested == that.isVisibleRequested
&& isSleeping == that.isSleeping
&& Objects.equals(mTopActivityLocusId, that.mTopActivityLocusId)
&& parentTaskId == that.parentTaskId
@@ -591,6 +598,7 @@ public class TaskInfo {
parentTaskId = source.readInt();
isFocused = source.readBoolean();
isVisible = source.readBoolean();
+ isVisibleRequested = source.readBoolean();
isSleeping = source.readBoolean();
topActivityInSizeCompat = source.readBoolean();
topActivityEligibleForLetterboxEducation = source.readBoolean();
@@ -644,6 +652,7 @@ public class TaskInfo {
dest.writeInt(parentTaskId);
dest.writeBoolean(isFocused);
dest.writeBoolean(isVisible);
+ dest.writeBoolean(isVisibleRequested);
dest.writeBoolean(isSleeping);
dest.writeBoolean(topActivityInSizeCompat);
dest.writeBoolean(topActivityEligibleForLetterboxEducation);
@@ -687,6 +696,7 @@ public class TaskInfo {
+ " parentTaskId=" + parentTaskId
+ " isFocused=" + isFocused
+ " isVisible=" + isVisible
+ + " isVisibleRequested=" + isVisibleRequested
+ " isSleeping=" + isSleeping
+ " topActivityInSizeCompat=" + topActivityInSizeCompat
+ " topActivityEligibleForLetterboxEducation= "
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index d96a9d104ec2..34f0964cf823 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -39,7 +39,6 @@ import android.os.ServiceManager;
import android.os.UserHandle;
import android.permission.IPermissionManager;
import android.util.Log;
-import android.util.Pair;
import android.view.IWindowManager;
import android.view.InputDevice;
import android.view.InputEvent;
@@ -52,7 +51,8 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.IAccessibilityManager;
import android.window.ScreenCapture;
import android.window.ScreenCapture.CaptureArgs;
-import android.window.ScreenCapture.ScreenCaptureListener;
+import android.window.ScreenCapture.ScreenshotHardwareBuffer;
+import android.window.ScreenCapture.SynchronousScreenCaptureListener;
import libcore.io.IoUtils;
@@ -235,12 +235,12 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
final CaptureArgs captureArgs = new CaptureArgs.Builder<>()
.setSourceCrop(crop)
.build();
- Pair<ScreenCaptureListener, ScreenCapture.ScreenshotSync> syncScreenCapture =
+ SynchronousScreenCaptureListener syncScreenCapture =
ScreenCapture.createSyncCaptureListener();
mWindowManager.captureDisplay(DEFAULT_DISPLAY, captureArgs,
- syncScreenCapture.first);
- final ScreenCapture.ScreenshotHardwareBuffer screenshotBuffer =
- syncScreenCapture.second.get();
+ syncScreenCapture);
+ final ScreenshotHardwareBuffer screenshotBuffer =
+ syncScreenCapture.getBuffer();
return screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
} catch (RemoteException re) {
re.rethrowAsRuntimeException();
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 57935e3bd5b1..ee888ed7d872 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -913,7 +913,7 @@ public class WallpaperManager {
* instead the default system wallpaper is returned
* (some versions of T may throw a {@code SecurityException}).</li>
* <li>From version U, this method should not be used
- * and will always throw a @code SecurityException}.</li>
+ * and will always throw a {@code SecurityException}.</li>
* <li> Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE}
* can still access the real wallpaper on all versions. </li>
* </ul>
@@ -935,18 +935,9 @@ public class WallpaperManager {
}
/**
- * <strong> Important note: </strong>
- * <ul>
- * <li>Up to version S, this method requires the
- * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission.</li>
- * <li>Starting in T, directly accessing the wallpaper is not possible anymore,
- * instead the default system wallpaper is returned
- * (some versions of T may throw a {@code SecurityException}).</li>
- * <li>From version U, this method should not be used
- * and will always throw a @code SecurityException}.</li>
- * <li> Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE}
- * can still access the real wallpaper on all versions. </li>
- * </ul>
+ * <strong> Important note: </strong> only apps with
+ * {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} should use this method.
+ * Otherwise, a {@code SecurityException} will be thrown.
*
* <p>
* Retrieve the requested wallpaper for the specified wallpaper type if the wallpaper is not
@@ -1206,7 +1197,7 @@ public class WallpaperManager {
* instead the default system wallpaper is returned
* (some versions of T may throw a {@code SecurityException}).</li>
* <li>From version U, this method should not be used
- * and will always throw a @code SecurityException}.</li>
+ * and will always throw a {@code SecurityException}.</li>
* <li> Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE}
* can still access the real wallpaper on all versions. </li>
* </ul>
@@ -1228,18 +1219,9 @@ public class WallpaperManager {
}
/**
- * <strong> Important note: </strong>
- * <ul>
- * <li>Up to version S, this method requires the
- * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission.</li>
- * <li>Starting in T, directly accessing the wallpaper is not possible anymore,
- * instead the default system wallpaper is returned
- * (some versions of T may throw a {@code SecurityException}).</li>
- * <li>From version U, this method should not be used
- * and will always throw a @code SecurityException}.</li>
- * <li> Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE}
- * can still access the real wallpaper on all versions. </li>
- * </ul>
+ * <strong> Important note: </strong> only apps with
+ * {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} should use this method.
+ * Otherwise, a {@code SecurityException} will be thrown.
*
* <p>
* Equivalent to {@link #getDrawable(int)}.
@@ -1268,7 +1250,7 @@ public class WallpaperManager {
* instead the default wallpaper is returned
* (some versions of T may throw a {@code SecurityException}).</li>
* <li>From version U, this method should not be used
- * and will always throw a @code SecurityException}.</li>
+ * and will always throw a {@code SecurityException}.</li>
* <li> Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE}
* can still access the real wallpaper on all versions. </li>
* </ul>
@@ -1290,19 +1272,9 @@ public class WallpaperManager {
}
/**
- * <strong> Important note: </strong>
- * <ul>
- * <li>Up to version S, this method requires the
- * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission.</li>
- * <li>Starting in T, directly accessing the wallpaper is not possible anymore,
- * instead the default system wallpaper is returned
- * (some versions of T may throw a {@code SecurityException}).</li>
- * <li>From version U, this method should not be used
- * and will always throw a @code SecurityException}.</li>
- * <li> Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE}
- * can still access the real wallpaper on all versions. </li>
- * </ul>
- * <br>
+ * <strong> Important note: </strong> only apps with
+ * {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} should use this method.
+ * Otherwise, a {@code SecurityException} will be thrown.
*
* Like {@link #getDrawable(int)}, but the returned Drawable has a number
* of limitations to reduce its overhead as much as possible. It will
@@ -1334,18 +1306,9 @@ public class WallpaperManager {
}
/**
- * <strong> Important note: </strong>
- * <ul>
- * <li>Up to version S, this method requires the
- * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission.</li>
- * <li>Starting in T, directly accessing the wallpaper is not possible anymore,
- * instead the default system wallpaper is returned
- * (some versions of T may throw a {@code SecurityException}).</li>
- * <li>From version U, this method should not be used
- * and will always throw a @code SecurityException}.</li>
- * <li> Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE}
- * can still access the real wallpaper on all versions. </li>
- * </ul>
+ * <strong> Important note: </strong> only apps with
+ * {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} should use this method.
+ * Otherwise, a {@code SecurityException} will be thrown.
*
* <p>
* Equivalent to {@link #getFastDrawable()}.
@@ -1364,18 +1327,9 @@ public class WallpaperManager {
}
/**
- * <strong> Important note: </strong>
- * <ul>
- * <li>Up to version S, this method requires the
- * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission.</li>
- * <li>Starting in T, directly accessing the wallpaper is not possible anymore,
- * instead the default system wallpaper is returned
- * (some versions of T may throw a {@code SecurityException}).</li>
- * <li>From version U, this method should not be used
- * and will always throw a @code SecurityException}.</li>
- * <li> Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE}
- * can still access the real wallpaper on all versions. </li>
- * </ul>
+ * <strong> Important note: </strong> only apps with
+ * {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE}
+ * should use this method. Otherwise, a {@code SecurityException} will be thrown.
*
* <p>
* Equivalent to {@link #getFastDrawable(int)}.
@@ -1562,7 +1516,7 @@ public class WallpaperManager {
* instead the default system wallpaper is returned
* (some versions of T may throw a {@code SecurityException}).</li>
* <li>From version U, this method should not be used
- * and will always throw a @code SecurityException}.</li>
+ * and will always throw a {@code SecurityException}.</li>
* <li> Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE}
* can still access the real wallpaper on all versions. </li>
* </ul>
@@ -2933,62 +2887,21 @@ public class WallpaperManager {
}
}
- if (!isComponentExist(context, cn)) {
- cn = null;
- }
-
- return cn;
- }
-
- /**
- * Return {@link ComponentName} of the CMF default wallpaper, or
- * {@link #getDefaultWallpaperComponent(Context)} if none is defined.
- *
- * @hide
- */
- public static ComponentName getCmfDefaultWallpaperComponent(Context context) {
- ComponentName cn = null;
- String[] cmfWallpaperMap = context.getResources().getStringArray(
- com.android.internal.R.array.cmf_default_wallpaper_component);
- if (cmfWallpaperMap == null || cmfWallpaperMap.length == 0) {
- Log.d(TAG, "No CMF wallpaper config");
- return getDefaultWallpaperComponent(context);
- }
-
- for (String entry : cmfWallpaperMap) {
- String[] cmfWallpaper;
- if (!TextUtils.isEmpty(entry)) {
- cmfWallpaper = entry.split(",");
- if (cmfWallpaper != null && cmfWallpaper.length == 2 && VALUE_CMF_COLOR.equals(
- cmfWallpaper[0]) && !TextUtils.isEmpty(cmfWallpaper[1])) {
- cn = ComponentName.unflattenFromString(cmfWallpaper[1]);
- break;
- }
+ // Check if the package exists
+ if (cn != null) {
+ try {
+ final PackageManager packageManager = context.getPackageManager();
+ packageManager.getPackageInfo(cn.getPackageName(),
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
+ } catch (PackageManager.NameNotFoundException e) {
+ cn = null;
}
}
- if (!isComponentExist(context, cn)) {
- cn = null;
- }
-
return cn;
}
- private static boolean isComponentExist(Context context, ComponentName cn) {
- if (cn == null) {
- return false;
- }
- try {
- final PackageManager packageManager = context.getPackageManager();
- packageManager.getPackageInfo(cn.getPackageName(),
- PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
- } catch (PackageManager.NameNotFoundException e) {
- return false;
- }
- return true;
- }
-
/**
* Register a callback for lock wallpaper observation. Only the OS may use this.
*
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index b2a923043dbe..da5e40aedbd2 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -11369,7 +11369,8 @@ public class DevicePolicyManager {
* @throws SecurityException if the caller is not a profile owner on an organization-owned
* managed profile.
* @throws IllegalStateException if called after the device setup has been completed.
- * @throws UnsupportedOperationException if the api is not enabled.
+ * @throws UnsupportedOperationException if managed subscriptions policy is not explicitly
+ * enabled by the device policy management role holder during device setup.
* @see ManagedSubscriptionsPolicy
*/
public void setManagedSubscriptionsPolicy(@Nullable ManagedSubscriptionsPolicy policy) {
diff --git a/core/java/android/app/admin/WifiSsidPolicy.java b/core/java/android/app/admin/WifiSsidPolicy.java
index 3fefe4bda331..ffc4480f81a2 100644
--- a/core/java/android/app/admin/WifiSsidPolicy.java
+++ b/core/java/android/app/admin/WifiSsidPolicy.java
@@ -135,6 +135,10 @@ public final class WifiSsidPolicy implements Parcelable {
dest.writeArraySet(mSsids);
}
+ /**
+ * Two instances of WifiSsidPolicy are considered equal if they have
+ * the same WifiSsidPolicyType and the same set of WifiSsids
+ */
@Override
public boolean equals(Object thatObject) {
if (this == thatObject) {
@@ -147,6 +151,9 @@ public final class WifiSsidPolicy implements Parcelable {
return mPolicyType == that.mPolicyType && Objects.equals(mSsids, that.mSsids);
}
+ /**
+ * Returns the hash code value of WifiSsidPolicyType and WifiSsid set
+ */
@Override
public int hashCode() {
return Objects.hash(mPolicyType, mSsids);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 960d10adbfbb..048289f56a0c 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2628,15 +2628,6 @@ public class PackageParser {
return Build.VERSION_CODES.CUR_DEVELOPMENT;
}
- // STOPSHIP: hack for the pre-release SDK
- if (platformSdkCodenames.length == 0
- && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
- targetCode)) {
- Slog.w(TAG, "Package requires development platform " + targetCode
- + ", returning current version " + Build.VERSION.SDK_INT);
- return Build.VERSION.SDK_INT;
- }
-
// Otherwise, we're looking at an incompatible pre-release SDK.
if (platformSdkCodenames.length > 0) {
outError[0] = "Requires development platform " + targetCode
@@ -2708,15 +2699,6 @@ public class PackageParser {
return Build.VERSION_CODES.CUR_DEVELOPMENT;
}
- // STOPSHIP: hack for the pre-release SDK
- if (platformSdkCodenames.length == 0
- && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
- minCode)) {
- Slog.w(TAG, "Package requires min development platform " + minCode
- + ", returning current version " + Build.VERSION.SDK_INT);
- return Build.VERSION.SDK_INT;
- }
-
// Otherwise, we're looking at an incompatible pre-release SDK.
if (platformSdkCodenames.length > 0) {
outError[0] = "Requires development platform " + minCode
diff --git a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
index 8cc4cdb955ca..3e1c5bb3d7ec 100644
--- a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
@@ -316,15 +316,6 @@ public class FrameworkParsingPackageUtils {
return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
}
- // STOPSHIP: hack for the pre-release SDK
- if (platformSdkCodenames.length == 0
- && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
- minCode)) {
- Slog.w(TAG, "Parsed package requires min development platform " + minCode
- + ", returning current version " + Build.VERSION.SDK_INT);
- return input.success(Build.VERSION.SDK_INT);
- }
-
// Otherwise, we're looking at an incompatible pre-release SDK.
if (platformSdkCodenames.length > 0) {
return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
@@ -377,27 +368,19 @@ public class FrameworkParsingPackageUtils {
return input.success(targetVers);
}
- // If it's a pre-release SDK and the codename matches this platform, it
- // definitely targets this SDK.
- if (matchTargetCode(platformSdkCodenames, targetCode)) {
- return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
- }
-
- // STOPSHIP: hack for the pre-release SDK
- if (platformSdkCodenames.length == 0
- && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
- targetCode)) {
- Slog.w(TAG, "Parsed package requires development platform " + targetCode
- + ", returning current version " + Build.VERSION.SDK_INT);
- return input.success(Build.VERSION.SDK_INT);
- }
-
try {
if (allowUnknownCodenames && UnboundedSdkLevel.isAtMost(targetCode)) {
return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
}
} catch (IllegalArgumentException e) {
- return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, "Bad package SDK");
+ // isAtMost() throws it when encountering an older SDK codename
+ return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, e.getMessage());
+ }
+
+ // If it's a pre-release SDK and the codename matches this platform, it
+ // definitely targets this SDK.
+ if (matchTargetCode(platformSdkCodenames, targetCode)) {
+ return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
}
// Otherwise, we're looking at an incompatible pre-release SDK.
diff --git a/core/java/android/content/res/ConfigurationBoundResourceCache.java b/core/java/android/content/res/ConfigurationBoundResourceCache.java
index 4da3c18883bd..5e10a5768358 100644
--- a/core/java/android/content/res/ConfigurationBoundResourceCache.java
+++ b/core/java/android/content/res/ConfigurationBoundResourceCache.java
@@ -37,16 +37,16 @@ public class ConfigurationBoundResourceCache<T> extends ThemedResourceCache<Cons
* @param key a key that uniquely identifies the drawable resource
* @param resources a Resources object from which to create new instances.
* @param theme the theme where the resource will be used
- * @return an Entry wrapping a new instance of the resource, or {@code null} if not in
+ * @return a new instance of the resource, or {@code null} if not in
* the cache
*/
- public Entry<T> getInstance(long key, Resources resources, Resources.Theme theme) {
- final Entry<ConstantState<T>> e = get(key, theme);
- if (e.hasValue()) {
- return new Entry<>(e.getValue().newInstance(resources, theme), e.getGeneration());
+ public T getInstance(long key, Resources resources, Resources.Theme theme) {
+ final ConstantState<T> entry = get(key, theme);
+ if (entry != null) {
+ return entry.newInstance(resources, theme);
}
- return new Entry<>(null, e.getGeneration());
+ return null;
}
@Override
diff --git a/core/java/android/content/res/DrawableCache.java b/core/java/android/content/res/DrawableCache.java
index b51d14a3c472..d0ebe3304065 100644
--- a/core/java/android/content/res/DrawableCache.java
+++ b/core/java/android/content/res/DrawableCache.java
@@ -40,32 +40,14 @@ class DrawableCache extends ThemedResourceCache<Drawable.ConstantState> {
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public Drawable getInstance(long key, Resources resources, Resources.Theme theme) {
- final Entry<Drawable.ConstantState> entry = get(key, theme);
- if (entry.getValue() != null) {
- return entry.getValue().newDrawable(resources, theme);
+ final Drawable.ConstantState entry = get(key, theme);
+ if (entry != null) {
+ return entry.newDrawable(resources, theme);
}
return null;
}
- /**
- * If the resource is cached, creates and returns a new instance of it.
- *
- * @param key a key that uniquely identifies the drawable resource
- * @param resources a Resources object from which to create new instances.
- * @param theme the theme where the resource will be used
- * @return an Entry wrapping a a new instance of the resource, or {@code null} if not in
- * the cache
- */
- public Entry<Drawable> getDrawable(long key, Resources resources, Resources.Theme theme) {
- final Entry<Drawable.ConstantState> e = get(key, theme);
- if (e.hasValue()) {
- return new Entry<>(e.getValue().newDrawable(resources, theme), e.getGeneration());
- }
-
- return new Entry<>(null, e.getGeneration());
- }
-
@Override
public boolean shouldInvalidateEntry(Drawable.ConstantState entry, int configChanges) {
return Configuration.needNewResources(configChanges, entry.getChangingConfigurations());
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 25154d5c1623..1fdfcd067867 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -650,21 +650,16 @@ public class ResourcesImpl {
key = (((long) value.assetCookie) << 32) | value.data;
}
- int cacheGeneration;
+ int cacheGeneration = caches.getGeneration();
// First, check whether we have a cached version of this drawable
// that was inflated against the specified theme. Skip the cache if
// we're currently preloading or we're not using the cache.
if (!mPreloading && useCache) {
- final ThemedResourceCache.Entry<Drawable> cachedDrawable =
- caches.getDrawable(key, wrapper, theme);
- if (cachedDrawable.hasValue()) {
- cachedDrawable.getValue().setChangingConfigurations(
- value.changingConfigurations);
- return cachedDrawable.getValue();
+ Drawable cachedDrawable = caches.getInstance(key, wrapper, theme);
+ if (cachedDrawable != null) {
+ cachedDrawable.setChangingConfigurations(value.changingConfigurations);
+ return cachedDrawable;
}
- cacheGeneration = cachedDrawable.getGeneration();
- } else {
- cacheGeneration = ThemedResourceCache.UNDEFINED_GENERATION;
}
// Next, check preloaded drawables. Preloaded drawables may contain
@@ -1009,16 +1004,15 @@ public class ResourcesImpl {
TypedValue value, int id) {
final long key = (((long) value.assetCookie) << 32) | value.data;
final ConfigurationBoundResourceCache<ComplexColor> cache = mComplexColorCache;
- ThemedResourceCache.Entry<ComplexColor> complexColorEntry =
- cache.getInstance(key, wrapper, theme);
- if (complexColorEntry.hasValue()) {
- return complexColorEntry.getValue();
+ ComplexColor complexColor = cache.getInstance(key, wrapper, theme);
+ if (complexColor != null) {
+ return complexColor;
}
+ int cacheGeneration = cache.getGeneration();
final android.content.res.ConstantState<ComplexColor> factory =
sPreloadedComplexColors.get(key);
- ComplexColor complexColor = null;
if (factory != null) {
complexColor = factory.newInstance(wrapper, theme);
}
@@ -1035,8 +1029,7 @@ public class ResourcesImpl {
sPreloadedComplexColors.put(key, complexColor.getConstantState());
}
} else {
- cache.put(key, theme, complexColor.getConstantState(),
- complexColorEntry.getGeneration());
+ cache.put(key, theme, complexColor.getConstantState(), cacheGeneration);
}
}
return complexColor;
diff --git a/core/java/android/content/res/ThemedResourceCache.java b/core/java/android/content/res/ThemedResourceCache.java
index e7fd2755a941..a7cd168690b4 100644
--- a/core/java/android/content/res/ThemedResourceCache.java
+++ b/core/java/android/content/res/ThemedResourceCache.java
@@ -41,29 +41,6 @@ abstract class ThemedResourceCache<T> {
private int mGeneration;
- public static class Entry<S> {
- private S mValue;
- private int mGeneration;
-
-
- public S getValue() {
- return mValue;
- }
-
- public boolean hasValue() {
- return mValue != null;
- }
-
- public int getGeneration() {
- return mGeneration;
- }
-
- Entry(S value, int generation) {
- this.mValue = value;
- this.mGeneration = generation;
- }
- }
-
/**
* Adds a new theme-dependent entry to the cache.
*
@@ -109,6 +86,15 @@ abstract class ThemedResourceCache<T> {
}
/**
+ * Returns the current generation of the cache
+ *
+ * @return The current generation
+ */
+ public int getGeneration() {
+ return mGeneration;
+ }
+
+ /**
* Returns an entry from the cache.
*
* @param key a key that uniquely identifies the entry
@@ -116,7 +102,7 @@ abstract class ThemedResourceCache<T> {
* @return a cached entry, or {@code null} if not in the cache
*/
@Nullable
- public Entry get(long key, @Nullable Theme theme) {
+ public T get(long key, @Nullable Theme theme) {
// The themed (includes null-themed) and unthemed caches are mutually
// exclusive, so we'll give priority to whichever one we think we'll
// hit first. Since most of the framework drawables are themed, that's
@@ -126,7 +112,7 @@ abstract class ThemedResourceCache<T> {
if (themedEntries != null) {
final WeakReference<T> themedEntry = themedEntries.get(key);
if (themedEntry != null) {
- return new Entry(themedEntry.get(), mGeneration);
+ return themedEntry.get();
}
}
@@ -134,14 +120,15 @@ abstract class ThemedResourceCache<T> {
if (unthemedEntries != null) {
final WeakReference<T> unthemedEntry = unthemedEntries.get(key);
if (unthemedEntry != null) {
- return new Entry(unthemedEntry.get(), mGeneration);
+ return unthemedEntry.get();
}
}
}
- return new Entry(null, mGeneration);
+ return null;
}
+
/**
* Prunes cache entries that have been invalidated by a configuration
* change.
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index d1063f647c4f..d1c10fa46aaa 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -190,8 +190,7 @@ public final class PowerManager {
/**
* Wake lock flag: Turn the screen on when the wake lock is acquired.
* <p>
- * This flag requires {@link android.Manifest.permission#TURN_SCREEN_ON} for apps targeting
- * Android version {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and higher.
+ * This flag will require {@link android.Manifest.permission#TURN_SCREEN_ON} in future releases.
* </p><p>
* Normally wake locks don't actually wake the device, they just cause the screen to remain on
* once it's already on. This flag will cause the device to wake up when the wake lock is
diff --git a/core/java/android/service/dreams/DreamOverlayService.java b/core/java/android/service/dreams/DreamOverlayService.java
index 5469916bea4e..9a02b74b37d0 100644
--- a/core/java/android/service/dreams/DreamOverlayService.java
+++ b/core/java/android/service/dreams/DreamOverlayService.java
@@ -71,13 +71,7 @@ public abstract class DreamOverlayService extends Service {
@Override
public void wakeUp() {
- mService.wakeUp(this, () -> {
- try {
- mDreamOverlayCallback.onWakeUpComplete();
- } catch (RemoteException e) {
- Log.e(TAG, "Could not notify dream of wakeUp", e);
- }
- });
+ mService.wakeUp(this);
}
@Override
@@ -125,14 +119,14 @@ public abstract class DreamOverlayService extends Service {
mCurrentClient = null;
}
- private void wakeUp(OverlayClient client, Runnable callback) {
+ private void wakeUp(OverlayClient client) {
// Run on executor as this is a binder call from OverlayClient.
mExecutor.execute(() -> {
if (mCurrentClient != client) {
return;
}
- onWakeUp(callback);
+ onWakeUp();
});
}
@@ -190,19 +184,10 @@ public abstract class DreamOverlayService extends Service {
/**
* This method is overridden by implementations to handle when the dream has been requested
- * to wakeup. This allows any overlay animations to run. By default, the method will invoke
- * the callback immediately.
- *
- * This callback will be run on the {@link Executor} provided in the constructor if provided, or
- * on the main executor if none was provided.
- *
- * @param onCompleteCallback The callback to trigger to notify the dream service that the
- * overlay has completed waking up.
+ * to wakeup.
* @hide
*/
- public void onWakeUp(@NonNull Runnable onCompleteCallback) {
- onCompleteCallback.run();
- }
+ public void onWakeUp() {}
/**
* This method is overridden by implementations to handle when the dream has ended. There may
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 3a323524b68e..cd57de5649da 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -249,13 +249,6 @@ public class DreamService extends Service implements Window.Callback {
// Simply finish dream when exit is requested.
mHandler.post(() -> finish());
}
-
- @Override
- public void onWakeUpComplete() {
- // Finish the dream once overlay animations are complete. Execute on handler since
- // this is coming in on the overlay binder.
- mHandler.post(() -> finish());
- }
};
@@ -923,6 +916,7 @@ public class DreamService extends Service implements Window.Callback {
overlay.wakeUp();
} catch (RemoteException e) {
Slog.e(TAG, "Error waking the overlay service", e);
+ } finally {
finish();
}
});
diff --git a/core/java/android/service/dreams/IDreamOverlayCallback.aidl b/core/java/android/service/dreams/IDreamOverlayCallback.aidl
index 4ad63f1317d1..ec76a334d5b2 100644
--- a/core/java/android/service/dreams/IDreamOverlayCallback.aidl
+++ b/core/java/android/service/dreams/IDreamOverlayCallback.aidl
@@ -28,7 +28,4 @@ interface IDreamOverlayCallback {
* Invoked to request the dream exit.
*/
void onExitRequested();
-
- /** Invoked when the dream overlay wakeUp animation is complete. */
- void onWakeUpComplete();
} \ No newline at end of file
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 4e086c2ad134..dbc1be141571 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -44,6 +44,7 @@ import android.app.WallpaperManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.BLASTBufferQueue;
import android.graphics.Bitmap;
@@ -190,6 +191,9 @@ public abstract class WallpaperService extends Service {
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
+ // TODO (b/287037772) remove this flag and the forceReport argument in reportVisibility
+ private boolean mIsWearOs;
+
static final class WallpaperCommand {
String action;
int x;
@@ -2282,7 +2286,8 @@ public abstract class WallpaperService extends Service {
@Override
public void onDisplayChanged(int displayId) {
if (mDisplay.getDisplayId() == displayId) {
- boolean forceReport = mDisplay.getState() != Display.STATE_DOZE_SUSPEND;
+ boolean forceReport = mIsWearOs
+ && mDisplay.getState() != Display.STATE_DOZE_SUSPEND;
reportVisibility(forceReport);
}
}
@@ -2734,6 +2739,7 @@ public abstract class WallpaperService extends Service {
mBackgroundThread = new HandlerThread("DefaultWallpaperLocalColorExtractor");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
+ mIsWearOs = getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
super.onCreate();
Trace.endSection();
}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index d87198a0dc85..ff7d8bb956ca 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -238,7 +238,7 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put(SETTINGS_BIOMETRICS2_ENROLLMENT, "false");
DEFAULT_FLAGS.put(SETTINGS_ACCESSIBILITY_HEARING_AID_PAGE, "true");
DEFAULT_FLAGS.put(SETTINGS_PREFER_ACCESSIBILITY_MENU_IN_SYSTEM, "false");
- DEFAULT_FLAGS.put(SETTINGS_AUDIO_ROUTING, "true");
+ DEFAULT_FLAGS.put(SETTINGS_AUDIO_ROUTING, "false");
DEFAULT_FLAGS.put(SETTINGS_FLASH_NOTIFICATIONS, "true");
DEFAULT_FLAGS.put(SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, "true");
DEFAULT_FLAGS.put(SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API, "true");
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 5b974cdb2bca..b55d25aa7013 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -177,7 +177,8 @@ public class InsetsState implements Parcelable {
if ((legacyWindowFlags & FLAG_FULLSCREEN) != 0) {
compatInsetsTypes &= ~statusBars();
}
- if (clearsCompatInsets(windowType, legacyWindowFlags, windowingMode)) {
+ if (clearsCompatInsets(windowType, legacyWindowFlags, windowingMode)
+ && !alwaysConsumeSystemBars) {
compatInsetsTypes = 0;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 1bbb7b4bd671..a28be4be24ad 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -5459,7 +5459,7 @@ public final class ViewRootImpl implements ViewParent,
}
private void updateRenderHdrSdrRatio() {
- mRenderHdrSdrRatio = mDisplay.getHdrSdrRatio();
+ mRenderHdrSdrRatio = Math.min(mDesiredHdrSdrRatio, mDisplay.getHdrSdrRatio());
mUpdateHdrSdrRatioInfo = true;
}
@@ -5487,22 +5487,14 @@ public final class ViewRootImpl implements ViewParent,
mHdrSdrRatioChangedListener = null;
} else {
mHdrSdrRatioChangedListener = display -> {
- setTargetHdrSdrRatio(display.getHdrSdrRatio());
+ updateRenderHdrSdrRatio();
+ invalidate();
};
mDisplay.registerHdrSdrRatioChangedListener(mExecutor, mHdrSdrRatioChangedListener);
}
}
}
- /** happylint */
- public void setTargetHdrSdrRatio(float ratio) {
- if (mRenderHdrSdrRatio != ratio) {
- mRenderHdrSdrRatio = ratio;
- mUpdateHdrSdrRatioInfo = true;
- invalidate();
- }
- }
-
@Override
public void requestChildFocus(View child, View focused) {
if (DEBUG_INPUT_RESIZE) {
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index ea750765799f..739c1bfccd3b 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -2065,7 +2065,7 @@ public final class AutofillManager {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (SyncResultReceiver.TimeoutException e) {
- throw new RuntimeException("Fail to get enabled autofill services status.");
+ throw new RuntimeException("Fail to get enabled autofill services status. " + e);
}
}
@@ -2084,7 +2084,7 @@ public final class AutofillManager {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (SyncResultReceiver.TimeoutException e) {
- throw new RuntimeException("Fail to get autofill services component name.");
+ throw new RuntimeException("Fail to get autofill services component name. " + e);
}
}
@@ -2111,7 +2111,7 @@ public final class AutofillManager {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (SyncResultReceiver.TimeoutException e) {
- throw new RuntimeException("Fail to get user data id for field classification.");
+ throw new RuntimeException("Fail to get user data id for field classification. " + e);
}
}
@@ -2134,7 +2134,7 @@ public final class AutofillManager {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (SyncResultReceiver.TimeoutException e) {
- throw new RuntimeException("Fail to get user data for field classification.");
+ throw new RuntimeException("Fail to get user data for field classification. " + e);
}
}
@@ -2174,7 +2174,7 @@ public final class AutofillManager {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (SyncResultReceiver.TimeoutException e) {
- throw new RuntimeException("Fail to get field classification enabled status.");
+ throw new RuntimeException("Fail to get field classification enabled status. " + e);
}
}
@@ -2198,7 +2198,7 @@ public final class AutofillManager {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (SyncResultReceiver.TimeoutException e) {
- throw new RuntimeException("Fail to get default field classification algorithm.");
+ throw new RuntimeException("Fail to get default field classification algorithm. " + e);
}
}
@@ -2220,7 +2220,8 @@ public final class AutofillManager {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (SyncResultReceiver.TimeoutException e) {
- throw new RuntimeException("Fail to get available field classification algorithms.");
+ throw new
+ RuntimeException("Fail to get available field classification algorithms. " + e);
}
}
@@ -2244,7 +2245,7 @@ public final class AutofillManager {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (SyncResultReceiver.TimeoutException e) {
- throw new RuntimeException("Fail to get autofill supported status.");
+ throw new RuntimeException("Fail to get autofill supported status. " + e);
}
}
diff --git a/core/java/android/webkit/SslErrorHandler.java b/core/java/android/webkit/SslErrorHandler.java
index 1d5c6f1f12b1..6f229f6e0054 100644
--- a/core/java/android/webkit/SslErrorHandler.java
+++ b/core/java/android/webkit/SslErrorHandler.java
@@ -20,11 +20,15 @@ import android.annotation.SystemApi;
import android.os.Handler;
/**
- * Represents a request for handling an SSL error. Instances of this class are
- * created by the WebView and passed to
- * {@link WebViewClient#onReceivedSslError}. The host application must call
- * either {@link #proceed} or {@link #cancel} to set the WebView's response
- * to the request.
+ * Represents a request for handling an SSL error.
+ *
+ * <p>A {@link WebView} creates an instance of this class. The instance is
+ * passed to {@link WebViewClient#onReceivedSslError(WebView, SslErrorHandler,
+ * SslError)}.
+ *
+ * <p>The host application must call {@link #cancel()} or, contrary to secure
+ * web communication standards, {@link #proceed()} to provide the web view's
+ * response to the request.
*/
public class SslErrorHandler extends Handler {
@@ -35,17 +39,29 @@ public class SslErrorHandler extends Handler {
public SslErrorHandler() {}
/**
- * Proceed with the SSL certificate.
- * <p>
- * It is not recommended to proceed past SSL errors and this method should
- * generally not be used; see {@link WebViewClient#onReceivedSslError} for
- * more information.
+ * Instructs the {@code WebView} that encountered the SSL certificate error
+ * to ignore the error and continue communicating with the server.
+ *
+ * <p class="warning"><b>Warning:</b> When an SSL error occurs, the host
+ * application should always call {@link #cancel()} rather than
+ * {@code proceed()} because an invalid SSL certificate means the connection
+ * is not secure.
+ *
+ * @see WebViewClient#onReceivedSslError(WebView, SslErrorHandler,
+ * SslError)
*/
public void proceed() {}
/**
- * Cancel this request and all pending requests for the WebView that had
- * the error.
+ * Instructs the {@code WebView} that encountered the SSL certificate error
+ * to terminate communication with the server. Cancels the current server
+ * request and all pending requests for the {@code WebView}.
+ *
+ * <p>The host application must call this method to prevent a resource from
+ * loading when an SSL certificate is invalid.
+ *
+ * @see WebViewClient#onReceivedSslError(WebView, SslErrorHandler,
+ * SslError)
*/
public void cancel() {}
}
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 55f09f110f88..2dfeae3567e5 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -382,30 +382,34 @@ public class WebViewClient {
}
/**
- * Notify the host application that an SSL error occurred while loading a
- * resource. The host application must call either {@link SslErrorHandler#cancel} or
- * {@link SslErrorHandler#proceed}. Note that the decision may be retained for use in
- * response to future SSL errors. The default behavior is to cancel the
- * load.
- * <p>
- * This API is only called for recoverable SSL certificate errors. In the case of
- * non-recoverable errors (such as when the server fails the client), WebView will call {@link
- * #onReceivedError(WebView, WebResourceRequest, WebResourceError)} with {@link
- * #ERROR_FAILED_SSL_HANDSHAKE}.
- * <p>
- * Applications are advised not to prompt the user about SSL errors, as
- * the user is unlikely to be able to make an informed security decision
- * and WebView does not provide any UI for showing the details of the
+ * Notifies the host application that an SSL error occurred while loading a
+ * resource. The host application must call either
+ * {@link SslErrorHandler#cancel()} or {@link SslErrorHandler#proceed()}.
+ *
+ * <p class="warning"><b>Warning:</b> Application overrides of this method
+ * can be used to display custom error pages or to silently log issues, but
+ * the host application should always call {@code SslErrorHandler#cancel()}
+ * and never proceed past errors.
+ *
+ * <p class="note"><b>Note:</b> Do not prompt the user about SSL errors.
+ * Users are unlikely to be able to make an informed security decision, and
+ * {@code WebView} does not provide a UI for showing the details of the
* error in a meaningful way.
- * <p>
- * Application overrides of this method may display custom error pages or
- * silently log issues, but it is strongly recommended to always call
- * {@link SslErrorHandler#cancel} and never allow proceeding past errors.
*
- * @param view The WebView that is initiating the callback.
- * @param handler An {@link SslErrorHandler} that will handle the user's
- * response.
- * @param error The SSL error object.
+ * <p>The decision to call {@code proceed()} or {@code cancel()} may be
+ * retained to facilitate responses to future SSL errors. The default
+ * behavior is to cancel the resource loading process.
+ *
+ * <p>This API is called only for recoverable SSL certificate errors. For
+ * non-recoverable errors (such as when the server fails the client), the
+ * {@code WebView} calls {@link #onReceivedError(WebView,
+ * WebResourceRequest, WebResourceError) onReceivedError(WebView,
+ * WebResourceRequest, WebResourceError)} with the
+ * {@link #ERROR_FAILED_SSL_HANDSHAKE} argument.
+ *
+ * @param view {@code WebView} that initiated the callback.
+ * @param handler {@link SslErrorHandler} that handles the user's response.
+ * @param error SSL error object.
*/
public void onReceivedSslError(WebView view, SslErrorHandler handler,
SslError error) {
diff --git a/core/java/android/window/ScreenCapture.java b/core/java/android/window/ScreenCapture.java
index fa7f577dadb8..0cc9c644f8ea 100644
--- a/core/java/android/window/ScreenCapture.java
+++ b/core/java/android/window/ScreenCapture.java
@@ -27,7 +27,6 @@ import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
-import android.util.Pair;
import android.view.SurfaceControl;
import libcore.util.NativeAllocationRegistry;
@@ -73,14 +72,14 @@ public class ScreenCapture {
*/
public static ScreenshotHardwareBuffer captureDisplay(
DisplayCaptureArgs captureArgs) {
- Pair<ScreenCaptureListener, ScreenshotSync> syncScreenCapture = createSyncCaptureListener();
- int status = captureDisplay(captureArgs, syncScreenCapture.first);
+ SynchronousScreenCaptureListener syncScreenCapture = createSyncCaptureListener();
+ int status = captureDisplay(captureArgs, syncScreenCapture);
if (status != 0) {
return null;
}
try {
- return syncScreenCapture.second.get();
+ return syncScreenCapture.getBuffer();
} catch (Exception e) {
return null;
}
@@ -133,14 +132,14 @@ public class ScreenCapture {
* @hide
*/
public static ScreenshotHardwareBuffer captureLayers(LayerCaptureArgs captureArgs) {
- Pair<ScreenCaptureListener, ScreenshotSync> syncScreenCapture = createSyncCaptureListener();
- int status = captureLayers(captureArgs, syncScreenCapture.first);
+ SynchronousScreenCaptureListener syncScreenCapture = createSyncCaptureListener();
+ int status = captureLayers(captureArgs, syncScreenCapture);
if (status != 0) {
return null;
}
try {
- return syncScreenCapture.second.get();
+ return syncScreenCapture.getBuffer();
} catch (Exception e) {
return null;
}
@@ -743,14 +742,35 @@ public class ScreenCapture {
* A helper method to handle the async screencapture callbacks synchronously. This should only
* be used if the screencapture caller doesn't care that it blocks waiting for a screenshot.
*
- * @return a Pair that holds the {@link ScreenCaptureListener} that should be used for capture
- * calls into SurfaceFlinger and a {@link ScreenshotSync} object to retrieve the results.
+ * @return a {@link SynchronousScreenCaptureListener} that should be used for capture
+ * calls into SurfaceFlinger.
*/
- public static Pair<ScreenCaptureListener, ScreenshotSync> createSyncCaptureListener() {
- final ScreenshotSync screenshotSync = new ScreenshotSync();
- final ScreenCaptureListener screenCaptureListener = new ScreenCaptureListener(
- screenshotSync::setScreenshotHardwareBuffer);
- return new Pair<>(screenCaptureListener, screenshotSync);
+ public static SynchronousScreenCaptureListener createSyncCaptureListener() {
+ ScreenshotHardwareBuffer[] bufferRef = new ScreenshotHardwareBuffer[1];
+ CountDownLatch latch = new CountDownLatch(1);
+ Consumer<ScreenshotHardwareBuffer> consumer = buffer -> {
+ bufferRef[0] = buffer;
+ latch.countDown();
+ };
+
+ return new SynchronousScreenCaptureListener(consumer) {
+ // In order to avoid requiring two GC cycles to clean up the consumer and the buffer
+ // it references, the underlying JNI listener holds a weak reference to the consumer.
+ // This property exists to ensure the consumer stays alive during the listener's
+ // lifetime.
+ private Consumer<ScreenshotHardwareBuffer> mConsumer = consumer;
+
+ @Override
+ public ScreenshotHardwareBuffer getBuffer() {
+ try {
+ latch.await(SCREENSHOT_WAIT_TIME_S, TimeUnit.SECONDS);
+ return bufferRef[0];
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to wait for screen capture result", e);
+ return null;
+ }
+ }
+ };
}
/**
@@ -758,28 +778,15 @@ public class ScreenCapture {
* {@link #captureLayers(LayerCaptureArgs, ScreenCaptureListener)} or
* {@link #captureDisplay(DisplayCaptureArgs, ScreenCaptureListener)}
*/
- public static class ScreenshotSync {
- private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
- private ScreenshotHardwareBuffer mScreenshotHardwareBuffer;
-
- private void setScreenshotHardwareBuffer(
- ScreenshotHardwareBuffer screenshotHardwareBuffer) {
- mScreenshotHardwareBuffer = screenshotHardwareBuffer;
- mCountDownLatch.countDown();
+ public abstract static class SynchronousScreenCaptureListener extends ScreenCaptureListener {
+ SynchronousScreenCaptureListener(Consumer<ScreenshotHardwareBuffer> consumer) {
+ super(consumer);
}
/**
* Get the {@link ScreenshotHardwareBuffer} synchronously. This can be null if the
* screenshot failed or if there was no callback in {@link #SCREENSHOT_WAIT_TIME_S} seconds.
*/
- public ScreenshotHardwareBuffer get() {
- try {
- mCountDownLatch.await(SCREENSHOT_WAIT_TIME_S, TimeUnit.SECONDS);
- return mScreenshotHardwareBuffer;
- } catch (Exception e) {
- Log.e(TAG, "Failed to wait for screen capture result", e);
- return null;
- }
- }
+ public abstract ScreenshotHardwareBuffer getBuffer();
}
}
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index bf265689c0e0..4e7bfe50cd30 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -16,42 +16,50 @@
package com.android.internal.app;
-import static android.graphics.PixelFormat.TRANSLUCENT;
+import static android.os.VibrationEffect.Composition.PRIMITIVE_SPIN;
import android.animation.ObjectAnimator;
+import android.animation.TimeAnimator;
+import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
-import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
+import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.CombinedVibration;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.os.VibrationEffect;
+import android.os.VibratorManager;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
+import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.OvershootInterpolator;
-import android.widget.AnalogClock;
+import android.view.WindowInsets;
import android.widget.FrameLayout;
import android.widget.ImageView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.internal.R;
import org.json.JSONObject;
-import java.time.Clock;
-import java.time.Instant;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
+import java.util.Random;
/**
* @hide
@@ -59,30 +67,160 @@ import java.time.ZonedDateTime;
public class PlatLogoActivity extends Activity {
private static final String TAG = "PlatLogoActivity";
- private static final String S_EGG_UNLOCK_SETTING = "egg_mode_s";
+ private static final long LAUNCH_TIME = 5000L;
+
+ private static final String U_EGG_UNLOCK_SETTING = "egg_mode_u";
+
+ private static final float MIN_WARP = 1f;
+ private static final float MAX_WARP = 10f; // after all these years
+ private static final boolean FINISH_AFTER_NEXT_STAGE_LAUNCH = false;
- private SettableAnalogClock mClock;
private ImageView mLogo;
- private BubblesDrawable mBg;
+ private Starfield mStarfield;
+
+ private FrameLayout mLayout;
+
+ private TimeAnimator mAnim;
+ private ObjectAnimator mWarpAnim;
+ private Random mRandom;
+ private float mDp;
+
+ private RumblePack mRumble;
+
+ private boolean mAnimationsEnabled = true;
+
+ private final View.OnTouchListener mTouchListener = new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ measureTouchPressure(event);
+ startWarp();
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ stopWarp();
+ break;
+ }
+ return true;
+ }
+
+ };
+
+ private final Runnable mLaunchNextStage = () -> {
+ stopWarp();
+ launchNextStage(false);
+ };
+
+ private final TimeAnimator.TimeListener mTimeListener = new TimeAnimator.TimeListener() {
+ @Override
+ public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
+ mStarfield.update(deltaTime);
+ final float warpFrac = (mStarfield.getWarp() - MIN_WARP) / (MAX_WARP - MIN_WARP);
+ if (mAnimationsEnabled) {
+ mLogo.setTranslationX(mRandom.nextFloat() * warpFrac * 5 * mDp);
+ mLogo.setTranslationY(mRandom.nextFloat() * warpFrac * 5 * mDp);
+ }
+ if (warpFrac > 0f) {
+ mRumble.rumble(warpFrac);
+ }
+ mLayout.postInvalidate();
+ }
+ };
+
+ private class RumblePack implements Handler.Callback {
+ private static final int MSG = 6464;
+ private static final int INTERVAL = 50;
+
+ private final VibratorManager mVibeMan;
+ private final HandlerThread mVibeThread;
+ private final Handler mVibeHandler;
+ private boolean mSpinPrimitiveSupported;
+
+ private long mLastVibe = 0;
+
+ @SuppressLint("MissingPermission")
+ @Override
+ public boolean handleMessage(Message msg) {
+ final float warpFrac = msg.arg1 / 100f;
+ if (mSpinPrimitiveSupported) {
+ if (msg.getWhen() > mLastVibe + INTERVAL) {
+ mLastVibe = msg.getWhen();
+ mVibeMan.vibrate(CombinedVibration.createParallel(
+ VibrationEffect.startComposition()
+ .addPrimitive(PRIMITIVE_SPIN, (float) Math.pow(warpFrac, 3.0))
+ .compose()
+ ));
+ }
+ } else {
+ if (mRandom.nextFloat() < warpFrac) {
+ mLogo.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
+ }
+ }
+ return false;
+ }
+ RumblePack() {
+ mVibeMan = getSystemService(VibratorManager.class);
+ mSpinPrimitiveSupported = mVibeMan.getDefaultVibrator()
+ .areAllPrimitivesSupported(PRIMITIVE_SPIN);
+
+ mVibeThread = new HandlerThread("VibratorThread");
+ mVibeThread.start();
+ mVibeHandler = Handler.createAsync(mVibeThread.getLooper(), this);
+ }
+
+ public void destroy() {
+ mVibeThread.quit();
+ }
+
+ private void rumble(float warpFrac) {
+ if (!mVibeThread.isAlive()) return;
+
+ final Message msg = Message.obtain();
+ msg.what = MSG;
+ msg.arg1 = (int) (warpFrac * 100);
+ mVibeHandler.removeMessages(MSG);
+ mVibeHandler.sendMessage(msg);
+ }
+
+ }
@Override
- protected void onPause() {
- super.onPause();
+ protected void onDestroy() {
+ mRumble.destroy();
+
+ super.onDestroy();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ getWindow().setDecorFitsSystemWindows(false);
getWindow().setNavigationBarColor(0);
getWindow().setStatusBarColor(0);
+ getWindow().getDecorView().getWindowInsetsController().hide(WindowInsets.Type.systemBars());
final ActionBar ab = getActionBar();
if (ab != null) ab.hide();
- final FrameLayout layout = new FrameLayout(this);
+ try {
+ mAnimationsEnabled = Settings.Global.getFloat(getContentResolver(),
+ Settings.Global.ANIMATOR_DURATION_SCALE) > 0f;
+ } catch (Settings.SettingNotFoundException e) {
+ mAnimationsEnabled = true;
+ }
- mClock = new SettableAnalogClock(this);
+ mRumble = new RumblePack();
+
+ mLayout = new FrameLayout(this);
+ mRandom = new Random();
+ mDp = getResources().getDisplayMetrics().density;
+ mStarfield = new Starfield(mRandom, mDp * 2f);
+ mStarfield.setVelocity(
+ 200f * (mRandom.nextFloat() - 0.5f),
+ 200f * (mRandom.nextFloat() - 0.5f));
+ mLayout.setBackground(mStarfield);
final DisplayMetrics dm = getResources().getDisplayMetrics();
final float dp = dm.density;
@@ -90,22 +228,79 @@ public class PlatLogoActivity extends Activity {
final int widgetSize = (int) (minSide * 0.75);
final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(widgetSize, widgetSize);
lp.gravity = Gravity.CENTER;
- layout.addView(mClock, lp);
mLogo = new ImageView(this);
- mLogo.setVisibility(View.GONE);
mLogo.setImageResource(R.drawable.platlogo);
- layout.addView(mLogo, lp);
+ mLogo.setOnTouchListener(mTouchListener);
+ mLogo.requestFocus();
+ mLayout.addView(mLogo, lp);
+
+ Log.v(TAG, "Hello");
+
+ setContentView(mLayout);
+ }
+
+ private void startAnimating() {
+ mAnim = new TimeAnimator();
+ mAnim.setTimeListener(mTimeListener);
+ mAnim.start();
+ }
+
+ private void stopAnimating() {
+ mAnim.cancel();
+ mAnim = null;
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_SPACE) {
+ if (event.getRepeatCount() == 0) {
+ startWarp();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_SPACE) {
+ stopWarp();
+ return true;
+ }
+ return false;
+ }
- mBg = new BubblesDrawable();
- mBg.setLevel(0);
- mBg.avoid = widgetSize / 2;
- mBg.padding = 0.5f * dp;
- mBg.minR = 1 * dp;
- layout.setBackground(mBg);
- layout.setOnLongClickListener(mBg);
+ private void startWarp() {
+ stopWarp();
+ mWarpAnim = ObjectAnimator.ofFloat(mStarfield, "warp", MIN_WARP, MAX_WARP)
+ .setDuration(LAUNCH_TIME);
+ mWarpAnim.start();
+
+ mLogo.postDelayed(mLaunchNextStage, LAUNCH_TIME + 1000L);
+ }
- setContentView(layout);
+ private void stopWarp() {
+ if (mWarpAnim != null) {
+ mWarpAnim.cancel();
+ mWarpAnim.removeAllListeners();
+ mWarpAnim = null;
+ }
+ mStarfield.setWarp(1f);
+ mLogo.removeCallbacks(mLaunchNextStage);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ startAnimating();
+ }
+
+ @Override
+ public void onPause() {
+ stopWarp();
+ stopAnimating();
+ super.onPause();
}
private boolean shouldWriteSettings() {
@@ -113,38 +308,14 @@ public class PlatLogoActivity extends Activity {
}
private void launchNextStage(boolean locked) {
- mClock.animate()
- .alpha(0f).scaleX(0.5f).scaleY(0.5f)
- .withEndAction(() -> mClock.setVisibility(View.GONE))
- .start();
-
- mLogo.setAlpha(0f);
- mLogo.setScaleX(0.5f);
- mLogo.setScaleY(0.5f);
- mLogo.setVisibility(View.VISIBLE);
- mLogo.animate()
- .alpha(1f)
- .scaleX(1f)
- .scaleY(1f)
- .setInterpolator(new OvershootInterpolator())
- .start();
-
- mLogo.postDelayed(() -> {
- final ObjectAnimator anim = ObjectAnimator.ofInt(mBg, "level", 0, 10000);
- anim.setInterpolator(new DecelerateInterpolator(1f));
- anim.start();
- },
- 500
- );
-
final ContentResolver cr = getContentResolver();
try {
if (shouldWriteSettings()) {
- Log.v(TAG, "Saving egg unlock=" + locked);
+ Log.v(TAG, "Saving egg locked=" + locked);
syncTouchPressure();
Settings.System.putLong(cr,
- S_EGG_UNLOCK_SETTING,
+ U_EGG_UNLOCK_SETTING,
locked ? 0 : System.currentTimeMillis());
}
} catch (RuntimeException e) {
@@ -152,14 +323,18 @@ public class PlatLogoActivity extends Activity {
}
try {
- startActivity(new Intent(Intent.ACTION_MAIN)
+ final Intent eggActivity = new Intent(Intent.ACTION_MAIN)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK)
- .addCategory("com.android.internal.category.PLATLOGO"));
+ .addCategory("com.android.internal.category.PLATLOGO");
+ Log.v(TAG, "launching: " + eggActivity);
+ startActivity(eggActivity);
} catch (ActivityNotFoundException ex) {
Log.e("com.android.internal.app.PlatLogoActivity", "No more eggs.");
}
- //finish(); // no longer finish upon unlock; it's fun to frob the dial
+ if (FINISH_AFTER_NEXT_STAGE_LAUNCH) {
+ finish(); // we're done here.
+ }
}
static final String TOUCH_STATS = "touch.stats";
@@ -217,266 +392,111 @@ public class PlatLogoActivity extends Activity {
super.onStop();
}
- /**
- * Subclass of AnalogClock that allows the user to flip up the glass and adjust the hands.
- */
- public class SettableAnalogClock extends AnalogClock {
- private int mOverrideHour = -1;
- private int mOverrideMinute = -1;
- private boolean mOverride = false;
+ private static class Starfield extends Drawable {
+ private static final int NUM_STARS = 34; // Build.VERSION_CODES.UPSIDE_DOWN_CAKE
+
+ private static final int NUM_PLANES = 2;
+ private final float[] mStars = new float[NUM_STARS * 4];
+ private float mVx, mVy;
+ private long mDt = 0;
+ private final Paint mStarPaint;
- public SettableAnalogClock(Context context) {
- super(context);
+ private final Random mRng;
+ private final float mSize;
+
+ private final Rect mSpace = new Rect();
+ private float mWarp = 1f;
+
+ private float mBuffer;
+
+ public void setWarp(float warp) {
+ mWarp = warp;
}
- @Override
- protected Instant now() {
- final Instant realNow = super.now();
- final ZoneId tz = Clock.systemDefaultZone().getZone();
- final ZonedDateTime zdTime = realNow.atZone(tz);
- if (mOverride) {
- if (mOverrideHour < 0) {
- mOverrideHour = zdTime.getHour();
- }
- return Clock.fixed(zdTime
- .withHour(mOverrideHour)
- .withMinute(mOverrideMinute)
- .withSecond(0)
- .toInstant(), tz).instant();
- } else {
- return realNow;
- }
+ public float getWarp() {
+ return mWarp;
}
- double toPositiveDegrees(double rad) {
- return (Math.toDegrees(rad) + 360 - 90) % 360;
+ Starfield(Random rng, float size) {
+ mRng = rng;
+ mSize = size;
+ mStarPaint = new Paint();
+ mStarPaint.setStyle(Paint.Style.STROKE);
+ mStarPaint.setColor(Color.WHITE);
}
@Override
- public boolean onTouchEvent(MotionEvent ev) {
- switch (ev.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- mOverride = true;
- // pass through
- case MotionEvent.ACTION_MOVE:
- measureTouchPressure(ev);
-
- float x = ev.getX();
- float y = ev.getY();
- float cx = getWidth() / 2f;
- float cy = getHeight() / 2f;
- float angle = (float) toPositiveDegrees(Math.atan2(x - cx, y - cy));
-
- int minutes = (75 - (int) (angle / 6)) % 60;
- int minuteDelta = minutes - mOverrideMinute;
- if (minuteDelta != 0) {
- if (Math.abs(minuteDelta) > 45 && mOverrideHour >= 0) {
- int hourDelta = (minuteDelta < 0) ? 1 : -1;
- mOverrideHour = (mOverrideHour + 24 + hourDelta) % 24;
- }
- mOverrideMinute = minutes;
- if (mOverrideMinute == 0) {
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- if (getScaleX() == 1f) {
- setScaleX(1.05f);
- setScaleY(1.05f);
- animate().scaleX(1f).scaleY(1f).setDuration(150).start();
- }
- } else {
- performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
- }
-
- onTimeChanged();
- postInvalidate();
- }
-
- return true;
- case MotionEvent.ACTION_UP:
- if (mOverrideMinute == 0 && (mOverrideHour % 12) == 1) {
- Log.v(TAG, "13:00");
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- launchNextStage(false);
- }
- return true;
+ public void onBoundsChange(Rect bounds) {
+ mSpace.set(bounds);
+ mBuffer = mSize * NUM_PLANES * 2 * MAX_WARP;
+ mSpace.inset(-(int) mBuffer, -(int) mBuffer);
+ final float w = mSpace.width();
+ final float h = mSpace.height();
+ for (int i = 0; i < NUM_STARS; i++) {
+ mStars[4 * i] = mRng.nextFloat() * w;
+ mStars[4 * i + 1] = mRng.nextFloat() * h;
+ mStars[4 * i + 2] = mStars[4 * i];
+ mStars[4 * i + 3] = mStars[4 * i + 1];
}
- return false;
}
- }
- private static final String[][] EMOJI_SETS = {
- {"🍇", "🍈", "🍉", "🍊", "🍋", "🍌", "🍍", "🥭", "🍎", "🍏", "🍐", "🍑",
- "🍒", "🍓", "🫐", "🥝"},
- {"😺", "😸", "😹", "😻", "😼", "😽", "🙀", "😿", "😾"},
- {"😀", "😃", "😄", "😁", "😆", "😅", "🤣", "😂", "🙂", "🙃", "🫠", "😉", "😊",
- "😇", "🥰", "😍", "🤩", "😘", "😗", "☺️", "😚", "😙", "🥲", "😋", "😛", "😜",
- "🤪", "😝", "🤑", "🤗", "🤭", "🫢", "🫣", "🤫", "🤔", "🫡", "🤐", "🤨", "😐",
- "😑", "😶", "🫥", "😏", "😒", "🙄", "😬", "🤥", "😌", "😔", "😪", "🤤", "😴",
- "😷"},
- { "🤩", "😍", "🥰", "😘", "🥳", "🥲", "🥹" },
- { "🫠" },
- {"💘", "💝", "💖", "💗", "💓", "💞", "💕", "❣", "💔", "❤", "🧡", "💛",
- "💚", "💙", "💜", "🤎", "🖤", "🤍"},
- // {"👁", "️🫦", "👁️"}, // this one is too much
- {"👽", "🛸", "✨", "🌟", "💫", "🚀", "🪐", "🌙", "⭐", "🌍"},
- {"🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘"},
- {"🐙", "🪸", "🦑", "🦀", "🦐", "🐡", "🦞", "🐠", "🐟", "🐳", "🐋", "🐬", "🫧", "🌊",
- "🦈"},
- {"🙈", "🙉", "🙊", "🐵", "🐒"},
- {"♈", "♉", "♊", "♋", "♌", "♍", "♎", "♏", "♐", "♑", "♒", "♓"},
- {"🕛", "🕧", "🕐", "🕜", "🕑", "🕝", "🕒", "🕞", "🕓", "🕟", "🕔", "🕠", "🕕", "🕡",
- "🕖", "🕢", "🕗", "🕣", "🕘", "🕤", "🕙", "🕥", "🕚", "🕦"},
- {"🌺", "🌸", "💮", "🏵️", "🌼", "🌿"},
- {"🐢", "✨", "🌟", "👑"}
- };
-
- static class Bubble {
- public float x, y, r;
- public int color;
- public String text = null;
- }
-
- class BubblesDrawable extends Drawable implements View.OnLongClickListener {
- private static final int MAX_BUBBS = 2000;
-
- private final int[] mColorIds = {
- android.R.color.system_accent3_400,
- android.R.color.system_accent3_500,
- android.R.color.system_accent3_600,
-
- android.R.color.system_accent2_400,
- android.R.color.system_accent2_500,
- android.R.color.system_accent2_600,
- };
-
- private int[] mColors = new int[mColorIds.length];
-
- private int mEmojiSet = -1;
-
- private final Bubble[] mBubbs = new Bubble[MAX_BUBBS];
- private int mNumBubbs;
-
- private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-
- public float avoid = 0f;
- public float padding = 0f;
- public float minR = 0f;
-
- BubblesDrawable() {
- for (int i = 0; i < mColorIds.length; i++) {
- mColors[i] = getColor(mColorIds[i]);
- }
- for (int j = 0; j < mBubbs.length; j++) {
- mBubbs[j] = new Bubble();
- }
+ public void setVelocity(float x, float y) {
+ mVx = x;
+ mVy = y;
}
@Override
- public void draw(Canvas canvas) {
- if (getLevel() == 0) return;
- final float f = getLevel() / 10000f;
- mPaint.setStyle(Paint.Style.FILL);
- mPaint.setTextAlign(Paint.Align.CENTER);
- int drawn = 0;
- for (int j = 0; j < mNumBubbs; j++) {
- if (mBubbs[j].color == 0 || mBubbs[j].r == 0) continue;
- if (mBubbs[j].text != null) {
- mPaint.setTextSize(mBubbs[j].r * 1.75f);
- canvas.drawText(mBubbs[j].text, mBubbs[j].x,
- mBubbs[j].y + mBubbs[j].r * f * 0.6f, mPaint);
- } else {
- mPaint.setColor(mBubbs[j].color);
- canvas.drawCircle(mBubbs[j].x, mBubbs[j].y, mBubbs[j].r * f, mPaint);
+ public void draw(@NonNull Canvas canvas) {
+ final float dtSec = mDt / 1000f;
+ final float dx = (mVx * dtSec * mWarp);
+ final float dy = (mVy * dtSec * mWarp);
+
+ final boolean inWarp = mWarp > 1f;
+
+ canvas.drawColor(Color.BLACK); // 0xFF16161D);
+
+ if (mDt > 0 && mDt < 1000) {
+ canvas.translate(
+ -(mBuffer) + mRng.nextFloat() * (mWarp - 1f),
+ -(mBuffer) + mRng.nextFloat() * (mWarp - 1f)
+ );
+ final float w = mSpace.width();
+ final float h = mSpace.height();
+ for (int i = 0; i < NUM_STARS; i++) {
+ final int plane = (int) ((((float) i) / NUM_STARS) * NUM_PLANES) + 1;
+ mStars[4 * i + 2] = (mStars[4 * i + 2] + dx * plane + w) % w;
+ mStars[4 * i + 3] = (mStars[4 * i + 3] + dy * plane + h) % h;
+ mStars[4 * i + 0] = inWarp ? mStars[4 * i + 2] - dx * mWarp * 2 * plane : -100;
+ mStars[4 * i + 1] = inWarp ? mStars[4 * i + 3] - dy * mWarp * 2 * plane : -100;
}
- drawn++;
}
- }
-
- public void chooseEmojiSet() {
- mEmojiSet = (int) (Math.random() * EMOJI_SETS.length);
- final String[] emojiSet = EMOJI_SETS[mEmojiSet];
- for (int j = 0; j < mBubbs.length; j++) {
- mBubbs[j].text = emojiSet[(int) (Math.random() * emojiSet.length)];
+ final int slice = (mStars.length / NUM_PLANES / 4) * 4;
+ for (int p = 0; p < NUM_PLANES; p++) {
+ mStarPaint.setStrokeWidth(mSize * (p + 1));
+ if (inWarp) {
+ canvas.drawLines(mStars, p * slice, slice, mStarPaint);
+ }
+ canvas.drawPoints(mStars, p * slice, slice, mStarPaint);
}
- invalidateSelf();
}
@Override
- protected boolean onLevelChange(int level) {
- invalidateSelf();
- return true;
- }
+ public void setAlpha(int alpha) {
- @Override
- protected void onBoundsChange(Rect bounds) {
- super.onBoundsChange(bounds);
- randomize();
- }
-
- private void randomize() {
- final float w = getBounds().width();
- final float h = getBounds().height();
- final float maxR = Math.min(w, h) / 3f;
- mNumBubbs = 0;
- if (avoid > 0f) {
- mBubbs[mNumBubbs].x = w / 2f;
- mBubbs[mNumBubbs].y = h / 2f;
- mBubbs[mNumBubbs].r = avoid;
- mBubbs[mNumBubbs].color = 0;
- mNumBubbs++;
- }
- for (int j = 0; j < MAX_BUBBS; j++) {
- // a simple but time-tested bubble-packing algorithm:
- // 1. pick a spot
- // 2. shrink the bubble until it is no longer overlapping any other bubble
- // 3. if the bubble hasn't popped, keep it
- int tries = 5;
- while (tries-- > 0) {
- float x = (float) Math.random() * w;
- float y = (float) Math.random() * h;
- float r = Math.min(Math.min(x, w - x), Math.min(y, h - y));
-
- // shrink radius to fit other bubbs
- for (int i = 0; i < mNumBubbs; i++) {
- r = (float) Math.min(r,
- Math.hypot(x - mBubbs[i].x, y - mBubbs[i].y) - mBubbs[i].r
- - padding);
- if (r < minR) break;
- }
-
- if (r >= minR) {
- // we have found a spot for this bubble to live, let's save it and move on
- r = Math.min(maxR, r);
-
- mBubbs[mNumBubbs].x = x;
- mBubbs[mNumBubbs].y = y;
- mBubbs[mNumBubbs].r = r;
- mBubbs[mNumBubbs].color = mColors[(int) (Math.random() * mColors.length)];
- mNumBubbs++;
- break;
- }
- }
- }
- Log.v(TAG, String.format("successfully placed %d bubbles (%d%%)",
- mNumBubbs, (int) (100f * mNumBubbs / MAX_BUBBS)));
}
@Override
- public void setAlpha(int alpha) { }
+ public void setColorFilter(@Nullable ColorFilter colorFilter) {
- @Override
- public void setColorFilter(ColorFilter colorFilter) { }
+ }
@Override
public int getOpacity() {
- return TRANSLUCENT;
+ return PixelFormat.OPAQUE;
}
- @Override
- public boolean onLongClick(View v) {
- if (getLevel() == 0) return false;
- chooseEmojiSet();
- return true;
+ public void update(long dt) {
+ mDt = dt;
}
}
-
-}
+} \ No newline at end of file
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 8135f9cd2f46..dd52de4f84c7 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -118,6 +118,9 @@ public final class SystemUiDeviceConfigFlags {
*/
public static final String NAS_DEFAULT_SERVICE = "nas_default_service";
+ /** (boolean) Whether notify() calls to NMS should acquire and hold WakeLocks. */
+ public static final String NOTIFY_WAKELOCK = "nms_notify_wakelock";
+
// Flags related to media notifications
/**
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 15f70f358d6e..af1fdd79169a 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -1111,8 +1111,13 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
: controller.getSystemBarsAppearance();
if (insets != null) {
- final boolean clearsCompatInsets = clearsCompatInsets(attrs.type, attrs.flags,
- getResources().getConfiguration().windowConfiguration.getWindowingMode());
+ mLastShouldAlwaysConsumeSystemBars = insets.shouldAlwaysConsumeSystemBars();
+
+ final boolean clearsCompatInsets =
+ clearsCompatInsets(attrs.type, attrs.flags,
+ getResources().getConfiguration().windowConfiguration
+ .getWindowingMode())
+ && !mLastShouldAlwaysConsumeSystemBars;
final Insets stableBarInsets = insets.getInsetsIgnoringVisibility(
WindowInsets.Type.systemBars());
final Insets systemInsets = clearsCompatInsets
@@ -1143,7 +1148,6 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
disallowAnimate |= (hasLeftStableInset != mLastHasLeftStableInset);
mLastHasLeftStableInset = hasLeftStableInset;
- mLastShouldAlwaysConsumeSystemBars = insets.shouldAlwaysConsumeSystemBars();
mLastSuppressScrimTypes = insets.getSuppressScrimTypes();
}
diff --git a/core/jni/android_window_ScreenCapture.cpp b/core/jni/android_window_ScreenCapture.cpp
index 986dbe9a204c..e729750b812e 100644
--- a/core/jni/android_window_ScreenCapture.cpp
+++ b/core/jni/android_window_ScreenCapture.cpp
@@ -81,22 +81,28 @@ class ScreenCaptureListenerWrapper : public gui::BnScreenCaptureListener {
public:
explicit ScreenCaptureListenerWrapper(JNIEnv* env, jobject jobject) {
env->GetJavaVM(&mVm);
- mConsumerObject = env->NewGlobalRef(jobject);
- LOG_ALWAYS_FATAL_IF(!mConsumerObject, "Failed to make global ref");
+ mConsumerWeak = env->NewWeakGlobalRef(jobject);
}
~ScreenCaptureListenerWrapper() {
- if (mConsumerObject) {
- getenv()->DeleteGlobalRef(mConsumerObject);
- mConsumerObject = nullptr;
+ if (mConsumerWeak) {
+ getenv()->DeleteWeakGlobalRef(mConsumerWeak);
+ mConsumerWeak = nullptr;
}
}
binder::Status onScreenCaptureCompleted(
const gui::ScreenCaptureResults& captureResults) override {
JNIEnv* env = getenv();
+
+ ScopedLocalRef<jobject> consumer{env, env->NewLocalRef(mConsumerWeak)};
+ if (consumer == nullptr) {
+ ALOGE("ScreenCaptureListenerWrapper consumer not alive.");
+ return binder::Status::ok();
+ }
+
if (!captureResults.fenceResult.ok() || captureResults.buffer == nullptr) {
- env->CallVoidMethod(mConsumerObject, gConsumerClassInfo.accept, nullptr);
+ env->CallVoidMethod(consumer.get(), gConsumerClassInfo.accept, nullptr);
checkAndClearException(env, "accept");
return binder::Status::ok();
}
@@ -111,7 +117,7 @@ public:
captureResults.capturedSecureLayers,
captureResults.capturedHdrLayers);
checkAndClearException(env, "builder");
- env->CallVoidMethod(mConsumerObject, gConsumerClassInfo.accept, screenshotHardwareBuffer);
+ env->CallVoidMethod(consumer.get(), gConsumerClassInfo.accept, screenshotHardwareBuffer);
checkAndClearException(env, "accept");
env->DeleteLocalRef(jhardwareBuffer);
env->DeleteLocalRef(screenshotHardwareBuffer);
@@ -119,7 +125,7 @@ public:
}
private:
- jobject mConsumerObject;
+ jweak mConsumerWeak;
JavaVM* mVm;
JNIEnv* getenv() {
diff --git a/core/res/res/drawable-nodpi/platlogo.xml b/core/res/res/drawable-nodpi/platlogo.xml
index da214868ca05..f3acab063bbf 100644
--- a/core/res/res/drawable-nodpi/platlogo.xml
+++ b/core/res/res/drawable-nodpi/platlogo.xml
@@ -13,33 +13,186 @@ Copyright (C) 2021 The Android Open Source Project
See the License for the specific language governing permissions and
limitations under the License.
-->
-<vector android:height="128dp"
- android:width="128dp"
- android:viewportHeight="24"
- android:viewportWidth="24"
- xmlns:android="http://schemas.android.com/apk/res/android">
- <path
- android:fillColor="@android:color/system_accent1_400"
- android:pathData="M11,0.3c0.6,-0.3 1.4,-0.3 2,0l0.6,0.4c0.7,0.4 1.4,0.6 2.2,0.6l0.7,-0.1c0.7,0 1.4,0.3 1.8,0.9l0.3,0.6c0.4,0.7 1,1.2 1.7,1.5L21,4.5c0.7,0.3 1.1,0.9 1.2,1.7v0.7C22.2,7.7 22.5,8.4 23,9l0.4,0.5c0.4,0.6 0.5,1.3 0.2,2l-0.3,0.6c-0.3,0.7 -0.4,1.5 -0.3,2.3l0.1,0.7c0.1,0.7 -0.2,1.4 -0.7,1.9L22,17.5c-0.6,0.5 -1.1,1.1 -1.3,1.9L20.5,20c-0.2,0.7 -0.8,1.2 -1.5,1.4l-0.7,0.1c-0.8,0.2 -1.4,0.5 -2,1.1l-0.5,0.5c-0.5,0.5 -1.3,0.7 -2,0.5l-0.6,-0.2c-0.8,-0.2 -1.5,-0.2 -2.3,0l-0.6,0.2c-0.7,0.2 -1.5,0 -2,-0.5l-0.5,-0.5c-0.5,-0.5 -1.2,-0.9 -2,-1.1L5,21.4c-0.7,-0.2 -1.3,-0.7 -1.5,-1.4l-0.2,-0.7C3.1,18.6 2.6,18 2,17.5l-0.6,-0.4c-0.6,-0.5 -0.8,-1.2 -0.7,-1.9l0.1,-0.7c0.1,-0.8 0,-1.6 -0.3,-2.3l-0.3,-0.6c-0.3,-0.7 -0.2,-1.4 0.2,-2L1,9c0.5,-0.6 0.7,-1.4 0.8,-2.2V6.2C1.9,5.5 2.3,4.8 3,4.5l0.6,-0.3c0.7,-0.3 1.3,-0.9 1.7,-1.5l0.3,-0.6c0.4,-0.6 1.1,-1 1.8,-0.9l0.7,0.1c0.8,0 1.6,-0.2 2.2,-0.6L11,0.3z"
- />
- <path
- android:pathData="M6.3,6.5l3,0l0,12.2"
- android:strokeWidth="2.22"
- android:strokeColor="@android:color/system_accent3_800"
- />
- <path
- android:pathData="M12.3,6.5h4l-2,4c2.2,0.3 3.6,2.4 3.3,4.5c-0.3,1.9 -1.9,3.3 -3.8,3.3c-0.5,0 -1,-0.1 -1.4,-0.3"
- android:strokeWidth="2.22"
- android:strokeColor="@android:color/system_accent3_800"
- />
- <path
- android:pathData="M6.3,6.5l3,0l0,12.2"
- android:strokeWidth="0.56"
- android:strokeColor="@android:color/system_neutral1_100"
- />
- <path
- android:pathData="M12.3,6.5h4l-2,4c2.2,0.3 3.6,2.4 3.3,4.5c-0.3,1.9 -1.9,3.3 -3.8,3.3c-0.5,0 -1,-0.1 -1.4,-0.3"
- android:strokeWidth="0.56"
- android:strokeColor="@android:color/system_neutral1_100"
- />
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt"
+ android:width="512dp"
+ android:height="512dp"
+ android:viewportWidth="512"
+ android:viewportHeight="512">
+ <path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0">
+ <aapt:attr name="android:fillColor">
+ <gradient
+ android:startX="256"
+ android:startY="21.81"
+ android:endX="256"
+ android:endY="350.42"
+ android:type="linear">
+ <item android:offset="0" android:color="#FF073042"/>
+ <item android:offset="1" android:color="#FF073042"/>
+ </gradient>
+ </aapt:attr>
+ </path>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="m195.27,187.64l2.25,-6.69c13.91,78.13 50.84,284.39 50.84,50.33 0,-0.97 0.72,-1.81 1.62,-1.81h12.69c0.9,0 1.62,0.83 1.62,1.8 -0.2,409.91 -69.03,-43.64 -69.03,-43.64Z"
+ android:fillColor="#3ddc84"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="m158.77,180.68l-33.17,57.45c-1.9,3.3 -0.77,7.52 2.53,9.42 3.3,1.9 7.52,0.77 9.42,-2.53l33.59,-58.17c54.27,24.33 116.34,24.33 170.61,0l33.59,58.17c1.97,3.26 6.21,4.3 9.47,2.33 3.17,-1.91 4.26,-5.99 2.47,-9.23l-33.16,-57.45c56.95,-30.97 95.91,-88.64 101.61,-156.76H57.17c5.7,68.12 44.65,125.79 101.61,156.76Z"
+ android:fillColor="#fff"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M250.26,187.66L262.17,187.66A2.13,2.13 0,0 1,264.3 189.78L264.3,217.85A2.13,2.13 0,0 1,262.17 219.98L250.26,219.98A2.13,2.13 0,0 1,248.14 217.85L248.14,189.78A2.13,2.13 0,0 1,250.26 187.66z"
+ android:fillColor="#3ddc84"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M250.12,170.29L262.32,170.29A1.98,1.98 0,0 1,264.3 172.26L264.3,176.39A1.98,1.98 0,0 1,262.32 178.37L250.12,178.37A1.98,1.98 0,0 1,248.14 176.39L248.14,172.26A1.98,1.98 0,0 1,250.12 170.29z"
+ android:fillColor="#3ddc84"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M171.92,216.82h4.04v4.04h-4.04z"
+ android:fillColor="#fff"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M188.8,275.73h4.04v4.04h-4.04z"
+ android:fillColor="#fff"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M369.04,337.63h4.04v4.04h-4.04z"
+ android:fillColor="#fff"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M285.93,252.22h4.04v4.04h-4.04z"
+ android:fillColor="#fff"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M318.96,218.84h4.04v4.04h-4.04z"
+ android:fillColor="#fff"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M294.05,288.55h4.04v4.04h-4.04z"
+ android:fillColor="#fff"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M330.82,273.31h8.08v8.08h-8.08z"
+ android:fillColor="#fff"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M188.8,298.95h4.04v4.04h-4.04z"
+ android:fillColor="#fff"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M220.14,238.94h8.08v8.08h-8.08z"
+ android:fillColor="#fff"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M272.1,318.9h8.08v8.08h-8.08z"
+ android:fillColor="#fff"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M293.34,349.25h8.08v8.08h-8.08z"
+ android:fillColor="#fff"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M161.05,254.24h8.08v8.08h-8.08z"
+ android:fillColor="#fff"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M378.92,192h8.08v8.08h-8.08z"
+ android:fillColor="#fff"/>
+ </group>
+ <group>
+ <clip-path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"/>
+ <path
+ android:pathData="M137.87,323.7h8.08v8.08h-8.08z"
+ android:fillColor="#fff"/>
+ </group>
+ <path
+ android:pathData="M256,256m-200,0a200,200 0,1 1,400 0a200,200 0,1 1,-400 0"
+ android:strokeWidth="56.561"
+ android:fillColor="#00000000"
+ android:strokeColor="#f86734"/>
+ <path
+ android:pathData="m256.22,126.57c-6.69,0 -12.12,5.27 -12.12,11.77v14.52c0,1.25 1.02,2.27 2.27,2.27h0c1.25,0 2.27,-1.02 2.27,-2.27v-3.91c0,-2.51 2.04,-4.55 4.55,-4.55h6.06c2.51,0 4.55,2.04 4.55,4.55v3.91c0,1.25 1.02,2.27 2.27,2.27s2.27,-1.02 2.27,-2.27v-14.52c0,-6.5 -5.43,-11.77 -12.12,-11.77Z"
+ android:fillColor="#3ddc84"/>
+ <path
+ android:pathData="m93.34,116.36l3.85,-4.36 29.64,9.76 -4.44,5.03 -6.23,-2.1 -7.86,8.91 2.86,5.92 -4.43,5.03 -13.39,-28.18ZM110.43,122.76l-8.86,-3.02 4.11,8.41 4.76,-5.39Z"
+ android:fillColor="#fff"/>
+ <path
+ android:pathData="m153.62,100.85l-21.71,-6.2 10.38,14.38 -5.21,3.76 -16.78,-23.26 4.49,-3.24 21.65,6.19 -10.35,-14.35 5.24,-3.78 16.78,23.26 -4.49,3.24Z"
+ android:fillColor="#fff"/>
+ <path
+ android:pathData="m161.46,63.15l8.99,-3.84c7.43,-3.18 15.96,0.12 19.09,7.44 3.13,7.32 -0.38,15.76 -7.81,18.94l-8.99,3.84 -11.28,-26.38ZM179.41,80.26c4.46,-1.91 5.96,-6.72 4.15,-10.96 -1.81,-4.24 -6.33,-6.48 -10.79,-4.57l-3.08,1.32 6.64,15.53 3.08,-1.32Z"
+ android:fillColor="#fff"/>
+ <path
+ android:pathData="m204.23,47.57l11.1,-2.2c5.31,-1.05 9.47,2.08 10.4,6.76 0.72,3.65 -0.76,6.37 -4.07,8.34l12.4,10.44 -7.57,1.5 -11.65,-9.76 -1.03,0.2 2.3,11.61 -6.3,1.25 -5.57,-28.14ZM216.78,56.7c1.86,-0.37 3,-1.71 2.68,-3.33 -0.34,-1.7 -1.88,-2.43 -3.74,-2.06l-4.04,0.8 1.07,5.39 4.04,-0.8Z"
+ android:fillColor="#fff"/>
+ <path
+ android:pathData="m244.29,55.6c0.13,-8.16 6.86,-14.72 15.06,-14.58 8.16,0.13 14.72,6.9 14.58,15.06s-6.91,14.72 -15.06,14.58c-8.2,-0.13 -14.71,-6.9 -14.58,-15.06ZM267.44,55.98c0.08,-4.64 -3.54,-8.66 -8.18,-8.74 -4.68,-0.08 -8.42,3.82 -8.5,8.47 -0.08,4.65 3.54,8.66 8.22,8.74 4.64,0.08 8.39,-3.82 8.46,-8.47Z"
+ android:fillColor="#fff"/>
+ <path
+ android:pathData="m294.39,44.84l6.31,1.23 -5.49,28.16 -6.31,-1.23 5.49,-28.16Z"
+ android:fillColor="#fff"/>
+ <path
+ android:pathData="m321.94,51.41l9.14,3.48c7.55,2.88 11.39,11.17 8.56,18.61 -2.83,7.44 -11.22,11.07 -18.77,8.19l-9.14,-3.48 10.22,-26.8ZM322.96,76.19c4.53,1.73 8.95,-0.69 10.6,-5 1.64,-4.3 -0.05,-9.06 -4.58,-10.78l-3.13,-1.19 -6.01,15.78 3.13,1.19Z"
+ android:fillColor="#fff"/>
+ <path
+ android:pathData="m381.41,89.24l-4.21,-3.21 3.65,-4.78 9.06,6.91 -17.4,22.81 -4.85,-3.7 13.75,-18.02Z"
+ android:fillColor="#fff"/>
+ <path
+ android:pathData="m397.96,126.37l-9.56,-10.26 3.61,-3.36 22.8,-1.25 3.74,4.02 -12.35,11.51 2.51,2.69 -4.08,3.8 -2.51,-2.69 -4.55,4.24 -4.16,-4.46 4.55,-4.24ZM407.83,117.17l-10.28,0.58 4.49,4.82 5.79,-5.4Z"
+ android:fillColor="#fff"/>
</vector>
+
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index a6b1fdbc588d..6a7c06581d8a 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Swiep van bo na onder as jy wil uitgaan."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Het dit"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Draai vir ’n beter aansig"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Verlaat gedeelde skerm vir ’n beter aansig"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Maak <xliff:g id="NAME">%s</xliff:g> in volskerm oop vir ’n beter aansig"</string>
<string name="done_label" msgid="7283767013231718521">"Klaar"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Ure se sirkelglyer"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Minute se sirkelglyer"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index f3896a3a8381..ecab978bee6c 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"ለመውጣት፣ ከላይ ወደታች ጠረግ ያድርጉ።"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"ገባኝ"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"ለተሻለ ዕይታ ያሽከርክሩ"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ለተሻለ ዕይታ የተከፈለ ማያ ገጽን ትተው ይውጡ"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"ለተሻለ ዕይታ <xliff:g id="NAME">%s</xliff:g>ን በሙሉ ገጽ ዕይታ ይክፈቱ"</string>
<string name="done_label" msgid="7283767013231718521">"ተከናውኗል"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"የሰዓታት ክብ ተንሸራታች"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"የደቂቃዎች ክብ ተንሸራታች"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 546713586c8a..942b78f3d4ae 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1854,7 +1854,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"للخروج، مرر بسرعة من أعلى إلى أسفل."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"حسنًا"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"يمكنك تدوير الجهاز لرؤية شاشة معاينة الكاميرا بشكل أوضح."</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"يمكنك الخروج من وضع \"تقسيم الشاشة\" لرؤية شاشة معاينة الكاميرا بشكل أوضح."</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"عليك فتح \"<xliff:g id="NAME">%s</xliff:g>\" في وضع ملء الشاشة لرؤية شاشة معاينة الكاميرا بشكل أوضح."</string>
<string name="done_label" msgid="7283767013231718521">"تم"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"شريط التمرير الدائري للساعات"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"شريط التمرير الدائري للدقائق"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 123030175923..df238d725204 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"বাহিৰ হ\'বলৈ ওপৰৰপৰা তললৈ ছোৱাইপ কৰক।"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"বুজি পালোঁ"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"ভালকৈ চাবলৈ ঘূৰাওক"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ভালকৈ চাবলৈ বিভাজিত স্ক্ৰীনৰ পৰা বাহিৰ হওক"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"ভালকৈ চাবলৈ <xliff:g id="NAME">%s</xliff:g> পূৰ্ণ স্ক্ৰীনত খোলক"</string>
<string name="done_label" msgid="7283767013231718521">"সম্পন্ন কৰা হ’ল"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"ঘড়ীৰ বৃত্তাকাৰ শ্লাইডাৰ"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"মিনিটৰ বৃত্তাকাৰ শ্লাইডাৰ"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 45b67ebabb2a..3d7e48779ce8 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Çıxmaq üçün yuxarıdan aşağı sürüşdürün."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Anladım"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Daha yaxşı görünüş üçün fırladın"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Daha yaxşı görünüş üçün bölünmüş ekrandan çıxın"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Yaxşı görmək üçün <xliff:g id="NAME">%s</xliff:g> tətbiqini tam ekranda açın"</string>
<string name="done_label" msgid="7283767013231718521">"Hazırdır"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Dairəvi saat slayderi"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Dairəvi dəqiqə slayderi"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index a310cfbad129..aa9d10abdbd7 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -626,11 +626,11 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Greška pri potvrdi identiteta"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Koristite zaključavanje ekrana"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Upotrebite zaključavanje ekrana da biste nastavili"</string>
- <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Jako pritisnite senzor"</string>
+ <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Čvrsto pritisnite senzor"</string>
<string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Prepoznavanje otiska prsta nije uspelo. Probajte ponovo."</string>
<string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Obrišite senzor za otisak prsta i probajte ponovo"</string>
<string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Obrišite senzor i probajte ponovo"</string>
- <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Jako pritisnite senzor"</string>
+ <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Čvrsto pritisnite senzor"</string>
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Previše sporo ste pomerili prst. Probajte ponovo."</string>
<string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Probajte sa drugim otiskom prsta"</string>
<string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Previše je svetlo"</string>
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Da biste izašli, prevucite nadole odozgo."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Važi"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotirajte radi boljeg prikaza"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Izađite iz podeljenog ekrana radi boljeg prikaza"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Otvorite aplikaciju <xliff:g id="NAME">%s</xliff:g> preko celog ekrana da biste bolje videli"</string>
<string name="done_label" msgid="7283767013231718521">"Gotovo"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Kružni klizač za sate"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Kružni klizač za minute"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 7e24c7bfc9c6..f8b6daa797d4 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -627,11 +627,11 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Памылка аўтэнтыфікацыі"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ужываць блакіроўку экрана"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Каб працягнуць, скарыстайце свой сродак блакіроўкі экрана"</string>
- <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Моцна націсніце на сканер"</string>
+ <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Шчыльна прыкладзіце палец да сканера"</string>
<string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Не ўдалося распазнаць адбітак пальца. Паўтарыце спробу."</string>
<string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Ачысціце сканер адбіткаў пальцаў і паўтарыце спробу"</string>
<string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Ачысціце сканер і паўтарыце спробу"</string>
- <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Моцна націсніце на сканер"</string>
+ <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Шчыльна прыкладзіце палец да сканера"</string>
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Палец рухаўся занадта павольна. Паспрабуйце яшчэ раз."</string>
<string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Паспрабуйце іншы адбітак пальца"</string>
<string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Занадта светла"</string>
@@ -1852,7 +1852,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Для выхаду правядзіце зверху ўніз."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Зразумела"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Павярнуць для лепшага прагляду"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Выйсці з рэжыму падзеленага экрана для лепшага прагляду"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Для больш зручнага прагляду адкрыйце праграму \"<xliff:g id="NAME">%s</xliff:g>\", выкарыстоўваючы поўнаэкранны рэжым"</string>
<string name="done_label" msgid="7283767013231718521">"Гатова"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Кругавы паўзунок гадзін"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Кругавы паўзунок хвілін"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index d2afdb2981bb..f4374fb9e1d0 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"За изход плъзнете пръст надолу от горната част."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Разбрах"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Завъртете за по-добър изглед"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Излезте от разделения екран за по-добър изглед"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Отворете <xliff:g id="NAME">%s</xliff:g> на цял екран за по-добър изглед"</string>
<string name="done_label" msgid="7283767013231718521">"Готово"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Кръгов плъзгач за часовете"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Кръгов плъзгач за минутите"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 42c00f4b043b..7b164417e291 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"প্রস্থান করতে উপর থেকে নিচের দিকে সোয়াইপ করুন"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"বুঝেছি"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"আরও ভাল ক্যামেরা ভিউ পাওয়ার জন্য ঘোরান"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"আরও ভাল ক্যামেরা ভিউ পাওয়ার জন্য স্প্লিট স্ক্রিন থেকে বেরিয়ে আসুন"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"আরও ভাল ভিউয়ের জন্য ফুল স্ক্রিনে <xliff:g id="NAME">%s</xliff:g> খুলুন"</string>
<string name="done_label" msgid="7283767013231718521">"সম্পন্ন হয়েছে"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"বৃত্তাকার ঘণ্টা নির্বাচকের স্লাইডার"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"বৃত্তাকার মিনিট নির্বাচকের স্লাইডার"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 3e5700493c1b..874a3b55a692 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -627,7 +627,7 @@
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Koristi zaključavanje ekrana"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Unesite zaključavanje ekrana da nastavite"</string>
<string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Čvrsto pritisnite senzor"</string>
- <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Nije moguće prepoznati otisak prsta. Pokušajte ponovo."</string>
+ <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Otisak prsta nije prepoznat. Pokušajte ponovo."</string>
<string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Očistite senzor za otisak prsta i pokušajte ponovo"</string>
<string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Očistite senzor i pokušajte ponovo"</string>
<string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Čvrsto pritisnite senzor"</string>
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Da izađete, prevucite odozgo nadolje."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Razumijem"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotirajte za bolji prikaz"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Izađite iz podijeljenog ekrana za bolji prikaz"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Otvorite aplikaciju <xliff:g id="NAME">%s</xliff:g> preko cijelog ekrana radi boljeg pregleda"</string>
<string name="done_label" msgid="7283767013231718521">"Gotovo"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Kružni klizač za odabir sata"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Kružni klizač za minute"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 622d648943a3..5889f940b204 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Per sortir, llisca cap avall des de la part superior."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Entesos"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Gira per a una millor visualització"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Surt de la pantalla dividida per a una millor visualització"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Obre <xliff:g id="NAME">%s</xliff:g> en pantalla completa per a una millor visualització"</string>
<string name="done_label" msgid="7283767013231718521">"Fet"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Control circular de les hores"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Control circular dels minuts"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 01f4572345b6..cb4e5f06f2f5 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1852,7 +1852,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Režim ukončíte přejetím prstem shora dolů."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Rozumím"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Otočte obrazovku, abyste lépe viděli"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Ukončete režim rozdělené obrazovky, abyste lépe viděli"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Otevřete aplikaci <xliff:g id="NAME">%s</xliff:g> na celou obrazovku, aby byla lépe vidět"</string>
<string name="done_label" msgid="7283767013231718521">"Hotovo"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Kruhový posuvník hodin"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Kruhový posuvník minut"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index ebd38c89cfcf..43f89fc7cc6c 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Stryg ned fra toppen for at afslutte."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"OK, det er forstået"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Roter, og få en bedre visning"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Afslut opdelt skærm, og få en bedre visning"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Åbn <xliff:g id="NAME">%s</xliff:g> i fuld skærm for at få en bedre visning"</string>
<string name="done_label" msgid="7283767013231718521">"Udfør"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Cirkulær timevælger"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Cirkulær minutvælger"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 4441580842b4..55e845586ef1 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Zum Beenden von oben nach unten wischen"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Ok"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Drehen, um die Ansicht zu verbessern"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Splitscreen-Modus beenden, um die Ansicht zu verbessern"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Du kannst <xliff:g id="NAME">%s</xliff:g> im Vollbildmodus öffnen, um die Ansicht zu verbessern"</string>
<string name="done_label" msgid="7283767013231718521">"Fertig"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Kreisförmiger Schieberegler für Stunden"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Kreisförmiger Schieberegler für Minuten"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 7a0f5c0520e9..3ebf3da8dfea 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -626,7 +626,7 @@
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Χρήση κλειδώματος οθόνης"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Χρησιμοποιήστε το κλείδωμα οθόνης για να συνεχίσετε"</string>
<string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Πιέστε σταθερά τον αισθητήρα"</string>
- <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Δεν είναι δυνατή η αναγνώριση του δακτυλικού αποτυπώματος. Δοκιμάστε ξανά."</string>
+ <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"To δακτ. αποτύπωμα δεν αναγνωρίστηκε. Δοκιμάστε ξανά."</string>
<string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Καθαρίστε τον αισθητήρα δακτυλικών αποτυπωμάτων και δοκιμάστε ξανά"</string>
<string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Καθαρίστε τον αισθητήρα και δοκιμάστε ξανά"</string>
<string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Πιέστε σταθερά τον αισθητήρα"</string>
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Για έξοδο, σύρετε προς τα κάτω από το επάνω μέρος."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Το κατάλαβα"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Περιστρέψτε την οθόνη για καλύτερη προβολή"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Εξέλθετε από τον διαχωρισμό οθόνης για καλύτερη προβολή"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Ανοίξτε την εφαρμογή <xliff:g id="NAME">%s</xliff:g> σε πλήρη οθόνη για καλύτερη προβολή"</string>
<string name="done_label" msgid="7283767013231718521">"Τέλος"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Κυκλικό ρυθμιστικό ωρών"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Κυκλικό ρυθμιστικό λεπτών"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 725f9fa3d00a..73b2968ab9cc 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"To exit, swipe down from the top."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Got it"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotate for a better view"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Exit split screen for a better view"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Open <xliff:g id="NAME">%s</xliff:g> in full screen for a better view"</string>
<string name="done_label" msgid="7283767013231718521">"Done"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Hours circular slider"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Minutes circular slider"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 86e1267eca9d..73017c11ac25 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"To exit, swipe down from the top."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Got it"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotate for a better view"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Exit split screen for a better view"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Open <xliff:g id="NAME">%s</xliff:g> in full screen for a better view"</string>
<string name="done_label" msgid="7283767013231718521">"Done"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Hours circular slider"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Minutes circular slider"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index f0af9de9e6a9..aeabd0096974 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"To exit, swipe down from the top."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Got it"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotate for a better view"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Exit split screen for a better view"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Open <xliff:g id="NAME">%s</xliff:g> in full screen for a better view"</string>
<string name="done_label" msgid="7283767013231718521">"Done"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Hours circular slider"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Minutes circular slider"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 2677a55b7aeb..92f989728902 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"To exit, swipe down from the top."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Got it"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotate for a better view"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Exit split screen for a better view"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Open <xliff:g id="NAME">%s</xliff:g> in full screen for a better view"</string>
<string name="done_label" msgid="7283767013231718521">"Done"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Hours circular slider"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Minutes circular slider"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index fc93b3cccc43..b560c017b7f8 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‏‏‎‎‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‏‏‎‎‎‎‎‎To exit, swipe down from the top.‎‏‎‎‏‎"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‎‎‎‎‏‏‎‎‎‎‎‏‏‎‏‏‎Got it‎‏‎‎‏‎"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‏‏‏‏‎‎Rotate for a better view‎‏‎‎‏‎"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‎‎‎‏‏‏‎‏‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‏‎‏‎‎Exit split screen for a better view‎‏‎‎‏‎"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‎‎‏‎‎‏‎‎‏‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎Open ‎‏‎‎‏‏‎<xliff:g id="NAME">%s</xliff:g>‎‏‎‎‏‏‏‎ in full screen for a better view‎‏‎‎‏‎"</string>
<string name="done_label" msgid="7283767013231718521">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‏‎‎‏‎‎‎‏‏‏‎‎‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‏‎‎‏‏‏‎‎‎‎‎‏‏‏‏‎‎‏‎Done‎‏‎‎‏‎"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‎‎‎‏‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎‎‏‎‏‎‎‏‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎Hours circular slider‎‏‎‎‏‎"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‏‏‏‎‏‎‏‎‏‎‎‎‏‎‏‏‏‏‏‏‎‎Minutes circular slider‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 2bf0e3618c5c..6aabdfe70e32 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1257,7 +1257,7 @@
<string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando aplicaciones"</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"Finalizando el inicio"</string>
<string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Presionaste el botón de encendido. Por lo general, esta acción apaga la pantalla.\n\nPresiona suavemente mientras configuras tu huella dactilar."</string>
- <string name="fp_power_button_enrollment_title" msgid="6976841690455338563">"Para finalizar, apaga la pantalla"</string>
+ <string name="fp_power_button_enrollment_title" msgid="6976841690455338563">"Para salir, apaga la pantalla"</string>
<string name="fp_power_button_enrollment_button_text" msgid="3199783266386029200">"Apagar"</string>
<string name="fp_power_button_bp_title" msgid="5585506104526820067">"¿Verificar huella dactilar?"</string>
<string name="fp_power_button_bp_message" msgid="2983163038168903393">"Presionaste el botón de encendido. Por lo general, esta acción apaga la pantalla.\n\nPresiona suavemente para verificar tu huella dactilar."</string>
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Para salir, desliza el dedo hacia abajo desde la parte superior."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Entendido"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Gira la pantalla para obtener una mejor vista"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Sal de la pantalla dividida para obtener una mejor vista"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Abre <xliff:g id="NAME">%s</xliff:g> en pantalla completa para una mejor visualización"</string>
<string name="done_label" msgid="7283767013231718521">"Listo"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Control deslizante circular de horas"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Control deslizante circular de minutos"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 69128d9bdd48..b1edd4dda3c4 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1371,7 +1371,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Se ha detectado un accesorio de audio analógico"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"El dispositivo adjunto no es compatible con este teléfono. Toca para obtener más información."</string>
<string name="adb_active_notification_title" msgid="408390247354560331">"Depuración por USB activa"</string>
- <string name="adb_active_notification_message" msgid="5617264033476778211">"Tocar para desactivar depuración USB"</string>
+ <string name="adb_active_notification_message" msgid="5617264033476778211">"Toca para desactivar depuración USB"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Seleccionar para inhabilitar la depuración por USB"</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Depuración inalámbrica conectada"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Toca para desactivar la depuración inalámbrica"</string>
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Para salir, desliza el dedo de arriba abajo."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Entendido"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Gira la pantalla para verlo mejor"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Sal de la pantalla dividida para verlo mejor"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Abre <xliff:g id="NAME">%s</xliff:g> en pantalla completa para verlo mejor"</string>
<string name="done_label" msgid="7283767013231718521">"Hecho"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Control deslizante circular de horas"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Control deslizante circular de minutos"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 0197f21e2b57..8cb08286e8a4 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Väljumiseks pühkige ülevalt alla."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Selge"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Pöörake parema vaate jaoks"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Parema vaate jaoks väljuge jagatud ekraanikuvast"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Parema vaate jaoks avage rakendus <xliff:g id="NAME">%s</xliff:g> täisekraanil"</string>
<string name="done_label" msgid="7283767013231718521">"Valmis"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Ringikujuline tunniliugur"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Ringikujuline minutiliugur"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index f14a0070177f..a165af18472e 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Irteteko, pasatu hatza goitik behera."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Ados"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Biratu pantaila ikuspegi hobea lortzeko"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Irten pantaila zatitutik ikuspegi hobea lortzeko"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Ireki <xliff:g id="NAME">%s</xliff:g> pantaila osoan eta ikuspegi hobea lortuko duzu"</string>
<string name="done_label" msgid="7283767013231718521">"Eginda"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Ordua aukeratzeko ikuspegi zirkularra"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Minutuak aukeratzeko ikuspegi zirkularra"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 74332ecc5439..9bb14bc9f0a7 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"برای خروج، انگشتتان را از بالای صفحه به پایین بکشید."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"متوجه شدم"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"برای دید بهتر، دستگاه را بچرخانید"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"برای دید بهتر، از صفحهٔ دونیمه خارج شوید"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"برای دید بهتر، <xliff:g id="NAME">%s</xliff:g> را به‌صورت تمام‌صفحه باز کنید"</string>
<string name="done_label" msgid="7283767013231718521">"تمام"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"لغزنده دایره‌ای ساعت"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"لغزنده دایره‌ای دقیقه"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index a5a0a3f7d9b3..5e1984b3029d 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Sulje palkki pyyhkäisemällä alas ruudun ylälaidasta."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Selvä"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Kierrä, niin saat paremman näkymän"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Poistu jaetulta näytöltä, niin saat paremman näkymän"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Avaa <xliff:g id="NAME">%s</xliff:g>, niin saat paremman näkymän"</string>
<string name="done_label" msgid="7283767013231718521">"Valmis"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Tuntien ympyränmuotoinen liukusäädin"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Minuuttien ympyränmuotoinen liukusäädin"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index da9399298d18..b26a68ac7fcf 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Pour quitter, balayez vers le bas à partir du haut."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Faire pivoter pour obtenir un meilleur affichage"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Quitter l\'écran partagé pour obtenir un meilleur affichage"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Ouvrir <xliff:g id="NAME">%s</xliff:g> en plein écran pour un meilleur affichage"</string>
<string name="done_label" msgid="7283767013231718521">"Terminé"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Curseur circulaire des heures"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Curseur circulaire des minutes"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index f80373d07f01..e04b49bfcfab 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Pour quitter, balayez l\'écran du haut vers le bas."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Faites pivoter pour mieux voir"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Quittez l\'écran partagé pour mieux voir"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Ouvrez <xliff:g id="NAME">%s</xliff:g> en plein écran pour mieux voir"</string>
<string name="done_label" msgid="7283767013231718521">"OK"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Curseur circulaire des heures"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Curseur circulaire des minutes"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 7aa45be7d126..cc5ced3a760a 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Para saír, pasa o dedo cara abaixo desde a parte superior."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Entendido"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Xira a pantalla para que se vexa mellor"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Sae da pantalla dividida para que se vexa mellor"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Abre <xliff:g id="NAME">%s</xliff:g> en pantalla completa para unha mellor visualización"</string>
<string name="done_label" msgid="7283767013231718521">"Feito"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Control desprazable circular das horas"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Control desprazable circular dos minutos"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 9bc39626d133..ab3859e39800 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"બહાર નીકળવા માટે, ટોચ પરથી નીચે સ્વાઇપ કરો."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"સમજાઈ ગયું"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"બહેતર વ્યૂ માટે ફેરવો"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"બહેતર વ્યૂ માટે, વિભાજિત સ્ક્રીનમાંથી બહાર નીકળો"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"બહેતર વ્યૂ માટે, પૂર્ણ સ્ક્રીનમાં <xliff:g id="NAME">%s</xliff:g> ખોલો"</string>
<string name="done_label" msgid="7283767013231718521">"થઈ ગયું"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"કલાકનું વર્તુળાકાર સ્લાઇડર"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"મિનિટનું વર્તુળાકાર સ્લાઇડર"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 9ebe4f70c3e1..8dd913440ec1 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1715,7 +1715,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"रंग में सुधार करने की सुविधा"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"वन-हैंडेड मोड"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"स्क्रीन की रोशनी को सामान्य लेवल से और कम करने की सुविधा"</string>
- <string name="hearing_aids_feature_name" msgid="1125892105105852542">"सुनने में मदद करने वाले डिवाइस"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"कान की मशीन"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"आवाज़ कम-ज़्यादा करने वाले दोनों बटन दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को चालू कर दिया गया."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"आवाज़ कम-ज़्यादा करने वाले दोनों बटन दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को बंद कर दिया गया."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"आवाज़ बटन को छोड़ें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> की सुविधा चालू करने के लिए, आवाज़ वाले दोनों बटन तीन सेकंड तक दबाकर रखें."</string>
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"बाहर निकलने के लिए, ऊपर से नीचे स्वा‍इप करें."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"ठीक है"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"बेहतर व्यू पाने के लिए, डिवाइस की स्क्रीन को घुमाएं"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"बेहतर व्यू पाने के लिए, स्प्लिट स्क्रीन मोड बंद करें"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"बेहतर व्यू पाने के लिए <xliff:g id="NAME">%s</xliff:g> को फ़ुल स्क्रीन में खोलें"</string>
<string name="done_label" msgid="7283767013231718521">"हो गया"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"घंटो का चक्राकार स्लाइडर"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"मिनटों का चक्राकार स्लाइडर"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 4ba22b28bcbc..eb8d11118970 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -161,7 +161,7 @@
<string name="httpErrorLookup" msgid="3099834738227549349">"URL nije moguće pronaći."</string>
<string name="httpErrorUnsupportedAuthScheme" msgid="3976195595501606787">"Shema autentifikacije web-lokacije nije podržana."</string>
<string name="httpErrorAuth" msgid="469553140922938968">"Autentifikacija nije moguća."</string>
- <string name="httpErrorProxyAuth" msgid="7229662162030113406">"Provjera autentičnosti preko proxy poslužitelja nije bila uspješna."</string>
+ <string name="httpErrorProxyAuth" msgid="7229662162030113406">"Autentifikacija preko proxy poslužitelja nije bila uspješna."</string>
<string name="httpErrorConnect" msgid="3295081579893205617">"Povezivanje s poslužiteljem nije moguće."</string>
<string name="httpErrorIO" msgid="3860318696166314490">"Komunikacija s poslužiteljem nije moguća. Pokušajte ponovno kasnije."</string>
<string name="httpErrorTimeout" msgid="7446272815190334204">"Veza s poslužiteljem privremeno je zaustavljena."</string>
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Za izlaz prijeđite prstom od vrha prema dolje."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Shvaćam"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Zakrenite kako biste bolje vidjeli"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Zatvorite podijeljeni zaslon kako biste bolje vidjeli"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Otvorite aplikaciju <xliff:g id="NAME">%s</xliff:g> preko cijelog zaslona za bolji prikaz"</string>
<string name="done_label" msgid="7283767013231718521">"Gotovo"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Kružni klizač sati"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Kružni klizač minuta"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 38fd4ac989a2..793fc8699d1e 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Kilépéshez csúsztassa ujját fentről lefelé."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Értem"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Forgassa el a jobb élmény érdekében"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Lépjen ki az osztott képernyős módból a jobb élmény érdekében"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"A jobb élmény érdekében teljes képernyős módban nyissa meg a(z) <xliff:g id="NAME">%s</xliff:g> alkalmazást"</string>
<string name="done_label" msgid="7283767013231718521">"Kész"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Óra kör alakú csúszkája"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Perc kör alakú csúszkája"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 272dfee4002f..f20230f7049e 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Դուրս գալու համար վերևից սահահարվածեք դեպի ներքև:"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Պարզ է"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Պտտեք՝ դիտակերպը լավացնելու համար"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Դուրս եկեք կիսված էկրանի ռեժիմից՝ դիտակերպը լավացնելու համար"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Բացեք <xliff:g id="NAME">%s</xliff:g> հավելվածը լիաէկրան ռեժիմում՝ դիտակերպը լավացնելու համար"</string>
<string name="done_label" msgid="7283767013231718521">"Պատրաստ է"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Ժամերի ընտրություն թվատախտակից"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Րոպեների ընտրություն թվատախտակից"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index c854e12fa4e3..9ced3ef5eac7 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Untuk keluar, geser layar ke bawah dari atas."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Mengerti"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Putar posisi layar untuk mendapatkan tampilan yang lebih baik"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Keluar dari layar terpisah untuk mendapatkan tampilan yang lebih baik"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Buka <xliff:g id="NAME">%s</xliff:g> dalam layar penuh untuk mendapatkan tampilan yang lebih baik"</string>
<string name="done_label" msgid="7283767013231718521">"Selesai"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Penggeser putar jam"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Penggeser putar menit"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 1c7a07df45a8..b43935f17844 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Strjúktu niður frá efri brún til að hætta."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Ég skil"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Snúðu til að sjá betur"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Lokaðu skjáskiptingu til að sjá betur"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Opnaðu <xliff:g id="NAME">%s</xliff:g> á öllum skjánum til að fá betra yfirlit"</string>
<string name="done_label" msgid="7283767013231718521">"Lokið"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Valskífa fyrir klukkustundir"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Valskífa fyrir mínútur"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 2e9d1ec2158c..d67dceaf770e 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Per uscire, scorri dall\'alto verso il basso."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Ruota per migliorare l\'anteprima"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Esci dallo schermo diviso per migliorare l\'anteprima"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Apri <xliff:g id="NAME">%s</xliff:g> a schermo intero per migliorare la visualizzazione"</string>
<string name="done_label" msgid="7283767013231718521">"Fine"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Cursore circolare per le ore"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Cursore circolare per i minuti"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 84f56ff54f36..34ca18fc446f 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"כדי לצאת, פשוט מחליקים אצבע מלמעלה למטה."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"הבנתי"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"מסובבים כדי לראות טוב יותר"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"צריך לצאת מהמסך המפוצל כדי לראות טוב יותר"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"צריך לפתוח את <xliff:g id="NAME">%s</xliff:g> במסך מלא כדי לראות טוב יותר"</string>
<string name="done_label" msgid="7283767013231718521">"סיום"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"מחוון שעות מעגלי"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"מחוון דקות מעגלי"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index dc4694d03bed..d8d721c0b741 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -648,8 +648,8 @@
<string name="fingerprint_error_timeout" msgid="7361192266621252164">"指紋の設定がタイムアウトしました。もう一度お試しください。"</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"指紋の操作をキャンセルしました。"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"指紋の操作がユーザーによりキャンセルされました。"</string>
- <string name="fingerprint_error_lockout" msgid="6626753679019351368">"試行回数が上限を超えました。代わりに PIN を入力してください。"</string>
- <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"試行回数が上限を超えました。代わりに PIN を入力してください。"</string>
+ <string name="fingerprint_error_lockout" msgid="6626753679019351368">"試行回数が上限を超えました。代わりに画面ロックを使用してください。"</string>
+ <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"試行回数が上限を超えました。代わりに画面ロックを使用してください。"</string>
<string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"指紋を処理できません。もう一度お試しください。"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"指紋が登録されていません。"</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"このデバイスには指紋認証センサーがありません。"</string>
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"終了するには、上から下にスワイプします。"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"画面を回転させて見やすくしましょう"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"分割画面を終了して見やすくしましょう"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"<xliff:g id="NAME">%s</xliff:g> を全画面表示で開いて見やすくしましょう"</string>
<string name="done_label" msgid="7283767013231718521">"完了"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"円形スライダー(時)"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"円形スライダー(分)"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 13d430c985fe..a87e99dd5cb4 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"გამოსვლისათვის, გაასრიალეთ ზემოდან ქვემოთ."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"გასაგებია"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"შეატრიალეთ უკეთესი ხედისთვის"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"უკეთესი ხედვისთვის გამოდით გაყოფილი ეკრანიდან"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"გახსენით <xliff:g id="NAME">%s</xliff:g> სრულ ეკრანზე უკეთესი ხედისთვის"</string>
<string name="done_label" msgid="7283767013231718521">"დასრულდა"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"საათების წრიული სლაიდერი"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"წუთების წრიული სლაიდერი"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 03897c1e90f7..581ab023a24b 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Шығу үшін жоғарыдан төмен қарай сырғытыңыз."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Түсінікті"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Жақсырақ көру үшін бұрыңыз."</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Жақсырақ көру үшін экранды бөлу режимінен шығыңыз."</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Жақсырақ көру үшін <xliff:g id="NAME">%s</xliff:g> қолданбасын толық экранда ашыңыз."</string>
<string name="done_label" msgid="7283767013231718521">"Дайын"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Сағаттар айналымының қозғалтқышы"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Минут айналымын қозғалтқыш"</string>
@@ -1943,7 +1943,7 @@
<string name="language_picker_regions_section_suggested" msgid="6080131515268225316">"Ұсынылатын аймақтар"</string>
<string name="language_picker_section_suggested_bilingual" msgid="5932198319583556613">"Ұсынылған тілдер"</string>
<string name="region_picker_section_suggested_bilingual" msgid="704607569328224133">"Ұсынылған аймақтар"</string>
- <string name="language_picker_section_all" msgid="1985809075777564284">"Барлық тілдер"</string>
+ <string name="language_picker_section_all" msgid="1985809075777564284">"Барлық тіл"</string>
<string name="region_picker_section_all" msgid="756441309928774155">"Барлық аймақтар"</string>
<string name="locale_search_menu" msgid="6258090710176422934">"Іздеу"</string>
<string name="app_suspended_title" msgid="888873445010322650">"Қолданба қолжетімді емес"</string>
@@ -2289,7 +2289,7 @@
<string name="window_magnification_prompt_title" msgid="2876703640772778215">"Жаңа ұлғайту параметрлері"</string>
<string name="window_magnification_prompt_content" msgid="8159173903032344891">"Енді экранның бір бөлігін ұлғайтуға болады."</string>
<string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Параметрлер бөлімінен қосу"</string>
- <string name="dismiss_action" msgid="1728820550388704784">"Қабылдамау"</string>
+ <string name="dismiss_action" msgid="1728820550388704784">"Жабу"</string>
<string name="sensor_privacy_start_use_mic_notification_content_title" msgid="2420858361276370367">"Құрылғы микрофонын блоктан шығарыңыз"</string>
<string name="sensor_privacy_start_use_camera_notification_content_title" msgid="7287720213963466672">"Құрылғы камерасын блоктан шығарыңыз"</string>
<string name="sensor_privacy_start_use_notification_content_text" msgid="7595608891015777346">"&lt;b&gt;<xliff:g id="APP">%s</xliff:g>&lt;/b&gt; және барлық қолданбалар мен қызметтерге арналған."</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index d7f979f49ee5..ce930a50780e 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -683,7 +683,7 @@
<string name="face_acquired_too_far" msgid="2922278214231064859">"ដាក់​ទូរសព្ទ​ឱ្យជិត​ជាងមុន"</string>
<string name="face_acquired_too_high" msgid="8278815780046368576">"រំកិល​ទូរសព្ទឡើងលើ"</string>
<string name="face_acquired_too_low" msgid="4075391872960840081">"រំកិល​ទូរសព្ទចុះក្រោម"</string>
- <string name="face_acquired_too_right" msgid="6245286514593540859">"ដាក់​ទូរសព្ទ​ទៅខាងឆ្វេងអ្នក"</string>
+ <string name="face_acquired_too_right" msgid="6245286514593540859">"រំកិលទូរសព្ទ​ទៅខាងឆ្វេង"</string>
<string name="face_acquired_too_left" msgid="9201762240918405486">"រំកិលទូរសព្ទ​ទៅខាងស្ដាំ"</string>
<string name="face_acquired_poor_gaze" msgid="4427153558773628020">"សូមមើល​ឱ្យចំ​ឧបករណ៍​របស់អ្នក​ជាងមុន។"</string>
<string name="face_acquired_not_detected" msgid="1057966913397548150">"មើលមិនឃើញ​មុខរបស់អ្នកទេ។ កាន់ទូរសព្ទរបស់អ្នក​ដាក់ត្រឹមភ្នែក។"</string>
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"ដើម្បីចាកចេញ សូមអូសពីលើចុះក្រោម។"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"យល់ហើយ"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"បង្វិលដើម្បីមើលបានកាន់តែច្បាស់"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ចេញពីមុខងារ​បំបែកអេក្រង់ដើម្បីមើលបានកាន់តែច្បាស់"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"បើក <xliff:g id="NAME">%s</xliff:g> នៅក្នុងអេក្រង់ពេញ ដើម្បីមើលបានកាន់តែច្បាស់"</string>
<string name="done_label" msgid="7283767013231718521">"រួចរាល់"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"គ្រាប់​រំកិល​រង្វង់​ម៉ោង"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"គ្រាប់​រំកិល​រង្វង់​នាទី"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 55a0a8430122..812a3b304763 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1351,7 +1351,7 @@
<string name="time_picker_dialog_title" msgid="9053376764985220821">"ಸಮಯವನ್ನು ಹೊಂದಿಸಿ"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"ದಿನಾಂಕವನ್ನು ಹೊಂದಿಸಿ"</string>
<string name="date_time_set" msgid="4603445265164486816">"ಹೊಂದಿಸು"</string>
- <string name="date_time_done" msgid="8363155889402873463">"ಮುಗಿದಿದೆ"</string>
+ <string name="date_time_done" msgid="8363155889402873463">"ಆಯಿತು"</string>
<string name="perms_new_perm_prefix" msgid="6984556020395757087"><font size="12" fgcolor="#ff33b5e5">"ಹೊಸ: "</font></string>
<string name="perms_description_app" msgid="2747752389870161996">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಮೂಲಕ ಒದಗಿಸಲಾಗಿದೆ."</string>
<string name="no_permissions" msgid="5729199278862516390">"ಯಾವುದೇ ಅನುಮತಿಗಳ ಅಗತ್ಯವಿಲ್ಲ"</string>
@@ -1850,8 +1850,8 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"ನಿರ್ಗಮಿಸಲು, ಮೇಲಿನಿಂದ ಕೆಳಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"ತಿಳಿಯಿತು"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"ಅತ್ಯುತ್ತಮ ವೀಕ್ಷಣೆಗಾಗಿ ತಿರುಗಿಸಿ"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ಅತ್ಯುತ್ತಮ ವೀಕ್ಷಣೆಗಾಗಿ ಸ್ಪ್ಲಿಟ್‌ ಸ್ಕ್ರೀನ್‌ನಿಂದ ನಿರ್ಗಮಿಸಿ"</string>
- <string name="done_label" msgid="7283767013231718521">"ಮುಗಿದಿದೆ"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"ಅತ್ಯುತ್ತಮ ವೀಕ್ಷಣೆಗಾಗಿ <xliff:g id="NAME">%s</xliff:g> ಅನ್ನು ಪೂರ್ಣ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ತೆರೆಯಿರಿ"</string>
+ <string name="done_label" msgid="7283767013231718521">"ಆಯಿತು"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"ಗಂಟೆಗಳ ವೃತ್ತಾಕಾರ ಸ್ಲೈಡರ್"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"ನಿಮಿಷಗಳ ವೃತ್ತಾಕಾರ ಸ್ಲೈಡರ್"</string>
<string name="select_hours" msgid="5982889657313147347">"ಗಂಟೆಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 93a7352eb7e0..59a11bcef616 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -635,7 +635,7 @@
<string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"너무 밝음"</string>
<string name="fingerprint_acquired_power_press" msgid="3107864151278434961">"전원 누름이 감지되었습니다."</string>
<string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"조정 시도"</string>
- <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"지문이 인식될 때마다 손가락을 조금씩 이동하세요"</string>
+ <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"지문이 인식될 때마다 손가락의 위치를 조금씩 바꾸세요"</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_error_not_match" msgid="4599441812893438961">"지문이 인식되지 않았습니다."</string>
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"종료하려면 위에서 아래로 스와이프합니다."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"확인"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"카메라 미리보기 화면이 잘 보이도록 회전하세요."</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"카메라 미리보기 화면이 잘 보이도록 화면 분할을 종료하세요."</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"화면이 더 잘 보이도록 <xliff:g id="NAME">%s</xliff:g>을(를) 전체 화면에서 여세요."</string>
<string name="done_label" msgid="7283767013231718521">"완료"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"시간 원형 슬라이더"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"분 원형 슬라이더"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 5cd22384f59c..6949977f2cd7 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Чыгуу үчүн экранды ылдый сүрүп коюңуз."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Түшүндүм"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Жакшыраак көрүү үчүн буруңуз"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Жакшыраак көрүү үчүн экранды бөлүү режиминен чыгыңыз"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Жакшыраак көрүү үчүн <xliff:g id="NAME">%s</xliff:g> колдонмосун толук экранда ачыңыз"</string>
<string name="done_label" msgid="7283767013231718521">"Даяр"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Саат жебеси"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Мүнөт жебеси"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 269fa169bd43..15517b5ee3e3 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"ຫາກຕ້ອງການອອກ, ໃຫ້ຮູດຈາກທາງເທິງລົງມາທາງລຸ່ມ."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"ໄດ້​ແລ້ວ"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"ໝຸນເພື່ອມຸມມອງທີ່ດີຂຶ້ນ"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ອອກຈາກແບ່ງໜ້າຈໍເພື່ອມຸມມອງທີ່ດີຂຶ້ນ"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"ເປີດ <xliff:g id="NAME">%s</xliff:g> ໃນໂໝດເຕັມຈໍເພື່ອມຸມມອງທີ່ດີຂຶ້ນ"</string>
<string name="done_label" msgid="7283767013231718521">"ແລ້ວໆ"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"ໂຕໝຸນປັບຊົ່ວໂມງ"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"ໂຕໝຸນປັບນາທີ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 4ae49ac1207d..ded4bbac3053 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1852,7 +1852,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Jei norite išeiti, perbraukite žemyn iš viršaus."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Supratau"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Pasukite, kad geriau matytumėte vaizdą"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Išeikite iš išskaidyto ekrano režimo, kad geriau matytumėte vaizdą"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Atidarykite „<xliff:g id="NAME">%s</xliff:g>“ viso ekrano režimu, kad geriau matytumėte vaizdą"</string>
<string name="done_label" msgid="7283767013231718521">"Atlikta"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Apskritas valandų šliaužiklis"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Apskritas minučių šliaužiklis"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 0c0082967dff..fade02ed8dac 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Lai izietu, no augšdaļas velciet lejup."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Labi"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Lai uzlabotu skatu, pagrieziet ekrānu."</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Lai uzlabotu skatu, izejiet no ekrāna sadalīšanas režīma."</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Labākam skatam atveriet lietotni <xliff:g id="NAME">%s</xliff:g> pilnekrāna režīmā."</string>
<string name="done_label" msgid="7283767013231718521">"Gatavs"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Stundu apļveida slīdnis"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Minūšu apļveida slīdnis"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 0a4c9bf30243..202099a85c4d 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"За да излезете, повлечете одозгора надолу."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Сфатив"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Ротирајте за подобар приказ"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"За подобар приказ, излезете од поделениот екран"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"За подобар приказ, отворете ја апликацијата <xliff:g id="NAME">%s</xliff:g> на цел екран"</string>
<string name="done_label" msgid="7283767013231718521">"Готово"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Приказ на часови во кружно движење"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Приказ на минути во кружно движење"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 5fa3b52d7000..fe9c02e5b04a 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"അവസാനിപ്പിക്കാൻ, മുകളിൽ നിന്ന് താഴോട്ട് സ്വൈപ്പ് ചെയ്യുക."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"മനസ്സിലായി"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"മികച്ച കാഴ്‌ചയ്‌ക്കായി റൊട്ടേറ്റ് ചെയ്യുക"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"മികച്ച കാഴ്‌ചയ്‌ക്കായി സ്‌ക്രീൻ വിഭജന മോഡിൽ നിന്ന് പുറത്തുകടക്കുക"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"മികച്ച കാഴ്‌‌ചയ്ക്ക് പൂർണ്ണ സ്‌ക്രീനിൽ <xliff:g id="NAME">%s</xliff:g> തുറക്കുക"</string>
<string name="done_label" msgid="7283767013231718521">"പൂർത്തിയാക്കി"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"ചാക്രികമായി മണിക്കൂറുകൾ ദൃശ്യമാകുന്ന സ്ലൈഡർ"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"ചാക്രികമായി മിനിറ്റുകൾ ദൃശ്യമാകുന്ന സ്ലൈഡർ"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 204cf39de5f6..b69fb83dde35 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Гарахаар бол дээрээс нь доош нь чирнэ үү."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Ойлголоо"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Харагдах байдлыг сайжруулах бол эргүүлнэ үү"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Харагдах байдлыг сайжруулах бол дэлгэцийг хуваах горимоос гарна уу"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Харагдах байдлыг сайжруулах бол <xliff:g id="NAME">%s</xliff:g>-г бүтэн дэлгэцээр нээнэ үү"</string>
<string name="done_label" msgid="7283767013231718521">"Дууссан"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Цаг гүйлгэгч"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Минут гүйлгэгч"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index c728050bfa2b..5f6b35dfb887 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"बाहेर पडण्यासाठी, वरून खाली स्वाइप करा."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"समजले"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"अधिक चांगल्या दृश्यासाठी फिरवा"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"अधिक चांगल्या दृश्यासाठी स्प्लिट स्क्रीनमधून बाहेर पडा"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"अधिक चांगल्या दृश्यासाठी <xliff:g id="NAME">%s</xliff:g> हे फुल स्क्रीनमध्ये उघडा"</string>
<string name="done_label" msgid="7283767013231718521">"पूर्ण झाले"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"तास परिपत्रक स्लायडर"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"मिनिटे परिपत्रक स्लायडर"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 5cb9c09890fe..f62c70690f05 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Untuk keluar, leret dari atas ke bawah."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Faham"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Putar untuk mendapatkan paparan yang lebih baik"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Keluar daripada skrin pisah untuk mendapatkan paparan yang lebih baik"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Buka <xliff:g id="NAME">%s</xliff:g> dalam skrin penuh untuk mendapatkan paparan yang lebih baik"</string>
<string name="done_label" msgid="7283767013231718521">"Selesai"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Penggelangsar bulatan jam"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Penggelangsar bulatan minit"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index d90c5b825537..5a849570766c 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -199,7 +199,7 @@
<string name="sensor_notification_service" msgid="7474531979178682676">"အာရုံခံကိရိယာ အကြောင်းကြားချက် ဝန်ဆောင်မှု"</string>
<string name="twilight_service" msgid="8964898045693187224">"နေဝင်ဆည်းဆာ ဝန်ဆောင်မှု"</string>
<string name="gnss_time_update_service" msgid="9039489496037616095">"GNSS အချိန်အပ်ဒိတ် ဝန်ဆောင်မှု"</string>
- <string name="device_policy_manager_service" msgid="5085762851388850332">"ကိရိယာဆိုင်ရာ မူဝါဒ မန်နေဂျာဝန်ဆောင်မှု"</string>
+ <string name="device_policy_manager_service" msgid="5085762851388850332">"ကိရိယာ မူဝါဒ မန်နေဂျာဝန်ဆောင်မှု"</string>
<string name="music_recognition_manager_service" msgid="7481956037950276359">"တေးဂီတကို သိရှိမှတ်မိခြင်း စီမံခန့်ခွဲမှုစနစ် ဝန်ဆောင်မှု"</string>
<string name="factory_reset_warning" msgid="6858705527798047809">"သင့်ကိရိယာအား ပယ်ဖျက်လိမ့်မည်"</string>
<string name="factory_reset_message" msgid="2657049595153992213">"စက်စီမံအက်ပ်ကို သုံး၍မရပါ။ သင်၏ စက်ပစ္စည်းအတွင်းရှိ အရာများကို ဖျက်လိုက်ပါမည်\n\nမေးစရာများရှိပါက သင့်အဖွဲ့အစည်း၏ စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string>
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"ထွက်ရန် အပေါ်မှ အောက်သို့ ဆွဲချပါ။"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"ရပါပြီ"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"ပိုကောင်းသောမြင်ကွင်းအတွက် လှည့်ပါ"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ပိုကောင်းသောမြင်ကွင်းအတွက် မျက်နှာပြင် ခွဲ၍ပြသခြင်းမှ ထွက်ပါ"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"ပိုကောင်းသောမြင်ကွင်းအတွက် ဖန်သားပြင်အပြည့်ဖြင့် <xliff:g id="NAME">%s</xliff:g> ကို ဖွင့်ပါ"</string>
<string name="done_label" msgid="7283767013231718521">"ပြီးပါပြီ"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"နာရီရွေးချက်စရာ"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"မိနစ်လှည့်သော ရွေ့လျားတန်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 845eb92dc559..15ef328cfbb0 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Sveip ned fra toppen for å avslutte."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Skjønner"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Roter for å få en bedre visning"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Avslutt delt skjerm for å få en bedre visning"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Åpne <xliff:g id="NAME">%s</xliff:g> i fullskjerm for å se bedre"</string>
<string name="done_label" msgid="7283767013231718521">"Ferdig"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Sirkulær glidebryter for timer"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Sirkulær glidebryter for minutter"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index e7de30871a0d..9a9021b34e3c 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -89,8 +89,8 @@
<string name="notification_channel_call_forward" msgid="8230490317314272406">"कल फर्वार्ड गर्ने सेवा"</string>
<string name="notification_channel_emergency_callback" msgid="54074839059123159">"आपत्‌कालीन कलब्याक मोड"</string>
<string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"मोबाइल डेटाको स्थिति"</string>
- <string name="notification_channel_sms" msgid="1243384981025535724">"SMS सन्देशहरू"</string>
- <string name="notification_channel_voice_mail" msgid="8457433203106654172">"भ्वाइस मेल सन्देशहरू"</string>
+ <string name="notification_channel_sms" msgid="1243384981025535724">"SMS म्यासेजहरू"</string>
+ <string name="notification_channel_voice_mail" msgid="8457433203106654172">"भ्वाइस मेल म्यासेजहरू"</string>
<string name="notification_channel_wfc" msgid="9048240466765169038">"Wi-Fi कल"</string>
<string name="notification_channel_sim" msgid="5098802350325677490">"SIM को स्थिति"</string>
<string name="notification_channel_sim_high_prio" msgid="642361929452850928">"उच्च प्राथमिकता रहेको SIM को स्थिति"</string>
@@ -122,7 +122,7 @@
<string name="roamingTextSearching" msgid="5323235489657753486">"सेवाको खोजी गर्दै…"</string>
<string name="wfcRegErrorTitle" msgid="3193072971584858020">"Wi-Fi कलिङ सेटअप गर्न सकिएन"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="468830943567116703">"Wi-Fi मार्फत कलहरू गर्न र सन्देशहरू पठाउन सबभन्दा पहिला आफ्नो सेवा प्रदायकलाई यो सेवा सेट गर्न भन्नुहोस्। त्यसपछि सेटिङहरूबाट Wi-Fi कलिङलाई सक्रिय पार्नुहोस्। (त्रुटिसम्बन्धी कोड: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ <item msgid="468830943567116703">"Wi-Fi मार्फत कलहरू गर्न र म्यासेजहरू पठाउन सबभन्दा पहिला आफ्नो सेवा प्रदायकलाई यो सेवा सेट गर्न भन्नुहोस्। त्यसपछि सेटिङहरूबाट Wi-Fi कलिङलाई सक्रिय पार्नुहोस्। (त्रुटिसम्बन्धी कोड: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="4795145070505729156">"तपाईंको सेवा प्रदायकमार्फत Wi-Fi कलिङ सुविधा दर्ता गर्ने क्रममा देखिएको समस्या: <xliff:g id="CODE">%1$s</xliff:g>"</item>
@@ -275,8 +275,8 @@
<string name="notification_channel_security" msgid="8516754650348238057">"सुरक्षा"</string>
<string name="notification_channel_car_mode" msgid="2123919247040988436">"कार मोड"</string>
<string name="notification_channel_account" msgid="6436294521740148173">"खाताको स्थिति"</string>
- <string name="notification_channel_developer" msgid="1691059964407549150">"विकासकर्ताका सन्देशहरू"</string>
- <string name="notification_channel_developer_important" msgid="7197281908918789589">"विकासकर्तासम्बन्धी महत्त्वपूर्ण सन्देशहरू"</string>
+ <string name="notification_channel_developer" msgid="1691059964407549150">"विकासकर्ताका म्यासेजहरू"</string>
+ <string name="notification_channel_developer_important" msgid="7197281908918789589">"विकासकर्तासम्बन्धी महत्त्वपूर्ण म्यासेजहरू"</string>
<string name="notification_channel_updates" msgid="7907863984825495278">"अद्यावधिकहरू"</string>
<string name="notification_channel_network_status" msgid="2127687368725272809">"नेटवर्कको स्थिति"</string>
<string name="notification_channel_network_alerts" msgid="6312366315654526528">"नेटवर्कका अलर्टहरू"</string>
@@ -300,14 +300,14 @@
<string name="managed_profile_label" msgid="7316778766973512382">"कार्य प्रोफाइलमा बदल्नुहोस्"</string>
<string name="user_owner_app_label" msgid="1553595155465750298">"<xliff:g id="APP_NAME">%1$s</xliff:g> को व्यक्तिगत प्रोफाइल प्रयोग गर्नुहोस्"</string>
<string name="managed_profile_app_label" msgid="367401088383965725">"<xliff:g id="APP_NAME">%1$s</xliff:g> को कार्य प्रोफाइल प्रयोग गर्नुहोस्"</string>
- <string name="permgrouplab_contacts" msgid="4254143639307316920">"सम्पर्कहरू"</string>
+ <string name="permgrouplab_contacts" msgid="4254143639307316920">"कन्ट्याक्टहरू"</string>
<string name="permgroupdesc_contacts" msgid="9163927941244182567">"तपाईँको सम्पर्कमाथि पहुँच गर्नुहोस्"</string>
<string name="permgrouplab_location" msgid="1858277002233964394">"लोकेसन"</string>
<string name="permgroupdesc_location" msgid="1995955142118450685">"यस डिभाइसको स्थानमाथि पहुँच"</string>
<string name="permgrouplab_calendar" msgid="6426860926123033230">"पात्रो"</string>
<string name="permgroupdesc_calendar" msgid="6762751063361489379">"तपाईंको पात्रोमाथि पहुँच गर्नुहोस्"</string>
<string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
- <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS सन्देशहरू पठाउनुहोस् र हेर्नुहोस्"</string>
+ <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS म्यासेजहरू पठाउनुहोस् र हेर्नुहोस्"</string>
<string name="permgrouplab_storage" msgid="17339216290379241">"फाइलहरू"</string>
<string name="permgroupdesc_storage" msgid="5378659041354582769">"आफ्नो डिभाइसमा रहेका फाइलहरू हेर्नुहोस् र प्रयोग गर्नुहोस्"</string>
<string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"सङ्गीत तथा अडियो"</string>
@@ -362,25 +362,25 @@
<string name="permlab_answerPhoneCalls" msgid="4131324833663725855">"फोन कलहरूको जवाफ दिनुहोस्"</string>
<string name="permdesc_answerPhoneCalls" msgid="894386681983116838">"एपलाई आगमन फोन कलको जवाफ दिन अनुमति दिन्छ।"</string>
<string name="permlab_receiveSms" msgid="505961632050451881">"टेक्स्ट म्यासेजहरू (SMS) प्राप्त गर्नुहोस्"</string>
- <string name="permdesc_receiveSms" msgid="1797345626687832285">"एपलाई SMS सन्देशहरू प्राप्त गर्न र प्रक्रिया गर्न अनुमति दिन्छ। यसको मतलब अनुप्रयोगले तपाईंको उपकरणमा पठाइएको सन्देशहरू तपाईंलाई नदेखाईनै मोनिटर गर्न वा मेटाउन सक्दछ।"</string>
+ <string name="permdesc_receiveSms" msgid="1797345626687832285">"एपलाई SMS म्यासेजहरू प्राप्त गर्न र प्रक्रिया गर्न अनुमति दिन्छ। यसको मतलब अनुप्रयोगले तपाईंको उपकरणमा पठाइएको म्यासेजहरू तपाईंलाई नदेखाईनै मोनिटर गर्न वा मेटाउन सक्दछ।"</string>
<string name="permlab_receiveMms" msgid="4000650116674380275">"टेक्स्ट म्यासेज (MMS) प्राप्त गर्नुहोस्"</string>
- <string name="permdesc_receiveMms" msgid="958102423732219710">"एपलाई MMS सन्देशहरू प्राप्त गर्न र प्रकृया गर्न अनुमति दिन्छ। यसको मतलब अनुप्रयोगले तपाईंको उपकरणमा पठाइएको सन्देशहरू तपाईंलाई नदेखाईनै मोनिटर गर्न वा मेटाउन सक्दछ।"</string>
- <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"मोबाइल प्रसारणसम्बन्धी सन्देशहरू फर्वार्ड गर्नुहोस्"</string>
- <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"मोबाइल प्रसारणसम्बन्धी सन्देशहरू प्राप्त हुनासाथै तिनीहरूलाई फर्वार्ड गर्नका लागि यसले एपलाई मोबाइल प्रसारण मोड्युलमा जोडिने अनुमति दिन्छ। तपाईंलाई कतिपय स्थानमा आपत्‌कालीन अवस्थाका बारेमा जानकारी दिनका लागि मोबाइल प्रसारणसम्बन्धी अलर्टहरू पठाइन्छ। हानिकारक एपहरूले आपत्‌कालीन मोबाइल प्रसारण प्राप्त हुँदा तपाईंको यन्त्रलाई कार्य सम्पादन गर्ने वा सञ्चालित हुने क्रममा हस्तक्षेप गर्न सक्छन्।"</string>
+ <string name="permdesc_receiveMms" msgid="958102423732219710">"एपलाई MMS म्यासेजहरू प्राप्त गर्न र प्रकृया गर्न अनुमति दिन्छ। यसको मतलब अनुप्रयोगले तपाईंको उपकरणमा पठाइएको म्यासेजहरू तपाईंलाई नदेखाईनै मोनिटर गर्न वा मेटाउन सक्दछ।"</string>
+ <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"मोबाइल प्रसारणसम्बन्धी म्यासेजहरू फर्वार्ड गर्नुहोस्"</string>
+ <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"मोबाइल प्रसारणसम्बन्धी म्यासेजहरू प्राप्त हुनासाथै तिनीहरूलाई फर्वार्ड गर्नका लागि यसले एपलाई मोबाइल प्रसारण मोड्युलमा जोडिने अनुमति दिन्छ। तपाईंलाई कतिपय स्थानमा आपत्‌कालीन अवस्थाका बारेमा जानकारी दिनका लागि मोबाइल प्रसारणसम्बन्धी अलर्टहरू पठाइन्छ। हानिकारक एपहरूले आपत्‌कालीन मोबाइल प्रसारण प्राप्त हुँदा तपाईंको यन्त्रलाई कार्य सम्पादन गर्ने वा सञ्चालित हुने क्रममा हस्तक्षेप गर्न सक्छन्।"</string>
<string name="permlab_manageOngoingCalls" msgid="281244770664231782">"जारी रहेका कलहरू व्यवस्थापन गर्न"</string>
<string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"तपाईं यो एपलाई अनुमति दिनुभयो यस एपले तपाईंको डिभाइसमा जारी रहेका कलसम्बन्धी विवरण हेर्न र ती कलहरू नियन्त्रण गर्न सक्छ।"</string>
- <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"सेल प्रसारित सन्देशहरू पढ्नुहोस्"</string>
- <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"तपाईंको उपकरणद्वारा प्राप्त सेल प्रसारण सन्देशहरू एपलाई पढ्न अनुमति दिन्छ। सेल प्रसारण चेतावनीहरू केही स्थानहरूमा तपाईंलाई आपत्‌कालीन गतिविधिहरूको बारेमा सचेत गराउन गरिएका छन्। खराब एपहरूले एउटा आपत्‌कालीन सेल प्रसारण प्राप्त गर्दछ जब तपाईंको उपकरणको प्रदर्शन वा अपरेशनको साथ हस्तक्षेप गर्न सक्दछन्।"</string>
+ <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"सेल प्रसारित म्यासेजहरू पढ्नुहोस्"</string>
+ <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"तपाईंको उपकरणद्वारा प्राप्त सेल प्रसारण म्यासेजहरू एपलाई पढ्न अनुमति दिन्छ। सेल प्रसारण चेतावनीहरू केही स्थानहरूमा तपाईंलाई आपत्‌कालीन गतिविधिहरूको बारेमा सचेत गराउन गरिएका छन्। खराब एपहरूले एउटा आपत्‌कालीन सेल प्रसारण प्राप्त गर्दछ जब तपाईंको उपकरणको प्रदर्शन वा अपरेशनको साथ हस्तक्षेप गर्न सक्दछन्।"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"सदस्य बनाइका फिडहरू पढ्नुहोस्"</string>
<string name="permdesc_subscribedFeedsRead" msgid="6911349196661811865">"एपलाई अहिलेको समीकरण गरिएका सूचकहरू बारे विवरणहरू लिने अनुमति दिन्छ।"</string>
- <string name="permlab_sendSms" msgid="7757368721742014252">"SMS सन्देशहरू पठाउनुहोस् र हेर्नुहोस्"</string>
- <string name="permdesc_sendSms" msgid="6757089798435130769">"एपलाई SMS सन्देशहरू पठाउन अनुमति दिन्छ। यसले अप्रत्यासित चार्जहरूको परिणाम दिन सक्दछ। खराब एपहरूले तपाईंको पुष्टि बिना सन्देशहरू पठाएर तपाईंको पैसा खर्च गराउन सक्दछ।"</string>
+ <string name="permlab_sendSms" msgid="7757368721742014252">"SMS म्यासेजहरू पठाउनुहोस् र हेर्नुहोस्"</string>
+ <string name="permdesc_sendSms" msgid="6757089798435130769">"एपलाई SMS म्यासेजहरू पठाउन अनुमति दिन्छ। यसले अप्रत्यासित चार्जहरूको परिणाम दिन सक्दछ। खराब एपहरूले तपाईंको पुष्टि बिना म्यासेजहरू पठाएर तपाईंको पैसा खर्च गराउन सक्दछ।"</string>
<string name="permlab_readSms" msgid="5164176626258800297">"तपाईंका टेक्स्ट म्यासेजहरू (SMS वा MMS) पढ्नुहोस्"</string>
- <string name="permdesc_readSms" product="tablet" msgid="7912990447198112829">"यस एपले तपाईंको ट्याब्लेटमा भण्डारण गरिएका सबै SMS (पाठ) सन्देशहरू पढ्न सक्छ।"</string>
- <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"यस एपले तपाईंको Android टिभी डिभाइसमा भण्डारण गरिएका सबै SMS.(पाठ) सन्देशहरू पढ्न सक्छ।"</string>
- <string name="permdesc_readSms" product="default" msgid="774753371111699782">"यस एपले तपाईंको फोनमा भण्डारण गरिएका सबै SMS (पाठ) सन्देशहरू पढ्न सक्छ।"</string>
+ <string name="permdesc_readSms" product="tablet" msgid="7912990447198112829">"यस एपले तपाईंको ट्याब्लेटमा भण्डारण गरिएका सबै SMS (पाठ) म्यासेजहरू पढ्न सक्छ।"</string>
+ <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"यस एपले तपाईंको Android टिभी डिभाइसमा भण्डारण गरिएका सबै SMS.(पाठ) म्यासेजहरू पढ्न सक्छ।"</string>
+ <string name="permdesc_readSms" product="default" msgid="774753371111699782">"यस एपले तपाईंको फोनमा भण्डारण गरिएका सबै SMS (पाठ) म्यासेजहरू पढ्न सक्छ।"</string>
<string name="permlab_receiveWapPush" msgid="4223747702856929056">"टेक्स्ट म्यासेजहरू (WAP) प्राप्त गर्नुहोस्"</string>
- <string name="permdesc_receiveWapPush" msgid="1638677888301778457">"WAP सन्देशहरू प्राप्त गर्न र प्रशोधन गर्न एपलाई अनुमति दिन्छ। यो अनुमतिमा मोनिटर गर्ने वा तपाईँलाई पठाइएका म्यासेजहरू तपाईँलाई नदेखाई मेट्ने क्षमता समावेश हुन्छ।"</string>
+ <string name="permdesc_receiveWapPush" msgid="1638677888301778457">"WAP म्यासेजहरू प्राप्त गर्न र प्रशोधन गर्न एपलाई अनुमति दिन्छ। यो अनुमतिमा मोनिटर गर्ने वा तपाईँलाई पठाइएका म्यासेजहरू तपाईँलाई नदेखाई मेट्ने क्षमता समावेश हुन्छ।"</string>
<string name="permlab_getTasks" msgid="7460048811831750262">"चलिरहेका एपहरू पुनःबहाली गर्नुहोस्"</string>
<string name="permdesc_getTasks" msgid="7388138607018233726">"वर्तमानमा र भरखरै चलिरहेका कार्यहरू बारेको सूचना पुनःबहाली गर्न एपलाई अनुमित दिन्छ। यसले उपकरणमा प्रयोग भएका अनुप्रयोगहरूको बारेमा सूचना पत्ता लगाउन एपलाई अनुमति दिन सक्छ।"</string>
<string name="permlab_manageProfileAndDeviceOwners" msgid="639849495253987493">"प्रोफाइल र यन्त्र मालिकहरूको व्यवस्थापन गराउनुहोस्"</string>
@@ -470,9 +470,9 @@
<string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"यस एपले तपाईंको Android टिभी डिभाइसमा भण्डारण गरिएका पात्रोसम्बन्धी सबै कार्यक्रमहरू पढ्न र तपाईंको पात्रोको डेटा आदान प्रदान वा सुरक्षित गर्न सक्छ।"</string>
<string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"यस एपले तपाईंको फोनमा भण्डारण गरिएका पात्रो सम्बन्धी सबै कार्यक्रमहरू पढ्न र तपाईंको पात्रोको डेटा आदान प्रदान वा सुरक्षित गर्न सक्छ।"</string>
<string name="permlab_writeCalendar" msgid="6422137308329578076">"पात्रो घटनाहरू थप्नुहोस् वा परिमार्जन गर्नुहोस् र मालिकको ज्ञान बिना नै पाहुनाहरूलाई इमेल पठाउनुहोस्"</string>
- <string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"यस एपले तपाईंको ट्याब्लेटमा पात्रोका कार्यक्रमहरू थप्न, हटाउन वा परिवर्तन गर्न सक्छ। यस एपले पात्रोका मालिकहरू मार्फत आएको जस्तो लाग्ने सन्देशहरू पठाउन वा तिनीहरूका मालिकहरूलाई सूचित नगरिकन कार्यक्रमहरू परिवर्तन गर्न सक्छ।"</string>
- <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"यस एपले तपाईंको Android टिभी डिभाइसमा पात्रोका कार्यक्रमहरू थप्न, हटाउन वा परिवर्तन गर्न सक्छ। यस एपले पात्रोका मालिकहरूले पठाएको जस्तै देखिने सन्देशहरू पठाउन वा कार्यक्रमका मालिकहरूलाई सूचित नगरिकन कार्यक्रमहरू परिवर्तन गर्न सक्छ।"</string>
- <string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"यस एपले तपाईंको फोनमा पात्रोका कार्यक्रमहरू थप्न, हटाउन वा परिवर्तन गर्न सक्छ। यस एपले पात्रोका मालिकहरू मार्फत आएको जस्तो लाग्ने सन्देशहरू पठाउन वा तिनीहरूका मालिकहरूलाई सूचित नगरिकन कार्यक्रमहरू परिवर्तन गर्न सक्छ।"</string>
+ <string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"यस एपले तपाईंको ट्याब्लेटमा पात्रोका कार्यक्रमहरू थप्न, हटाउन वा परिवर्तन गर्न सक्छ। यस एपले पात्रोका मालिकहरू मार्फत आएको जस्तो लाग्ने म्यासेजहरू पठाउन वा तिनीहरूका मालिकहरूलाई सूचित नगरिकन कार्यक्रमहरू परिवर्तन गर्न सक्छ।"</string>
+ <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"यस एपले तपाईंको Android टिभी डिभाइसमा पात्रोका कार्यक्रमहरू थप्न, हटाउन वा परिवर्तन गर्न सक्छ। यस एपले पात्रोका मालिकहरूले पठाएको जस्तै देखिने म्यासेजहरू पठाउन वा कार्यक्रमका मालिकहरूलाई सूचित नगरिकन कार्यक्रमहरू परिवर्तन गर्न सक्छ।"</string>
+ <string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"यस एपले तपाईंको फोनमा पात्रोका कार्यक्रमहरू थप्न, हटाउन वा परिवर्तन गर्न सक्छ। यस एपले पात्रोका मालिकहरू मार्फत आएको जस्तो लाग्ने म्यासेजहरू पठाउन वा तिनीहरूका मालिकहरूलाई सूचित नगरिकन कार्यक्रमहरू परिवर्तन गर्न सक्छ।"</string>
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"अधिक स्थान प्रदायक आदेशहरू पहुँच गर्नुहोस्"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"एपलाई अतिरिक्त स्थान प्रदायक आदेशहरू पहुँच गर्न अनुमति दिन्छ। यो एपलाई GPS वा अन्य स्थान स्रोतहरूको संचालन साथै हस्तक्षेप गर्न अनुमति दिन सक्छ।"</string>
<string name="permlab_accessFineLocation" msgid="6426318438195622966">"अग्रभूमिमा मात्र सटीक स्थानमाथि पहुँच राख्नुहोस्"</string>
@@ -1143,7 +1143,7 @@
<string name="selectAll" msgid="1532369154488982046">"सबैलाई चयन गर्नुहोस्"</string>
<string name="cut" msgid="2561199725874745819">"काट्नुहोस्"</string>
<string name="copy" msgid="5472512047143665218">"कपी गर्नुहोस्"</string>
- <string name="failed_to_copy_to_clipboard" msgid="725919885138539875">"क्लिपबोर्डमा प्रतिलिपि गर्न सकिएन"</string>
+ <string name="failed_to_copy_to_clipboard" msgid="725919885138539875">"क्लिपबोर्डमा कपी गर्न सकिएन"</string>
<string name="paste" msgid="461843306215520225">"टाँस्नुहोस्"</string>
<string name="paste_as_plain_text" msgid="7664800665823182587">"सामान्य पाठको रूपमा टाँस्नुहोस्"</string>
<string name="replace" msgid="7842675434546657444">"विस्थापन गर्नुहोस्…"</string>
@@ -1323,8 +1323,8 @@
<string name="accept" msgid="5447154347815825107">"स्वीकार्नुहोस्"</string>
<string name="decline" msgid="6490507610282145874">"अस्वीकार गर्नुहोस्"</string>
<string name="select_character" msgid="3352797107930786979">"अक्षरहरू प्रवेश गराउनुहोस्"</string>
- <string name="sms_control_title" msgid="4748684259903148341">"SMS सन्देशहरू पठाइँदै"</string>
- <string name="sms_control_message" msgid="6574313876316388239">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ले धरै संख्यामा SMS सन्देशहरू पठाउँदैछ। के तपाईं यस एपलाई सन्देशहरू पठाउन सुचारु गर्न अनुमति दिन चाहनु हुन्छ?"</string>
+ <string name="sms_control_title" msgid="4748684259903148341">"SMS म्यासेजहरू पठाइँदै"</string>
+ <string name="sms_control_message" msgid="6574313876316388239">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ले धरै संख्यामा SMS म्यासेजहरू पठाउँदैछ। के तपाईं यस एपलाई म्यासेजहरू पठाउन सुचारु गर्न अनुमति दिन चाहनु हुन्छ?"</string>
<string name="sms_control_yes" msgid="4858845109269524622">"अनुमति दिनुहोस्"</string>
<string name="sms_control_no" msgid="4845717880040355570">"अस्वीकार गर्नुहोस्"</string>
<string name="sms_short_code_confirm_message" msgid="1385416688897538724">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; के तपाईं सन्देश पठाउन चाहुनु हुन्छ &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
@@ -1513,7 +1513,7 @@
<string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ड्राइभिङ अनुप्रयोगबाट बाहिर निस्कन ट्याप गर्नुहोस्।"</string>
<string name="back_button_label" msgid="4078224038025043387">"पछाडि"</string>
<string name="next_button_label" msgid="6040209156399907780">"अर्को"</string>
- <string name="skip_button_label" msgid="3566599811326688389">"छोड्नुहोस्"</string>
+ <string name="skip_button_label" msgid="3566599811326688389">"स्किप गर्नुहोस्"</string>
<string name="no_matches" msgid="6472699895759164599">"कुनै मिलेन"</string>
<string name="find_on_page" msgid="5400537367077438198">"पृष्ठमा फेला पार्नुहोस्"</string>
<string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# वटा मिल्दोजुल्दो परिणाम}other{{total} मध्ये # वटा मिल्दाजुल्दा परिणाम}}"</string>
@@ -1650,8 +1650,8 @@
<string name="kg_sim_pin_instructions" msgid="6479401489471690359">"SIM PIN हाल्नुहोस्"</string>
<string name="kg_pin_instructions" msgid="7355933174673539021">"PIN हाल्नुहोस्"</string>
<string name="kg_password_instructions" msgid="7179782578809398050">"पासवर्ड प्रविष्टि गर्नुहोस्"</string>
- <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM कार्ड अहिले असक्षम छ। सुचारु गर्नको लागि PUK कोड प्रविष्टि गर्नुहोस्। विवरणको लागि वाहकलाई सम्पर्क गर्नुहोस्।"</string>
- <string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"इच्छित PIN कोड प्रविष्टि गर्नुहोस्"</string>
+ <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM कार्ड अहिले असक्षम छ। सुचारु गर्नको लागि PUK कोड हाल्नुहोस्। विवरणको लागि वाहकलाई सम्पर्क गर्नुहोस्।"</string>
+ <string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"इच्छित PIN कोड हाल्नुहोस्"</string>
<string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"मनपर्दो PIN कोड निश्चित गर्नुहोस्"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="5743634657721110967">"SIM कार्ड अनलक गरिँदै छ…"</string>
<string name="kg_password_wrong_pin_code" msgid="9013856346870572451">"गलत PIN कोड।"</string>
@@ -1715,7 +1715,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"रङ सच्याउने सुविधा"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"एक हाते मोड"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"अझै मधुरो"</string>
- <string name="hearing_aids_feature_name" msgid="1125892105105852542">"हियरिङ डिभाइसहरू"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"श्रवण यन्त्रहरू"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अन भयो।"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अफ भयो।"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"भोल्युम बटनहरू थिच्न छाड्नुहोस्। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अन गर्न दुवै भोल्युम बटन फेरि ३ सेकेन्डसम्म थिचिराख्नुहोस्।"</string>
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"बाहिर निस्कन, माथिबाट तल स्वाइप गर्नुहोस्।"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"बुझेँ"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"अझ राम्रो दृश्य हेर्न चाहनुहुन्छ भने रोटेट गर्नुहोस्"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"अझ राम्रो दृश्य हेर्न चाहनुहुन्छ भने \"स्प्लिट स्क्रिन\" बाट बाहिरिनुहोस्"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"अझ राम्रो दृश्य हेर्न चाहनुहुन्छ भने <xliff:g id="NAME">%s</xliff:g> खोल्नुहोस्"</string>
<string name="done_label" msgid="7283767013231718521">"भयो"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"घन्टा गोलाकार स्लाइडर"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"मिनेट गोलाकार स्लाइडर"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index f2b03086ea94..bc42afa72efa 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Swipe omlaag vanaf de bovenkant van het scherm om af te sluiten."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Ik snap het"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Draai voor een betere weergave"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Sluit het gesplitste scherm voor een betere weergave"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Open <xliff:g id="NAME">%s</xliff:g> op volledig scherm voor een betere weergave"</string>
<string name="done_label" msgid="7283767013231718521">"Klaar"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Ronde schuifregelaar voor uren"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Ronde schuifregelaar voor minuten"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 5d1de82e71f5..92f7c5b103c4 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -1607,7 +1607,7 @@
<string name="fingerprints" msgid="148690767172613723">"ଆଙ୍ଗୁଠି ଚିହ୍ନ:"</string>
<string name="sha256_fingerprint" msgid="7103976380961964600">"SHA-256 ଆଙ୍ଗୁଠି ଚିହ୍ନ:"</string>
<string name="sha1_fingerprint" msgid="2339915142825390774">"SHA-1 ଟିପଚିହ୍ନ:"</string>
- <string name="activity_chooser_view_see_all" msgid="3917045206812726099">"ସମସ୍ତ ଦେଖନ୍ତୁ"</string>
+ <string name="activity_chooser_view_see_all" msgid="3917045206812726099">"ସବୁ ଦେଖନ୍ତୁ"</string>
<string name="activity_chooser_view_dialog_title_default" msgid="8880731437191978314">"ଗତିବିଧି ଚୟନ କରନ୍ତୁ"</string>
<string name="share_action_provider_share_with" msgid="1904096863622941880">"ଏହାଙ୍କ ସହ ସେୟାର୍‍ କରନ୍ତୁ"</string>
<string name="sending" msgid="206925243621664438">"ପଠାଯାଉଛି…"</string>
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"ବାହାରିବା ପାଇଁ, ଉପରୁ ତଳକୁ ସ୍ୱାଇପ୍‍ କରନ୍ତୁ।"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"ବୁଝିଗଲି"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"ଏକ ଭଲ ଭ୍ୟୁ ପାଇଁ ରୋଟେଟ କରନ୍ତୁ"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ଏକ ଭଲ ଭ୍ୟୁ ପାଇଁ ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନରୁ ବାହାରି ଯାଆନ୍ତୁ"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"ଏକ ଭଲ ଭ୍ୟୁ ପାଇଁ ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନରେ <xliff:g id="NAME">%s</xliff:g> ଖୋଲନ୍ତୁ"</string>
<string name="done_label" msgid="7283767013231718521">"ହୋଇଗଲା"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"ଘଣ୍ଟା ସର୍କୁଲାର୍‍ ସ୍ଲାଇଡର୍‍"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"ମିନିଟ୍ସ ସର୍କୁଲାର୍‍ ସ୍ଲାଇଡର୍‍"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 25f7f7cf6976..8d330ad6024a 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -191,7 +191,7 @@
<string name="network_logging_notification_title" msgid="554983187553845004">"ਡੀਵਾਈਸ ਪ੍ਰਬੰਧਨ ਅਧੀਨ ਹੈ"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"ਤੁਹਾਡਾ ਸੰਗਠਨ ਇਸ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਦਾ ਹੈ ਅਤੇ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦਾ ਹੈ। ਵੇਰਵਿਆਂ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="location_changed_notification_title" msgid="3620158742816699316">"ਐਪਾਂ ਤੁਹਾਡੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀਆਂ ਹਨ"</string>
- <string name="location_changed_notification_text" msgid="7158423339982706912">"ਹੋਰ ਜਾਣਨ ਲਈ ਆਪਣੇ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ"</string>
+ <string name="location_changed_notification_text" msgid="7158423339982706912">"ਹੋਰ ਜਾਣਨ ਲਈ ਆਪਣੇ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ"</string>
<string name="geofencing_service" msgid="3826902410740315456">"ਭੂਗੋਲਿਕ-ਘੇਰੇ ਸੰਬੰਧੀ ਸੇਵਾ"</string>
<string name="country_detector" msgid="7023275114706088854">"ਦੇਸ਼ ਦਾ ਪਤਾ ਲਗਾਉਣ ਦੀ ਸੁਵਿਧਾ"</string>
<string name="location_service" msgid="2439187616018455546">"ਟਿਕਾਣਾ ਸੇਵਾ"</string>
@@ -635,7 +635,7 @@
<string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"ਬਹੁਤ ਜ਼ਿਆਦਾ ਚਮਕ"</string>
<string name="fingerprint_acquired_power_press" msgid="3107864151278434961">"ਪਾਵਰ ਬਟਨ ਦਬਾਏ ਜਾਣ ਦਾ ਪਤਾ ਲੱਗਿਆ ਹੈ"</string>
<string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"ਵਿਵਸਥਿਤ ਕਰਕੇ ਦੇਖੋ"</string>
- <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"ਹਰ ਵਾਰ ਆਪਣੀ ਉਂਗਲ ਨੂੰ ਥੋੜ੍ਹਾ ਹਿਲਾਓ"</string>
+ <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"ਹਰ ਵਾਰ ਆਪਣੀ ਉਂਗਲੀ ਦੀ ਸਥਿਤੀ ਨੂੰ ਥੋੜਾ ਜਿਹਾ ਬਦਲੋ"</string>
<string-array name="fingerprint_acquired_vendor">
</string-array>
<string name="fingerprint_error_not_match" msgid="4599441812893438961">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦੀ ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string>
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"ਬਾਹਰ ਜਾਣ ਲਈ, ਉਪਰੋਂ ਹੇਠਾਂ ਸਵਾਈਪ ਕਰੋ।"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"ਸਮਝ ਲਿਆ"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"ਬਿਹਤਰ ਦ੍ਰਿਸ਼ ਅਨੁਭਵ ਲਈ ਘੁਮਾਓ"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ਬਿਹਤਰ ਦ੍ਰਿਸ਼ ਅਨੁਭਵ ਲਈ ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਤੋਂ ਬਾਹਰ ਆਓ"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"ਬਿਹਤਰ ਦ੍ਰਿਸ਼ ਅਨੁਭਵ ਲਈ <xliff:g id="NAME">%s</xliff:g> ਨੂੰ ਪੂਰੀ-ਸਕ੍ਰੀਨ ਵਿੱਚ ਖੋਲ੍ਹੋ"</string>
<string name="done_label" msgid="7283767013231718521">"ਹੋ ਗਿਆ"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"ਘੰਟੇ ਸਰਕੁਲਰ ਸਲਾਈਡਰ"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"ਮਿੰਟ ਸਰਕੁਲਰ ਸਲਾਈਡਰ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 9871ccbccaa0..7a8684f4e8bc 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1852,7 +1852,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Aby wyjść, przesuń palcem z góry na dół."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Obróć, aby lepiej widzieć"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Zamknij podzielony ekran, aby lepiej widzieć"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Otwórz aplikację <xliff:g id="NAME">%s</xliff:g> na pełnym ekranie, aby lepiej widzieć"</string>
<string name="done_label" msgid="7283767013231718521">"Gotowe"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Kołowy suwak godzin"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Kołowy suwak minut"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 2ce7094055ed..fac87ffc3cf1 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -627,7 +627,7 @@
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar bloqueio de tela"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Insira seu bloqueio de tela para continuar"</string>
<string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Pressione o sensor com firmeza"</string>
- <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Não foi possível reconhecer a impressão digital. Tente de novo."</string>
+ <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Impressão digital não reconhecida. Tente de novo."</string>
<string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Limpe o sensor de impressão digital e tente novamente"</string>
<string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Limpe o sensor e tente novamente"</string>
<string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Pressione o sensor com firmeza"</string>
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Para sair, deslize de cima para baixo."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Entendi"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Gire a tela para ter uma visualização melhor"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Saia da tela dividida para ter uma visualização melhor"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Abra o app <xliff:g id="NAME">%s</xliff:g> em tela cheia para ter uma melhor visualização"</string>
<string name="done_label" msgid="7283767013231718521">"Concluído"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Controle deslizante circular das horas"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Controle deslizante circular dos minutos"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index ea30d7c3e322..7e9dfac34ad3 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -627,7 +627,7 @@
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar o bloqueio de ecrã"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Introduza o bloqueio de ecrã para continuar"</string>
<string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Prima firmemente o sensor"</string>
- <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Não é possível reconhecer a impressão digital. Tente novamente."</string>
+ <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Impossível reconhecer impressão digital. Volte a tentar."</string>
<string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Limpe o sensor de impressões digitais e tente novamente"</string>
<string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Limpe o sensor e tente novamente"</string>
<string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Prima firmemente o sensor"</string>
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Para sair, deslize rapidamente para baixo a partir da parte superior."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rode para uma melhor visualização"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Saia do ecrã dividido para uma melhor visualização"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Abra <xliff:g id="NAME">%s</xliff:g> em ecrã inteiro para uma melhor visualização"</string>
<string name="done_label" msgid="7283767013231718521">"Concluído"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Controlo de deslize circular das horas"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Controlo de deslize circular dos minutos"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 2ce7094055ed..fac87ffc3cf1 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -627,7 +627,7 @@
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar bloqueio de tela"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Insira seu bloqueio de tela para continuar"</string>
<string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Pressione o sensor com firmeza"</string>
- <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Não foi possível reconhecer a impressão digital. Tente de novo."</string>
+ <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Impressão digital não reconhecida. Tente de novo."</string>
<string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Limpe o sensor de impressão digital e tente novamente"</string>
<string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Limpe o sensor e tente novamente"</string>
<string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Pressione o sensor com firmeza"</string>
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Para sair, deslize de cima para baixo."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Entendi"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Gire a tela para ter uma visualização melhor"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Saia da tela dividida para ter uma visualização melhor"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Abra o app <xliff:g id="NAME">%s</xliff:g> em tela cheia para ter uma melhor visualização"</string>
<string name="done_label" msgid="7283767013231718521">"Concluído"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Controle deslizante circular das horas"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Controle deslizante circular dos minutos"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index e103148cba3b..0354a0f8a71b 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Pentru a ieși, glisează de sus în jos."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Am înțeles"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotește pentru o previzualizare mai bună"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Ieși din ecranul împărțit pentru o previzualizare mai bună"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Deschide <xliff:g id="NAME">%s</xliff:g> pe ecran complet pentru o imagine mai bună"</string>
<string name="done_label" msgid="7283767013231718521">"Terminat"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Selector circular pentru ore"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Selector circular pentru minute"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index cbdd5cb6cc86..80ca2ce733c5 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -627,8 +627,8 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Ошибка аутентификации."</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Использовать блокировку экрана"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Чтобы продолжить, разблокируйте экран."</string>
- <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Плотно прижмите палец к сканеру."</string>
- <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Не удалось распознать отпечаток пальца. Повторите попытку."</string>
+ <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Плотно прижмите палец к сканеру"</string>
+ <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Не удалось распознать отпечаток. Повторите попытку."</string>
<string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Очистите сканер отпечатков пальцев и повторите попытку."</string>
<string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Очистите сканер и повторите попытку."</string>
<string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Плотно прижмите палец к сканеру."</string>
@@ -1852,7 +1852,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Чтобы выйти, проведите по экрану сверху вниз."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"ОК"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Поверните, чтобы лучше видеть."</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Выйдите из режима разделения экрана, чтобы лучше видеть."</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Откройте приложение \"<xliff:g id="NAME">%s</xliff:g>\" в полноэкранном режиме, чтобы лучше видеть."</string>
<string name="done_label" msgid="7283767013231718521">"Готово"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Выбор часов на циферблате"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Выбор минут на циферблате"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 7358a9acb3a2..0df5c652a35a 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"ඉවත් වීමට, ඉහළ සිට පහළට ස්වයිප් කරන්න"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"වැටහුණි"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"වඩා හොඳ දසුනක් සඳහා කරකවන්න"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"වඩා හොඳ දර්ශනයක් සඳහා බෙදුම් තිරයෙන් පිටවන්න"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"වඩා හොඳ දසුනක් සඳහා <xliff:g id="NAME">%s</xliff:g> පූර්ණ තිරයේ විවෘත කරන්න"</string>
<string name="done_label" msgid="7283767013231718521">"අවසන්"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"පැය කවාකාර සර්පනය"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"මිනිත්තු කවාකාර සර්පනය"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 68f0ed4aa429..f13ef2b2e120 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1852,7 +1852,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Ukončíte potiahnutím zhora nadol."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Dobre"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Otočte zariadenie pre lepšie zobrazenie"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Ukončite rozdelenú obrazovku pre lepšie zobrazenie"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Otvorte <xliff:g id="NAME">%s</xliff:g> na celej obrazovke pre lepšie zobrazenie"</string>
<string name="done_label" msgid="7283767013231718521">"Hotovo"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Kruhový posúvač hodín"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Kruhový posúvač minút"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 90fa4ae188aa..3d4f2db885d2 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1852,7 +1852,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Zaprete ga tako, da z vrha s prstom povlečete navzdol."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Razumem"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Zasukajte za boljši pregled."</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Zaprite razdeljeni zaslon za boljši pregled."</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Aplikacijo <xliff:g id="NAME">%s</xliff:g> odprite v celozaslonskem načinu za boljši pregled."</string>
<string name="done_label" msgid="7283767013231718521">"Dokončano"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Okrogli drsnik za ure"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Okrogli drsnik za minute"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 2ad8a50f412b..3d31b1f8f27e 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Për të dalë, rrëshqit nga lart poshtë."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"E kuptova"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rrotullo për një pamje më të mirë"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Dil nga ekrani i ndarë për një pamje më të mirë"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Hape <xliff:g id="NAME">%s</xliff:g> në ekran të plotë për pamje më të mirë"</string>
<string name="done_label" msgid="7283767013231718521">"U krye"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Rrëshqitësi rrethor i orëve"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Rrëshqitësi rrethor i minutave"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index ab47275db2b8..4af7e78df010 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -626,11 +626,11 @@
<string name="biometric_error_generic" msgid="6784371929985434439">"Грешка при потврди идентитета"</string>
<string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Користите закључавање екрана"</string>
<string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Употребите закључавање екрана да бисте наставили"</string>
- <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Јако притисните сензор"</string>
+ <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Чврсто притисните сензор"</string>
<string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Препознавање отиска прста није успело. Пробајте поново."</string>
<string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Обришите сензор за отисак прста и пробајте поново"</string>
<string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Обришите сензор и пробајте поново"</string>
- <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Јако притисните сензор"</string>
+ <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Чврсто притисните сензор"</string>
<string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Превише споро сте померили прст. Пробајте поново."</string>
<string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Пробајте са другим отиском прста"</string>
<string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Превише је светло"</string>
@@ -1851,7 +1851,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Да бисте изашли, превуците надоле одозго."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Важи"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Ротирајте ради бољег приказа"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Изађите из подељеног екрана ради бољег приказа"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Отворите апликацију <xliff:g id="NAME">%s</xliff:g> преко целог екрана да бисте боље видели"</string>
<string name="done_label" msgid="7283767013231718521">"Готово"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Кружни клизач за сате"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Кружни клизач за минуте"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 815c9a94193e..87e8a0470969 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Svep nedåt från skärmens överkant för att avsluta."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Rotera för att få en bättre vy"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Stäng delad skärm för att få en bättre vy"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Öppna <xliff:g id="NAME">%s</xliff:g> i fullskärmsläget för att få en bättre vy"</string>
<string name="done_label" msgid="7283767013231718521">"Klart"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Cirkelreglage för timmar"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Cirkelreglage för minuter"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index d2766803787a..caf09cbd81c6 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Ili kuondoka, telezesha kidole kutoka juu hadi chini."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Nimeelewa"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Zungusha ili upate mwonekano bora"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Funga skrini iliyogawanywa ili upate mwonekano bora"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Fungua <xliff:g id="NAME">%s</xliff:g> kwenye skrini nzima ili uone maudhui kwa urahisi"</string>
<string name="done_label" msgid="7283767013231718521">"Imekamilika"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Kitelezi cha mviringo wa saa"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Kitelezi cha mviringo wa dakika"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index c6a4530ba469..4c765ed52773 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"வெளியேற, மேலிருந்து கீழே ஸ்வைப் செய்யவும்"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"புரிந்தது"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"சிறந்த காட்சிக்கு சுழற்றுங்கள்"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"சிறந்த காட்சிக்கு திரைப் பிரிப்புப் பயன்முறையில் இருந்து வெளியேறுங்கள்"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"சிறந்த காட்சிக்கு, <xliff:g id="NAME">%s</xliff:g> ஆப்ஸை முழுத்திரைப் பயன்முறையில் திறக்கவும்"</string>
<string name="done_label" msgid="7283767013231718521">"முடிந்தது"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"மணிநேர வட்ட வடிவ ஸ்லைடர்"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"நிமிடங்களுக்கான வட்டவடிவ ஸ்லைடர்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 174429cb573e..5a470755431d 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1198,7 +1198,7 @@
<string name="whichSendApplicationLabel" msgid="7467813004769188515">"షేర్ చేయి"</string>
<string name="whichSendToApplication" msgid="77101541959464018">"దీన్ని ఉపయోగించి పంపండి"</string>
<string name="whichSendToApplicationNamed" msgid="3385686512014670003">"%1$sని ఉపయోగించి పంపండి"</string>
- <string name="whichSendToApplicationLabel" msgid="3543240188816513303">"పంపు"</string>
+ <string name="whichSendToApplicationLabel" msgid="3543240188816513303">"పంపండి"</string>
<string name="whichHomeApplication" msgid="8276350727038396616">"హోమ్ యాప్‌ను ఎంచుకోండి"</string>
<string name="whichHomeApplicationNamed" msgid="5855990024847433794">"%1$sని హోమ్‌గా ఉపయోగించండి"</string>
<string name="whichHomeApplicationLabel" msgid="8907334282202933959">"చిత్రాన్ని క్యాప్చర్ చేయి"</string>
@@ -1330,7 +1330,7 @@
<string name="sms_short_code_confirm_message" msgid="1385416688897538724">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ఒక మెసేజ్‌ను &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;కి పంపాలనుకుంటోంది."</string>
<string name="sms_short_code_details" msgid="2723725738333388351">"దీని వలన మీ మొబైల్ ఖాతాకు "<b>"ఛార్జీలు విధించబడవచ్చు"</b>"."</string>
<string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"దీని వలన మీ మొబైల్ ఖాతాకు ఛార్జీలు విధించబడవచ్చు."</b></string>
- <string name="sms_short_code_confirm_allow" msgid="920477594325526691">"పంపు"</string>
+ <string name="sms_short_code_confirm_allow" msgid="920477594325526691">"పంపండి"</string>
<string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"రద్దు చేయండి"</string>
<string name="sms_short_code_remember_choice" msgid="1374526438647744862">"నా ఎంపికను గుర్తుంచుకో"</string>
<string name="sms_short_code_remember_undo_instruction" msgid="2620984439143080410">"మీరు దీన్ని తర్వాత సెట్టింగ్‌లు &gt; అనువర్తనాలులో మార్చవచ్చు"</string>
@@ -1470,7 +1470,7 @@
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"విడ్జెట్‌ను జోడించడం సాధ్యపడలేదు."</string>
<string name="ime_action_go" msgid="5536744546326495436">"వెళ్లు"</string>
<string name="ime_action_search" msgid="4501435960587287668">"సెర్చ్"</string>
- <string name="ime_action_send" msgid="8456843745664334138">"పంపు"</string>
+ <string name="ime_action_send" msgid="8456843745664334138">"పంపండి"</string>
<string name="ime_action_next" msgid="4169702997635728543">"తర్వాత"</string>
<string name="ime_action_done" msgid="6299921014822891569">"పూర్తయింది"</string>
<string name="ime_action_previous" msgid="6548799326860401611">"మునుపటి"</string>
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"నిష్క్రమించడానికి, పై నుండి క్రిందికి స్వైప్ చేయండి."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"అర్థమైంది"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"మెరుగైన వీక్షణ కోసం తిప్పండి"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"మెరుగైన వీక్షణ కోసం స్ప్లిట్ స్క్రీన్ నుండి నిష్క్రమించండి"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"మెరుగైన వీక్షణ కోసం <xliff:g id="NAME">%s</xliff:g>‌ను ఫుల్ స్క్రీన్‌లో తెరవండి"</string>
<string name="done_label" msgid="7283767013231718521">"పూర్తయింది"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"గంటల వృత్తాకార స్లయిడర్"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"నిమిషాల వృత్తాకార స్లయిడర్"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index e5f76431d357..eb9b1f3a2538 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -656,7 +656,7 @@
<string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"ปิดใช้เซ็นเซอร์ชั่วคราวแล้ว"</string>
<string name="fingerprint_error_bad_calibration" msgid="4385512597740168120">"ใช้เซ็นเซอร์ลายนิ้วมือไม่ได้ โปรดติดต่อผู้ให้บริการซ่อม"</string>
<string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"กดปุ่มเปิด/ปิดแล้ว"</string>
- <string name="fingerprint_name_template" msgid="8941662088160289778">"นิ้ว <xliff:g id="FINGERID">%d</xliff:g>"</string>
+ <string name="fingerprint_name_template" msgid="8941662088160289778">"นิ้วมือ <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string name="fingerprint_app_setting_name" msgid="4253767877095495844">"ใช้ลายนิ้วมือ"</string>
<string name="fingerprint_or_screen_lock_app_setting_name" msgid="3501743523487644907">"ใช้ลายนิ้วมือหรือการล็อกหน้าจอ"</string>
<string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"ใช้ลายนิ้วมือของคุณเพื่อดำเนินการต่อ"</string>
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"หากต้องการออก ให้เลื่อนลงจากด้านบน"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"รับทราบ"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"หมุนเพื่อรับมุมมองที่ดียิ่งขึ้น"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"ออกจากโหมดแยกหน้าจอเพื่อรับมุมมองที่ดียิ่งขึ้น"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"เปิด <xliff:g id="NAME">%s</xliff:g> ในโหมดเต็มหน้าจอเพื่อรับมุมมองที่ดียิ่งขึ้น"</string>
<string name="done_label" msgid="7283767013231718521">"เสร็จสิ้น"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"ตัวเลื่อนหมุนระบุชั่วโมง"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"ตัวเลื่อนหมุนระบุนาที"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 1371de6143e9..549882b8480d 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Upang lumabas, mag-swipe mula sa itaas pababa."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Nakuha ko"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"I-rotate para sa mas magandang view"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Lumabas sa split screen para sa mas magandang view"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Buksan ang <xliff:g id="NAME">%s</xliff:g> sa full screen para sa mas magandang view"</string>
<string name="done_label" msgid="7283767013231718521">"Tapos na"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Pabilog na slider ng mga oras"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Pabilog na slider ng mga minuto"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index e73c55d9964e..f9f9c3a81931 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Çıkmak için yukarıdan aşağıya doğru hızlıca kaydırın."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Anladım"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Daha iyi bir görünüm elde etmek için ekranı döndürün"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Daha iyi bir görünüm elde etmek için bölünmüş ekrandan çıkın"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Daha iyi görünüm için <xliff:g id="NAME">%s</xliff:g> uygulamasını açın"</string>
<string name="done_label" msgid="7283767013231718521">"Bitti"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Saat kaydırma çemberi"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Dakika kaydırma çemberi"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index a8345eda3c5f..08d0bf28345e 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1852,7 +1852,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Щоб вийти, проведіть пальцем зверху вниз."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Оберніть для кращого огляду"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Для кращого огляду вийдіть із режиму розділення екрана"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Для кращого огляду відкрийте додаток <xliff:g id="NAME">%s</xliff:g> на весь екран"</string>
<string name="done_label" msgid="7283767013231718521">"Готово"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Вибір годин на циферблаті"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Вибір хвилин на циферблаті"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index a5658a8ce786..e692be7d9f7c 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"خارج ہونے کیلئے اوپر سے نیچے سوائپ کریں۔"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"سمجھ آ گئی"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"بہتر منظر کے لیے گھمائیں"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"بہتر منظر کے لیے اسپلٹ اسکرین سے باہر نکلیں"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"بہتر منظر کے لیے <xliff:g id="NAME">%s</xliff:g> کو فُل اسکرین میں کھولیں"</string>
<string name="done_label" msgid="7283767013231718521">"ہو گیا"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"گھنٹوں کا سرکلر سلائیڈر"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"منٹس سرکلر سلائیڈر"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 0e749faeb8aa..986bf9cc2426 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Chiqish uchun tepadan pastga torting."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Yaxshiroq koʻrish uchun kamerani buring"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Yaxshiroq koʻrish uchun ajratilgan ekran rejimidan chiqing"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Yaxshiroq koʻrish uchun butun ekranda <xliff:g id="NAME">%s</xliff:g> ilovasini oching"</string>
<string name="done_label" msgid="7283767013231718521">"Tayyor"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Doiradan soatni tanlang"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Doiradan daqiqani tanlang"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index ac4358ba717e..04ace241402e 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Để thoát, hãy vuốt từ trên cùng xuống dưới."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"OK"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Xoay để xem dễ hơn"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Thoát chế độ chia đôi màn hình để xem dễ hơn"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Mở <xliff:g id="NAME">%s</xliff:g> ở chế độ toàn màn hình để xem dễ hơn"</string>
<string name="done_label" msgid="7283767013231718521">"Xong"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Thanh trượt giờ hình tròn"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Thanh trượt phút hình tròn"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index e938fbfa1a66..273036200627 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"要退出,请从顶部向下滑动。"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"知道了"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"旋转可改善预览效果"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"退出分屏可改善预览效果"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"在全屏模式下打开“<xliff:g id="NAME">%s</xliff:g>”可改善预览效果"</string>
<string name="done_label" msgid="7283767013231718521">"完成"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"小时转盘"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"分钟转盘"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index b0f4c04d9603..305560032d00 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"由頂部向下滑動即可退出。"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"知道了"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"旋轉以改善預覽效果"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"退出分割螢幕,以改善預覽效果"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"以全螢幕模式開啟「<xliff:g id="NAME">%s</xliff:g>」,以改善預覽效果"</string>
<string name="done_label" msgid="7283767013231718521">"完成"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"小時環形滑桿"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"分鐘環形滑桿"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 14ced72ebf01..b3c40a948faa 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"如要退出,請從畫面頂端向下滑動。"</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"知道了"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"旋轉螢幕以瀏覽完整的檢視畫面"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"結束分割畫面以全螢幕瀏覽"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"如要享有更優質的預覽體驗,可透過全螢幕模式開啟「<xliff:g id="NAME">%s</xliff:g>」"</string>
<string name="done_label" msgid="7283767013231718521">"完成"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"小時數環狀滑桿"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"分鐘數環狀滑桿"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index e432c69d36de..270cc4bf1d61 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1850,7 +1850,7 @@
<string name="immersive_cling_description" msgid="7092737175345204832">"Ukuze uphume, swayiphela phansi kusuka phezulu."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Ngiyitholile"</string>
<string name="display_rotation_camera_compat_toast_after_rotation" msgid="7600891546249829854">"Zungezisa ukuze uthole ukubuka okungcono"</string>
- <string name="display_rotation_camera_compat_toast_in_split_screen" msgid="8393302456336805466">"Phuma ekuhlukaniseni isikrini ukuze ubuke kangcono"</string>
+ <string name="display_rotation_camera_compat_toast_in_multi_window" msgid="2473122980393502775">"Vula i-<xliff:g id="NAME">%s</xliff:g> kusikrini esigcwele ngokubuka okungcono"</string>
<string name="done_label" msgid="7283767013231718521">"Kwenziwe"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Amahora weslayidi esiyindingilizi"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Amaminithi weslayidi esiyindingilizi"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 00f8db0d9264..ee8c0f83304e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1817,16 +1817,6 @@
specified -->
<string name="default_wallpaper_component" translatable="false">@null</string>
- <!-- CMF colors to default wallpaper component map, the component with color matching the device
- color will be the cmf default wallpapers. The default wallpaper will be default wallpaper
- component if not specified.
-
- E.g. for SLV color, and com.android.example/com.android.example.SlVDefaultWallpaper
- <item>SLV,com.android.example/com.android.example.SlVDefaultWallpaper</item> -->
- <string-array name="cmf_default_wallpaper_component" translatable="false">
- <!-- Add packages here -->
- </string-array>
-
<!-- By default a product has no distinct default lock wallpaper -->
<item name="default_lock_wallpaper" type="drawable">@null</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a8518afd7d3d..dc4eafd2e00e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2116,7 +2116,6 @@
<java-symbol type="string" name="data_usage_rapid_body" />
<java-symbol type="string" name="data_usage_rapid_app_body" />
<java-symbol type="string" name="default_wallpaper_component" />
- <java-symbol type="array" name="cmf_default_wallpaper_component" />
<java-symbol type="string" name="device_storage_monitor_notification_channel" />
<java-symbol type="string" name="dlg_ok" />
<java-symbol type="string" name="dump_heap_notification" />
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
index b5f18c26dc97..6ffdee1c4b4f 100644
--- a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
+++ b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
@@ -45,7 +45,7 @@ public class ConfigurationBoundResourceCacheTest
@SmallTest
public void testGetEmpty() {
final Resources res = getActivity().getResources();
- assertNull(mCache.getInstance(-1, res, null).getValue());
+ assertNull(mCache.getInstance(-1, res, null));
}
@SmallTest
@@ -53,9 +53,9 @@ public class ConfigurationBoundResourceCacheTest
mCache.put(1, null, new DummyFloatConstantState(5f),
ThemedResourceCache.UNDEFINED_GENERATION);
final Resources res = getActivity().getResources();
- assertEquals(5f, mCache.getInstance(1, res, null).getValue());
- assertNotSame(5f, mCache.getInstance(1, res, null).getValue());
- assertEquals(false, mCache.getInstance(1, res, getActivity().getTheme()).hasValue());
+ assertEquals(5f, mCache.getInstance(1, res, null));
+ assertNotSame(5f, mCache.getInstance(1, res, null));
+ assertEquals(null, mCache.getInstance(1, res, getActivity().getTheme()));
}
@SmallTest
@@ -63,9 +63,9 @@ public class ConfigurationBoundResourceCacheTest
mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f),
ThemedResourceCache.UNDEFINED_GENERATION);
final Resources res = getActivity().getResources();
- assertEquals(false, mCache.getInstance(1, res, null).hasValue());
- assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()).getValue());
- assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()).getValue());
+ assertEquals(null, mCache.getInstance(1, res, null));
+ assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()));
+ assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()));
}
@SmallTest
@@ -75,10 +75,10 @@ public class ConfigurationBoundResourceCacheTest
mCache.put(1, null, new DummyFloatConstantState(10f),
ThemedResourceCache.UNDEFINED_GENERATION);
final Resources res = getActivity().getResources();
- assertEquals(10f, mCache.getInstance(1, res, null).getValue());
- assertNotSame(10f, mCache.getInstance(1, res, null).getValue());
- assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()).getValue());
- assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()).getValue());
+ assertEquals(10f, mCache.getInstance(1, res, null));
+ assertNotSame(10f, mCache.getInstance(1, res, null));
+ assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()));
+ assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()));
}
@SmallTest
@@ -98,9 +98,9 @@ public class ConfigurationBoundResourceCacheTest
Configuration.ORIENTATION_PORTRAIT
: Configuration.ORIENTATION_LANDSCAPE;
int changes = calcConfigChanges(res, newCnf);
- assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()).getValue());
+ assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()));
mCache.onConfigurationChange(changes);
- assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()).getValue());
+ assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()));
}
@SmallTest
@@ -123,9 +123,9 @@ public class ConfigurationBoundResourceCacheTest
: Configuration.ORIENTATION_LANDSCAPE;
int changes = calcConfigChanges(res, newCnf);
assertEquals(changingDim,
- mCache.getInstance(key, res, getActivity().getTheme()).getValue());
+ mCache.getInstance(key, res, getActivity().getTheme()));
mCache.onConfigurationChange(changes);
- assertNull(mCache.get(key, getActivity().getTheme()).getValue());
+ assertNull(mCache.get(key, getActivity().getTheme()));
}
@SmallTest
@@ -152,15 +152,15 @@ public class ConfigurationBoundResourceCacheTest
: Configuration.ORIENTATION_LANDSCAPE;
int changes = calcConfigChanges(res, newCnf);
assertEquals(staticDim, mCache.getInstance(R.dimen.resource_cache_test_generic, res,
- getActivity().getTheme()).getValue());
+ getActivity().getTheme()));
assertEquals(changingDim,
mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
- getActivity().getTheme()).getValue());
+ getActivity().getTheme()));
mCache.onConfigurationChange(changes);
assertEquals(staticDim, mCache.getInstance(R.dimen.resource_cache_test_generic, res,
- getActivity().getTheme()).getValue());
+ getActivity().getTheme()));
assertNull(mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
- getActivity().getTheme()).getValue());
+ getActivity().getTheme()));
}
@SmallTest
@@ -198,18 +198,18 @@ public class ConfigurationBoundResourceCacheTest
for (int i = 0; i < 2; i++) {
final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
assertEquals(staticDim,
- mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme).getValue());
+ mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme));
assertEquals(changingDim,
mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
- theme).getValue());
+ theme));
}
mCache.onConfigurationChange(changes);
for (int i = 0; i < 2; i++) {
final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
assertEquals(staticDim,
- mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme).getValue());
+ mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme));
assertNull(mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
- theme).getValue());
+ theme));
}
}
diff --git a/data/keyboards/Vendor_0957_Product_0001.kl b/data/keyboards/Vendor_0957_Product_0001.kl
index 54f8808e2285..5d7fd85fc178 100644
--- a/data/keyboards/Vendor_0957_Product_0001.kl
+++ b/data/keyboards/Vendor_0957_Product_0001.kl
@@ -45,6 +45,7 @@ key 11 0
# custom keys
key usage 0x000c01BB TV_INPUT
+key usage 0x000c0186 MACRO_1
key usage 0x000c0185 TV_TELETEXT
key usage 0x000c0061 CAPTIONS
@@ -77,4 +78,4 @@ key usage 0x000c009D CHANNEL_DOWN
key usage 0x000c0077 BUTTON_3 WAKE #YouTube
key usage 0x000c0078 BUTTON_4 WAKE #Netflix
key usage 0x000c0079 BUTTON_6 WAKE
-key usage 0x000c007A BUTTON_7 WAKE \ No newline at end of file
+key usage 0x000c007A BUTTON_7 WAKE
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 2307d6080f9f..b9d3756ac6d2 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -997,12 +997,63 @@ public final class Bitmap implements Parcelable {
canvas.concat(m);
canvas.drawBitmap(source, srcR, dstR, paint);
canvas.setBitmap(null);
+
+ // If the source has a gainmap, apply the same set of transformations to the gainmap
+ // and set it on the output
+ if (source.hasGainmap()) {
+ Bitmap newMapContents = transformGainmap(source, m, neww, newh, paint, srcR, dstR,
+ deviceR);
+ if (newMapContents != null) {
+ bitmap.setGainmap(new Gainmap(source.getGainmap(), newMapContents));
+ }
+ }
+
if (isHardware) {
return bitmap.copy(Config.HARDWARE, false);
}
return bitmap;
}
+ private static Bitmap transformGainmap(Bitmap source, Matrix m, int neww, int newh, Paint paint,
+ Rect srcR, RectF dstR, RectF deviceR) {
+ Canvas canvas;
+ Bitmap sourceGainmap = source.getGainmap().getGainmapContents();
+ // Gainmaps can be scaled relative to the base image (eg, 1/4th res)
+ // Preserve that relative scaling between the base & gainmap in the output
+ float scaleX = (sourceGainmap.getWidth() / (float) source.getWidth());
+ float scaleY = (sourceGainmap.getHeight() / (float) source.getHeight());
+ int mapw = Math.round(neww * scaleX);
+ int maph = Math.round(newh * scaleY);
+
+ if (mapw == 0 || maph == 0) {
+ // The gainmap has been scaled away entirely, drop it
+ return null;
+ }
+
+ // Scale the computed `srcR` used for rendering the source bitmap to the destination
+ // to be in gainmap dimensions
+ Rect gSrcR = new Rect((int) (srcR.left * scaleX),
+ (int) (srcR.top * scaleY), (int) (srcR.right * scaleX),
+ (int) (srcR.bottom * scaleY));
+
+ // Note: createBitmap isn't used as that requires a non-null colorspace, however
+ // gainmaps don't have a colorspace. So use `nativeCreate` directly to bypass
+ // that colorspace enforcement requirement (#getColorSpace() allows a null return)
+ Bitmap newMapContents = nativeCreate(null, 0, mapw, mapw, maph,
+ sourceGainmap.getConfig().nativeInt, true, 0);
+ newMapContents.eraseColor(0);
+ canvas = new Canvas(newMapContents);
+ // Scale the translate & matrix to be in gainmap-relative dimensions
+ canvas.scale(scaleX, scaleY);
+ canvas.translate(-deviceR.left, -deviceR.top);
+ canvas.concat(m);
+ canvas.drawBitmap(sourceGainmap, gSrcR, dstR, paint);
+ canvas.setBitmap(null);
+ // Create a new gainmap using a copy of the metadata information from the source but
+ // with the transformed bitmap created above
+ return newMapContents;
+ }
+
/**
* Returns a mutable bitmap with the specified width and height. Its
* initial density is as per {@link #getDensity}. The newly created
diff --git a/graphics/java/android/graphics/Gainmap.java b/graphics/java/android/graphics/Gainmap.java
index 9ac84a6159da..f639521ff250 100644
--- a/graphics/java/android/graphics/Gainmap.java
+++ b/graphics/java/android/graphics/Gainmap.java
@@ -122,6 +122,16 @@ public final class Gainmap implements Parcelable {
}
/**
+ * Creates a new gainmap using the provided gainmap as the metadata source and the provided
+ * bitmap as the replacement for the gainmapContents
+ * TODO: Make public, it's useful
+ * @hide
+ */
+ public Gainmap(@NonNull Gainmap gainmap, @NonNull Bitmap gainmapContents) {
+ this(gainmapContents, nCreateCopy(gainmap.mNativePtr));
+ }
+
+ /**
* @return Returns the image data of the gainmap represented as a Bitmap. This is represented
* as a Bitmap for broad API compatibility, however certain aspects of the Bitmap are ignored
* such as {@link Bitmap#getColorSpace()} or {@link Bitmap#getGainmap()} as they are not
@@ -325,6 +335,7 @@ public final class Gainmap implements Parcelable {
private static native long nGetFinalizer();
private static native long nCreateEmpty();
+ private static native long nCreateCopy(long source);
private static native void nSetBitmap(long ptr, Bitmap bitmap);
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
index 7571e44a7713..d12989187281 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
@@ -24,6 +24,7 @@ import android.security.KeyStoreException;
import android.security.KeyStoreOperation;
import android.security.keymaster.KeymasterDefs;
import android.security.keystore.KeyStoreCryptoOperation;
+import android.system.keystore2.Authorization;
import libcore.util.EmptyArray;
@@ -119,6 +120,14 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
mCipher = null;
}
+ private Authorization[] getKeyCharacteristics(Key key) {
+ if (!(key instanceof AndroidKeyStoreKey)) {
+ return new Authorization[] {};
+ }
+
+ return ((AndroidKeyStoreKey) key).getAuthorizations();
+ }
+
@Override
protected final void engineInit(int opmode, Key key, SecureRandom random)
throws InvalidKeyException {
@@ -173,7 +182,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
init(opmode, key, random);
initAlgorithmSpecificParameters();
try {
- ensureKeystoreOperationInitialized();
+ ensureKeystoreOperationInitialized(getKeyCharacteristics(key));
} catch (InvalidAlgorithmParameterException e) {
throw new InvalidKeyException(e);
}
@@ -206,7 +215,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
try {
init(opmode, key, random);
initAlgorithmSpecificParameters(params);
- ensureKeystoreOperationInitialized();
+ ensureKeystoreOperationInitialized(getKeyCharacteristics(key));
success = true;
} finally {
if (!success) {
@@ -236,7 +245,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
try {
init(opmode, key, random);
initAlgorithmSpecificParameters(params);
- ensureKeystoreOperationInitialized();
+ ensureKeystoreOperationInitialized(getKeyCharacteristics(key));
success = true;
} finally {
if (!success) {
@@ -310,7 +319,8 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
mCachedException = null;
}
- private void ensureKeystoreOperationInitialized() throws InvalidKeyException,
+ private void ensureKeystoreOperationInitialized(Authorization[] keyCharacteristics)
+ throws InvalidKeyException,
InvalidAlgorithmParameterException {
if (mMainDataStreamer != null) {
return;
@@ -323,7 +333,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
}
List<KeyParameter> parameters = new ArrayList<>();
- addAlgorithmSpecificParametersToBegin(parameters);
+ addAlgorithmSpecificParametersToBegin(parameters, keyCharacteristics);
int purpose;
if (mKeymasterPurposeOverride != -1) {
@@ -404,7 +414,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
return null;
}
try {
- ensureKeystoreOperationInitialized();
+ ensureKeystoreOperationInitialized(getKeyCharacteristics(mKey));
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
mCachedException = e;
return null;
@@ -520,7 +530,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
}
try {
- ensureKeystoreOperationInitialized();
+ ensureKeystoreOperationInitialized(getKeyCharacteristics(mKey));
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
mCachedException = e;
return;
@@ -597,7 +607,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
}
try {
- ensureKeystoreOperationInitialized();
+ ensureKeystoreOperationInitialized(getKeyCharacteristics(mKey));
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e);
}
@@ -1012,6 +1022,22 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@NonNull List<KeyParameter> parameters);
/**
+ * Invoked to add algorithm-specific parameters for the KeyStore's {@code begin} operation,
+ * including the key characteristics. This is useful in case the parameters to {@code begin}
+ * depend on how the key was generated.
+ * The default implementation provided here simply ignores these key characteristics because
+ * they are not be needed for most engines.
+ *
+ * @param parameters keystore/keymaster arguments to be populated with algorithm-specific
+ * parameters.
+ * @param keyCharacteristics The key's characteristics.
+ */
+ protected void addAlgorithmSpecificParametersToBegin(
+ @NonNull List<KeyParameter> parameters, Authorization[] keyCharacteristics) {
+ addAlgorithmSpecificParametersToBegin(parameters);
+ }
+
+ /**
* Invoked to obtain algorithm-specific parameters from the result of the KeyStore's
* {@code begin} operation.
*
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
index e9b66aafc262..3bb2564807b6 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
@@ -288,16 +288,34 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
}
}
+ private static boolean isMgfDigestTagPresentInKeyProperties(
+ Authorization[] keyCharacteristics) {
+ for (Authorization authorization : keyCharacteristics) {
+ if (authorization.keyParameter.tag == KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
@Override
protected final void addAlgorithmSpecificParametersToBegin(
- @NonNull List<KeyParameter> parameters) {
- super.addAlgorithmSpecificParametersToBegin(parameters);
+ @NonNull List<KeyParameter> parameters, Authorization[] keyCharacteristics) {
+ super.addAlgorithmSpecificParametersToBegin(parameters, keyCharacteristics);
parameters.add(KeyStore2ParameterUtils.makeEnum(
KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest
));
- parameters.add(KeyStore2ParameterUtils.makeEnum(
- KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, mKeymasterMgf1Digest
- ));
+ // Only add the KM_TAG_RSA_OAEP_MGF_DIGEST tag to begin() if the MGF Digest is
+ // present in the key properties. Keys generated prior to Android 14 did not have
+ // this tag (Keystore didn't add it) so specifying any MGF digest tag would cause
+ // a begin() operation (on an Android 14 device) to fail (with a key that was generated
+ // on Android 13 or below).
+ if (isMgfDigestTagPresentInKeyProperties(keyCharacteristics)) {
+ parameters.add(KeyStore2ParameterUtils.makeEnum(
+ KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, mKeymasterMgf1Digest
+ ));
+ }
}
@Override
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
index 96190c4bc00a..f9aa1bd98e38 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
@@ -28,6 +28,7 @@ import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.Display;
import android.view.DisplayAddress;
+import android.view.Surface;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -36,6 +37,7 @@ import androidx.window.extensions.core.util.function.Consumer;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import java.util.Objects;
@@ -229,27 +231,41 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
* @since {@link WindowExtensions#VENDOR_API_LEVEL_3}
*/
@Override
+ @NonNull
public DisplayMetrics getRearDisplayMetrics() {
- DisplayMetrics metrics = null;
+ DisplayMetrics rearDisplayMetrics = null;
// DISPLAY_CATEGORY_REAR displays are only available when you are in the concurrent
// display state, so we have to look through all displays to match the address
- Display[] displays = mDisplayManager.getDisplays(
+ final Display[] displays = mDisplayManager.getDisplays(
DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
+ final Display defaultDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
+
for (int i = 0; i < displays.length; i++) {
DisplayAddress.Physical address =
(DisplayAddress.Physical) displays[i].getAddress();
if (mRearDisplayAddress == address.getPhysicalDisplayId()) {
- metrics = new DisplayMetrics();
- displays[i].getRealMetrics(metrics);
+ rearDisplayMetrics = new DisplayMetrics();
+ final Display rearDisplay = displays[i];
+
+ // We must always retrieve the metrics for the rear display regardless of if it is
+ // the default display or not.
+ rearDisplay.getRealMetrics(rearDisplayMetrics);
+
+ // TODO(b/287170025): This should be something like if (!rearDisplay.isEnabled)
+ // instead. Currently when the rear display is disabled, its state is STATE_OFF.
+ if (rearDisplay.getDisplayId() != Display.DEFAULT_DISPLAY) {
+ rotateRearDisplayMetricsIfNeeded(defaultDisplay.getRotation(),
+ rearDisplay.getRotation(), rearDisplayMetrics);
+ }
break;
}
}
synchronized (mLock) {
// Update the rear display metrics with our latest value if one was received
- if (metrics != null) {
- mRearDisplayMetrics = metrics;
+ if (rearDisplayMetrics != null) {
+ mRearDisplayMetrics = rearDisplayMetrics;
}
return Objects.requireNonNullElseGet(mRearDisplayMetrics, DisplayMetrics::new);
@@ -540,6 +556,34 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
return mLastReportedRearDisplayPresentationStatus;
}
+ @VisibleForTesting
+ static void rotateRearDisplayMetricsIfNeeded(
+ @Surface.Rotation int defaultDisplayRotation,
+ @Surface.Rotation int rearDisplayRotation,
+ @NonNull DisplayMetrics inOutMetrics) {
+ // If the rear display has a non-zero rotation, it means the backing DisplayContent /
+ // DisplayRotation is fresh.
+ if (rearDisplayRotation != Surface.ROTATION_0) {
+ return;
+ }
+
+ // If the default display is 0 or 180, the rear display must also be 0 or 180.
+ if (defaultDisplayRotation == Surface.ROTATION_0
+ || defaultDisplayRotation == Surface.ROTATION_180) {
+ return;
+ }
+
+ final int heightPixels = inOutMetrics.heightPixels;
+ final int widthPixels = inOutMetrics.widthPixels;
+ inOutMetrics.widthPixels = heightPixels;
+ inOutMetrics.heightPixels = widthPixels;
+
+ final int noncompatHeightPixels = inOutMetrics.noncompatHeightPixels;
+ final int noncompatWidthPixels = inOutMetrics.noncompatWidthPixels;
+ inOutMetrics.noncompatWidthPixels = noncompatHeightPixels;
+ inOutMetrics.noncompatHeightPixels = noncompatWidthPixels;
+ }
+
/**
* Callback for the {@link DeviceStateRequest} to be notified of when the request has been
* activated or cancelled. This callback provides information to the client library
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java
new file mode 100644
index 000000000000..ccb4ebe9199e
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.area;
+
+import static org.junit.Assert.assertEquals;
+
+import android.platform.test.annotations.Presubmit;
+import android.util.DisplayMetrics;
+import android.view.Surface;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WindowAreaComponentImplTests {
+
+ private final DisplayMetrics mTestDisplayMetrics = new DisplayMetrics();
+
+ @Before
+ public void setup() {
+ mTestDisplayMetrics.widthPixels = 1;
+ mTestDisplayMetrics.heightPixels = 2;
+ mTestDisplayMetrics.noncompatWidthPixels = 3;
+ mTestDisplayMetrics.noncompatHeightPixels = 4;
+ }
+
+ /**
+ * Cases where the rear display metrics does not need to be transformed.
+ */
+ @Test
+ public void testRotateRearDisplayMetrics_noTransformNeeded() {
+ final DisplayMetrics originalMetrics = new DisplayMetrics();
+ originalMetrics.setTo(mTestDisplayMetrics);
+
+ WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+ Surface.ROTATION_0, Surface.ROTATION_0, mTestDisplayMetrics);
+ assertEquals(originalMetrics, mTestDisplayMetrics);
+
+ WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+ Surface.ROTATION_180, Surface.ROTATION_180, mTestDisplayMetrics);
+ assertEquals(originalMetrics, mTestDisplayMetrics);
+
+ WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+ Surface.ROTATION_0, Surface.ROTATION_180, mTestDisplayMetrics);
+ assertEquals(originalMetrics, mTestDisplayMetrics);
+
+ WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+ Surface.ROTATION_180, Surface.ROTATION_0, mTestDisplayMetrics);
+ assertEquals(originalMetrics, mTestDisplayMetrics);
+ }
+
+ /**
+ * Cases where the rear display metrics need to be transformed.
+ */
+ @Test
+ public void testRotateRearDisplayMetrics_transformNeeded() {
+ DisplayMetrics originalMetrics = new DisplayMetrics();
+ originalMetrics.setTo(mTestDisplayMetrics);
+
+ DisplayMetrics expectedMetrics = new DisplayMetrics();
+ expectedMetrics.setTo(mTestDisplayMetrics);
+ expectedMetrics.widthPixels = mTestDisplayMetrics.heightPixels;
+ expectedMetrics.heightPixels = mTestDisplayMetrics.widthPixels;
+ expectedMetrics.noncompatWidthPixels = mTestDisplayMetrics.noncompatHeightPixels;
+ expectedMetrics.noncompatHeightPixels = mTestDisplayMetrics.noncompatWidthPixels;
+
+ WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+ Surface.ROTATION_90, Surface.ROTATION_0, mTestDisplayMetrics);
+ assertEquals(expectedMetrics, mTestDisplayMetrics);
+
+ mTestDisplayMetrics.setTo(originalMetrics);
+ WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+ Surface.ROTATION_270, Surface.ROTATION_0, mTestDisplayMetrics);
+ assertEquals(expectedMetrics, mTestDisplayMetrics);
+ }
+}
diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml
index 8635c56b7bc6..d902fd49ba60 100644
--- a/libs/WindowManager/Shell/res/values/styles.xml
+++ b/libs/WindowManager/Shell/res/values/styles.xml
@@ -93,62 +93,34 @@
<style name="RestartDialogTitleText">
<item name="android:textSize">24sp</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
- <item name="android:lineSpacingExtra">2sp</item>
- <item name="android:textAppearance">
- @*android:style/TextAppearance.DeviceDefault.Headline
- </item>
- <item name="android:fontFamily">
- @*android:string/config_bodyFontFamilyMedium
- </item>
+ <item name="android:lineSpacingExtra">8sp</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
</style>
- <style name="RestartDialogBodyText">
+ <style name="RestartDialogBodyStyle">
<item name="android:textSize">14sp</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+ </style>
+
+ <style name="RestartDialogBodyText" parent="RestartDialogBodyStyle">
<item name="android:letterSpacing">0.02</item>
<item name="android:textColor">?android:attr/textColorSecondary</item>
- <item name="android:lineSpacingExtra">2sp</item>
- <item name="android:textAppearance">
- @*android:style/TextAppearance.DeviceDefault.Body2
- </item>
- <item name="android:fontFamily">
- @*android:string/config_bodyFontFamily
- </item>
+ <item name="android:lineSpacingExtra">6sp</item>
</style>
- <style name="RestartDialogCheckboxText">
- <item name="android:textSize">16sp</item>
+ <style name="RestartDialogCheckboxText" parent="RestartDialogBodyStyle">
<item name="android:textColor">?android:attr/textColorPrimary</item>
- <item name="android:lineSpacingExtra">4sp</item>
- <item name="android:textAppearance">
- @*android:style/TextAppearance.DeviceDefault.Headline
- </item>
- <item name="android:fontFamily">
- @*android:string/config_bodyFontFamilyMedium
- </item>
+ <item name="android:lineSpacingExtra">6sp</item>
</style>
- <style name="RestartDialogDismissButton">
+ <style name="RestartDialogDismissButton" parent="RestartDialogBodyStyle">
<item name="android:lineSpacingExtra">2sp</item>
- <item name="android:textSize">14sp</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
- <item name="android:textAppearance">
- @*android:style/TextAppearance.DeviceDefault.Body2
- </item>
- <item name="android:fontFamily">
- @*android:string/config_bodyFontFamily
- </item>
</style>
- <style name="RestartDialogConfirmButton">
+ <style name="RestartDialogConfirmButton" parent="RestartDialogBodyStyle">
<item name="android:lineSpacingExtra">2sp</item>
- <item name="android:textSize">14sp</item>
<item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
- <item name="android:textAppearance">
- @*android:style/TextAppearance.DeviceDefault.Body2
- </item>
- <item name="android:fontFamily">
- @*android:string/config_bodyFontFamily
- </item>
</style>
<style name="ReachabilityEduHandLayout" parent="Theme.AppCompat.Light">
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 3eb9fa2eef6b..0fdfbb8c0c61 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -80,8 +80,7 @@ import android.view.ViewRootImpl;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.window.ScreenCapture;
-import android.window.ScreenCapture.ScreenCaptureListener;
-import android.window.ScreenCapture.ScreenshotSync;
+import android.window.ScreenCapture.SynchronousScreenCaptureListener;
import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
@@ -1222,10 +1221,11 @@ public class BubbleController implements ConfigurationChangeListener,
/**
* Performs a screenshot that may exclude the bubble layer, if one is present. The screenshot
- * can be access via the supplied {@link ScreenshotSync#get()} asynchronously.
+ * can be access via the supplied {@link SynchronousScreenCaptureListener#getBuffer()}
+ * asynchronously.
*/
public void getScreenshotExcludingBubble(int displayId,
- Pair<ScreenCaptureListener, ScreenshotSync> screenCaptureListener) {
+ SynchronousScreenCaptureListener screenCaptureListener) {
try {
ScreenCapture.CaptureArgs args = null;
if (mStackView != null) {
@@ -1240,7 +1240,7 @@ public class BubbleController implements ConfigurationChangeListener,
}
}
- mWmService.captureDisplay(displayId, args, screenCaptureListener.first);
+ mWmService.captureDisplay(displayId, args, screenCaptureListener);
} catch (RemoteException e) {
Log.e(TAG, "Failed to capture screenshot");
}
@@ -2211,15 +2211,15 @@ public class BubbleController implements ConfigurationChangeListener,
@Override
@Nullable
- public ScreenshotSync getScreenshotExcludingBubble(int displayId) {
- Pair<ScreenCaptureListener, ScreenshotSync> screenCaptureListener =
+ public SynchronousScreenCaptureListener getScreenshotExcludingBubble(int displayId) {
+ SynchronousScreenCaptureListener screenCaptureListener =
ScreenCapture.createSyncCaptureListener();
mMainExecutor.execute(
() -> BubbleController.this.getScreenshotExcludingBubble(displayId,
screenCaptureListener));
- return screenCaptureListener.second;
+ return screenCaptureListener;
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
index 259f69296ac7..4d329dd5d446 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
@@ -16,8 +16,6 @@
package com.android.wm.shell.bubbles;
-import static android.window.ScreenCapture.ScreenshotSync;
-
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.PARAMETER;
@@ -34,6 +32,7 @@ import android.service.notification.NotificationListenerService.RankingMap;
import android.util.Pair;
import android.util.SparseArray;
import android.window.ScreenCapture.ScreenshotHardwareBuffer;
+import android.window.ScreenCapture.SynchronousScreenCaptureListener;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
@@ -150,13 +149,14 @@ public interface Bubbles {
boolean isAppBubbleTaskId(int taskId);
/**
- * @return a {@link ScreenshotSync} after performing a screenshot that may exclude the bubble
- * layer, if one is present. The underlying {@link ScreenshotHardwareBuffer} can be access via
- * {@link ScreenshotSync#get()} asynchronously and care should be taken to
- * {@link HardwareBuffer#close()} the associated
- * {@link ScreenshotHardwareBuffer#getHardwareBuffer()} when no longer required.
+` * @return a {@link SynchronousScreenCaptureListener} after performing a screenshot that may
+ * exclude the bubble layer, if one is present. The underlying
+ * {@link ScreenshotHardwareBuffer} can be accessed via
+ * {@link SynchronousScreenCaptureListener#getBuffer()} asynchronously and care should be taken
+ * to {@link HardwareBuffer#close()} the associated
+ * {@link ScreenshotHardwareBuffer#getHardwareBuffer()} when no longer required.`
*/
- ScreenshotSync getScreenshotExcludingBubble(int displayId);
+ SynchronousScreenCaptureListener getScreenshotExcludingBubble(int displayId);
/**
* @return a bubble that matches the provided shortcutId, if one exists.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java
index ae1f43320c8b..72702e7c2b88 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayChangeController.java
@@ -79,7 +79,7 @@ public class DisplayChangeController {
}
/** Query all listeners for changes that should happen on display change. */
- public void dispatchOnDisplayChange(WindowContainerTransaction outWct, int displayId,
+ void dispatchOnDisplayChange(WindowContainerTransaction outWct, int displayId,
int fromRotation, int toRotation, DisplayAreaInfo newDisplayAreaInfo) {
for (OnDisplayChangingListener c : mDisplayChangeListener) {
c.onDisplayChange(displayId, fromRotation, toRotation, newDisplayAreaInfo, outWct);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
index f07ea751b044..8353900be0ef 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
@@ -29,6 +29,7 @@ import android.view.Display;
import android.view.IDisplayWindowListener;
import android.view.IWindowManager;
import android.view.InsetsState;
+import android.window.WindowContainerTransaction;
import androidx.annotation.BinderThread;
@@ -85,11 +86,6 @@ public class DisplayController {
}
}
- /** Get the DisplayChangeController. */
- public DisplayChangeController getChangeController() {
- return mChangeController;
- }
-
/**
* Gets a display by id from DisplayManager.
*/
@@ -195,6 +191,26 @@ public class DisplayController {
}
}
+
+ /** Called when a display rotate requested. */
+ public void onDisplayRotateRequested(WindowContainerTransaction wct, int displayId,
+ int fromRotation, int toRotation) {
+ synchronized (mDisplays) {
+ final DisplayRecord dr = mDisplays.get(displayId);
+ if (dr == null) {
+ Slog.w(TAG, "Skipping Display rotate on non-added display.");
+ return;
+ }
+
+ if (dr.mDisplayLayout != null) {
+ dr.mDisplayLayout.rotateTo(dr.mContext.getResources(), toRotation);
+ }
+
+ mChangeController.dispatchOnDisplayChange(
+ wct, displayId, fromRotation, toRotation, null /* newDisplayAreaInfo */);
+ }
+ }
+
private void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
synchronized (mDisplays) {
final DisplayRecord dr = mDisplays.get(displayId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
index d6e1a82a68ff..1959eb03a6b3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
@@ -300,9 +300,12 @@ public class DisplayLayout {
return mAllowSeamlessRotationDespiteNavBarMoving;
}
- /** @return whether the navigation bar will change sides during rotation. */
+ /**
+ * Returns {@code true} if the navigation bar will change sides during rotation and the display
+ * is not square.
+ */
public boolean navigationBarCanMove() {
- return mNavigationBarCanMove;
+ return mNavigationBarCanMove && mWidth != mHeight;
}
/** @return the rotation that would make the physical display "upside down". */
@@ -375,16 +378,15 @@ public class DisplayLayout {
insetsState.getDisplayFrame(),
WindowInsets.Type.navigationBars(),
false /* ignoreVisibility */);
- outInsets.set(insets.left, insets.top, insets.right, insets.bottom);
int position = navigationBarPosition(res, displayWidth, displayHeight, displayRotation);
int navBarSize =
getNavigationBarSize(res, position, displayWidth > displayHeight, uiMode);
if (position == NAV_BAR_BOTTOM) {
- outInsets.bottom = Math.max(outInsets.bottom , navBarSize);
+ outInsets.bottom = Math.max(insets.bottom , navBarSize);
} else if (position == NAV_BAR_RIGHT) {
- outInsets.right = Math.max(outInsets.right , navBarSize);
+ outInsets.right = Math.max(insets.right , navBarSize);
} else if (position == NAV_BAR_LEFT) {
- outInsets.left = Math.max(outInsets.left , navBarSize);
+ outInsets.left = Math.max(insets.left , navBarSize);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index ab8e7e63ef7f..f70d3aec9ec8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -63,8 +63,10 @@ import com.android.internal.policy.DockedDividerUtils;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.animation.Interpolators;
+import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.InteractionJankMonitorUtils;
import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
@@ -104,6 +106,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
private final Rect mWinBounds2 = new Rect();
private final SplitLayoutHandler mSplitLayoutHandler;
private final SplitWindowManager mSplitWindowManager;
+ private final DisplayController mDisplayController;
private final DisplayImeController mDisplayImeController;
private final ImePositionProcessor mImePositionProcessor;
private final ResizingEffectPolicy mSurfaceEffectPolicy;
@@ -128,13 +131,14 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
public SplitLayout(String windowName, Context context, Configuration configuration,
SplitLayoutHandler splitLayoutHandler,
SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks,
- DisplayImeController displayImeController, ShellTaskOrganizer taskOrganizer,
- int parallaxType) {
+ DisplayController displayController, DisplayImeController displayImeController,
+ ShellTaskOrganizer taskOrganizer, int parallaxType) {
mContext = context.createConfigurationContext(configuration);
mOrientation = configuration.orientation;
mRotation = configuration.windowConfiguration.getRotation();
mDensity = configuration.densityDpi;
mSplitLayoutHandler = splitLayoutHandler;
+ mDisplayController = displayController;
mDisplayImeController = displayImeController;
mSplitWindowManager = new SplitWindowManager(windowName, mContext, configuration,
parentContainerCallbacks);
@@ -145,7 +149,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
updateDividerConfig(mContext);
mRootBounds.set(configuration.windowConfiguration.getBounds());
- mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
+ mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds);
resetDividerPosition();
mDimNonImeSide = mContext.getResources().getBoolean(R.bool.config_dimNonImeAttachedSide);
@@ -314,7 +318,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
mRotation = rotation;
mDensity = density;
mUiMode = uiMode;
- mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
+ mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds);
updateDividerConfig(mContext);
initDividerPosition(mTempRect);
updateInvisibleRect();
@@ -324,7 +328,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
/** Rotate the layout to specific rotation and calculate new bounds. The stable insets value
* should be calculated by display layout. */
- public void rotateTo(int newRotation, Rect stableInsets) {
+ public void rotateTo(int newRotation) {
final int rotationDelta = (newRotation - mRotation + 4) % 4;
final boolean changeOrient = (rotationDelta % 2) != 0;
@@ -337,7 +341,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
// We only need new bounds here, other configuration should be update later.
mTempRect.set(mRootBounds);
mRootBounds.set(tmpRect);
- mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, stableInsets);
+ mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds);
initDividerPosition(mTempRect);
}
@@ -548,10 +552,9 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
return mDividerSnapAlgorithm.calculateSnapTarget(position, velocity, hardDismiss);
}
- private DividerSnapAlgorithm getSnapAlgorithm(Context context, Rect rootBounds,
- @Nullable Rect stableInsets) {
+ private DividerSnapAlgorithm getSnapAlgorithm(Context context, Rect rootBounds) {
final boolean isLandscape = isLandscape(rootBounds);
- final Rect insets = stableInsets != null ? stableInsets : getDisplayInsets(context);
+ final Rect insets = getDisplayStableInsets(context);
// Make split axis insets value same as the larger one to avoid bounds1 and bounds2
// have difference for avoiding size-compat mode when switching unresizable apps in
@@ -634,7 +637,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
public void splitSwitching(SurfaceControl.Transaction t, SurfaceControl leash1,
SurfaceControl leash2, Consumer<Rect> finishCallback) {
final boolean isLandscape = isLandscape();
- final Rect insets = getDisplayInsets(mContext);
+ final Rect insets = getDisplayStableInsets(mContext);
insets.set(isLandscape ? insets.left : 0, isLandscape ? 0 : insets.top,
isLandscape ? insets.right : 0, isLandscape ? 0 : insets.bottom);
@@ -705,13 +708,17 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
return animator;
}
- private static Rect getDisplayInsets(Context context) {
- return context.getSystemService(WindowManager.class)
- .getMaximumWindowMetrics()
- .getWindowInsets()
- .getInsetsIgnoringVisibility(WindowInsets.Type.systemBars()
- | WindowInsets.Type.displayCutout())
- .toRect();
+ private Rect getDisplayStableInsets(Context context) {
+ final DisplayLayout displayLayout =
+ mDisplayController.getDisplayLayout(context.getDisplayId());
+ return displayLayout != null
+ ? displayLayout.stableInsets()
+ : context.getSystemService(WindowManager.class)
+ .getMaximumWindowMetrics()
+ .getWindowInsets()
+ .getInsetsIgnoringVisibility(WindowInsets.Type.systemBars()
+ | WindowInsets.Type.displayCutout())
+ .toRect();
}
private static boolean isLandscape(Rect bounds) {
@@ -784,7 +791,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
private int getSmallestWidthDp(Rect bounds) {
mTempRect.set(bounds);
- mTempRect.inset(getDisplayInsets(mContext));
+ mTempRect.inset(getDisplayStableInsets(mContext));
final int minWidth = Math.min(mTempRect.width(), mTempRect.height());
final float density = mContext.getResources().getDisplayMetrics().density;
return (int) (minWidth / density);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 4980e49a6fc3..acbdbf9d6769 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -61,7 +61,6 @@ import com.android.wm.shell.freeform.FreeformTaskListener;
import com.android.wm.shell.freeform.FreeformTaskTransitionHandler;
import com.android.wm.shell.freeform.FreeformTaskTransitionObserver;
import com.android.wm.shell.keyguard.KeyguardTransitionHandler;
-import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipAnimationController;
@@ -536,9 +535,11 @@ public abstract class WMShellModule {
Optional<PipTouchHandler> pipTouchHandlerOptional,
Optional<RecentsTransitionHandler> recentsTransitionHandler,
KeyguardTransitionHandler keyguardTransitionHandler,
+ Optional<UnfoldTransitionHandler> unfoldHandler,
Transitions transitions) {
return new DefaultMixedHandler(shellInit, transitions, splitScreenOptional,
- pipTouchHandlerOptional, recentsTransitionHandler, keyguardTransitionHandler);
+ pipTouchHandlerOptional, recentsTransitionHandler, keyguardTransitionHandler,
+ unfoldHandler);
}
@WMSingleton
@@ -709,42 +710,4 @@ public abstract class WMShellModule {
static DesktopModeTaskRepository provideDesktopModeTaskRepository() {
return new DesktopModeTaskRepository();
}
-
- //
- // Kids mode
- //
- @WMSingleton
- @Provides
- static KidsModeTaskOrganizer provideKidsModeTaskOrganizer(
- Context context,
- ShellInit shellInit,
- ShellCommandHandler shellCommandHandler,
- SyncTransactionQueue syncTransactionQueue,
- DisplayController displayController,
- DisplayInsetsController displayInsetsController,
- Optional<UnfoldAnimationController> unfoldAnimationController,
- Optional<RecentTasksController> recentTasksOptional,
- @ShellMainThread ShellExecutor mainExecutor,
- @ShellMainThread Handler mainHandler
- ) {
- return new KidsModeTaskOrganizer(context, shellInit, shellCommandHandler,
- syncTransactionQueue, displayController, displayInsetsController,
- unfoldAnimationController, recentTasksOptional, mainExecutor, mainHandler);
- }
-
- //
- // Misc
- //
-
- // TODO: Temporarily move dependencies to this instead of ShellInit since that is needed to add
- // the callback. We will be moving to a different explicit startup mechanism in a follow- up CL.
- @WMSingleton
- @ShellCreateTriggerOverride
- @Provides
- static Object provideIndependentShellComponentsToCreate(
- DefaultMixedHandler defaultMixedHandler,
- KidsModeTaskOrganizer kidsModeTaskOrganizer,
- Optional<DesktopModeController> desktopModeController) {
- return new Object();
- }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
index cef7e1666331..56bd188a0d7d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
@@ -156,6 +156,8 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler
"start keyguard %s transition, info = %s", description, info);
try {
+ mStartedTransitions.put(transition,
+ new StartedTransition(info, finishTransaction, remoteHandler));
remoteHandler.startAnimation(transition, info, startTransaction,
new IRemoteTransitionFinishedCallback.Stub() {
@Override
@@ -164,14 +166,13 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler
if (sct != null) {
finishTransaction.merge(sct);
}
- mMainExecutor.execute(() -> {
+ // Post our finish callback to let startAnimation finish first.
+ mMainExecutor.executeDelayed(() -> {
mStartedTransitions.remove(transition);
finishCallback.onTransitionFinished(wct, null);
- });
+ }, 0);
}
});
- mStartedTransitions.put(transition,
- new StartedTransition(info, finishTransaction, remoteHandler));
} catch (RemoteException e) {
Log.wtf(TAG, "RemoteException thrown from local IRemoteTransition", e);
return false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeSettingsObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeSettingsObserver.java
deleted file mode 100644
index 65cb7ac1e5f7..000000000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeSettingsObserver.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.kidsmode;
-
-import android.annotation.NonNull;
-import android.app.ActivityManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.provider.Settings;
-
-import java.util.Collection;
-
-/**
- * A ContentObserver for listening kids mode relative setting keys:
- * - {@link Settings.Secure#NAVIGATION_MODE}
- * - {@link Settings.Secure#NAV_BAR_KIDS_MODE}
- *
- * @hide
- */
-public class KidsModeSettingsObserver extends ContentObserver {
- private Context mContext;
- private Runnable mOnChangeRunnable;
-
- public KidsModeSettingsObserver(Handler handler, Context context) {
- super(handler);
- mContext = context;
- }
-
- public void setOnChangeRunnable(Runnable r) {
- mOnChangeRunnable = r;
- }
-
- /**
- * Registers the observer.
- */
- public void register() {
- final ContentResolver r = mContext.getContentResolver();
- r.registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.NAVIGATION_MODE),
- false, this, UserHandle.USER_ALL);
- r.registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_KIDS_MODE),
- false, this, UserHandle.USER_ALL);
- }
-
- /**
- * Unregisters the observer.
- */
- public void unregister() {
- mContext.getContentResolver().unregisterContentObserver(this);
- }
-
- @Override
- public void onChange(boolean selfChange, @NonNull Collection<Uri> uris, int flags, int userId) {
- if (userId != ActivityManager.getCurrentUser()) {
- return;
- }
-
- if (mOnChangeRunnable != null) {
- mOnChangeRunnable.run();
- }
- }
-
- /**
- * Returns true only when it's in three button nav mode and the kid nav bar mode is enabled.
- * Otherwise, return false.
- */
- public boolean isEnabled() {
- return Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.NAVIGATION_MODE, 0, UserHandle.USER_CURRENT) == 0
- && Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.NAV_BAR_KIDS_MODE, 0, UserHandle.USER_CURRENT) == 1;
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
deleted file mode 100644
index 6d46a9c3d0e7..000000000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.kidsmode;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import android.app.ActivityManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.view.Display;
-import android.view.InsetsSource;
-import android.view.InsetsState;
-import android.view.SurfaceControl;
-import android.view.WindowInsets;
-import android.window.ITaskOrganizerController;
-import android.window.TaskAppearedInfo;
-import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
-
-import androidx.annotation.NonNull;
-
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.DisplayInsetsController;
-import com.android.wm.shell.common.DisplayLayout;
-import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.recents.RecentTasksController;
-import com.android.wm.shell.sysui.ShellCommandHandler;
-import com.android.wm.shell.sysui.ShellInit;
-import com.android.wm.shell.unfold.UnfoldAnimationController;
-
-import java.io.PrintWriter;
-import java.util.List;
-import java.util.Optional;
-
-/**
- * A dedicated task organizer when kids mode is enabled.
- * - Creates a root task with bounds that exclude the navigation bar area
- * - Launch all task into the root task except for Launcher
- */
-public class KidsModeTaskOrganizer extends ShellTaskOrganizer {
- private static final String TAG = "KidsModeTaskOrganizer";
-
- private static final int[] CONTROLLED_ACTIVITY_TYPES =
- {ACTIVITY_TYPE_UNDEFINED, ACTIVITY_TYPE_STANDARD, ACTIVITY_TYPE_HOME};
- private static final int[] CONTROLLED_WINDOWING_MODES =
- {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED};
-
- private final Handler mMainHandler;
- private final Context mContext;
- private final ShellCommandHandler mShellCommandHandler;
- private final SyncTransactionQueue mSyncQueue;
- private final DisplayController mDisplayController;
- private final DisplayInsetsController mDisplayInsetsController;
-
- /**
- * The value of the {@link R.bool.config_reverseDefaultRotation} property which defines how
- * {@link Display#getRotation} values are mapped to screen orientations
- */
- private final boolean mReverseDefaultRotationEnabled;
-
- @VisibleForTesting
- ActivityManager.RunningTaskInfo mLaunchRootTask;
- @VisibleForTesting
- SurfaceControl mLaunchRootLeash;
- @VisibleForTesting
- final IBinder mCookie = new Binder();
-
- private final InsetsState mInsetsState = new InsetsState();
- private int mDisplayWidth;
- private int mDisplayHeight;
-
- private KidsModeSettingsObserver mKidsModeSettingsObserver;
- private boolean mEnabled;
-
- private ActivityManager.RunningTaskInfo mHomeTask;
-
- private final BroadcastReceiver mUserSwitchIntentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- updateKidsModeState();
- }
- };
-
- DisplayController.OnDisplaysChangedListener mOnDisplaysChangedListener =
- new DisplayController.OnDisplaysChangedListener() {
- @Override
- public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
- if (displayId != DEFAULT_DISPLAY) {
- return;
- }
- final DisplayLayout displayLayout =
- mDisplayController.getDisplayLayout(DEFAULT_DISPLAY);
- if (displayLayout == null) {
- return;
- }
- final int displayWidth = displayLayout.width();
- final int displayHeight = displayLayout.height();
- if (displayWidth == mDisplayWidth || displayHeight == mDisplayHeight) {
- return;
- }
- mDisplayWidth = displayWidth;
- mDisplayHeight = displayHeight;
- updateBounds();
- }
- };
-
- DisplayInsetsController.OnInsetsChangedListener mOnInsetsChangedListener =
- new DisplayInsetsController.OnInsetsChangedListener() {
- @Override
- public void insetsChanged(InsetsState insetsState) {
- final boolean[] navigationBarChanged = {false};
- InsetsState.traverse(insetsState, mInsetsState, new InsetsState.OnTraverseCallbacks() {
- @Override
- public void onIdMatch(InsetsSource source1, InsetsSource source2) {
- if (source1.getType() == WindowInsets.Type.navigationBars()
- && !source1.equals(source2)) {
- navigationBarChanged[0] = true;
- }
- }
-
- @Override
- public void onIdNotFoundInState1(int index2, InsetsSource source2) {
- if (source2.getType() == WindowInsets.Type.navigationBars()) {
- navigationBarChanged[0] = true;
- }
- }
-
- @Override
- public void onIdNotFoundInState2(int index1, InsetsSource source1) {
- if (source1.getType() == WindowInsets.Type.navigationBars()) {
- navigationBarChanged[0] = true;
- }
- }
- });
- if (!navigationBarChanged[0]) {
- return;
- }
- // Update bounds only when the insets of navigation bar or task bar is changed.
- mInsetsState.set(insetsState);
- updateBounds();
- }
- };
-
- @VisibleForTesting
- KidsModeTaskOrganizer(
- Context context,
- ShellInit shellInit,
- ShellCommandHandler shellCommandHandler,
- ITaskOrganizerController taskOrganizerController,
- SyncTransactionQueue syncTransactionQueue,
- DisplayController displayController,
- DisplayInsetsController displayInsetsController,
- Optional<UnfoldAnimationController> unfoldAnimationController,
- Optional<RecentTasksController> recentTasks,
- KidsModeSettingsObserver kidsModeSettingsObserver,
- ShellExecutor mainExecutor,
- Handler mainHandler) {
- // Note: we don't call super with the shell init because we will be initializing manually
- super(/* shellInit= */ null, /* shellCommandHandler= */ null, taskOrganizerController,
- /* compatUI= */ null, unfoldAnimationController, recentTasks, mainExecutor);
- mContext = context;
- mShellCommandHandler = shellCommandHandler;
- mMainHandler = mainHandler;
- mSyncQueue = syncTransactionQueue;
- mDisplayController = displayController;
- mDisplayInsetsController = displayInsetsController;
- mKidsModeSettingsObserver = kidsModeSettingsObserver;
- shellInit.addInitCallback(this::onInit, this);
- mReverseDefaultRotationEnabled = context.getResources().getBoolean(
- R.bool.config_reverseDefaultRotation);
- }
-
- public KidsModeTaskOrganizer(
- Context context,
- ShellInit shellInit,
- ShellCommandHandler shellCommandHandler,
- SyncTransactionQueue syncTransactionQueue,
- DisplayController displayController,
- DisplayInsetsController displayInsetsController,
- Optional<UnfoldAnimationController> unfoldAnimationController,
- Optional<RecentTasksController> recentTasks,
- ShellExecutor mainExecutor,
- Handler mainHandler) {
- // Note: we don't call super with the shell init because we will be initializing manually
- super(/* shellInit= */ null, /* taskOrganizerController= */ null, /* compatUI= */ null,
- unfoldAnimationController, recentTasks, mainExecutor);
- mContext = context;
- mShellCommandHandler = shellCommandHandler;
- mMainHandler = mainHandler;
- mSyncQueue = syncTransactionQueue;
- mDisplayController = displayController;
- mDisplayInsetsController = displayInsetsController;
- shellInit.addInitCallback(this::onInit, this);
- mReverseDefaultRotationEnabled = context.getResources().getBoolean(
- R.bool.config_reverseDefaultRotation);
- }
-
- /**
- * Initializes kids mode status.
- */
- public void onInit() {
- if (mShellCommandHandler != null) {
- mShellCommandHandler.addDumpCallback(this::dump, this);
- }
- if (mKidsModeSettingsObserver == null) {
- mKidsModeSettingsObserver = new KidsModeSettingsObserver(mMainHandler, mContext);
- }
- mKidsModeSettingsObserver.setOnChangeRunnable(() -> updateKidsModeState());
- updateKidsModeState();
- mKidsModeSettingsObserver.register();
-
- final IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_USER_SWITCHED);
- mContext.registerReceiverForAllUsers(mUserSwitchIntentReceiver, filter, null, mMainHandler);
- }
-
- @Override
- public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
- if (mEnabled && mLaunchRootTask == null && taskInfo.launchCookies != null
- && taskInfo.launchCookies.contains(mCookie)) {
- mLaunchRootTask = taskInfo;
- mLaunchRootLeash = leash;
- updateTask();
- }
- super.onTaskAppeared(taskInfo, leash);
-
- // Only allow home to draw under system bars.
- if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME) {
- final WindowContainerTransaction wct = getWindowContainerTransaction();
- wct.setBounds(taskInfo.token, new Rect(0, 0, mDisplayWidth, mDisplayHeight));
- mSyncQueue.queue(wct);
- mHomeTask = taskInfo;
- }
- mSyncQueue.runInSync(t -> {
- // Reset several properties back to fullscreen (PiP, for example, leaves all these
- // properties in a bad state).
- t.setCrop(leash, null);
- t.setPosition(leash, 0, 0);
- t.setAlpha(leash, 1f);
- t.setMatrix(leash, 1, 0, 0, 1);
- t.show(leash);
- });
- }
-
- @Override
- public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
- if (mLaunchRootTask != null && mLaunchRootTask.taskId == taskInfo.taskId
- && !taskInfo.equals(mLaunchRootTask)) {
- mLaunchRootTask = taskInfo;
- }
-
- if (mHomeTask != null && mHomeTask.taskId == taskInfo.taskId
- && !taskInfo.equals(mHomeTask)) {
- mHomeTask = taskInfo;
- }
-
- super.onTaskInfoChanged(taskInfo);
- }
-
- @VisibleForTesting
- void updateKidsModeState() {
- final boolean enabled = mKidsModeSettingsObserver.isEnabled();
- if (mEnabled == enabled) {
- return;
- }
- mEnabled = enabled;
- if (mEnabled) {
- enable();
- } else {
- disable();
- }
- }
-
- @VisibleForTesting
- void enable() {
- // Needed since many Kids apps aren't optimised to support both orientations and it will be
- // hard for kids to understand the app compat mode.
- // TODO(229961548): Remove ignoreOrientationRequest exception for Kids Mode once possible.
- if (mReverseDefaultRotationEnabled) {
- setOrientationRequestPolicy(/* isIgnoreOrientationRequestDisabled */ true,
- /* fromOrientations */
- new int[]{SCREEN_ORIENTATION_LANDSCAPE, SCREEN_ORIENTATION_REVERSE_LANDSCAPE},
- /* toOrientations */
- new int[]{SCREEN_ORIENTATION_SENSOR_LANDSCAPE,
- SCREEN_ORIENTATION_SENSOR_LANDSCAPE});
- } else {
- setOrientationRequestPolicy(/* isIgnoreOrientationRequestDisabled */ true,
- /* fromOrientations */ null, /* toOrientations */ null);
- }
- final DisplayLayout displayLayout = mDisplayController.getDisplayLayout(DEFAULT_DISPLAY);
- if (displayLayout != null) {
- mDisplayWidth = displayLayout.width();
- mDisplayHeight = displayLayout.height();
- }
- mInsetsState.set(mDisplayController.getInsetsState(DEFAULT_DISPLAY));
- mDisplayInsetsController.addInsetsChangedListener(DEFAULT_DISPLAY,
- mOnInsetsChangedListener);
- mDisplayController.addDisplayWindowListener(mOnDisplaysChangedListener);
- List<TaskAppearedInfo> taskAppearedInfos = registerOrganizer();
- for (int i = 0; i < taskAppearedInfos.size(); i++) {
- final TaskAppearedInfo info = taskAppearedInfos.get(i);
- onTaskAppeared(info.getTaskInfo(), info.getLeash());
- }
- createRootTask(DEFAULT_DISPLAY, WINDOWING_MODE_FULLSCREEN, mCookie);
- updateTask();
- }
-
- @VisibleForTesting
- void disable() {
- setOrientationRequestPolicy(/* isIgnoreOrientationRequestDisabled */ false,
- /* fromOrientations */ null, /* toOrientations */ null);
- mDisplayInsetsController.removeInsetsChangedListener(DEFAULT_DISPLAY,
- mOnInsetsChangedListener);
- mDisplayController.removeDisplayWindowListener(mOnDisplaysChangedListener);
- updateTask();
- final WindowContainerToken token = mLaunchRootTask.token;
- if (token != null) {
- deleteRootTask(token);
- }
- mLaunchRootTask = null;
- mLaunchRootLeash = null;
- if (mHomeTask != null && mHomeTask.token != null) {
- final WindowContainerToken homeToken = mHomeTask.token;
- final WindowContainerTransaction wct = getWindowContainerTransaction();
- wct.setBounds(homeToken, null);
- mSyncQueue.queue(wct);
- }
- mHomeTask = null;
- unregisterOrganizer();
- }
-
- private void updateTask() {
- updateTask(getWindowContainerTransaction());
- }
-
- private void updateTask(WindowContainerTransaction wct) {
- if (mLaunchRootTask == null || mLaunchRootLeash == null) {
- return;
- }
- final Rect taskBounds = calculateBounds();
- final WindowContainerToken rootToken = mLaunchRootTask.token;
- wct.setBounds(rootToken, mEnabled ? taskBounds : null);
- wct.setLaunchRoot(rootToken,
- mEnabled ? CONTROLLED_WINDOWING_MODES : null,
- mEnabled ? CONTROLLED_ACTIVITY_TYPES : null);
- wct.reparentTasks(
- mEnabled ? null : rootToken /* currentParent */,
- mEnabled ? rootToken : null /* newParent */,
- CONTROLLED_WINDOWING_MODES,
- CONTROLLED_ACTIVITY_TYPES,
- true /* onTop */);
- wct.reorder(rootToken, mEnabled /* onTop */);
- mSyncQueue.queue(wct);
- if (mEnabled) {
- final SurfaceControl rootLeash = mLaunchRootLeash;
- mSyncQueue.runInSync(t -> {
- t.setPosition(rootLeash, taskBounds.left, taskBounds.top);
- t.setWindowCrop(rootLeash, mDisplayWidth, mDisplayHeight);
- });
- }
- }
-
- private Rect calculateBounds() {
- final Rect bounds = new Rect(0, 0, mDisplayWidth, mDisplayHeight);
- bounds.inset(mInsetsState.calculateInsets(
- bounds, WindowInsets.Type.navigationBars(), false /* ignoreVisibility */));
- return bounds;
- }
-
- private void updateBounds() {
- if (mLaunchRootTask == null) {
- return;
- }
- final WindowContainerTransaction wct = getWindowContainerTransaction();
- final Rect taskBounds = calculateBounds();
- wct.setBounds(mLaunchRootTask.token, taskBounds);
- wct.setBounds(mHomeTask.token, new Rect(0, 0, mDisplayWidth, mDisplayHeight));
- mSyncQueue.queue(wct);
- final SurfaceControl finalLeash = mLaunchRootLeash;
- mSyncQueue.runInSync(t -> {
- t.setPosition(finalLeash, taskBounds.left, taskBounds.top);
- t.setWindowCrop(finalLeash, mDisplayWidth, mDisplayHeight);
- });
- }
-
- @VisibleForTesting
- WindowContainerTransaction getWindowContainerTransaction() {
- return new WindowContainerTransaction();
- }
-
- @Override
- public void dump(@NonNull PrintWriter pw, String prefix) {
- final String innerPrefix = prefix + " ";
- pw.println(prefix + TAG);
- pw.println(innerPrefix + " mEnabled=" + mEnabled);
- pw.println(innerPrefix + " mLaunchRootTask=" + mLaunchRootTask);
- pw.println(innerPrefix + " mLaunchRootLeash=" + mLaunchRootLeash);
- pw.println(innerPrefix + " mDisplayWidth=" + mDisplayWidth);
- pw.println(innerPrefix + " mDisplayHeight=" + mDisplayHeight);
- pw.println(innerPrefix + " mInsetsState=" + mInsetsState);
- super.dump(pw, innerPrefix);
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 18898f1f2153..4dbb50f34a35 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -534,17 +534,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
return;
}
- if (ENABLE_SHELL_TRANSITIONS) {
- if (requestEnterSplit && mSplitScreenOptional.isPresent()) {
- mSplitScreenOptional.get().prepareEnterSplitScreen(wct, mTaskInfo,
- isPipTopLeft()
- ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT);
- mPipTransitionController.startExitTransition(
- TRANSIT_EXIT_PIP_TO_SPLIT, wct, null /* destinationBounds */);
- return;
- }
- }
-
final Rect displayBounds = mPipBoundsState.getDisplayBounds();
final Rect destinationBounds = new Rect(displayBounds);
final int direction = syncWithSplitScreenBounds(destinationBounds, requestEnterSplit)
@@ -553,10 +542,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
// For exiting to fullscreen, the windowing mode of task will be changed to fullscreen
// until the animation is finished. Otherwise if the activity is resumed and focused at the
// begin of aniamtion, the app may do something too early to distub the animation.
- final boolean toFullscreen = destinationBounds.equals(displayBounds);
- if (Transitions.SHELL_TRANSITIONS_ROTATION || (Transitions.ENABLE_SHELL_TRANSITIONS
- && !toFullscreen)) {
+ if (Transitions.SHELL_TRANSITIONS_ROTATION) {
// When exit to fullscreen with Shell transition enabled, we update the Task windowing
// mode directly so that it can also trigger display rotation and visibility update in
// the same transition if there will be any.
@@ -588,9 +575,29 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
mPipTransitionState.setTransitionState(PipTransitionState.EXITING_PIP);
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+ if (requestEnterSplit && mSplitScreenOptional.isPresent()) {
+ wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+ mSplitScreenOptional.get().prepareEnterSplitScreen(wct, mTaskInfo,
+ isPipToTopLeft()
+ ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT);
+ mPipTransitionController.startExitTransition(
+ TRANSIT_EXIT_PIP_TO_SPLIT, wct, destinationBounds);
+ return;
+ }
+
+ if (mSplitScreenOptional.isPresent()) {
+ // If pip activity will reparent to origin task case and if the origin task still
+ // under split root, apply exit split transaction to make it expand to fullscreen.
+ SplitScreenController split = mSplitScreenOptional.get();
+ if (split.isTaskInSplitScreen(mTaskInfo.lastParentTaskIdBeforePip)) {
+ split.prepareExitSplitScreen(wct, split.getStageOfTask(
+ mTaskInfo.lastParentTaskIdBeforePip));
+ }
+ }
mPipTransitionController.startExitTransition(TRANSIT_EXIT_PIP, wct, destinationBounds);
return;
}
+
if (mSplitScreenOptional.isPresent()) {
// If pip activity will reparent to origin task case and if the origin task still under
// split root, just exit split screen here to ensure it could expand to fullscreen.
@@ -1139,7 +1146,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
public void setPipVisibility(boolean visible) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"setPipVisibility: %s, state=%s visible=%s",
- mTaskInfo.topActivity, mPipTransitionState, visible);
+ (mTaskInfo != null ? mTaskInfo.topActivity : null), mPipTransitionState, visible);
if (!isInPip()) {
return;
}
@@ -1666,17 +1673,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
}
}
- private boolean isPipTopLeft() {
- if (!mSplitScreenOptional.isPresent()) {
- return false;
- }
- final Rect topLeft = new Rect();
- final Rect bottomRight = new Rect();
- mSplitScreenOptional.get().getStageBounds(topLeft, bottomRight);
-
- return topLeft.contains(mPipBoundsState.getBounds());
- }
-
private boolean isPipToTopLeft() {
if (!mSplitScreenOptional.isPresent()) {
return false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 5086e2c4b05d..86b0f33ad54c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -816,6 +816,12 @@ public class PipTransition extends PipTransitionController {
final ActivityManager.RunningTaskInfo taskInfo = pipChange.getTaskInfo();
final SurfaceControl leash = pipChange.getLeash();
final int startRotation = pipChange.getStartRotation();
+ // Check again in case some callers use startEnterAnimation directly so the flag was not
+ // set in startAnimation, e.g. from DefaultMixedHandler.
+ if (!mInFixedRotation) {
+ mEndFixedRotation = pipChange.getEndFixedRotation();
+ mInFixedRotation = mEndFixedRotation != ROTATION_UNDEFINED;
+ }
final int endRotation = mInFixedRotation ? mEndFixedRotation : pipChange.getEndRotation();
setBoundsStateForEntry(taskInfo.topActivity, taskInfo.pictureInPictureParams,
@@ -844,7 +850,7 @@ public class PipTransition extends PipTransitionController {
&& taskInfo.pictureInPictureParams.isAutoEnterEnabled()
&& mPipTransitionState.getInSwipePipToHomeTransition()) {
handleSwipePipToHomeTransition(startTransaction, finishTransaction, leash,
- sourceHintRect, destinationBounds, rotationDelta, taskInfo);
+ sourceHintRect, destinationBounds, taskInfo);
return;
}
@@ -935,8 +941,15 @@ public class PipTransition extends PipTransitionController {
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull SurfaceControl leash, @Nullable Rect sourceHintRect,
- @NonNull Rect destinationBounds, int rotationDelta,
+ @NonNull Rect destinationBounds,
@NonNull ActivityManager.RunningTaskInfo pipTaskInfo) {
+ if (mInFixedRotation) {
+ // If rotation changes when returning to home, the transition should contain both the
+ // entering PiP and the display change (PipController#startSwipePipToHome has updated
+ // the display layout to new rotation). So it is not expected to see fixed rotation.
+ ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ "%s: SwipePipToHome should not use fixed rotation %d", TAG, mEndFixedRotation);
+ }
final SurfaceControl swipePipToHomeOverlay = mPipOrganizer.mSwipePipToHomeOverlay;
if (swipePipToHomeOverlay != null) {
// Launcher fade in the overlay on top of the fullscreen Task. It is possible we
@@ -947,12 +960,7 @@ public class PipTransition extends PipTransitionController {
mPipOrganizer.mSwipePipToHomeOverlay = null;
}
- Rect sourceBounds = pipTaskInfo.configuration.windowConfiguration.getBounds();
- if (!Transitions.SHELL_TRANSITIONS_ROTATION && rotationDelta % 2 == 1) {
- // PipController#startSwipePipToHome has updated the display layout to new rotation,
- // so flip the source bounds to match the same orientation.
- sourceBounds = new Rect(0, 0, sourceBounds.height(), sourceBounds.width());
- }
+ final Rect sourceBounds = pipTaskInfo.configuration.windowConfiguration.getBounds();
final PipAnimationController.PipTransitionAnimator animator =
mPipAnimationController.getAnimator(pipTaskInfo, leash, sourceBounds, sourceBounds,
destinationBounds, sourceHintRect, TRANSITION_DIRECTION_TO_PIP,
@@ -981,12 +989,7 @@ public class PipTransition extends PipTransitionController {
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback,
@NonNull TaskInfo taskInfo) {
- final int changeSize = info.getChanges().size();
- if (changeSize < 4) {
- throw new RuntimeException(
- "Got an exit-pip-to-split transition with unexpected change-list");
- }
- for (int i = changeSize - 1; i >= 0; i--) {
+ for (int i = info.getChanges().size() - 1; i >= 0; i--) {
final TransitionInfo.Change change = info.getChanges().get(i);
final int mode = change.getMode();
@@ -1015,24 +1018,17 @@ public class PipTransition extends PipTransitionController {
private void resetPrevPip(@NonNull TransitionInfo.Change prevPipTaskChange,
@NonNull SurfaceControl.Transaction startTransaction) {
final SurfaceControl leash = prevPipTaskChange.getLeash();
- final Rect bounds = prevPipTaskChange.getEndAbsBounds();
- final Point offset = prevPipTaskChange.getEndRelOffset();
- bounds.offset(-offset.x, -offset.y);
-
- startTransaction.setWindowCrop(leash, null);
- startTransaction.setMatrix(leash, 1, 0, 0, 1);
- startTransaction.setCornerRadius(leash, 0);
- startTransaction.setPosition(leash, bounds.left, bounds.top);
-
- if (mHasFadeOut && prevPipTaskChange.getTaskInfo().isVisible()) {
- if (mPipAnimationController.getCurrentAnimator() != null) {
- mPipAnimationController.getCurrentAnimator().cancel();
- }
- startTransaction.setAlpha(leash, 1);
- }
+ startTransaction.remove(leash);
+
mHasFadeOut = false;
mCurrentPipTaskToken = null;
- mPipOrganizer.onExitPipFinished(prevPipTaskChange.getTaskInfo());
+
+ // clean-up the state in PipTaskOrganizer if the PipTaskOrganizer#onTaskAppeared() hasn't
+ // been called yet with its leash reference now pointing to a new SurfaceControl not
+ // matching the leash of the pip we are removing.
+ if (mPipOrganizer.getSurfaceControl() == leash) {
+ mPipOrganizer.onExitPipFinished(prevPipTaskChange.getTaskInfo());
+ }
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
index 2fff0e469f3d..e1bcd70c256b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
@@ -38,6 +38,7 @@ import android.window.WindowContainerTransaction;
import androidx.annotation.NonNull;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.split.SplitScreenUtils;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
@@ -223,6 +224,13 @@ public abstract class PipTransitionController implements Transitions.TransitionH
return false;
}
+ /** Whether a particular package is same as current pip package. */
+ public boolean isInPipPackage(String packageName) {
+ final TaskInfo inPipTask = mPipOrganizer.getTaskInfo();
+ return packageName != null && inPipTask != null
+ && packageName.equals(SplitScreenUtils.getPackageName(inPipTask.baseIntent));
+ }
+
/** Add PiP-related changes to `outWCT` for the given request. */
public void augmentRequest(@NonNull IBinder transition,
@NonNull TransitionRequestInfo request, @NonNull WindowContainerTransaction outWCT) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java
index fc674a8aa59b..f9332e4bdb2e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java
@@ -63,6 +63,15 @@ public class PhonePipKeepClearAlgorithm implements PipKeepClearAlgorithmInterfac
if (pipBoundsState.isImeShowing()) {
insets.bottom -= pipBoundsState.getImeHeight();
}
+ // if PiP is stashed we only adjust the vertical position if it's outside of insets and
+ // ignore all keep clear areas, since it's already on the side
+ if (pipBoundsState.isStashed()) {
+ if (startingBounds.bottom > insets.bottom || startingBounds.top < insets.top) {
+ // bring PiP back to be aligned by bottom inset
+ startingBounds.offset(0, insets.bottom - startingBounds.bottom);
+ }
+ return startingBounds;
+ }
Rect pipBounds = new Rect(startingBounds);
boolean shouldApplyGravity = false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
index e7a1395f541c..5e1b6becfa45 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
@@ -31,6 +31,8 @@ import android.os.RemoteException;
import android.util.Size;
import android.view.MotionEvent;
import android.view.SurfaceControl;
+import android.view.View;
+import android.view.ViewRootImpl;
import android.view.WindowManagerGlobal;
import com.android.internal.protolog.common.ProtoLog;
@@ -131,6 +133,8 @@ public class PhonePipMenuController implements PipMenuController {
private PipMenuView mPipMenuView;
+ private SurfaceControl mLeash;
+
private ActionListener mMediaActionListener = new ActionListener() {
@Override
public void onMediaActionsChanged(List<RemoteAction> mediaActions) {
@@ -166,6 +170,7 @@ public class PhonePipMenuController implements PipMenuController {
*/
@Override
public void attach(SurfaceControl leash) {
+ mLeash = leash;
attachPipMenuView();
}
@@ -176,6 +181,7 @@ public class PhonePipMenuController implements PipMenuController {
public void detach() {
hideMenu();
detachPipMenuView();
+ mLeash = null;
}
void attachPipMenuView() {
@@ -185,6 +191,36 @@ public class PhonePipMenuController implements PipMenuController {
}
mPipMenuView = new PipMenuView(mContext, this, mMainExecutor, mMainHandler,
mSplitScreenController, mPipUiEventLogger);
+ mPipMenuView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ v.getViewRootImpl().addSurfaceChangedCallback(
+ new ViewRootImpl.SurfaceChangedCallback() {
+ @Override
+ public void surfaceCreated(SurfaceControl.Transaction t) {
+ final SurfaceControl sc = getSurfaceControl();
+ if (sc != null) {
+ t.reparent(sc, mLeash);
+ // make menu on top of the surface
+ t.setLayer(sc, Integer.MAX_VALUE);
+ }
+ }
+
+ @Override
+ public void surfaceReplaced(SurfaceControl.Transaction t) {
+ }
+
+ @Override
+ public void surfaceDestroyed() {
+ }
+ });
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ }
+ });
+
mSystemWindows.addView(mPipMenuView,
getPipMenuLayoutParams(mContext, MENU_WINDOW_TITLE, 0 /* width */, 0 /* height */),
0, SHELL_ROOT_LAYER_PIP);
@@ -321,30 +357,10 @@ public class PhonePipMenuController implements PipMenuController {
return;
}
- // If there is no pip leash supplied, that means the PiP leash is already finalized
- // resizing and the PiP menu is also resized. We then want to do a scale from the current
- // new menu bounds.
+ // TODO(b/286307861) transaction should be applied outside of PiP menu controller
if (pipLeash != null && t != null) {
- mPipMenuView.getBoundsOnScreen(mTmpSourceBounds);
- } else {
- mTmpSourceBounds.set(0, 0, destinationBounds.width(), destinationBounds.height());
+ t.apply();
}
-
- mTmpSourceRectF.set(mTmpSourceBounds);
- mTmpDestinationRectF.set(destinationBounds);
- mMoveTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
- final SurfaceControl surfaceControl = getSurfaceControl();
- if (surfaceControl == null) {
- return;
- }
- final SurfaceControl.Transaction menuTx =
- mSurfaceControlTransactionFactory.getTransaction();
- menuTx.setMatrix(surfaceControl, mMoveTransform, mTmpTransform);
- if (pipLeash != null && t != null) {
- // Merge the two transactions, vsyncId has been set on menuTx.
- menuTx.merge(t);
- }
- menuTx.apply();
}
/**
@@ -362,18 +378,10 @@ public class PhonePipMenuController implements PipMenuController {
return;
}
- final SurfaceControl surfaceControl = getSurfaceControl();
- if (surfaceControl == null) {
- return;
- }
- final SurfaceControl.Transaction menuTx =
- mSurfaceControlTransactionFactory.getTransaction();
- menuTx.setCrop(surfaceControl, destinationBounds);
+ // TODO(b/286307861) transaction should be applied outside of PiP menu controller
if (pipLeash != null && t != null) {
- // Merge the two transactions, vsyncId has been set on menuTx.
- menuTx.merge(t);
+ t.apply();
}
- menuTx.apply();
}
private boolean checkPipMenuState() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index 8723f9b0181d..843e5af67af9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -313,7 +313,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
private Pair<int[], TaskSnapshot[]> getSnapshotsForPausingTasks() {
int[] taskIds = null;
TaskSnapshot[] snapshots = null;
- if (mPausingTasks.size() > 0) {
+ if (mPausingTasks != null && mPausingTasks.size() > 0) {
taskIds = new int[mPausingTasks.size()];
snapshots = new TaskSnapshot[mPausingTasks.size()];
try {
@@ -424,6 +424,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
// the change count). This lets us categorize things into above/below/between
// while maintaining their relative ordering.
final int belowLayers = info.getChanges().size();
+ final int middleLayers = info.getChanges().size() * 2;
final int aboveLayers = info.getChanges().size() * 3;
for (int i = 0; i < info.getChanges().size(); ++i) {
final TransitionInfo.Change change = info.getChanges().get(i);
@@ -441,14 +442,19 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
belowLayers - i, info, t, mLeashMap);
apps.add(target);
if (TransitionUtil.isClosingType(change.getMode())) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
- " adding pausing leaf taskId=%d", taskInfo.taskId);
- // raise closing (pausing) task to "above" layer so it isn't covered
- t.setLayer(target.leash, aboveLayers - i);
mPausingTasks.add(new TaskState(change, target.leash));
if (taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ " adding pausing leaf home taskId=%d", taskInfo.taskId);
// This can only happen if we have a separate recents/home (3p launcher)
mPausingSeparateHome = true;
+ } else {
+ final int layer = aboveLayers - i;
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ " adding pausing leaf taskId=%d at layer=%d",
+ taskInfo.taskId, layer);
+ // raise closing (pausing) task to "above" layer so it isn't covered
+ t.setLayer(target.leash, layer);
}
if (taskInfo.pictureInPictureParams != null
&& taskInfo.pictureInPictureParams.isAutoEnterEnabled()) {
@@ -456,8 +462,12 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
}
} else if (taskInfo != null
&& taskInfo.topActivityType == ACTIVITY_TYPE_RECENTS) {
- // There's a 3p launcher, so make sure recents goes above that.
- t.setLayer(target.leash, aboveLayers - i);
+ final int layer = middleLayers - i;
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ " setting recents activity layer=%d", layer);
+ // There's a 3p launcher, so make sure recents goes above that, but under
+ // the pausing apps.
+ t.setLayer(target.leash, layer);
} else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
// do nothing
} else if (TransitionUtil.isOpeningType(change.getMode())) {
@@ -468,16 +478,18 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
} else if (taskInfo != null && TransitionInfo.isIndependent(change, info)) {
// Root tasks
if (TransitionUtil.isClosingType(change.getMode())) {
+ final int layer = aboveLayers - i;
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
- " adding pausing taskId=%d", taskInfo.taskId);
+ " adding pausing taskId=%d at layer=%d", taskInfo.taskId, layer);
// raise closing (pausing) task to "above" layer so it isn't covered
- t.setLayer(change.getLeash(), aboveLayers - i);
+ t.setLayer(change.getLeash(), layer);
mPausingTasks.add(new TaskState(change, null /* leash */));
} else if (TransitionUtil.isOpeningType(change.getMode())) {
+ final int layer = belowLayers - i;
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
- " adding opening taskId=%d", taskInfo.taskId);
+ " adding opening taskId=%d at layer=%d", taskInfo.taskId, layer);
// Put into the "below" layer space.
- t.setLayer(change.getLeash(), belowLayers - i);
+ t.setLayer(change.getLeash(), layer);
mOpeningTasks.add(new TaskState(change, null /* leash */));
}
} else if (TransitionUtil.isDividerBar(change)) {
@@ -595,9 +607,20 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
cancel(mWillFinishToHome, true /* withScreenshots */, "display change");
return;
}
- // Don't consider order-only changes as changing apps.
- if (!TransitionUtil.isOrderOnly(change)) {
+ // Don't consider order-only & non-leaf changes as changing apps.
+ if (!TransitionUtil.isOrderOnly(change) && isLeafTask) {
hasChangingApp = true;
+ } else if (isLeafTask && taskInfo.topActivityType == ACTIVITY_TYPE_HOME
+ && !mRecentsTask.equals(change.getContainer())) {
+ // Unless it is a 3p launcher. This means that the 3p launcher was already
+ // visible (eg. the "pausing" task is translucent over the 3p launcher).
+ // Treat it as if we are "re-opening" the 3p launcher.
+ if (openingTasks == null) {
+ openingTasks = new ArrayList<>();
+ openingTaskIsLeafs = new IntArray();
+ }
+ openingTasks.add(change);
+ openingTaskIsLeafs.add(1);
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index ea33a1f1b56d..e7a367f1992d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -88,6 +88,7 @@ import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.draganddrop.DragAndDropPolicy;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.recents.RecentTasksController;
+import com.android.wm.shell.splitscreen.SplitScreen.StageType;
import com.android.wm.shell.sysui.KeyguardChangeListener;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
@@ -332,6 +333,11 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
return mStageCoordinator.getStageOfTask(taskId) != STAGE_TYPE_UNDEFINED;
}
+ /** Get the split stage of task is under it. */
+ public @StageType int getStageOfTask(int taskId) {
+ return mStageCoordinator.getStageOfTask(taskId);
+ }
+
/** Check split is foreground and task is under split or not by taskId. */
public boolean isTaskInSplitScreenForeground(int taskId) {
return isTaskInSplitScreen(taskId) && isSplitScreenVisible();
@@ -378,17 +384,35 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
mStageCoordinator.setSideStagePosition(sideStagePosition, null /* wct */);
}
- public void enterSplitScreen(int taskId, boolean leftOrTop) {
- enterSplitScreen(taskId, leftOrTop, new WindowContainerTransaction());
- }
-
+ /**
+ * Doing necessary window transaction for other transition handler need to enter split in
+ * transition.
+ */
public void prepareEnterSplitScreen(WindowContainerTransaction wct,
ActivityManager.RunningTaskInfo taskInfo, int startPosition) {
- mStageCoordinator.prepareEnterSplitScreen(wct, taskInfo, startPosition);
+ mStageCoordinator.prepareEnterSplitScreen(wct, taskInfo, startPosition,
+ false /* resizeAnim */);
+ }
+
+ /**
+ * Doing necessary surface transaction for other transition handler need to enter split in
+ * transition when finished.
+ */
+ public void finishEnterSplitScreen(SurfaceControl.Transaction finishT) {
+ mStageCoordinator.finishEnterSplitScreen(finishT);
}
- public void finishEnterSplitScreen(SurfaceControl.Transaction t) {
- mStageCoordinator.finishEnterSplitScreen(t);
+ /**
+ * Doing necessary window transaction for other transition handler need to exit split in
+ * transition.
+ */
+ public void prepareExitSplitScreen(WindowContainerTransaction wct,
+ @StageType int stageToTop) {
+ mStageCoordinator.prepareExitSplitScreen(stageToTop, wct);
+ }
+
+ public void enterSplitScreen(int taskId, boolean leftOrTop) {
+ enterSplitScreen(taskId, leftOrTop, new WindowContainerTransaction());
}
public void enterSplitScreen(int taskId, boolean leftOrTop, WindowContainerTransaction wct) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
index 986309948ada..d21f8a48e62a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
@@ -199,19 +199,7 @@ class SplitScreenTransitions {
boolean isOpening = TransitionUtil.isOpeningType(info.getType());
if (!isOpening && (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK)) {
// fade out
- if (change.getSnapshot() != null) {
- // This case is happened if task is going to reparent to TDA, the origin leash
- // doesn't rendor so we use snapshot to replace it animating.
- t.reparent(change.getSnapshot(), info.getRoot(rootIdx).getLeash());
- // Use origin leash layer.
- t.setLayer(change.getSnapshot(), info.getChanges().size() - i);
- t.setPosition(change.getSnapshot(), change.getStartAbsBounds().left,
- change.getStartAbsBounds().top);
- t.show(change.getSnapshot());
- startFadeAnimation(change.getSnapshot(), false /* show */);
- } else {
- startFadeAnimation(leash, false /* show */);
- }
+ startFadeAnimation(leash, false /* show */);
} else if (mode == TRANSIT_CHANGE && change.getSnapshot() != null) {
t.reparent(change.getSnapshot(), info.getRoot(rootIdx).getLeash());
// Ensure snapshot it on the top of all transition surfaces
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index c8e88fcc0a6a..da14d03adb35 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -23,7 +23,6 @@ import static android.app.ComponentOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVIT
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
@@ -122,7 +121,6 @@ import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
-import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ScreenshotUtils;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
@@ -171,7 +169,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private final StageListenerImpl mMainStageListener = new StageListenerImpl();
private final SideStage mSideStage;
private final StageListenerImpl mSideStageListener = new StageListenerImpl();
- private final DisplayLayout mDisplayLayout;
@SplitPosition
private int mSideStagePosition = SPLIT_POSITION_BOTTOM_OR_RIGHT;
@@ -311,7 +308,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSplitTransitions = new SplitScreenTransitions(transactionPool, transitions,
this::onTransitionAnimationComplete, this);
mDisplayController.addDisplayWindowListener(this);
- mDisplayLayout = new DisplayLayout(displayController.getDisplayLayout(displayId));
transitions.addHandler(this);
mSplitUnsupportedToast = Toast.makeText(mContext,
R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT);
@@ -345,7 +341,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mMainExecutor = mainExecutor;
mRecentTasks = recentTasks;
mDisplayController.addDisplayWindowListener(this);
- mDisplayLayout = new DisplayLayout();
transitions.addHandler(this);
mSplitUnsupportedToast = Toast.makeText(mContext,
R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT);
@@ -368,6 +363,27 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return mMainStage.isActive();
}
+ /** @return whether the transition-request implies entering pip from split. */
+ public boolean requestImpliesSplitToPip(TransitionRequestInfo request) {
+ if (!isSplitActive() || !mMixedHandler.requestHasPipEnter(request)) {
+ return false;
+ }
+
+ if (request.getTriggerTask() != null && getSplitPosition(
+ request.getTriggerTask().taskId) != SPLIT_POSITION_UNDEFINED) {
+ return true;
+ }
+
+ // If one of the splitting tasks support auto-pip, wm-core might reparent the task to TDA
+ // and file a TRANSIT_PIP transition when finishing transitions.
+ // @see com.android.server.wm.RootWindowContainer#moveActivityToPinnedRootTask
+ if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
+ return true;
+ }
+
+ return false;
+ }
+
/** Checks if `transition` is a pending enter-split transition. */
public boolean isPendingEnter(IBinder transition) {
return mSplitTransitions.isPendingEnter(transition);
@@ -393,7 +409,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
boolean moveToStage(ActivityManager.RunningTaskInfo task, @SplitPosition int stagePosition,
WindowContainerTransaction wct) {
- prepareEnterSplitScreen(wct, task, stagePosition);
+ prepareEnterSplitScreen(wct, task, stagePosition, false /* resizeAnim */);
if (ENABLE_SHELL_TRANSITIONS) {
mSplitTransitions.startEnterTransition(TRANSIT_TO_FRONT, wct,
null, this,
@@ -491,20 +507,26 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
/** Launches an activity into split. */
void startIntent(PendingIntent intent, Intent fillInIntent, @SplitPosition int position,
@Nullable Bundle options) {
+ mSplitRequest = new SplitRequest(intent.getIntent(), position);
if (!ENABLE_SHELL_TRANSITIONS) {
startIntentLegacy(intent, fillInIntent, position, options);
return;
}
final WindowContainerTransaction wct = new WindowContainerTransaction();
-
options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, null /* wct */);
wct.sendPendingIntent(intent, fillInIntent, options);
+ // If this should be mixed, just send the intent to avoid split handle transition directly.
+ if (mMixedHandler != null && mMixedHandler.shouldSplitEnterMixed(intent)) {
+ mTaskOrganizer.applyTransaction(wct);
+ return;
+ }
+
// If split screen is not activated, we're expecting to open a pair of apps to split.
final int extraTransitType = mMainStage.isActive()
? TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE : TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
- prepareEnterSplitScreen(wct, null /* taskInfo */, position);
+ prepareEnterSplitScreen(wct, null /* taskInfo */, position, !mIsDropEntering);
mSplitTransitions.startEnterTransition(TRANSIT_TO_FRONT, wct, null, this,
extraTransitType, !mIsDropEntering);
@@ -561,7 +583,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (isEnteringSplit && mLogger.isEnterRequestedByDrag()) {
updateWindowBounds(mSplitLayout, wct);
}
- mSplitRequest = new SplitRequest(intent.getIntent(), position);
wct.sendPendingIntent(intent, fillInIntent, options);
mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
}
@@ -1449,7 +1470,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
* an existing WindowContainerTransaction (rather than applying immediately). This is intended
* to be used when exiting split might be bundled with other window operations.
*/
- private void prepareExitSplitScreen(@StageType int stageToTop,
+ void prepareExitSplitScreen(@StageType int stageToTop,
@NonNull WindowContainerTransaction wct) {
if (!mMainStage.isActive()) return;
mSideStage.removeAllTasks(wct, stageToTop == STAGE_TYPE_SIDE);
@@ -1457,7 +1478,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
private void prepareEnterSplitScreen(WindowContainerTransaction wct) {
- prepareEnterSplitScreen(wct, null /* taskInfo */, SPLIT_POSITION_UNDEFINED);
+ prepareEnterSplitScreen(wct, null /* taskInfo */, SPLIT_POSITION_UNDEFINED,
+ !mIsDropEntering);
}
/**
@@ -1465,17 +1487,19 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
* into side stage.
*/
void prepareEnterSplitScreen(WindowContainerTransaction wct,
- @Nullable ActivityManager.RunningTaskInfo taskInfo, @SplitPosition int startPosition) {
+ @Nullable ActivityManager.RunningTaskInfo taskInfo, @SplitPosition int startPosition,
+ boolean resizeAnim) {
onSplitScreenEnter();
if (isSplitActive()) {
- prepareBringSplit(wct, taskInfo, startPosition);
+ prepareBringSplit(wct, taskInfo, startPosition, resizeAnim);
} else {
- prepareActiveSplit(wct, taskInfo, startPosition);
+ prepareActiveSplit(wct, taskInfo, startPosition, resizeAnim);
}
}
private void prepareBringSplit(WindowContainerTransaction wct,
- @Nullable ActivityManager.RunningTaskInfo taskInfo, @SplitPosition int startPosition) {
+ @Nullable ActivityManager.RunningTaskInfo taskInfo, @SplitPosition int startPosition,
+ boolean resizeAnim) {
if (taskInfo != null) {
wct.startTask(taskInfo.taskId,
resolveStartStage(STAGE_TYPE_UNDEFINED, startPosition, null, wct));
@@ -1487,33 +1511,38 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// won't guarantee to put the task to the indicated new position.
mMainStage.evictAllChildren(wct);
mMainStage.reparentTopTask(wct);
- prepareSplitLayout(wct);
+ prepareSplitLayout(wct, resizeAnim);
}
}
private void prepareActiveSplit(WindowContainerTransaction wct,
- @Nullable ActivityManager.RunningTaskInfo taskInfo, @SplitPosition int startPosition) {
+ @Nullable ActivityManager.RunningTaskInfo taskInfo, @SplitPosition int startPosition,
+ boolean resizeAnim) {
if (!ENABLE_SHELL_TRANSITIONS) {
// Legacy transition we need to create divider here, shell transition case we will
// create it on #finishEnterSplitScreen
mSplitLayout.init();
+ } else {
+ // We handle split visibility itself on shell transition, but sometimes we didn't
+ // reset it correctly after dismiss by some reason, so just set invisible before active.
+ setSplitsVisible(false);
}
if (taskInfo != null) {
setSideStagePosition(startPosition, wct);
mSideStage.addTask(taskInfo, wct);
}
mMainStage.activate(wct, true /* includingTopTask */);
- prepareSplitLayout(wct);
+ prepareSplitLayout(wct, resizeAnim);
}
- private void prepareSplitLayout(WindowContainerTransaction wct) {
- if (mIsDropEntering) {
- mSplitLayout.resetDividerPosition();
- } else {
+ private void prepareSplitLayout(WindowContainerTransaction wct, boolean resizeAnim) {
+ if (resizeAnim) {
mSplitLayout.setDividerAtBorder(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT);
+ } else {
+ mSplitLayout.resetDividerPosition();
}
updateWindowBounds(mSplitLayout, wct);
- if (!mIsDropEntering) {
+ if (resizeAnim) {
// Reset its smallest width dp to avoid is change layout before it actually resized to
// split bounds.
wct.setSmallestScreenWidthDp(mMainStage.mRootTaskInfo.token,
@@ -1523,21 +1552,22 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
setRootForceTranslucent(false, wct);
}
- void finishEnterSplitScreen(SurfaceControl.Transaction t) {
- mSplitLayout.update(t);
+ void finishEnterSplitScreen(SurfaceControl.Transaction finishT) {
+ mSplitLayout.update(finishT);
mMainStage.getSplitDecorManager().inflate(mContext, mMainStage.mRootLeash,
getMainStageBounds());
mSideStage.getSplitDecorManager().inflate(mContext, mSideStage.mRootLeash,
getSideStageBounds());
- setDividerVisibility(true, t);
+ setDividerVisibility(true, finishT);
// Ensure divider surface are re-parented back into the hierarchy at the end of the
// transition. See Transition#buildFinishTransaction for more detail.
- t.reparent(mSplitLayout.getDividerLeash(), mRootTaskLeash);
+ finishT.reparent(mSplitLayout.getDividerLeash(), mRootTaskLeash);
- updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
- t.show(mRootTaskLeash);
+ updateSurfaceBounds(mSplitLayout, finishT, false /* applyResizingOffset */);
+ finishT.show(mRootTaskLeash);
setSplitsVisible(true);
mIsDropEntering = false;
+ mSplitRequest = null;
updateRecentTasksSplitPair();
if (!mLogger.hasStartedSession()) {
mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
@@ -1630,7 +1660,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mLogger.logSideStageAppChange(getSideStagePosition(), mSideStage.getTopChildTaskUid(),
mSplitLayout.isLandscape());
}
- if (present && visible) {
+ if (present) {
updateRecentTasksSplitPair();
}
@@ -1689,7 +1719,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (mSplitLayout == null) {
mSplitLayout = new SplitLayout(TAG + "SplitDivider", mContext,
mRootTaskInfo.configuration, this, mParentContainerCallbacks,
- mDisplayImeController, mTaskOrganizer,
+ mDisplayController, mDisplayImeController, mTaskOrganizer,
PARALLAX_ALIGN_CENTER /* parallaxType */);
mDisplayInsetsController.addInsetsChangedListener(mDisplayId, mSplitLayout);
}
@@ -2153,8 +2183,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (displayId != DEFAULT_DISPLAY) {
return;
}
- mDisplayLayout.set(mDisplayController.getDisplayLayout(displayId));
-
if (mSplitLayout != null && mSplitLayout.isDensityChanged(newConfig.densityDpi)
&& mMainStage.isActive()
&& mSplitLayout.updateConfiguration(newConfig)
@@ -2171,10 +2199,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private void onDisplayChange(int displayId, int fromRotation, int toRotation,
@Nullable DisplayAreaInfo newDisplayAreaInfo, WindowContainerTransaction wct) {
- if (!mMainStage.isActive()) return;
+ if (displayId != DEFAULT_DISPLAY || !mMainStage.isActive()) return;
- mDisplayLayout.rotateTo(mContext.getResources(), toRotation);
- mSplitLayout.rotateTo(toRotation, mDisplayLayout.stableInsets());
+ mSplitLayout.rotateTo(toRotation);
if (newDisplayAreaInfo != null) {
mSplitLayout.updateConfiguration(newDisplayAreaInfo.configuration);
}
@@ -2317,7 +2344,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
} else if (!isSplitScreenVisible() && isOpening) {
// If split is running in the background and the trigger task is appearing into
// split, prepare to enter split screen.
- setSideStagePosition(SPLIT_POSITION_BOTTOM_OR_RIGHT, out);
prepareEnterSplitScreen(out);
mSplitTransitions.setEnterTransition(transition, request.getRemoteTransition(),
TRANSIT_SPLIT_SCREEN_PAIR_OPEN, !mIsDropEntering);
@@ -2343,7 +2369,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (isOpening && getStageOfTask(triggerTask) != null) {
// One task is appearing into split, prepare to enter split screen.
out = new WindowContainerTransaction();
- setSideStagePosition(SPLIT_POSITION_BOTTOM_OR_RIGHT, out);
prepareEnterSplitScreen(out);
mSplitTransitions.setEnterTransition(transition, request.getRemoteTransition(),
TRANSIT_SPLIT_SCREEN_PAIR_OPEN, !mIsDropEntering);
@@ -2500,6 +2525,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (mMixedHandler.animatePendingSplitWithDisplayChange(transition, info,
startTransaction, finishTransaction, finishCallback)) {
mSplitLayout.update(startTransaction);
+ startTransaction.apply();
return true;
}
}
@@ -2638,11 +2664,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (mSplitTransitions.mPendingEnter.mExtraTransitType
== TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE) {
+ // Open to side should only be used when split already active and foregorund.
if (mainChild == null && sideChild == null) {
Log.w(TAG, "Launched a task in split, but didn't receive any task in transition.");
- mSplitTransitions.mPendingEnter.cancel((cancelWct, cancelT)
- -> prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, cancelWct));
- mSplitUnsupportedToast.show();
+ // This should happen when the target app is already on front, so just cancel.
+ mSplitTransitions.mPendingEnter.cancel(null);
return true;
}
} else {
@@ -2796,19 +2822,19 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
}
- mRecentTasks.ifPresent(recentTasks -> {
+ if (shouldBreakPairedTaskInRecents(dismissReason)) {
// Notify recents if we are exiting in a way that breaks the pair, and disable further
// updates to splits in the recents until we enter split again
- if (shouldBreakPairedTaskInRecents(dismissReason)) {
- for (TransitionInfo.Change change : info.getChanges()) {
- final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
- if (taskInfo != null
- && taskInfo.getWindowingMode() != WINDOWING_MODE_MULTI_WINDOW) {
- recentTasks.removeSplitPair(taskInfo.taskId);
- }
+ mRecentTasks.ifPresent(recentTasks -> {
+ for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+ final TransitionInfo.Change change = info.getChanges().get(i);
+ final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+ if (taskInfo != null && getStageOfTask(taskInfo) != null) {
+ recentTasks.removeSplitPair(taskInfo.taskId);
}
- }
- });
+ }
+ });
+ }
mSplitRequest = null;
// Update local states.
@@ -2884,6 +2910,12 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
/** Call this when the recents animation canceled during split-screen. */
public void onRecentsInSplitAnimationCanceled() {
mPausingTasks.clear();
+ setSplitsVisible(false);
+
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
+ true /* reparentLeafTaskIfRelaunch */);
+ mTaskOrganizer.applyTransaction(wct);
}
/** Call this when the recents animation during split-screen finishes. */
@@ -2910,7 +2942,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
setSplitsVisible(false);
finishWct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
true /* reparentLeafTaskIfRelaunch */);
- logExit(EXIT_REASON_UNKNOWN);
}
/** Call this when the recents animation finishes by doing pair-to-pair switch. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 92ff5fed4584..a01eddbc9b9f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -127,7 +127,8 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
* Returns the top visible child task's id.
*/
int getTopVisibleChildTaskId() {
- final ActivityManager.RunningTaskInfo taskInfo = getChildTaskInfo(t -> t.isVisible);
+ final ActivityManager.RunningTaskInfo taskInfo = getChildTaskInfo(t -> t.isVisible
+ && t.isVisibleRequested);
return taskInfo != null ? taskInfo.taskId : INVALID_TASK_ID;
}
@@ -183,12 +184,13 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
final int taskId = taskInfo.taskId;
mChildrenLeashes.put(taskId, leash);
mChildrenTaskInfo.put(taskId, taskInfo);
- updateChildTaskSurface(taskInfo, leash, true /* firstAppeared */);
- mCallbacks.onChildTaskStatusChanged(taskId, true /* present */, taskInfo.isVisible);
+ mCallbacks.onChildTaskStatusChanged(taskId, true /* present */,
+ taskInfo.isVisible && taskInfo.isVisibleRequested);
if (ENABLE_SHELL_TRANSITIONS) {
// Status is managed/synchronized by the transition lifecycle.
return;
}
+ updateChildTaskSurface(taskInfo, leash, true /* firstAppeared */);
mCallbacks.onChildTaskAppeared(taskId);
sendStatusChanged();
} else {
@@ -223,7 +225,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
}
mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
mCallbacks.onChildTaskStatusChanged(taskInfo.taskId, true /* present */,
- taskInfo.isVisible);
+ taskInfo.isVisible && taskInfo.isVisibleRequested);
if (!ENABLE_SHELL_TRANSITIONS) {
updateChildTaskSurface(
taskInfo, mChildrenLeashes.get(taskInfo.taskId), false /* firstAppeared */);
@@ -417,7 +419,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
}
t.setCrop(leash, null);
t.setPosition(leash, taskPositionInParent.x, taskPositionInParent.y);
- if (firstAppeared && !ENABLE_SHELL_TRANSITIONS) {
+ if (firstAppeared) {
t.setAlpha(leash, 1f);
t.setMatrix(leash, 1, 0, 0, 1);
t.show(leash);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
index ae722208782e..4cfbbd971fe3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
@@ -20,6 +20,7 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Choreographer.CALLBACK_INSETS_ANIMATION;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
@@ -370,8 +371,11 @@ class SplashscreenWindowCreator extends AbsSplashWindowCreator {
mStartingWindowRecordManager.addRecord(taskId, tView);
}
- private void removeWindowInner(View decorView, boolean hideView) {
+ private void removeWindowInner(@NonNull View decorView, boolean hideView) {
requestTopUi(false);
+ if (!decorView.isAttachedToWindow()) {
+ return;
+ }
if (hideView) {
decorView.setVisibility(View.GONE);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
index 1bbd3679948b..163cf501734c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
@@ -61,6 +61,16 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
private TaskViewBase mTaskViewBase;
private final Context mContext;
+ /**
+ * There could be a situation where we have task info and receive
+ * {@link #onTaskAppeared(ActivityManager.RunningTaskInfo, SurfaceControl)}, however, the
+ * activity might fail to open, and in this case we need to clean up the task view / notify
+ * listeners of a task removal. This requires task info, so we save the info from onTaskAppeared
+ * in this situation to allow us to notify listeners correctly if the task failed to open.
+ */
+ private ActivityManager.RunningTaskInfo mPendingInfo;
+ /* Indicates that the task we attempted to launch in the task view failed to launch. */
+ private boolean mTaskNotFound;
protected ActivityManager.RunningTaskInfo mTaskInfo;
private WindowContainerToken mTaskToken;
private SurfaceControl mTaskLeash;
@@ -236,6 +246,8 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
mTaskInfo = null;
mTaskToken = null;
mTaskLeash = null;
+ mPendingInfo = null;
+ mTaskNotFound = false;
}
private void updateTaskVisibility() {
@@ -257,6 +269,12 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl leash) {
if (isUsingShellTransitions()) {
+ mPendingInfo = taskInfo;
+ if (mTaskNotFound) {
+ // If we were already notified by shell transit that we don't have the
+ // the task, clean it up now.
+ cleanUpPendingTask();
+ }
// Everything else handled by enter transition.
return;
}
@@ -455,6 +473,42 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
return mTaskInfo;
}
+ /**
+ * Indicates that the task was not found in the start animation for the transition.
+ * In this case we should clean up the task if we have the pending info. If we don't
+ * have the pending info, we'll do it when we receive it in
+ * {@link #onTaskAppeared(ActivityManager.RunningTaskInfo, SurfaceControl)}.
+ */
+ void setTaskNotFound() {
+ mTaskNotFound = true;
+ if (mPendingInfo != null) {
+ cleanUpPendingTask();
+ }
+ }
+
+ /**
+ * Called when a task failed to open and we need to clean up task view /
+ * notify users of task view.
+ */
+ void cleanUpPendingTask() {
+ if (mPendingInfo != null) {
+ if (mListener != null) {
+ final int taskId = mPendingInfo.taskId;
+ mListenerExecutor.execute(() -> {
+ mListener.onTaskRemovalStarted(taskId);
+ });
+ }
+ mTaskViewBase.onTaskVanished(mPendingInfo);
+ mTaskOrganizer.setInterceptBackPressedOnTaskRoot(mPendingInfo.token, false);
+
+ // Make sure the task is removed
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.removeTask(mPendingInfo.token);
+ mTaskViewTransitions.closeTaskView(wct, this);
+ }
+ resetTaskInfo();
+ }
+
void prepareHideAnimation(@NonNull SurfaceControl.Transaction finishTransaction) {
if (mTaskToken == null) {
// Nothing to update, task is not yet available
@@ -492,6 +546,7 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
@NonNull SurfaceControl.Transaction finishTransaction,
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash,
WindowContainerTransaction wct) {
+ mPendingInfo = null;
mTaskInfo = taskInfo;
mTaskToken = mTaskInfo.token;
mTaskLeash = leash;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
index 2e7fca3f2b46..5baf2e320227 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
@@ -139,7 +139,8 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
* `taskView`.
* @param taskView the pending transition should be for this.
*/
- private PendingTransition findPendingOpeningTransition(TaskViewTaskController taskView) {
+ @VisibleForTesting
+ PendingTransition findPendingOpeningTransition(TaskViewTaskController taskView) {
for (int i = mPending.size() - 1; i >= 0; --i) {
if (mPending.get(i).mTaskView != taskView) continue;
if (TransitionUtil.isOpeningType(mPending.get(i).mType)) {
@@ -398,10 +399,11 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
}
}
if (stillNeedsMatchingLaunch) {
- throw new IllegalStateException("Expected a TaskView launch in this transition but"
- + " didn't get one.");
- }
- if (wct == null && pending == null && changesHandled != info.getChanges().size()) {
+ Slog.w(TAG, "Expected a TaskView launch in this transition but didn't get one, "
+ + "cleaning up the task view");
+ // Didn't find a task so the task must have never launched
+ pending.mTaskView.setTaskNotFound();
+ } else if (wct == null && pending == null && changesHandled != info.getChanges().size()) {
// Just some house-keeping, let another handler animate.
return false;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index 3ec433e55da9..3059e855b16c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -24,14 +24,15 @@ import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP;
import static com.android.wm.shell.util.TransitionUtil.isOpeningType;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.PendingIntent;
import android.os.IBinder;
-import android.util.Log;
import android.util.Pair;
import android.view.SurfaceControl;
import android.view.WindowManager;
@@ -41,6 +42,7 @@ import android.window.WindowContainerTransaction;
import android.window.WindowContainerTransactionCallback;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.common.split.SplitScreenUtils;
import com.android.wm.shell.keyguard.KeyguardTransitionHandler;
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.pip.phone.PipTouchHandler;
@@ -49,6 +51,7 @@ import com.android.wm.shell.recents.RecentsTransitionHandler;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.splitscreen.StageCoordinator;
import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.unfold.UnfoldTransitionHandler;
import com.android.wm.shell.util.TransitionUtil;
import java.util.ArrayList;
@@ -66,6 +69,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
private RecentsTransitionHandler mRecentsHandler;
private StageCoordinator mSplitHandler;
private final KeyguardTransitionHandler mKeyguardHandler;
+ private UnfoldTransitionHandler mUnfoldHandler;
private static class MixedTransition {
static final int TYPE_ENTER_PIP_FROM_SPLIT = 1;
@@ -82,6 +86,9 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
/** Keyguard exit/occlude/unocclude transition. */
static final int TYPE_KEYGUARD = 5;
+ /** Fuld/Unfold transition. */
+ static final int TYPE_UNFOLD = 6;
+
/** The default animation for this mixed transition. */
static final int ANIM_TYPE_DEFAULT = 0;
@@ -133,7 +140,8 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
Optional<SplitScreenController> splitScreenControllerOptional,
Optional<PipTouchHandler> pipTouchHandlerOptional,
Optional<RecentsTransitionHandler> recentsHandlerOptional,
- KeyguardTransitionHandler keyguardHandler) {
+ KeyguardTransitionHandler keyguardHandler,
+ Optional<UnfoldTransitionHandler> unfoldHandler) {
mPlayer = player;
mKeyguardHandler = keyguardHandler;
if (Transitions.ENABLE_SHELL_TRANSITIONS && pipTouchHandlerOptional.isPresent()
@@ -150,6 +158,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
if (mRecentsHandler != null) {
mRecentsHandler.addMixer(this);
}
+ mUnfoldHandler = unfoldHandler.orElse(null);
}, this);
}
}
@@ -158,7 +167,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
@Override
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
@NonNull TransitionRequestInfo request) {
- if (mPipHandler.requestHasPipEnter(request) && mSplitHandler.isSplitActive()) {
+ if (mSplitHandler.requestImpliesSplitToPip(request)) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a PiP-enter request while "
+ "Split-Screen is active, so treat it as Mixed.");
if (request.getRemoteTransition() != null) {
@@ -213,6 +222,16 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
mixed.mLeftoversHandler = handler.first;
mActiveTransitions.add(mixed);
return handler.second;
+ } else if (mUnfoldHandler != null && mUnfoldHandler.hasUnfold(request)) {
+ final WindowContainerTransaction wct =
+ mUnfoldHandler.handleRequest(transition, request);
+ if (wct != null) {
+ final MixedTransition mixed = new MixedTransition(
+ MixedTransition.TYPE_UNFOLD, transition);
+ mixed.mLeftoversHandler = mUnfoldHandler;
+ mActiveTransitions.add(mixed);
+ }
+ return wct;
}
return null;
}
@@ -302,11 +321,26 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
return animateOpenIntentWithRemoteAndPip(mixed, info, startTransaction,
finishTransaction, finishCallback);
} else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_SPLIT) {
+ for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+ final TransitionInfo.Change change = info.getChanges().get(i);
+ // Pip auto-entering info might be appended to recent transition like pressing
+ // home-key in 3-button navigation. This offers split handler the opportunity to
+ // handle split to pip animation.
+ if (mPipHandler.isEnteringPip(change, info.getType())
+ && mSplitHandler.getSplitItemPosition(change.getLastParent())
+ != SPLIT_POSITION_UNDEFINED) {
+ return animateEnterPipFromSplit(mixed, info, startTransaction,
+ finishTransaction, finishCallback);
+ }
+ }
+
return animateRecentsDuringSplit(mixed, info, startTransaction, finishTransaction,
finishCallback);
} else if (mixed.mType == MixedTransition.TYPE_KEYGUARD) {
return animateKeyguard(mixed, info, startTransaction, finishTransaction,
finishCallback);
+ } else if (mixed.mType == MixedTransition.TYPE_UNFOLD) {
+ return animateUnfold(mixed, info, startTransaction, finishTransaction, finishCallback);
} else {
mActiveTransitions.remove(mixed);
throw new IllegalStateException("Starting mixed animation without a known mixed type? "
@@ -574,11 +608,12 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
finishCallback.onTransitionFinished(wct, wctCB);
}
};
+ mixed.mInFlightSubAnimations++;
if (!mKeyguardHandler.startAnimation(
mixed.mTransition, info, startTransaction, finishTransaction, finishCB)) {
+ mixed.mInFlightSubAnimations--;
return false;
}
- mixed.mInFlightSubAnimations++;
// Sync pip state.
if (mPipHandler != null) {
// We don't know when to apply `startTransaction` so use a separate transaction here.
@@ -590,6 +625,49 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
return true;
}
+ private boolean animateUnfold(@NonNull final MixedTransition mixed,
+ @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction startTransaction,
+ @NonNull SurfaceControl.Transaction finishTransaction,
+ @NonNull Transitions.TransitionFinishCallback finishCallback) {
+ final Transitions.TransitionFinishCallback finishCB = (wct, wctCB) -> {
+ mixed.mInFlightSubAnimations--;
+ if (mixed.mInFlightSubAnimations > 0) return;
+ mActiveTransitions.remove(mixed);
+ finishCallback.onTransitionFinished(wct, wctCB);
+ };
+ mixed.mInFlightSubAnimations = 1;
+ if (!mUnfoldHandler.startAnimation(
+ mixed.mTransition, info, startTransaction, finishTransaction, finishCB)) {
+ return false;
+ }
+ // Sync pip state.
+ if (mPipHandler != null) {
+ // We don't know when to apply `startTransaction` so use a separate transaction here.
+ // This should be fine because these surface properties are independent.
+ final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ mPipHandler.syncPipSurfaceState(info, t, finishTransaction);
+ t.apply();
+ }
+ return true;
+ }
+
+ /** Use to when split use intent to enter, check if this enter transition should be mixed or
+ * not.*/
+ public boolean shouldSplitEnterMixed(PendingIntent intent) {
+ // Check if this intent package is same as pip one or not, if true we want let the pip
+ // task enter split.
+ if (mPipHandler != null) {
+ return mPipHandler.isInPipPackage(SplitScreenUtils.getPackageName(intent.getIntent()));
+ }
+ return false;
+ }
+
+ /** @return whether the transition-request represents a pip-entry. */
+ public boolean requestHasPipEnter(TransitionRequestInfo request) {
+ return mPipHandler.requestHasPipEnter(request);
+ }
+
@Override
public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
@@ -633,6 +711,8 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
finishCallback);
} else if (mixed.mType == MixedTransition.TYPE_KEYGUARD) {
mKeyguardHandler.mergeAnimation(transition, info, t, mergeTarget, finishCallback);
+ } else if (mixed.mType == MixedTransition.TYPE_UNFOLD) {
+ mUnfoldHandler.mergeAnimation(transition, info, t, mergeTarget, finishCallback);
} else {
throw new IllegalStateException("Playing a mixed transition with unknown type? "
+ mixed.mType);
@@ -658,6 +738,8 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
mixed.mLeftoversHandler.onTransitionConsumed(transition, aborted, finishT);
} else if (mixed.mType == MixedTransition.TYPE_KEYGUARD) {
mKeyguardHandler.onTransitionConsumed(transition, aborted, finishT);
+ } else if (mixed.mType == MixedTransition.TYPE_UNFOLD) {
+ mUnfoldHandler.onTransitionConsumed(transition, aborted, finishT);
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index 3bf278cc46cf..e52fd00e7df7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -260,6 +260,12 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
// This is the only way to get display-id currently, so check display capabilities here.
final DisplayLayout displayLayout = displayController.getDisplayLayout(
topTaskInfo.displayId);
+ // This condition should be true when using gesture navigation or the screen size is large
+ // (>600dp) because the bar is small relative to screen.
+ if (displayLayout.allowSeamlessRotationDespiteNavBarMoving()) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " nav bar allows seamless.");
+ return ROTATION_ANIMATION_SEAMLESS;
+ }
// For the upside down rotation we don't rotate seamlessly as the navigation bar moves
// position. Note most apps (using orientation:sensor or user as opposed to fullSensor)
// will not enter the reverse portrait orientation, so actually the orientation won't
@@ -272,13 +278,9 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
return animationHint;
}
- // If the navigation bar can't change sides, then it will jump when we change orientations
- // and we don't rotate seamlessly - unless that is allowed, e.g. with gesture navigation
- // where the navbar is low-profile enough that this isn't very noticeable.
- if (!displayLayout.allowSeamlessRotationDespiteNavBarMoving()
- && (!(displayLayout.navigationBarCanMove()
- && (displayChange.getStartAbsBounds().width()
- != displayChange.getStartAbsBounds().height())))) {
+ // If the navigation bar cannot change sides, then it will jump when changing orientation
+ // so do not use seamless rotation.
+ if (!displayLayout.navigationBarCanMove()) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
" nav bar changes sides, so not seamless.");
return animationHint;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index cdc82eadcd90..2327d86ab618 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -809,6 +809,9 @@ public class Transitions implements RemoteCallable<Transitions>,
track.mReadyTransitions.remove(0);
track.mActiveTransition = ready;
if (ready.mAborted) {
+ if (ready.mStartT != null) {
+ ready.mStartT.apply();
+ }
// finish now since there's nothing to animate. Calls back into processReadyQueue
onFinish(ready, null, null);
return;
@@ -936,10 +939,6 @@ public class Transitions implements RemoteCallable<Transitions>,
/** Aborts a transition. This will still queue it up to maintain order. */
private void onAbort(ActiveTransition transition) {
final Track track = mTracks.get(transition.getTrack());
- // apply immediately since they may be "parallel" operations: We currently we use abort for
- // thing which are independent to other transitions (like starting-window transfer).
- transition.mStartT.apply();
- transition.mFinishT.apply();
transition.mAborted = true;
mTracer.logAborted(transition.mInfo.getDebugId());
@@ -1086,9 +1085,8 @@ public class Transitions implements RemoteCallable<Transitions>,
if (wct == null) {
wct = new WindowContainerTransaction();
}
- mDisplayController.getChangeController().dispatchOnDisplayChange(wct,
- change.getDisplayId(), change.getStartRotation(),
- change.getEndRotation(), null /* newDisplayAreaInfo */);
+ mDisplayController.onDisplayRotateRequested(wct, change.getDisplayId(),
+ change.getStartRotation(), change.getEndRotation());
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java
index c504f57216f3..f148412205bf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java
@@ -20,6 +20,7 @@ import static android.view.WindowManager.TRANSIT_CHANGE;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TRANSITIONS;
+import android.app.ActivityManager;
import android.os.IBinder;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
@@ -178,18 +179,36 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene
@NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
@NonNull TransitionFinishCallback finishCallback) {
if (info.getType() == TRANSIT_CHANGE) {
+ // TODO (b/286928742) unfold transition handler should be part of mixed handler to
+ // handle merges better.
+ for (int i = 0; i < info.getChanges().size(); ++i) {
+ final TransitionInfo.Change change = info.getChanges().get(i);
+ final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+ if (taskInfo != null
+ && taskInfo.configuration.windowConfiguration.isAlwaysOnTop()) {
+ // Tasks that are always on top (e.g. bubbles), will handle their own transition
+ // as they are on top of everything else. So skip merging transitions here.
+ return;
+ }
+ }
// Apply changes happening during the unfold animation immediately
t.apply();
finishCallback.onTransitionFinished(null, null);
}
}
+ /** Whether `request` contains an unfold action. */
+ public boolean hasUnfold(@NonNull TransitionRequestInfo request) {
+ return (request.getType() == TRANSIT_CHANGE
+ && request.getDisplayChange() != null
+ && request.getDisplayChange().isPhysicalDisplayChanged());
+ }
+
@Nullable
@Override
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
@NonNull TransitionRequestInfo request) {
- if (request.getType() == TRANSIT_CHANGE && request.getDisplayChange() != null
- && request.getDisplayChange().isPhysicalDisplayChanged()) {
+ if (hasUnfold(request)) {
mTransition = transition;
return new WindowContainerTransaction();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
index c33a633f2068..936faa3ee6bf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
@@ -170,6 +170,9 @@ public class TransitionUtil {
if (isOpeningType(mode)) {
t.setAlpha(leash, 0.f);
}
+ // Set the transition leash position to 0 in case the divider leash position being
+ // taking down.
+ t.setPosition(leash, 0, 0);
t.setLayer(leash, Integer.MAX_VALUE);
return;
}
@@ -228,7 +231,11 @@ public class TransitionUtil {
t.reparent(change.getLeash(), leashSurface);
t.setAlpha(change.getLeash(), 1.0f);
t.show(change.getLeash());
- t.setPosition(change.getLeash(), 0, 0);
+ if (!isDividerBar(change)) {
+ // For divider, don't modify its inner leash position when creating the outer leash
+ // for the transition. In case the position being wrong after the transition finished.
+ t.setPosition(change.getLeash(), 0, 0);
+ }
t.setLayer(change.getLeash(), 0);
return leashSurface;
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipFromSplitScreenOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipFromSplitScreenOnGoToHomeTest.kt
new file mode 100644
index 000000000000..f7ce87088040
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipFromSplitScreenOnGoToHomeTest.kt
@@ -0,0 +1,200 @@
+/*
+ * 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.wm.shell.flicker.pip
+
+import android.app.Instrumentation
+import android.os.SystemClock
+import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
+import android.tools.device.traces.parsers.toFlickerComponent
+import androidx.test.filters.RequiresDevice
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.BySelector
+import androidx.test.uiautomator.UiObject2
+import androidx.test.uiautomator.Until
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.server.wm.flicker.testapp.ActivityOptions
+import com.android.wm.shell.flicker.LAUNCHER_UI_PACKAGE_NAME
+import org.junit.Assume
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test entering pip from an app via auto-enter property when navigating to home from split screen.
+ *
+ * To run this test: `atest WMShellFlickerTests:AutoEnterPipOnGoToHomeTest`
+ *
+ * Actions:
+ * ```
+ * Launch an app in full screen
+ * Select "Auto-enter PiP" radio button
+ * Open all apps and drag another app icon to enter split screen
+ * Press Home button or swipe up to go Home and put [pipApp] in pip mode
+ * ```
+ *
+ * Notes:
+ * ```
+ * 1. All assertions are inherited from [EnterPipTest]
+ * 2. Part of the test setup occurs automatically via
+ * [android.tools.device.flicker.legacy.runner.TransitionRunner],
+ * including configuring navigation mode, initial orientation and ensuring no
+ * apps are running before setup
+ * ```
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class AutoEnterPipFromSplitScreenOnGoToHomeTest(flicker: FlickerTest) :
+ AutoEnterPipOnGoToHomeTest(flicker) {
+ private val portraitDisplayBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_0)
+ /** Second app used to enter split screen mode */
+ protected val secondAppForSplitScreen = getSplitScreenApp(instrumentation)
+ fun getSplitScreenApp(instrumentation: Instrumentation): StandardAppHelper =
+ SimpleAppHelper(
+ instrumentation,
+ ActivityOptions.SplitScreen.Primary.LABEL,
+ ActivityOptions.SplitScreen.Primary.COMPONENT.toFlickerComponent()
+ )
+
+ /** Defines the transition used to run the test */
+ override val transition: FlickerBuilder.() -> Unit
+ get() = {
+ setup {
+ secondAppForSplitScreen.launchViaIntent(wmHelper)
+ pipApp.launchViaIntent(wmHelper)
+ tapl.goHome()
+ enterSplitScreen()
+ // wait until split screen is established
+ wmHelper
+ .StateSyncBuilder()
+ .withWindowSurfaceAppeared(pipApp)
+ .withWindowSurfaceAppeared(secondAppForSplitScreen)
+ .withSplitDividerVisible()
+ .waitForAndVerify()
+ pipApp.enableAutoEnterForPipActivity()
+ }
+ teardown {
+ // close gracefully so that onActivityUnpinned() can be called before force exit
+ pipApp.closePipWindow(wmHelper)
+ pipApp.exit(wmHelper)
+ secondAppForSplitScreen.exit(wmHelper)
+ }
+ transitions { tapl.goHome() }
+ }
+
+ // TODO(b/285400227) merge the code in a common utility - this is copied from SplitScreenUtils
+ private val TIMEOUT_MS = 3_000L
+ private val overviewSnapshotSelector: BySelector
+ get() = By.res(LAUNCHER_UI_PACKAGE_NAME, "snapshot")
+ private fun enterSplitScreen() {
+ // Note: The initial split position in landscape is different between tablet and phone.
+ // In landscape, tablet will let the first app split to right side, and phone will
+ // split to left side.
+ if (tapl.isTablet) {
+ // TAPL's currentTask on tablet is sometimes not what we expected if the overview
+ // contains more than 3 task views. We need to use uiautomator directly to find the
+ // second task to split.
+ tapl.workspace.switchToOverview().overviewActions.clickSplit()
+ val snapshots = tapl.device.wait(Until.findObjects(overviewSnapshotSelector),
+ TIMEOUT_MS)
+ if (snapshots == null || snapshots.size < 1) {
+ error("Fail to find a overview snapshot to split.")
+ }
+
+ // Find the second task in the upper right corner in split select mode by sorting
+ // 'left' in descending order and 'top' in ascending order.
+ snapshots.sortWith { t1: UiObject2, t2: UiObject2 ->
+ t2.getVisibleBounds().left - t1.getVisibleBounds().left
+ }
+ snapshots.sortWith { t1: UiObject2, t2: UiObject2 ->
+ t1.getVisibleBounds().top - t2.getVisibleBounds().top
+ }
+ snapshots[0].click()
+ } else {
+ tapl.workspace
+ .switchToOverview()
+ .currentTask
+ .tapMenu()
+ .tapSplitMenuItem()
+ .currentTask
+ .open()
+ }
+ SystemClock.sleep(TIMEOUT_MS)
+ }
+
+ @Presubmit
+ @Test
+ override fun pipOverlayLayerAppearThenDisappear() {
+ // when entering from split screen we use alpha animation, without overlay
+ }
+
+ @Presubmit
+ @Test
+ override fun pipLayerOrOverlayRemainInsideVisibleBounds() {
+ // when entering from split screen we use alpha animation, without overlay
+ }
+
+ @Presubmit
+ @Test
+ override fun pipLayerReduces() {
+ // when entering from split screen we use alpha animation, so there is no size change
+ Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+ super.pipLayerReduces()
+ }
+
+ @Presubmit
+ @Test
+ override fun pipAppLayerAlwaysVisible() {
+ // pip layer in gesture nav will disappear during transition with alpha animation
+ Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+ super.pipAppLayerAlwaysVisible()
+ }
+
+ @Presubmit
+ @Test
+ override fun pipWindowRemainInsideVisibleBounds() {
+ if (tapl.isTablet) {
+ flicker.assertWmVisibleRegion(pipApp) { coversAtMost(displayBounds) }
+ } else {
+ // on phones home does not rotate in landscape, PiP enters back to portrait
+ // orientation so use display bounds from that orientation for assertion
+ flicker.assertWmVisibleRegion(pipApp) { coversAtMost(portraitDisplayBounds) }
+ }
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): List<FlickerTest> {
+ return FlickerTestFactory.nonRotationTests(
+ // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
+ )
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
index ef7bedf49a92..b95732e43357 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
@@ -53,7 +53,7 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class AutoEnterPipOnGoToHomeTest(flicker: FlickerTest) : EnterPipViaAppUiButtonTest(flicker) {
+open class AutoEnterPipOnGoToHomeTest(flicker: FlickerTest) : EnterPipViaAppUiButtonTest(flicker) {
override val thisTransition: FlickerBuilder.() -> Unit = {
transitions { tapl.goHome() }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
index 95121def07bc..cdbdb85a9195 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
@@ -62,7 +62,7 @@ abstract class EnterPipTransition(flicker: FlickerTest) : PipTransition(flicker)
*/
@Presubmit
@Test
- fun pipWindowRemainInsideVisibleBounds() {
+ open fun pipWindowRemainInsideVisibleBounds() {
flicker.assertWmVisibleRegion(pipApp) { coversAtMost(displayBounds) }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index 3d779481d361..443cea245a4f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
@@ -41,6 +42,7 @@ import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
+import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import org.junit.Before;
@@ -57,6 +59,7 @@ import org.mockito.MockitoAnnotations;
public class SplitLayoutTests extends ShellTestCase {
@Mock SplitLayout.SplitLayoutHandler mSplitLayoutHandler;
@Mock SplitWindowManager.ParentContainerCallbacks mCallbacks;
+ @Mock DisplayController mDisplayController;
@Mock DisplayImeController mDisplayImeController;
@Mock ShellTaskOrganizer mTaskOrganizer;
@Mock WindowContainerTransaction mWct;
@@ -72,6 +75,7 @@ public class SplitLayoutTests extends ShellTestCase {
getConfiguration(),
mSplitLayoutHandler,
mCallbacks,
+ mDisplayController,
mDisplayImeController,
mTaskOrganizer,
SplitLayout.PARALLAX_NONE));
@@ -100,6 +104,10 @@ public class SplitLayoutTests extends ShellTestCase {
// Verify updateConfiguration returns true if the density changed.
config.densityDpi = 123;
assertThat(mSplitLayout.updateConfiguration(config)).isTrue();
+
+ // Verify updateConfiguration checks the current DisplayLayout
+ verify(mDisplayController, times(5)) // init * 1 + updateConfiguration * 4
+ .getDisplayLayout(anyInt());
}
@Test
@@ -168,6 +176,14 @@ public class SplitLayoutTests extends ShellTestCase {
verify(mWct).setSmallestScreenWidthDp(eq(task2.token), anyInt());
}
+ @Test
+ public void testRoateTo_checksDisplayLayout() {
+ mSplitLayout.rotateTo(90);
+
+ verify(mDisplayController, times(2)) // init * 1 + rotateTo * 1
+ .getDisplayLayout(anyInt());
+ }
+
private void waitDividerFlingFinished() {
verify(mSplitLayout).flingDividePosition(anyInt(), anyInt(), anyInt(),
mRunnableCaptor.capture());
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java
deleted file mode 100644
index 58e91cb50c7a..000000000000
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.kidsmode;
-
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.pm.ParceledListSlice;
-import android.content.res.Resources;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.view.InsetsState;
-import android.view.SurfaceControl;
-import android.window.ITaskOrganizerController;
-import android.window.TaskAppearedInfo;
-import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.wm.shell.ShellTestCase;
-import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.DisplayInsetsController;
-import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.sysui.ShellCommandHandler;
-import com.android.wm.shell.sysui.ShellInit;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.Optional;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class KidsModeTaskOrganizerTest extends ShellTestCase {
- @Mock private ITaskOrganizerController mTaskOrganizerController;
- @Mock private Context mContext;
- @Mock private Handler mHandler;
- @Mock private SyncTransactionQueue mSyncTransactionQueue;
- @Mock private ShellExecutor mTestExecutor;
- @Mock private DisplayController mDisplayController;
- @Mock private SurfaceControl mLeash;
- @Mock private WindowContainerToken mToken;
- @Mock private WindowContainerTransaction mTransaction;
- @Mock private KidsModeSettingsObserver mObserver;
- @Mock private ShellInit mShellInit;
- @Mock private ShellCommandHandler mShellCommandHandler;
- @Mock private DisplayInsetsController mDisplayInsetsController;
- @Mock private Resources mResources;
-
- KidsModeTaskOrganizer mOrganizer;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- try {
- doReturn(ParceledListSlice.<TaskAppearedInfo>emptyList())
- .when(mTaskOrganizerController).registerTaskOrganizer(any());
- } catch (RemoteException e) {
- }
- // NOTE: KidsModeTaskOrganizer should have a null CompatUIController.
- doReturn(mResources).when(mContext).getResources();
- final KidsModeTaskOrganizer kidsModeTaskOrganizer = new KidsModeTaskOrganizer(mContext,
- mShellInit, mShellCommandHandler, mTaskOrganizerController, mSyncTransactionQueue,
- mDisplayController, mDisplayInsetsController, Optional.empty(), Optional.empty(),
- mObserver, mTestExecutor, mHandler);
- mOrganizer = spy(kidsModeTaskOrganizer);
- doReturn(mTransaction).when(mOrganizer).getWindowContainerTransaction();
- doReturn(new InsetsState()).when(mDisplayController).getInsetsState(DEFAULT_DISPLAY);
- }
-
- @Test
- public void instantiateController_addInitCallback() {
- verify(mShellInit, times(1)).addInitCallback(any(), any());
- }
-
- @Test
- public void testKidsModeOn() {
- doReturn(true).when(mObserver).isEnabled();
-
- mOrganizer.updateKidsModeState();
-
- verify(mOrganizer, times(1)).enable();
- verify(mOrganizer, times(1)).registerOrganizer();
- verify(mOrganizer, times(1)).createRootTask(
- eq(DEFAULT_DISPLAY), eq(WINDOWING_MODE_FULLSCREEN), eq(mOrganizer.mCookie));
- verify(mOrganizer, times(1))
- .setOrientationRequestPolicy(eq(true), any(), any());
-
- final ActivityManager.RunningTaskInfo rootTask = createTaskInfo(12,
- WINDOWING_MODE_FULLSCREEN, mOrganizer.mCookie);
- mOrganizer.onTaskAppeared(rootTask, mLeash);
-
- assertThat(mOrganizer.mLaunchRootLeash).isEqualTo(mLeash);
- assertThat(mOrganizer.mLaunchRootTask).isEqualTo(rootTask);
- }
-
- @Test
- public void testKidsModeOff() {
- doReturn(true).when(mObserver).isEnabled();
- mOrganizer.updateKidsModeState();
- final ActivityManager.RunningTaskInfo rootTask = createTaskInfo(12,
- WINDOWING_MODE_FULLSCREEN, mOrganizer.mCookie);
- mOrganizer.onTaskAppeared(rootTask, mLeash);
-
- doReturn(false).when(mObserver).isEnabled();
- mOrganizer.updateKidsModeState();
-
- verify(mOrganizer, times(1)).disable();
- verify(mOrganizer, times(1)).unregisterOrganizer();
- verify(mOrganizer, times(1)).deleteRootTask(rootTask.token);
- verify(mOrganizer, times(1))
- .setOrientationRequestPolicy(eq(false), any(), any());
- assertThat(mOrganizer.mLaunchRootLeash).isNull();
- assertThat(mOrganizer.mLaunchRootTask).isNull();
- }
-
- private ActivityManager.RunningTaskInfo createTaskInfo(
- int taskId, int windowingMode, IBinder cookies) {
- ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
- taskInfo.taskId = taskId;
- taskInfo.token = mToken;
- taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode);
- final ArrayList<IBinder> launchCookies = new ArrayList<>();
- if (cookies != null) {
- launchCookies.add(cookies);
- }
- taskInfo.launchCookies = launchCookies;
- return taskInfo;
- }
-}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java
index 4d7e9e450ceb..cc9e26b2c4f1 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java
@@ -18,6 +18,9 @@ package com.android.wm.shell.pip.phone;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
@@ -26,10 +29,13 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.pip.PipBoundsAlgorithm;
+import com.android.wm.shell.pip.PipBoundsState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import java.util.Set;
@@ -42,6 +48,10 @@ import java.util.Set;
public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
private PhonePipKeepClearAlgorithm mPipKeepClearAlgorithm;
+
+ @Mock private PipBoundsAlgorithm mMockPipBoundsAlgorithm;
+ @Mock private PipBoundsState mMockPipBoundsState;
+
private static final Rect DISPLAY_BOUNDS = new Rect(0, 0, 1000, 1000);
@Before
@@ -73,7 +83,6 @@ public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
@Test
public void findUnoccludedPosition_withCollidingUnrestrictedKeepClearArea_moveBounds() {
- // TODO(b/183746978): update this test to accommodate for the updated algorithm
final Rect inBounds = new Rect(0, 0, 100, 100);
final Rect keepClearRect = new Rect(50, 50, 150, 150);
@@ -93,4 +102,202 @@ public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
assertEquals(inBounds, outBounds);
}
+
+ @Test
+ public void adjust_withCollidingRestrictedKeepClearArea_moveBounds() {
+ final Rect pipBounds = new Rect(0, 0, 100, 100);
+ final Rect keepClearRect = new Rect(50, 50, 150, 150);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestrictedKeepClearAreas()).thenReturn(Set.of(keepClearRect));
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertFalse(outBounds.contains(keepClearRect));
+ }
+
+ @Test
+ public void adjust_withNonCollidingRestrictedKeepClearArea_boundsUnchanged() {
+ final Rect pipBounds = new Rect(0, 0, 100, 100);
+ final Rect keepClearRect = new Rect(100, 100, 150, 150);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestrictedKeepClearAreas()).thenReturn(Set.of(keepClearRect));
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertFalse(outBounds.contains(keepClearRect));
+ }
+
+ @Test
+ public void adjust_withCollidingRestrictedKeepClearArea_whileStashed_boundsUnchanged() {
+ final Rect pipBounds = new Rect(0, 0, 100, 100);
+ final Rect keepClearRect = new Rect(50, 50, 150, 150);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.isStashed()).thenReturn(true);
+ when(mMockPipBoundsState.getRestrictedKeepClearAreas()).thenReturn(Set.of(keepClearRect));
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(pipBounds, outBounds);
+ }
+
+ @Test
+ public void adjust_withNonCollidingRestrictedKeepClearArea_whileStashed_boundsUnchanged() {
+ final Rect pipBounds = new Rect(0, 0, 100, 100);
+ final Rect keepClearRect = new Rect(100, 100, 150, 150);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.isStashed()).thenReturn(true);
+ when(mMockPipBoundsState.getRestrictedKeepClearAreas()).thenReturn(Set.of(keepClearRect));
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(pipBounds, outBounds);
+ }
+
+ @Test
+ public void adjust_aboveDisplayBounds_onLeftEdge_appliesBottomLeftGravity() {
+ final Rect pipBounds = new Rect(
+ 0, DISPLAY_BOUNDS.top - 50, 100, DISPLAY_BOUNDS.top + 50);
+ final Rect expected = new Rect(
+ 0, DISPLAY_BOUNDS.bottom - 100, 100, DISPLAY_BOUNDS.bottom);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+ when(mMockPipBoundsAlgorithm.getSnapFraction(any(Rect.class))).thenReturn(0f);
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(expected, outBounds);
+ }
+
+ @Test
+ public void adjust_belowDisplayBounds_onLeftEdge_appliesBottomLeftGravity() {
+ final Rect pipBounds = new Rect(
+ 0, DISPLAY_BOUNDS.bottom - 50, 100, DISPLAY_BOUNDS.bottom + 50);
+ final Rect expected = new Rect(
+ 0, DISPLAY_BOUNDS.bottom - 100, 100, DISPLAY_BOUNDS.bottom);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+ when(mMockPipBoundsAlgorithm.getSnapFraction(any(Rect.class))).thenReturn(3f);
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(expected, outBounds);
+ }
+
+ @Test
+ public void adjust_aboveDisplayBounds_onRightEdge_appliesBottomRightGravity() {
+ final Rect pipBounds = new Rect(
+ DISPLAY_BOUNDS.right - 100, DISPLAY_BOUNDS.top - 50,
+ DISPLAY_BOUNDS.right, DISPLAY_BOUNDS.top + 50);
+ final Rect expected = new Rect(
+ DISPLAY_BOUNDS.right - 100, DISPLAY_BOUNDS.bottom - 100,
+ DISPLAY_BOUNDS.right, DISPLAY_BOUNDS.bottom);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+ when(mMockPipBoundsAlgorithm.getSnapFraction(any(Rect.class))).thenReturn(1f);
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(expected, outBounds);
+ }
+
+ @Test
+ public void adjust_belowDisplayBounds_onRightEdge_appliesBottomRightGravity() {
+ final Rect pipBounds = new Rect(
+ DISPLAY_BOUNDS.right - 100, DISPLAY_BOUNDS.bottom - 50,
+ DISPLAY_BOUNDS.right, DISPLAY_BOUNDS.bottom + 50);
+ final Rect expected = new Rect(
+ DISPLAY_BOUNDS.right - 100, DISPLAY_BOUNDS.bottom - 100,
+ DISPLAY_BOUNDS.right, DISPLAY_BOUNDS.bottom);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+ when(mMockPipBoundsAlgorithm.getSnapFraction(any(Rect.class))).thenReturn(2f);
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(expected, outBounds);
+ }
+
+ @Test
+ public void adjust_whileStashed_aboveDisplayBounds_alignsToBottomInset() {
+ final Rect pipBounds = new Rect(
+ 0, DISPLAY_BOUNDS.top - 50, 100, DISPLAY_BOUNDS.top + 50);
+ final Rect expected = new Rect(
+ 0, DISPLAY_BOUNDS.bottom - 100, 100, DISPLAY_BOUNDS.bottom);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.isStashed()).thenReturn(true);
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(expected, outBounds);
+ }
+
+ @Test
+ public void adjust_whileStashed_belowDisplayBounds_alignsToBottomInset() {
+ final Rect pipBounds = new Rect(
+ 0, DISPLAY_BOUNDS.bottom - 50, 100, DISPLAY_BOUNDS.bottom + 50);
+ final Rect expected = new Rect(
+ 0, DISPLAY_BOUNDS.bottom - 100, 100, DISPLAY_BOUNDS.bottom);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.isStashed()).thenReturn(true);
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(expected, outBounds);
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index 66b6c62f1dd6..2dcdc74e8ae7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -159,7 +159,7 @@ public class StageCoordinatorTests extends ShellTestCase {
mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
verify(mStageCoordinator).prepareEnterSplitScreen(eq(wct), eq(task),
- eq(SPLIT_POSITION_BOTTOM_OR_RIGHT));
+ eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), eq(false));
verify(mMainStage).reparentTopTask(eq(wct));
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition());
assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition());
@@ -177,7 +177,7 @@ public class StageCoordinatorTests extends ShellTestCase {
mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
verify(mStageCoordinator).prepareEnterSplitScreen(eq(wct), eq(task),
- eq(SPLIT_POSITION_BOTTOM_OR_RIGHT));
+ eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), eq(false));
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getMainStagePosition());
assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getSideStagePosition());
}
@@ -189,7 +189,7 @@ public class StageCoordinatorTests extends ShellTestCase {
mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
verify(mStageCoordinator).prepareEnterSplitScreen(eq(wct), eq(task),
- eq(SPLIT_POSITION_BOTTOM_OR_RIGHT));
+ eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), eq(false));
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition());
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
index 81fc8438eec0..1b389565c066 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
@@ -128,8 +128,8 @@ public class TaskViewTest extends ShellTestCase {
doReturn(true).when(mTransitions).isRegistered();
}
mTaskViewTransitions = spy(new TaskViewTransitions(mTransitions));
- mTaskViewTaskController = new TaskViewTaskController(mContext, mOrganizer,
- mTaskViewTransitions, mSyncQueue);
+ mTaskViewTaskController = spy(new TaskViewTaskController(mContext, mOrganizer,
+ mTaskViewTransitions, mSyncQueue));
mTaskView = new TaskView(mContext, mTaskViewTaskController);
mTaskView.setListener(mExecutor, mViewListener);
}
@@ -544,4 +544,23 @@ public class TaskViewTest extends ShellTestCase {
mTaskView.removeTask();
verify(mTaskViewTransitions).closeTaskView(any(), eq(mTaskViewTaskController));
}
+
+ @Test
+ public void testOnTaskAppearedWithTaskNotFound() {
+ assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
+
+ mTaskViewTaskController.setTaskNotFound();
+ mTaskViewTaskController.onTaskAppeared(mTaskInfo, mLeash);
+
+ verify(mTaskViewTaskController).cleanUpPendingTask();
+ verify(mTaskViewTransitions).closeTaskView(any(), eq(mTaskViewTaskController));
+ }
+
+ @Test
+ public void testOnTaskAppeared_withoutTaskNotFound() {
+ assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
+
+ mTaskViewTaskController.onTaskAppeared(mTaskInfo, mLeash);
+ verify(mTaskViewTaskController, never()).cleanUpPendingTask();
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionsTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionsTest.java
index 71ad0d79eaca..03ed18c86608 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionsTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionsTest.java
@@ -17,6 +17,7 @@
package com.android.wm.shell.taskview;
import static android.view.WindowManager.TRANSIT_CHANGE;
+import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static com.google.common.truth.Truth.assertThat;
@@ -25,16 +26,19 @@ import static org.junit.Assume.assumeTrue;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.graphics.Rect;
+import android.os.IBinder;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.transition.Transitions;
@@ -45,6 +49,7 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
import java.util.List;
@SmallTest
@@ -295,4 +300,34 @@ public class TaskViewTransitionsTest extends ShellTestCase {
mTaskViewTransitions.setTaskBounds(mTaskViewTaskController,
new Rect(0, 0, 100, 100));
}
+
+ @Test
+ public void test_startAnimation_setsTaskNotFound() {
+ assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
+
+ TransitionInfo.Change change = mock(TransitionInfo.Change.class);
+ when(change.getTaskInfo()).thenReturn(mTaskInfo);
+ when(change.getMode()).thenReturn(TRANSIT_OPEN);
+
+ List<TransitionInfo.Change> changes = new ArrayList<>();
+ changes.add(change);
+
+ TransitionInfo info = mock(TransitionInfo.class);
+ when(info.getChanges()).thenReturn(changes);
+
+ mTaskViewTransitions.startTaskView(new WindowContainerTransaction(),
+ mTaskViewTaskController,
+ mock(IBinder.class));
+
+ TaskViewTransitions.PendingTransition pending =
+ mTaskViewTransitions.findPendingOpeningTransition(mTaskViewTaskController);
+
+ mTaskViewTransitions.startAnimation(pending.mClaimed,
+ info,
+ new SurfaceControl.Transaction(),
+ new SurfaceControl.Transaction(),
+ mock(Transitions.TransitionFinishCallback.class));
+
+ verify(mTaskViewTaskController).setTaskNotFound();
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
index 963632b1f8f6..ff380e92322d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -51,7 +51,6 @@ import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
-import static org.mockito.Mockito.after;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
@@ -93,7 +92,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
-import com.android.server.testutils.StubTransaction;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestShellExecutor;
import com.android.wm.shell.TransitionInfoBuilder;
@@ -105,6 +103,7 @@ import com.android.wm.shell.recents.RecentsTransitionHandler;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.sysui.ShellSharedConstants;
+import com.android.wm.shell.util.StubTransaction;
import org.junit.Before;
import org.junit.Test;
@@ -703,8 +702,8 @@ public class ShellTransitionTests extends ShellTestCase {
createTaskInfo(1, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
final DisplayController displays = createTestDisplayController();
- final @Surface.Rotation int upsideDown = displays
- .getDisplayLayout(DEFAULT_DISPLAY).getUpsideDownRotation();
+ final DisplayLayout displayLayout = displays.getDisplayLayout(DEFAULT_DISPLAY);
+ final @Surface.Rotation int upsideDown = displayLayout.getUpsideDownRotation();
TransitionInfo.Change displayChange = new ChangeBuilder(TRANSIT_CHANGE)
.setFlags(FLAG_IS_DISPLAY).setRotate().build();
@@ -744,7 +743,8 @@ public class ShellTransitionTests extends ShellTestCase {
assertEquals(ROTATION_ANIMATION_ROTATE, DefaultTransitionHandler.getRotationAnimationHint(
displayChange, noTask, displays));
- // Not seamless if one of rotations is upside-down
+ // Not seamless if the nav bar cares rotation and one of rotations is upside-down.
+ doReturn(false).when(displayLayout).allowSeamlessRotationDespiteNavBarMoving();
displayChange = new ChangeBuilder(TRANSIT_CHANGE).setFlags(FLAG_IS_DISPLAY)
.setRotate(upsideDown, ROTATION_ANIMATION_UNSPECIFIED).build();
final TransitionInfo seamlessUpsideDown = new TransitionInfoBuilder(TRANSIT_CHANGE)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/StubTransaction.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/StubTransaction.java
new file mode 100644
index 000000000000..855f5416fd0f
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/StubTransaction.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.util;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.ColorSpace;
+import android.graphics.GraphicBuffer;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.hardware.HardwareBuffer;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.view.InputWindowHandle;
+import android.view.Surface;
+import android.view.SurfaceControl;
+
+import java.util.HashSet;
+import java.util.concurrent.Executor;
+
+/**
+ * Stubbed {@link SurfaceControl.Transaction} class that can be used when unit
+ * testing to avoid calls to native code.
+ *
+ * Note: This is a copy of com.android.server.testutils.StubTransaction
+ */
+public class StubTransaction extends SurfaceControl.Transaction {
+
+ private HashSet<Runnable> mWindowInfosReportedListeners = new HashSet<>();
+
+ @Override
+ public void apply() {
+ for (Runnable listener : mWindowInfosReportedListeners) {
+ listener.run();
+ }
+ }
+
+ @Override
+ public void close() {
+ }
+
+ @Override
+ public void apply(boolean sync) {
+ apply();
+ }
+
+ @Override
+ public SurfaceControl.Transaction setVisibility(SurfaceControl sc, boolean visible) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction show(SurfaceControl sc) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction hide(SurfaceControl sc) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setPosition(SurfaceControl sc, float x, float y) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setBufferSize(SurfaceControl sc,
+ int w, int h) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setLayer(SurfaceControl sc, int z) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setRelativeLayer(SurfaceControl sc, SurfaceControl relativeTo,
+ int z) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setTransparentRegionHint(SurfaceControl sc,
+ Region transparentRegion) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setAlpha(SurfaceControl sc, float alpha) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setInputWindowInfo(SurfaceControl sc,
+ InputWindowHandle handle) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setGeometry(SurfaceControl sc, Rect sourceCrop,
+ Rect destFrame, @Surface.Rotation int orientation) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setMatrix(SurfaceControl sc,
+ float dsdx, float dtdx, float dtdy, float dsdy) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setMatrix(SurfaceControl sc, Matrix matrix, float[] float9) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setColorTransform(SurfaceControl sc, float[] matrix,
+ float[] translation) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setWindowCrop(SurfaceControl sc, Rect crop) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setWindowCrop(SurfaceControl sc, int width, int height) {
+ return this;
+ }
+
+ @Override
+ @NonNull
+ public SurfaceControl.Transaction setCrop(@NonNull SurfaceControl sc, @Nullable Rect crop) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setCornerRadius(SurfaceControl sc, float cornerRadius) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setBackgroundBlurRadius(SurfaceControl sc, int radius) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setLayerStack(SurfaceControl sc, int layerStack) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction reparent(SurfaceControl sc, SurfaceControl newParent) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setColor(SurfaceControl sc, float[] color) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setSecure(SurfaceControl sc, boolean isSecure) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setOpaque(SurfaceControl sc, boolean isOpaque) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setDisplaySurface(IBinder displayToken, Surface surface) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setDisplayLayerStack(IBinder displayToken, int layerStack) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setDisplayFlags(IBinder displayToken, int flags) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setDisplayProjection(IBinder displayToken,
+ int orientation, Rect layerStackRect, Rect displayRect) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setDisplaySize(IBinder displayToken, int width, int height) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setAnimationTransaction() {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setMetadata(SurfaceControl sc, int key, int data) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setMetadata(SurfaceControl sc, int key, Parcel data) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction merge(SurfaceControl.Transaction other) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction remove(SurfaceControl sc) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction addTransactionCommittedListener(Executor executor,
+ SurfaceControl.TransactionCommittedListener listener) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setColorSpaceAgnostic(SurfaceControl sc, boolean agnostic) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setFrameRateSelectionPriority(SurfaceControl sc,
+ int priority) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setFrameRate(SurfaceControl sc, float frameRate,
+ int compatibility, int changeFrameRateStrategy) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction unsetColor(SurfaceControl sc) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setShadowRadius(SurfaceControl sc, float shadowRadius) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setFixedTransformHint(SurfaceControl sc,
+ @Surface.Rotation int transformHint) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction unsetFixedTransformHint(@NonNull SurfaceControl sc) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setBuffer(SurfaceControl sc, GraphicBuffer buffer) {
+ return this;
+ }
+
+ @Override
+ @NonNull
+ public SurfaceControl.Transaction setBuffer(@NonNull SurfaceControl sc,
+ @Nullable HardwareBuffer buffer) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setColorSpace(SurfaceControl sc, ColorSpace colorSpace) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setTrustedOverlay(SurfaceControl sc,
+ boolean isTrustedOverlay) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction addWindowInfosReportedListener(@NonNull Runnable listener) {
+ mWindowInfosReportedListeners.add(listener);
+ return this;
+ }
+}
diff --git a/libs/hwui/jni/Gainmap.cpp b/libs/hwui/jni/Gainmap.cpp
index 0f8a85dd9e62..cec0ee7ee247 100644
--- a/libs/hwui/jni/Gainmap.cpp
+++ b/libs/hwui/jni/Gainmap.cpp
@@ -86,6 +86,16 @@ jlong Gainmap_createEmpty(JNIEnv*, jobject) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(gainmap));
}
+jlong Gainmap_createCopy(JNIEnv*, jobject, jlong sourcePtr) {
+ Gainmap* gainmap = new Gainmap();
+ gainmap->incStrong(0);
+ if (sourcePtr) {
+ Gainmap* src = fromJava(sourcePtr);
+ gainmap->info = src->info;
+ }
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(gainmap));
+}
+
static void Gainmap_setBitmap(JNIEnv* env, jobject, jlong gainmapPtr, jobject jBitmap) {
android::Bitmap* bitmap = GraphicsJNI::getNativeBitmap(env, jBitmap);
fromJava(gainmapPtr)->bitmap = sk_ref_sp(bitmap);
@@ -237,6 +247,7 @@ static void Gainmap_readFromParcel(JNIEnv* env, jobject, jlong nativeObject, job
static const JNINativeMethod gGainmapMethods[] = {
{"nGetFinalizer", "()J", (void*)Gainmap_getNativeFinalizer},
{"nCreateEmpty", "()J", (void*)Gainmap_createEmpty},
+ {"nCreateCopy", "(J)J", (void*)Gainmap_createCopy},
{"nSetBitmap", "(JLandroid/graphics/Bitmap;)V", (void*)Gainmap_setBitmap},
{"nSetRatioMin", "(JFFF)V", (void*)Gainmap_setRatioMin},
{"nGetRatioMin", "(J[F)V", (void*)Gainmap_getRatioMin},
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 38bb447f8a16..b7c972083657 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -4933,8 +4933,12 @@ final public class MediaCodec {
* Called when an output frame has rendered on the output surface.
* <p>
* <strong>Note:</strong> This callback is for informational purposes only: to get precise
- * render timing samples, and can be significantly delayed and batched. Some frames may have
- * been rendered even if there was no callback generated.
+ * render timing samples, and can be significantly delayed and batched. Starting with
+ * Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, a callback will always
+ * be received for each rendered frame providing the MediaCodec is still in the executing
+ * state when the callback is dispatched. Prior to Android
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, some frames may have been
+ * rendered even if there was no callback generated.
*
* @param codec the MediaCodec instance
* @param presentationTimeUs the presentation time (media time) of the frame rendered.
diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml
index 9f7679b0628b..117d2aa6e6f4 100644
--- a/packages/CompanionDeviceManager/res/values-it/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-it/strings.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4470785958457506021">"Gestione dispositivi companion"</string>
+ <string name="app_label" msgid="4470785958457506021">"Gestione dispositivi associati"</string>
<string name="confirmation_title" msgid="4593465730772390351">"Vuoi consentire all\'app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; di accedere a &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
<string name="profile_name_watch" msgid="576290739483672360">"orologio"</string>
<string name="chooser_title" msgid="2262294130493605839">"Scegli un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> da gestire con &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
diff --git a/packages/PackageInstaller/res/values-kn/strings.xml b/packages/PackageInstaller/res/values-kn/strings.xml
index 037871264847..c9455aeb843b 100644
--- a/packages/PackageInstaller/res/values-kn/strings.xml
+++ b/packages/PackageInstaller/res/values-kn/strings.xml
@@ -98,7 +98,7 @@
<string name="anonymous_source_continue" msgid="4375745439457209366">"ಮುಂದುವರಿಸಿ"</string>
<string name="external_sources_settings" msgid="4046964413071713807">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
<string name="wear_app_channel" msgid="1960809674709107850">"wear ಆ್ಯಪ್‌ಗಳನ್ನು ಇನ್‌ಸ್ಟಾಲ್‌/ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
- <string name="app_installed_notification_channel_description" msgid="2695385797601574123">"ಆ್ಯಪ್ ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿರುವ ಕುರಿತು ಅಧಿಸೂಚನೆ"</string>
+ <string name="app_installed_notification_channel_description" msgid="2695385797601574123">"ಆ್ಯಪ್ ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿರುವ ಕುರಿತು ನೋಟಿಫಿಕೇಶನ್"</string>
<string name="notification_installation_success_message" msgid="6450467996056038442">"ಯಶಸ್ವಿಯಾಗಿ ಇನ್‌ಸ್ಟಾಲ್ ಆಗಿದೆ"</string>
<string name="notification_installation_success_status" msgid="3172502643504323321">"\"<xliff:g id="APPNAME">%1$s</xliff:g>\" ಆ್ಯಪ್ ಅನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲಾಗಿದೆ"</string>
</resources>
diff --git a/packages/PackageInstaller/res/values-or/strings.xml b/packages/PackageInstaller/res/values-or/strings.xml
index c191714516c5..b6caebd19711 100644
--- a/packages/PackageInstaller/res/values-or/strings.xml
+++ b/packages/PackageInstaller/res/values-or/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="7488448184431507488">"ପ୍ୟାକେଜ୍‌ ଇନଷ୍ଟଲର୍‍"</string>
- <string name="install" msgid="711829760615509273">"ଇନଷ୍ଟଲ୍‍ କରନ୍ତୁ"</string>
+ <string name="install" msgid="711829760615509273">"ଇନଷ୍ଟଲ କରନ୍ତୁ"</string>
<string name="update" msgid="3932142540719227615">"ଅପଡେଟ୍ କରନ୍ତୁ"</string>
<string name="done" msgid="6632441120016885253">"ହୋଇଗଲା"</string>
<string name="cancel" msgid="1018267193425558088">"ବାତିଲ କରନ୍ତୁ"</string>
diff --git a/packages/SettingsLib/BannerMessagePreference/res/values-te/strings.xml b/packages/SettingsLib/BannerMessagePreference/res/values-te/strings.xml
index 22a6f59f091c..102fdc899816 100644
--- a/packages/SettingsLib/BannerMessagePreference/res/values-te/strings.xml
+++ b/packages/SettingsLib/BannerMessagePreference/res/values-te/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"విస్మరించు"</string>
+ <string name="accessibility_banner_message_dismiss" msgid="5272928723898304168">"విస్మరించండి"</string>
</resources>
diff --git a/packages/SettingsLib/FooterPreference/res/values-kk/strings.xml b/packages/SettingsLib/FooterPreference/res/values-kk/strings.xml
index db11a766e8a5..dc3af2891266 100644
--- a/packages/SettingsLib/FooterPreference/res/values-kk/strings.xml
+++ b/packages/SettingsLib/FooterPreference/res/values-kk/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Толығырақ"</string>
+ <string name="settingslib_learn_more_text" msgid="7385478101223578464">"Толық ақпарат"</string>
</resources>
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-or/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-or/strings.xml
index 8b211e790017..567c4bc2220f 100644
--- a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-or/strings.xml
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-or/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="settings_label" msgid="5948970810295631236">"ସେଟିଂସ୍"</string>
+ <string name="settings_label" msgid="5948970810295631236">"ସେଟିଂସ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index aa28a3158abb..71aac42b755a 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -545,12 +545,9 @@
<string name="time_unit_just_now" msgid="3006134267292728099">"Толькі што"</string>
<string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Гэты тэлефон"</string>
<string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Гэты планшэт"</string>
- <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
- <skip />
- <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
- <skip />
- <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
- <skip />
+ <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Дынамік док-станцыі"</string>
+ <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Знешняя прылада"</string>
+ <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Падключаная прылада"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Гэты тэлефон"</string>
<string name="media_output_status_unknown_error" msgid="5098565887497902222">"Не ўдаецца прайграць на гэтай прыладзе"</string>
<string name="media_output_status_require_premium" msgid="8411255800047014822">"Для пераключэння перайдзіце на іншую версію ўліковага запісу"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 4c6f0c1c4b82..ac5d152d60ef 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -545,12 +545,9 @@
<string name="time_unit_just_now" msgid="3006134267292728099">"Gerade eben"</string>
<string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Dieses Smartphone"</string>
<string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Dieses Tablet"</string>
- <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
- <skip />
- <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
- <skip />
- <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
- <skip />
+ <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"Dock-Lautsprecher"</string>
+ <string name="media_transfer_external_device_name" msgid="2588672258721846418">"Externes Gerät"</string>
+ <string name="media_transfer_default_device_name" msgid="4315604017399871828">"Verbundenes Gerät"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Dieses Smartphone"</string>
<string name="media_output_status_unknown_error" msgid="5098565887497902222">"Wiedergabe auf diesem Gerät nicht möglich"</string>
<string name="media_output_status_require_premium" msgid="8411255800047014822">"Zum Umstellen Kontoupgrade durchführen"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 076d0223df9c..0032351abfa9 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -545,12 +545,9 @@
<string name="time_unit_just_now" msgid="3006134267292728099">"たった今"</string>
<string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"このデバイス"</string>
<string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"このタブレット"</string>
- <!-- no translation found for media_transfer_dock_speaker_device_name (2856219597113881950) -->
- <skip />
- <!-- no translation found for media_transfer_external_device_name (2588672258721846418) -->
- <skip />
- <!-- no translation found for media_transfer_default_device_name (4315604017399871828) -->
- <skip />
+ <string name="media_transfer_dock_speaker_device_name" msgid="2856219597113881950">"ホルダー スピーカー"</string>
+ <string name="media_transfer_external_device_name" msgid="2588672258721846418">"外部デバイス"</string>
+ <string name="media_transfer_default_device_name" msgid="4315604017399871828">"接続済みのデバイス"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"このデバイス"</string>
<string name="media_output_status_unknown_error" msgid="5098565887497902222">"このデバイスでは再生できません"</string>
<string name="media_output_status_require_premium" msgid="8411255800047014822">"アカウントを更新して切り替えてください"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index f7f6a2f22ce2..134f59149d86 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -524,7 +524,7 @@
<string name="back" msgid="5554327870352703710">"ಹಿಂದಕ್ಕೆ"</string>
<string name="save" msgid="3745809743277153149">"ಉಳಿಸಿ"</string>
<string name="okay" msgid="949938843324579502">"ಸರಿ"</string>
- <string name="done" msgid="381184316122520313">"ಮುಗಿದಿದೆ"</string>
+ <string name="done" msgid="381184316122520313">"ಆಯಿತು"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"ಅಲಾರಾಮ್‌ಗಳು ಮತ್ತು ರಿಮೈಂಡರ್‌ಗಳು"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"ಅಲಾರಂಗಳು ಮತ್ತು ರಿಮೈಂಡರ್‌ಗಳನ್ನು ಹೊಂದಿಸಲು ಅನುಮತಿಸಿ"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ಅಲಾರಂಗಳು ಮತ್ತು ರಿಮೈಂಡರ್‌ಗಳು"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 58a930f304de..7e7d3820f88b 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -259,7 +259,7 @@
<string name="keep_screen_on" msgid="1187161672348797558">"Ойгоо туруу"</string>
<string name="keep_screen_on_summary" msgid="1510731514101925829">"Түзмөк кубатталып жатканда экран өчпөйт"</string>
<string name="bt_hci_snoop_log" msgid="7291287955649081448">"Bluetooth HCI журналын иштетүү"</string>
- <string name="bt_hci_snoop_log_summary" msgid="6808538971394092284">"Bluetooth таңгактарын алуу. (Бул жөндөөнү өзгөрткөндөн кийин Bluetooth\'ду өчүрүп / күйгүзүңүз)"</string>
+ <string name="bt_hci_snoop_log_summary" msgid="6808538971394092284">"Bluetooth таңгактарын алуу. (Бул параметрди өзгөрткөндөн кийин Bluetooth\'ду өчүрүп / күйгүзүңүз)"</string>
<string name="oem_unlock_enable" msgid="5334869171871566731">"OEM бөгөттөн чыгаруу"</string>
<string name="oem_unlock_enable_summary" msgid="5857388174390953829">"Кайра жүктөгүчтү бөгөттөн чыгарууга уруксат берүү"</string>
<string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"OEM бөгөттөн чыгарууга уруксатпы?"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index f7b4c0feed86..583b0699e953 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -469,7 +469,7 @@
<string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Уредот може да се исклучи наскоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до полна батерија"</string>
- <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> до полна батерија"</string>
+ <string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полна батерија"</string>
<string name="power_charging_limited" msgid="8202147604844938236">"<xliff:g id="LEVEL">%1$s</xliff:g> - Полнењето е оптимизирано"</string>
<string name="power_charging_future_paused" msgid="4730177778538118032">"<xliff:g id="LEVEL">%1$s</xliff:g> - Полнењето е оптимизирано"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 4e3455256ba1..349b9d3c4d4d 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -320,9 +320,9 @@
<string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Wi-Fi अन हुँदा पनि मोबाइल डेटा सधैँ अन होस् (द्रुत रूपमा नेटवर्क बदल्न)।"</string>
<string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"उपलब्ध हुँदा टेदरिङ हार्डवेयर एक्सलरेसन प्रयोग गरियोस्"</string>
<string name="adb_warning_title" msgid="7708653449506485728">"USB डिबग गर्न लागि अनुमति दिने हो?"</string>
- <string name="adb_warning_message" msgid="8145270656419669221">"युएसबी डिबगिङ विकास प्रयोजनका लागि मात्र निर्मित हुन्छ। यसलाई तपाईँको कम्प्युटर र तपाईँको उपकरणका बीच डेटा प्रतिलिपि गर्न, बिना सूचना तपाईँको उपकरणमा एपहरू इन्स्टल गर्न र लग डेटा पढ्नका लागि प्रयोग गर्नुहोस्।"</string>
+ <string name="adb_warning_message" msgid="8145270656419669221">"युएसबी डिबगिङ विकास प्रयोजनका लागि मात्र निर्मित हुन्छ। यसलाई तपाईँको कम्प्युटर र तपाईँको उपकरणका बीच डेटा कपी गर्न, बिना सूचना तपाईँको उपकरणमा एपहरू इन्स्टल गर्न र लग डेटा पढ्नका लागि प्रयोग गर्नुहोस्।"</string>
<string name="adbwifi_warning_title" msgid="727104571653031865">"वायरलेस डिबगिङ सेवा सक्षम पार्ने हो?"</string>
- <string name="adbwifi_warning_message" msgid="8005936574322702388">"वायरलेस डिबगिङ डिभलपमेन्ट प्रयोजनका लागि मात्रै हो। यसलाई आफ्ना कम्प्युटर र उपकरणका बिच डेटा प्रतिलिपि गर्न, सूचना नदिई आफ्नो उपकरणमा एपहरू इन्स्टल गर्न र लग डेटा पढ्न प्रयोग गर्नुहोस्।"</string>
+ <string name="adbwifi_warning_message" msgid="8005936574322702388">"वायरलेस डिबगिङ डिभलपमेन्ट प्रयोजनका लागि मात्रै हो। यसलाई आफ्ना कम्प्युटर र उपकरणका बिच डेटा कपी गर्न, सूचना नदिई आफ्नो उपकरणमा एपहरू इन्स्टल गर्न र लग डेटा पढ्न प्रयोग गर्नुहोस्।"</string>
<string name="adb_keys_warning_message" msgid="2968555274488101220">"तपाईं पहिले नै अधिकृत गर्नुभएका सबै कम्प्यूटरबाट USB डिबग गर्नको लागि पहुँच रद्द गर्ने हो?"</string>
<string name="dev_settings_warning_title" msgid="8251234890169074553">"विकास सेटिङहरू अनुमति दिने हो?"</string>
<string name="dev_settings_warning_message" msgid="37741686486073668">"यी सेटिङहरू केवल विकास प्रयोगको लागि विचार गरिएको हो। तिनीहरूले तपाईंको उपकरण र एपहरूलाई विच्छेदन गर्न वा दुर्व्यवहार गर्न सक्दछ।"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 23b6ff3052af..6787f324b9e5 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -293,11 +293,11 @@
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3233402355917446304">"蓝牙音频 LDAC 编解码器:播放质量"</string>
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="7274396574659784285">"触发蓝牙音频 LDAC\n编解码器选择:播放质量"</string>
<string name="bluetooth_select_a2dp_codec_streaming_label" msgid="2040810756832027227">"正在流式传输:<xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
- <string name="select_private_dns_configuration_title" msgid="7887550926056143018">"私人 DNS"</string>
+ <string name="select_private_dns_configuration_title" msgid="7887550926056143018">"专用 DNS"</string>
<string name="select_private_dns_configuration_dialog_title" msgid="3731422918335951912">"选择私人 DNS 模式"</string>
<string name="private_dns_mode_off" msgid="7065962499349997041">"已关闭"</string>
<string name="private_dns_mode_opportunistic" msgid="1947864819060442354">"自动"</string>
- <string name="private_dns_mode_provider" msgid="3619040641762557028">"私人 DNS 提供商主机名"</string>
+ <string name="private_dns_mode_provider" msgid="3619040641762557028">"专用 DNS 提供商主机名"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"输入 DNS 提供商的主机名"</string>
<string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"无法连接"</string>
<string name="wifi_display_certification_summary" msgid="8111151348106907513">"显示无线显示认证选项"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index 3fcb7f398185..ffc0479f01c3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -116,10 +116,7 @@ public class InfoMediaManager extends MediaManager {
&& !TextUtils.isEmpty(mPackageName)) {
RouteListingPreference routeListingPreference =
mRouterManager.getRouteListingPreference(mPackageName);
- if (routeListingPreference != null) {
- Api34Impl.onRouteListingPreferenceUpdated(null, routeListingPreference,
- mPreferenceItemMap);
- }
+ Api34Impl.onRouteListingPreferenceUpdated(routeListingPreference, mPreferenceItemMap);
}
refreshDevices();
}
@@ -631,7 +628,7 @@ public class InfoMediaManager extends MediaManager {
}
/**
- * Ignore callback here since we'll also receive {@link onRequestFailed} with reason code.
+ * Ignore callback here since we'll also receive {@link #onRequestFailed} with reason code.
*/
@Override
public void onTransferFailed(RoutingSessionInfo session, MediaRoute2Info route) {
@@ -656,9 +653,9 @@ public class InfoMediaManager extends MediaManager {
public void onRouteListingPreferenceUpdated(
String packageName,
RouteListingPreference routeListingPreference) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
- Api34Impl.onRouteListingPreferenceUpdated(packageName, routeListingPreference,
- mPreferenceItemMap);
+ if (TextUtils.equals(mPackageName, packageName)) {
+ Api34Impl.onRouteListingPreferenceUpdated(
+ routeListingPreference, mPreferenceItemMap);
refreshDevices();
}
}
@@ -746,7 +743,6 @@ public class InfoMediaManager extends MediaManager {
@DoNotInline
static void onRouteListingPreferenceUpdated(
- String packageName,
RouteListingPreference routeListingPreference,
Map<String, RouteListingPreference.Item> preferenceItemMap) {
preferenceItemMap.clear();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
index aa5f3df1b750..39780f3a96ed 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
@@ -73,6 +73,7 @@ import java.util.Set;
public class InfoMediaManagerTest {
private static final String TEST_PACKAGE_NAME = "com.test.packagename";
+ private static final String TEST_PACKAGE_NAME_2 = "com.test.packagename2";
private static final String TEST_ID = "test_id";
private static final String TEST_ID_1 = "test_id_1";
private static final String TEST_ID_2 = "test_id_2";
@@ -308,7 +309,54 @@ public class InfoMediaManagerTest {
}
@Test
- public void onRouteChanged_getAvailableRoutesWithPrefernceListExit_ordersRoutes() {
+ public void onRouteChanged_getAvailableRoutesWithPreferenceListExit_ordersRoutes() {
+ RouteListingPreference routeListingPreference = setUpPreferenceList(TEST_PACKAGE_NAME);
+ setUpSelectedRoutes(TEST_PACKAGE_NAME);
+
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo sessionInfo = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(sessionInfo);
+
+ when(mRouterManager.getRoutingSessions(TEST_PACKAGE_NAME)).thenReturn(routingSessionInfos);
+ when(sessionInfo.getSelectedRoutes()).thenReturn(ImmutableList.of(TEST_ID));
+
+ setAvailableRoutesList(TEST_PACKAGE_NAME);
+
+ mInfoMediaManager.mRouterManager = mRouterManager;
+ mInfoMediaManager.mMediaRouterCallback.onRouteListingPreferenceUpdated(TEST_PACKAGE_NAME,
+ routeListingPreference);
+ mInfoMediaManager.mMediaRouterCallback.onRoutesUpdated();
+
+ assertThat(mInfoMediaManager.mMediaDevices).hasSize(3);
+ assertThat(mInfoMediaManager.mMediaDevices.get(0).getId()).isEqualTo(TEST_ID);
+ assertThat(mInfoMediaManager.mMediaDevices.get(1).getId()).isEqualTo(TEST_ID_4);
+ assertThat(mInfoMediaManager.mMediaDevices.get(1).isSuggestedDevice()).isTrue();
+ assertThat(mInfoMediaManager.mMediaDevices.get(2).getId()).isEqualTo(TEST_ID_3);
+ }
+
+ @Test
+ public void onRouteChanged_preferenceListUpdateWithDifferentPkg_notOrdersRoutes() {
+ RouteListingPreference routeListingPreference = setUpPreferenceList(TEST_PACKAGE_NAME_2);
+ setUpSelectedRoutes(TEST_PACKAGE_NAME);
+
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo sessionInfo = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(sessionInfo);
+
+ when(mRouterManager.getRoutingSessions(TEST_PACKAGE_NAME)).thenReturn(routingSessionInfos);
+ when(sessionInfo.getSelectedRoutes()).thenReturn(ImmutableList.of(TEST_ID));
+
+ setAvailableRoutesList(TEST_PACKAGE_NAME);
+ mInfoMediaManager.mRouterManager = mRouterManager;
+ mInfoMediaManager.mMediaRouterCallback.onRouteListingPreferenceUpdated(TEST_PACKAGE_NAME_2,
+ routeListingPreference);
+ mInfoMediaManager.mMediaRouterCallback.onRoutesUpdated();
+
+ assertThat(mInfoMediaManager.mMediaDevices).hasSize(1);
+ assertThat(mInfoMediaManager.mMediaDevices.get(0).getId()).isEqualTo(TEST_ID);
+ }
+
+ private RouteListingPreference setUpPreferenceList(String packageName) {
ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT",
Build.VERSION_CODES.UPSIDE_DOWN_CAKE);
final List<RouteListingPreference.Item> preferenceItemList = new ArrayList<>();
@@ -324,57 +372,40 @@ public class InfoMediaManagerTest {
RouteListingPreference routeListingPreference =
new RouteListingPreference.Builder().setItems(
preferenceItemList).setUseSystemOrdering(false).build();
- when(mRouterManager.getRouteListingPreference(TEST_PACKAGE_NAME))
+ when(mRouterManager.getRouteListingPreference(packageName))
.thenReturn(routeListingPreference);
+ return routeListingPreference;
+ }
+ private void setUpSelectedRoutes(String packageName) {
final List<MediaRoute2Info> selectedRoutes = new ArrayList<>();
final MediaRoute2Info info = mock(MediaRoute2Info.class);
when(info.getId()).thenReturn(TEST_ID);
- when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ when(info.getClientPackageName()).thenReturn(packageName);
when(info.isSystemRoute()).thenReturn(true);
selectedRoutes.add(info);
when(mRouterManager.getSelectedRoutes(any())).thenReturn(selectedRoutes);
-
- final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
- final RoutingSessionInfo sessionInfo = mock(RoutingSessionInfo.class);
- routingSessionInfos.add(sessionInfo);
-
- when(mRouterManager.getRoutingSessions(TEST_PACKAGE_NAME)).thenReturn(routingSessionInfos);
- when(sessionInfo.getSelectedRoutes()).thenReturn(ImmutableList.of(TEST_ID));
-
- setAvailableRoutesList();
-
- mInfoMediaManager.mRouterManager = mRouterManager;
- mInfoMediaManager.mMediaRouterCallback.onRouteListingPreferenceUpdated(TEST_PACKAGE_NAME,
- routeListingPreference);
- mInfoMediaManager.mMediaRouterCallback.onRoutesUpdated();
-
- assertThat(mInfoMediaManager.mMediaDevices).hasSize(3);
- assertThat(mInfoMediaManager.mMediaDevices.get(0).getId()).isEqualTo(TEST_ID);
- assertThat(mInfoMediaManager.mMediaDevices.get(1).getId()).isEqualTo(TEST_ID_4);
- assertThat(mInfoMediaManager.mMediaDevices.get(1).isSuggestedDevice()).isTrue();
- assertThat(mInfoMediaManager.mMediaDevices.get(2).getId()).isEqualTo(TEST_ID_3);
}
- private List<MediaRoute2Info> setAvailableRoutesList() {
+ private List<MediaRoute2Info> setAvailableRoutesList(String packageName) {
final List<MediaRoute2Info> availableRoutes = new ArrayList<>();
final MediaRoute2Info availableInfo1 = mock(MediaRoute2Info.class);
when(availableInfo1.getId()).thenReturn(TEST_ID_2);
- when(availableInfo1.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ when(availableInfo1.getClientPackageName()).thenReturn(packageName);
when(availableInfo1.getType()).thenReturn(TYPE_REMOTE_TV);
availableRoutes.add(availableInfo1);
final MediaRoute2Info availableInfo2 = mock(MediaRoute2Info.class);
when(availableInfo2.getId()).thenReturn(TEST_ID_3);
- when(availableInfo2.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ when(availableInfo2.getClientPackageName()).thenReturn(packageName);
availableRoutes.add(availableInfo2);
final MediaRoute2Info availableInfo3 = mock(MediaRoute2Info.class);
when(availableInfo3.getId()).thenReturn(TEST_ID_4);
- when(availableInfo3.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ when(availableInfo3.getClientPackageName()).thenReturn(packageName);
availableRoutes.add(availableInfo3);
- when(mRouterManager.getAvailableRoutes(TEST_PACKAGE_NAME)).thenReturn(
+ when(mRouterManager.getAvailableRoutes(packageName)).thenReturn(
availableRoutes);
return availableRoutes;
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 43f98c38715d..56e0643b1e20 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -839,6 +839,8 @@
<uses-permission android:name="android.permission.LAUNCH_CREDENTIAL_SELECTOR" />
<!-- Permission required for CTS test IntentRedirectionTest -->
<uses-permission android:name="android.permission.QUERY_CLONED_APPS" />
+ <!-- Permission required for accessing all content provider mime types -->
+ <uses-permission android:name="android.permission.GET_ANY_PROVIDER_TYPE" />
<application
android:label="@string/app_label"
diff --git a/packages/Shell/src/com/android/shell/Screenshooter.java b/packages/Shell/src/com/android/shell/Screenshooter.java
index baaddf53bcab..8a5b7daab7e0 100644
--- a/packages/Shell/src/com/android/shell/Screenshooter.java
+++ b/packages/Shell/src/com/android/shell/Screenshooter.java
@@ -21,12 +21,10 @@ import static android.view.Display.DEFAULT_DISPLAY;
import android.graphics.Bitmap;
import android.os.RemoteException;
import android.util.Log;
-import android.util.Pair;
import android.view.WindowManagerGlobal;
import android.window.ScreenCapture;
-import android.window.ScreenCapture.ScreenCaptureListener;
import android.window.ScreenCapture.ScreenshotHardwareBuffer;
-import android.window.ScreenCapture.ScreenshotSync;
+import android.window.ScreenCapture.SynchronousScreenCaptureListener;
/**
* Helper class used to take screenshots.
@@ -46,15 +44,15 @@ final class Screenshooter {
static Bitmap takeScreenshot() {
Log.d(TAG, "Taking fullscreen screenshot");
// Take the screenshot
- final Pair<ScreenCaptureListener, ScreenshotSync> syncScreenCapture =
+ final SynchronousScreenCaptureListener syncScreenCapture =
ScreenCapture.createSyncCaptureListener();
try {
WindowManagerGlobal.getWindowManagerService().captureDisplay(DEFAULT_DISPLAY, null,
- syncScreenCapture.first);
+ syncScreenCapture);
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
- final ScreenshotHardwareBuffer screenshotBuffer = syncScreenCapture.second.get();
+ final ScreenshotHardwareBuffer screenshotBuffer = syncScreenCapture.getBuffer();
final Bitmap screenShot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
if (screenShot == null) {
Log.e(TAG, "Failed to take fullscreen screenshot");
diff --git a/packages/SoundPicker/res/values-kn/strings.xml b/packages/SoundPicker/res/values-kn/strings.xml
index e6a05c2b4e2d..da90ccbaca0b 100644
--- a/packages/SoundPicker/res/values-kn/strings.xml
+++ b/packages/SoundPicker/res/values-kn/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="ringtone_default" msgid="798836092118824500">"ಡಿಫಾಲ್ಟ್ ರಿಂಗ್‌ಟೋನ್"</string>
- <string name="notification_sound_default" msgid="8133121186242636840">"ಡೀಫಾಲ್ಟ್ ಅಧಿಸೂಚನೆ ಧ್ವನಿ"</string>
+ <string name="notification_sound_default" msgid="8133121186242636840">"ಡೀಫಾಲ್ಟ್ ನೋಟಿಫಿಕೇಶನ್‌ ಧ್ವನಿ"</string>
<string name="alarm_sound_default" msgid="4787646764557462649">"ಡೀಫಾಲ್ಟ್ ಅಲಾರಾಂ ಧ್ವನಿ"</string>
<string name="add_ringtone_text" msgid="6642389991738337529">"ರಿಂಗ್‌ಟೋನ್ ಸೇರಿಸಿ"</string>
<string name="add_alarm_text" msgid="3545497316166999225">"ಅಲಾರಾಂ ಸೇರಿಸಿ"</string>
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 0a9a1842dd77..0aa121dfcc49 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -996,7 +996,6 @@
android:name=".notetask.shortcut.LaunchNoteTaskActivity"
android:exported="true"
android:excludeFromRecents="true"
- android:resizeableActivity="false"
android:theme="@android:style/Theme.NoDisplay" >
<intent-filter>
@@ -1012,7 +1011,6 @@
android:exported="false"
android:enabled="true"
android:excludeFromRecents="true"
- android:resizeableActivity="false"
android:theme="@android:style/Theme.NoDisplay" />
<activity
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-es/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-es/strings.xml
index b97df645dee7..877a43cc26cf 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-es/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-es/strings.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="accessibility_menu_service_name" msgid="730136711554740131">"Menú de accesibilidad"</string>
+ <string name="accessibility_menu_service_name" msgid="730136711554740131">"Menú Accesibilidad"</string>
<string name="accessibility_menu_intro" msgid="3164193281544042394">"El menú de accesibilidad es un menú de gran tamaño que se muestra en pantalla para controlar tu dispositivo. Puedes bloquear el dispositivo, controlar el volumen y el brillo, hacer capturas de pantalla y más."</string>
<string name="assistant_label" msgid="6796392082252272356">"Asistente"</string>
<string name="assistant_utterance" msgid="65509599221141377">"Asistente"</string>
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
index 7e1bfb921ca9..addabcc0282a 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
@@ -21,7 +21,6 @@ import android.graphics.fonts.FontVariationAxis
import android.util.Log
import android.util.LruCache
import android.util.MathUtils
-import android.util.MathUtils.abs
import androidx.annotation.VisibleForTesting
import java.lang.Float.max
import java.lang.Float.min
@@ -30,8 +29,6 @@ private const val TAG_WGHT = "wght"
private const val TAG_ITAL = "ital"
private const val FONT_WEIGHT_DEFAULT_VALUE = 400f
-private const val FONT_WEIGHT_ANIMATION_FRAME_COUNT = 100
-
private const val FONT_ITALIC_MAX = 1f
private const val FONT_ITALIC_MIN = 0f
private const val FONT_ITALIC_ANIMATION_STEP = 0.1f
@@ -39,11 +36,12 @@ private const val FONT_ITALIC_DEFAULT_VALUE = 0f
// Benchmarked via Perfetto, difference between 10 and 50 entries is about 0.3ms in
// frame draw time on a Pixel 6.
-@VisibleForTesting const val FONT_CACHE_MAX_ENTRIES = 10
+@VisibleForTesting const val DEFAULT_FONT_CACHE_MAX_ENTRIES = 10
/** Provide interpolation of two fonts by adjusting font variation settings. */
-class FontInterpolator {
-
+class FontInterpolator(
+ numberOfAnimationSteps: Int? = null,
+) {
/**
* Cache key for the interpolated font.
*
@@ -88,8 +86,9 @@ class FontInterpolator {
// Font interpolator has two level caches: one for input and one for font with different
// variation settings. No synchronization is needed since FontInterpolator is not designed to be
// thread-safe and can be used only on UI thread.
- private val interpCache = LruCache<InterpKey, Font>(FONT_CACHE_MAX_ENTRIES)
- private val verFontCache = LruCache<VarFontKey, Font>(FONT_CACHE_MAX_ENTRIES)
+ val cacheMaxEntries = numberOfAnimationSteps?.let { it * 2 } ?: DEFAULT_FONT_CACHE_MAX_ENTRIES
+ private val interpCache = LruCache<InterpKey, Font>(cacheMaxEntries)
+ private val verFontCache = LruCache<VarFontKey, Font>(cacheMaxEntries)
// Mutable keys for recycling.
private val tmpInterpKey = InterpKey(null, null, 0f)
@@ -128,18 +127,12 @@ class FontInterpolator {
val newAxes =
lerp(startAxes, endAxes) { tag, startValue, endValue ->
when (tag) {
- // TODO: Good to parse 'fvar' table for retrieving default value.
- TAG_WGHT -> {
- adaptiveAdjustWeight(
- MathUtils.lerp(
- startValue ?: FONT_WEIGHT_DEFAULT_VALUE,
- endValue ?: FONT_WEIGHT_DEFAULT_VALUE,
- progress
- ),
+ TAG_WGHT ->
+ MathUtils.lerp(
startValue ?: FONT_WEIGHT_DEFAULT_VALUE,
endValue ?: FONT_WEIGHT_DEFAULT_VALUE,
+ progress
)
- }
TAG_ITAL ->
adjustItalic(
MathUtils.lerp(
@@ -175,9 +168,9 @@ class FontInterpolator {
val newFont = Font.Builder(start).setFontVariationSettings(newAxes.toTypedArray()).build()
interpCache.put(InterpKey(start, end, progress), newFont)
verFontCache.put(VarFontKey(start, newAxes), newFont)
- if (DEBUG) {
- Log.d(LOG_TAG, "[$progress] Cache MISS for $tmpInterpKey / $tmpVarFontKey")
- }
+
+ // Cache misses are likely to create memory leaks, so this is logged at error level.
+ Log.e(LOG_TAG, "[$progress] Cache MISS for $tmpInterpKey / $tmpVarFontKey")
return newFont
}
@@ -225,15 +218,6 @@ class FontInterpolator {
return result
}
- // For the performance reasons, we animate weight with adaptive step. This helps
- // Cache hit ratio in the Skia glyph cache.
- // The reason we don't use fix step is because the range of weight axis is not normalized,
- // some are from 50 to 100, others are from 0 to 1000, so we cannot give a constant proper step
- private fun adaptiveAdjustWeight(value: Float, start: Float, end: Float): Float {
- val step = max(abs(end - start) / FONT_WEIGHT_ANIMATION_FRAME_COUNT, 1F)
- return coerceInWithStep(value, min(start, end), max(start, end), step)
- }
-
// For the performance reasons, we animate italic with FONT_ITALIC_ANIMATION_STEP. This helps
// Cache hit ratio in the Skia glyph cache.
private fun adjustItalic(value: Float) =
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
index 16ddf0c36d9d..b555fa583588 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
@@ -108,7 +108,8 @@ class TextAnimator(
}
// Following two members are for mutable for testing purposes.
- public var textInterpolator: TextInterpolator = TextInterpolator(layout, typefaceCache)
+ public var textInterpolator: TextInterpolator =
+ TextInterpolator(layout, typefaceCache, numberOfAnimationSteps)
public var animator: ValueAnimator =
ValueAnimator.ofFloat(1f).apply {
duration = DEFAULT_ANIMATION_DURATION
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
index 8ed8d8fb61fd..02caeeddd774 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
@@ -31,6 +31,7 @@ import java.lang.Math.max
class TextInterpolator(
layout: Layout,
var typefaceCache: TypefaceVariantCache,
+ numberOfAnimationSteps: Int? = null,
) {
/**
* Returns base paint used for interpolation.
@@ -85,7 +86,7 @@ class TextInterpolator(
private class Line(val runs: List<Run>)
private var lines = listOf<Line>()
- private val fontInterpolator = FontInterpolator()
+ private val fontInterpolator = FontInterpolator(numberOfAnimationSteps)
// Recycling object for glyph drawing and tweaking.
private val tmpPaint = TextPaint()
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index 3fc0965f4a81..fc9c917c152b 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -43,7 +43,7 @@
<!-- Not quite optimal but needed to translate these items as a group. The
NotificationIconContainer has its own logic for translation. -->
- <LinearLayout
+ <com.android.keyguard.KeyguardStatusAreaView
android:id="@+id/keyguard_status_area"
android:orientation="vertical"
android:layout_width="match_parent"
@@ -63,5 +63,5 @@
android:paddingStart="@dimen/below_clock_padding_start_icons"
android:visibility="invisible"
/>
- </LinearLayout>
+ </com.android.keyguard.KeyguardStatusAreaView>
</com.android.keyguard.KeyguardClockSwitch>
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index 40f16871c56f..c89855d2d06c 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -91,9 +91,9 @@
<string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIM को PIN हाल्नुहोस्।"</string>
<string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" को SIM को PIN हाल्नुहोस्।"</string>
<string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> मोबाइल सेवा बिना डिभाइसको प्रयोग गर्न eSIM लाई असक्षम पार्नुहोस्।"</string>
- <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM कार्ड अहिले असक्षम छ। सुचारु गर्नको लागि PUK कोड प्रविष्टि गर्नुहोस्। विवरणको लागि सेवा प्रदायकलाई सम्पर्क गर्नुहोस्।"</string>
- <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM <xliff:g id="CARRIER">%1$s</xliff:g> अहिले असक्षम छ। सुचारु गर्नको लागि PUK कोड प्रविष्टि गर्नुहोस्। विवरणका लागि सेवा प्रदायकलाई सम्पर्क गर्नुहोस्।"</string>
- <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"रूचाइएको PIN कोड प्रविष्टि गर्नुहोस्"</string>
+ <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM कार्ड अहिले असक्षम छ। सुचारु गर्नको लागि PUK कोड हाल्नुहोस्। विवरणको लागि सेवा प्रदायकलाई सम्पर्क गर्नुहोस्।"</string>
+ <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM <xliff:g id="CARRIER">%1$s</xliff:g> अहिले असक्षम छ। सुचारु गर्नको लागि PUK कोड हाल्नुहोस्। विवरणका लागि सेवा प्रदायकलाई सम्पर्क गर्नुहोस्।"</string>
+ <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"रूचाइएको PIN कोड हाल्नुहोस्"</string>
<string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"रूचाइएको PIN कोड पुष्टि गर्नुहोस्"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"SIM कार्ड अनलक गरिँदै छ…"</string>
<string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"४ देखि ८ वटा नम्बर भएको एउटा PIN टाइप गर्नुहोस्।"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sw600dp-land/integers.xml b/packages/SystemUI/res-keyguard/values-sw600dp-land/integers.xml
index 2a8092010a37..3d1cb5ee6177 100644
--- a/packages/SystemUI/res-keyguard/values-sw600dp-land/integers.xml
+++ b/packages/SystemUI/res-keyguard/values-sw600dp-land/integers.xml
@@ -16,5 +16,5 @@
-->
<resources>
<!-- Invisibility to use for the date & weather view when it is disabled by a clock -->
- <integer name="keyguard_date_weather_view_invisibility">8</integer>
+ <integer name="keyguard_date_weather_view_invisibility">4</integer>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 4b7968953420..39dd90e5ed60 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -148,4 +148,9 @@
<dimen name="default_dot_diameter">34dp</dimen>
<dimen name="default_dot_spacing">0dp</dimen>
+ <!-- Weather clock smartspace scaling to apply for the weather clock -->
+ <item name="weather_clock_smartspace_scale" type="dimen" format="float">1.0</item>
+ <dimen name="weather_clock_smartspace_translateX">0dp</dimen>
+ <dimen name="weather_clock_smartspace_translateY">0dp</dimen>
+
</resources>
diff --git a/packages/SystemUI/res-keyguard/values/ids.xml b/packages/SystemUI/res-keyguard/values/ids.xml
index 0dff4ffa3866..1435907eaef6 100644
--- a/packages/SystemUI/res-keyguard/values/ids.xml
+++ b/packages/SystemUI/res-keyguard/values/ids.xml
@@ -17,4 +17,18 @@
<resources>
<item type="id" name="header_footer_views_added_tag_key" />
+
+ <!-- animation channels for keyguard status area -->
+ <item type="id" name="translate_x_clock_design_animator_tag" />
+ <item type="id" name="translate_x_clock_design_animator_start_tag" />
+ <item type="id" name="translate_x_clock_design_animator_end_tag" />
+ <item type="id" name="translate_x_aod_animator_tag" />
+ <item type="id" name="translate_x_aod_animator_start_tag" />
+ <item type="id" name="translate_x_aod_animator_end_tag" />
+ <item type="id" name="translate_y_clock_size_animator_tag" />
+ <item type="id" name="translate_y_clock_size_animator_start_tag" />
+ <item type="id" name="translate_y_clock_size_animator_end_tag" />
+ <item type="id" name="translate_y_clock_design_animator_tag" />
+ <item type="id" name="translate_y_clock_design_animator_start_tag" />
+ <item type="id" name="translate_y_clock_design_animator_end_tag" />
</resources>
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index edd3047203b3..28f5f3d9edd7 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -348,4 +348,22 @@
<string name="clock_title_analog">Analog</string>
<!-- Title of bouncer when we want to authenticate before continuing with action. [CHAR LIMIT=NONE] -->
<string name="keyguard_unlock_to_continue">Unlock your device to continue</string>
+
+ <!-- Message shown to prepare for an unattended update (OTA). Also known as an over-the-air (OTA) update. [CHAR LIMIT=70] -->
+ <string name="kg_prompt_unattended_update_pin">Enter PIN to install update later</string>
+
+ <!-- Message shown to prepare for an unattended update (OTA). Also known as an over-the-air (OTA) update. [CHAR LIMIT=70] -->
+ <string name="kg_prompt_unattended_update_password">Enter password to install update later</string>
+
+ <!-- Message shown to prepare for an unattended update (OTA). Also known as an over-the-air (OTA) update. [CHAR LIMIT=70] -->
+ <string name="kg_prompt_unattended_update_pattern">Draw pattern to install update later</string>
+
+ <!-- Message shown after an unattended update (OTA) asking the user to enter their PIN. Also known as an over-the-air (OTA) update. [CHAR LIMIT=70] -->
+ <string name="kg_prompt_after_update_pin">Device updated. Enter PIN to continue.</string>
+
+ <!-- Message shown after an unattended update (OTA) asking the user to enter their password. Also known as an over-the-air (OTA) update. [CHAR LIMIT=70] -->
+ <string name="kg_prompt_after_update_password">Device updated. Enter password to continue.</string>
+
+ <!-- Message shown after an unattended update (OTA) asking the user to enter their pattern. Also known as an over-the-air (OTA) update. [CHAR LIMIT=70] -->
+ <string name="kg_prompt_after_update_pattern">Device updated. Draw pattern to continue.</string>
</resources>
diff --git a/packages/SystemUI/res/layout/media_output_list_item_advanced.xml b/packages/SystemUI/res/layout/media_output_list_item_advanced.xml
index a595566ef817..7105721aff70 100644
--- a/packages/SystemUI/res/layout/media_output_list_item_advanced.xml
+++ b/packages/SystemUI/res/layout/media_output_list_item_advanced.xml
@@ -110,7 +110,9 @@
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:ellipsize="end"
+ android:marqueeRepeatLimit="marquee_forever"
+ android:ellipsize="marquee"
+ android:singleLine="true"
android:maxLines="1"
android:textColor="@color/media_dialog_item_main_content"
android:textSize="14sp"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index cd56b8f1135a..ca58ba0ad7e5 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Gesig is gestaaf"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bevestig"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tik op Bevestig om te voltooi"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Ontsluit met gesig"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ontsluit met gesig. Druk om voort te gaan."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gesig is herken. Druk om voort te gaan."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gesig is herken. Druk die ontsluitikoon om voort te gaan."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kan nie stoor nie. Probeer weer."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kan nie stoor nie."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gebruik minstens 4 karakters"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Gebruik minder as <xliff:g id="LENGTH">%1$d</xliff:g> karakters"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Bounommer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Bounommer is na knipbord gekopieer."</string>
<string name="basic_status" msgid="2315371112182658176">"Maak gesprek oop"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Kom meer te wete"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Kom meer te wete by <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Maak <xliff:g id="APPNAME">%1$s</xliff:g> oop"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Die app opgestel is"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Minstens een kaart by Wallet gevoeg is"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Installeer ’n kamera-app"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Die app opgestel is"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Minstens een toestel beskikbaar is"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Kies ’n versteknotasapp om die notaneemkortpad te gebruik"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Kies app"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Raak en hou kortpad"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Kanselleer"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteitmodus is aan"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent-aandag is aan"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Stel versteknotasapp in Instellings"</string>
+ <string name="install_app" msgid="5066668100199613936">"Installeer app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index e754e25f1e38..ac682710e681 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"መልክ ተረጋግጧል"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ተረጋግጧል"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ለማጠናቀቅ አረጋግጥን መታ ያድርጉ"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"በመልክ ተከፍቷል"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"በመልክ ተከፍቷል። ለመቀጠል ይጫኑ።"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"መልክ ተለይቶ ታውቋል። ለመቀጠል ይጫኑ።"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"መልክ ተለይቶ ታውቋል። ለመቀጠል የመክፈቻ አዶውን ይጫኑ።"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ማስቀመጥ አልተቻለም። እንደገና ይሞክሩ።"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ማስቀመጥ አልተቻለም።"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ቢያንስ 4 ቁምፊዎችን ይጠቀሙ"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"ከ<xliff:g id="LENGTH">%1$d</xliff:g> የሚያንሱ ቁምፊዎችን ይጠቀሙ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"የግንብ ቁጥር"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"የገንባ ቁጥር ወደ ቅንጥብ ሰሌዳ ተቀድቷል።"</string>
<string name="basic_status" msgid="2315371112182658176">"ውይይት ይክፈቱ"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"የበለጠ ለመረዳት"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g> ላይ የበለጠ ይወቁ"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ይክፈቱ"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• መተግበሪያው ተዋቅሯል"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• ቢያንስ አንድ ካርድ ወደ Wallet ታክሏል"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"የማስታወሻ አያያዝ አቋራጭን ለመጠቀም ነባሪ የማስታወሻ መተግበሪያ ይምረጡ"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"መተግበሪያ ይምረጡ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"የይንኩ እና ይያዙ አቋራጭ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ይቅር"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"የቅድሚያ ሁነታ በርቷል"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"የረዳት ትኩረት በርቷል"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"በቅንብሮች ውስጥ ነባሪ የማስታወሻዎች መተግበሪያን ያቀናብሩ"</string>
+ <string name="install_app" msgid="5066668100199613936">"መተግበሪያን ጫን"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index d378aa8a8913..93f72f451ca7 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"تمّت مصادقة الوجه."</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تمّ التأكيد."</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"يمكنك النقر على \"تأكيد\" لإكمال المهمة."</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"تم فتح قفل جهازك عند تقريبه من وجهك."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"تم فتح قفل جهازك عند تقريبه من وجهك. اضغط للمتابعة."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"تم التعرّف على الوجه. اضغط للمتابعة."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"تم التعرّف على الوجه. للمتابعة، اضغط على رمز فتح القفل."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"لا يمكن إجراء الحفظ. يُرجى إعادة المحاولة."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"لا يمكن إجراء الحفظ."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"يجب استخدام 4 أحرف على الأقل."</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"يجب استخدام أقل من <xliff:g id="LENGTH">%1$d</xliff:g> حرف."</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"رقم الإصدار"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"تم نسخ رقم الإصدار إلى الحافظة."</string>
<string name="basic_status" msgid="2315371112182658176">"محادثة مفتوحة"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"مزيد من المعلومات"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"مزيد من المعلومات على <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"فتح \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• إعداد التطبيق"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"‏• إضافة بطاقة واحدة على الأقل إلى \"محفظة Google\""</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"اختَر تطبيقًا تلقائيًا لتدوين الملاحظات لاستخدام اختصار تدوين الملاحظات."</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"اختيار تطبيق"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"انقر مع الاستمرار على الاختصار."</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"إلغاء"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"وضع الأولوية مفعّل."</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"‏ميزة لفت انتباه \"مساعد Google\" مفعّلة."</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"يمكنك ضبط تطبيق تدوين الملاحظات التلقائي في \"الإعدادات\"."</string>
+ <string name="install_app" msgid="5066668100199613936">"تثبيت التطبيق"</string>
</resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 5f176ae64ab8..36a36938ad85 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"মুখমণ্ডলৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"নিশ্চিত কৰিলে"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"সম্পূৰ্ণ কৰিবলৈ নিশ্চিত কৰক-ত টিপক"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা হৈছে"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"মুখাৱয়বৰ জৰিয়তে আনলক কৰা হৈছে। অব্যাহত ৰাখিবলৈ টিপক।"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। অব্যাহত ৰাখিবলৈ টিপক।"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"মুখাৱয়ব চিনাক্ত কৰা হৈছে। অব্যাহত ৰাখিবলৈ আনলক কৰক চিহ্নটোত টিপক।"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ছেভ কৰিব নোৱাৰি। পুনৰ চেষ্টা কৰক।"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ছেভ কৰিব নোৱাৰি।"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"অতি কমেও ৪ টা বৰ্ণ ব্যৱহাৰ কৰক"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g> টাতকৈ কম বৰ্ণ ব্যৱহাৰ কৰক"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"বিল্ডৰ নম্বৰ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ক্লিপব’ৰ্ডলৈ বিল্ডৰ নম্বৰ প্ৰতিলিপি কৰা হ’ল।"</string>
<string name="basic_status" msgid="2315371112182658176">"বাৰ্তালাপ খোলক"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"অধিক জানক"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g>ত অধিক জানক"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> খোলক"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• এপ্‌টো ছেট আপ কৰা হৈছে"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Walletত অতি কমেও এখন কাৰ্ড যোগ দিয়া হৈছে"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"টোকাগ্ৰহণৰ শ্বৰ্টকাটটো ব্যৱহাৰ কৰিবলৈ এটা ডিফ’ল্ট টোকা লোৱা এপ্‌ বাছনি কৰক"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"এপ্‌ বাছনি কৰক"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"শ্বৰ্টকাটটোত স্পৰ্শ কৰি ধৰি ৰাখক"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"বাতিল কৰক"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"অগ্ৰাধিকাৰ দিয়া ম’ড অন আছে"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistantএ আপোনাৰ কথা শুনি আছে"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ছেটিঙত টোকাৰ ডিফ’ল্ট এপ্ ছেট কৰক"</string>
+ <string name="install_app" msgid="5066668100199613936">"এপ্‌টো ইনষ্টল কৰক"</string>
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index fcd433aed53f..85ec53a5776d 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Üz doğrulandı"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Təsdiqləndi"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tamamlamaq üçün \"Təsdiq edin\" seçiminə toxunun"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Üz ilə kiliddən çıxarılıb"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Üz ilə kiliddən çıxarılıb. Davam etmək üçün basın."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Üz tanınıb. Davam etmək üçün basın."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Üz tanınıb. \"Kiliddən çıxar\" ikonasına basıb davam edin."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Yadda saxlamaq mümkün deyil. Yenə cəhd edin."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Yadda saxlamaq mümkün deyil."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Ən azı 4 simvoldan istifadə edin"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Maksimum <xliff:g id="LENGTH">%1$d</xliff:g> simvol istifadə edin"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Montaj nömrəsi"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versiya nömrəsi mübadilə buferinə kopyalandı."</string>
<string name="basic_status" msgid="2315371112182658176">"Açıq söhbət"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Ətraflı məlumat"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Ətraflı məlumat: <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> tətbiqini açın"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Tətbiq ayarlanmalıdır"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Pulqabına ən azı bir kart əlavə edilməlidir"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Kamera tətbiqini quraşdırın"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Tətbiq ayarlanmalıdır"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ən azı bir cihaz əlçatandır"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Qeydgötürmə qısayolu üçün defolt qeyd tətbiqi seçin"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Tətbiq seçin"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Qısayola toxunub saxlayın"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Ləğv edin"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritet rejimi aktivdir"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent aktivdir"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ayarlarda defolt qeydlər tətbiqi ayarlayın"</string>
+ <string name="install_app" msgid="5066668100199613936">"Tətbiqi quraşdırın"</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index d37c709c9cee..71f149fe0735 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Lice je potvrđeno"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi da biste završili"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Otključano je licem"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Otključano je licem. Pritisnite da biste nastavili."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice je prepoznato. Pritisnite da biste nastavili."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice prepoznato. Pritisnite ikonu otključavanja za nastavak."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Čuvanje nije uspelo. Probajte ponovo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Čuvanje nije uspelo."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Koristite bar 4 znaka"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Koristite manji broj znakova od <xliff:g id="LENGTH">%1$d</xliff:g>"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Broj verzije je kopiran u privremenu memoriju."</string>
<string name="basic_status" msgid="2315371112182658176">"Otvorite konverzaciju"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Saznajte više"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Saznajte više na <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otvorite: <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• da je aplikacija podešena"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• da je u Novčanik dodata barem jedna kartica"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• da ste instalirali aplikaciju za kameru"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• da je aplikacija podešena"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• da je dostupan barem jedan uređaj"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Izaberite podrazumevanu aplikaciju za beleške da biste koristili prečicu za pravljenje beleški"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Izaberi aplikaciju"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Dodirnite i zadržite prečicu"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Otkaži"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritetni režim je uključen"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Pomoćnik je u aktivnom stanju"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Podesite podrazumevanu aplikaciju za beleške u Podešavanjima"</string>
+ <string name="install_app" msgid="5066668100199613936">"Instaliraj aplikaciju"</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 518c5e662a21..6ed2e319c667 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Твар распазнаны"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Пацверджана"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Націсніце \"Пацвердзіць\", каб завяршыць"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Разблакіравана распазнаваннем твару"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Разблакіравана распазнаваннем твару. Націсніце для працягу."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Твар распазнаны. Націсніце для працягу."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Твар распазнаны. Для працягу націсніце значок разблакіроўкі."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не ўдалося захаваць. Паўтарыце спробу."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не ўдалося захаваць."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Скарыстайце не менш як 4 сімвалы"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Колькасць сімвалаў павінна быць меншай за <xliff:g id="LENGTH">%1$d</xliff:g>"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Нумар зборкі"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Нумар зборкі скапіраваны ў буфер абмену."</string>
<string name="basic_status" msgid="2315371112182658176">"Адкрытая размова"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Даведацца больш"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Даведайцеся больш на старонцы <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Адкрыць праграму \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Праграма наладжана."</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• У Кашалёк дададзена хаця б адна картка."</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Выберыце стандартную праграму для нататак, каб карыстацца хуткай камандай для нататак"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Выберыце праграму"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Дакраніцеся і ўтрымлівайце ярлык"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Скасаваць"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Прыярытэтны рэжым уключаны"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Памочнік гатовы выконваць каманды"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Задайце ў Наладах стандартную праграму для нататак"</string>
+ <string name="install_app" msgid="5066668100199613936">"Усталяваць праграму"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 96646ada1ef2..016438fc978d 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лицето е удостоверено"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потвърдено"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Докоснете „Потвърждаване“ за завършване"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Отключено с лице"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Отключено с лице. Натиснете, за да продължите."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицето бе разпознато. Натиснете, за да продължите."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицето бе разпознато. Продължете чрез иконата за отключване."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не може да се запази. Опитайте отново."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не може да се запази."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Използвайте поне 4 знака"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Използвайте по-малко от <xliff:g id="LENGTH">%1$d</xliff:g> знака"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер на компилацията"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Номерът на компилацията е копиран в буферната памет."</string>
<string name="basic_status" msgid="2315371112182658176">"Отворен разговор"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Научете повече"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Научете повече на адрес <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Отваряне на <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Приложението е настроено."</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• В Wallet е добавена поне една карта."</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Изберете стандартно приложение за бележки, за да използвате прекия път за водене на бележки"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Избиране на приложение"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Докоснете и задръжте прекия път"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Отказ"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Приоритетният режим е включен"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Функцията за активиране на Асистент е включена"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Задайте стандартно приложение за бележки от настройките"</string>
+ <string name="install_app" msgid="5066668100199613936">"Инсталиране на приложението"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index a53baad686a8..358174e80e36 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ফেস যাচাই করা হয়েছে"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"কনফার্ম করা হয়েছে"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"সম্পূর্ণ করতে \'কনফার্ম করুন\' বোতামে ট্যাপ করুন"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"ফেস দেখিয়ে আনলক করা হয়েছে"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ফেসের সাহায্যে আনলক করা হয়েছে। চালিয়ে যেতে প্রেস করুন।"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ফেস শনাক্ত করা হয়েছে। চালিয়ে যেতে প্রেস করুন।"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ফেস শনাক্ত করা হয়েছে। চালিয়ে যেতে আনলক আইকন প্রেস করুন।"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"সেভ করা যাচ্ছে না। আবার চেষ্টা করুন।"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"সেভ করা যাচ্ছে না।"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"কমপক্ষে ৪টি অক্ষর ব্যবহার করুন"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g>টির চেয়ে কম অক্ষর ব্যবহার করুন"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"বিল্ড নম্বর"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"বিল্ড নম্বর ক্লিপবোর্ডে কপি করা হয়েছে।"</string>
<string name="basic_status" msgid="2315371112182658176">"খোলা কথোপকথন"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"আরও জানুন"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"আরও জানতে <xliff:g id="URL">%s</xliff:g>-এ যান"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> খুলুন"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• অ্যাপ সেট-আপ করা হয়ে গেছে"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• অন্তত একটি কার্ড Wallet-এ যোগ করা হয়েছে"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"নোট নেওয়ার শর্টকাট ব্যবহার করতে, ডিফল্ট কোনও নোট অ্যাপ বেছে নিন"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"অ্যাপ বেছে নিন"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"শর্টকাট টাচ করে ধরে রাখুন"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"বাতিল করুন"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"\'প্রায়োরিটি\' মোড চালু করা আছে"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"অ্যাসিস্ট্যান্ট আপনার কথা শোনার জন্য চালু করা আছে"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"\'সেটিংস\' থেকে ডিফল্ট নোট নেওয়ার অ্যাপ সেট করুন"</string>
+ <string name="install_app" msgid="5066668100199613936">"অ্যাপ ইনস্টল করুন"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 00790b38beca..4fe026c52b76 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Lice je provjereno"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi da završite"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Otključano je licem"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Otključano licem. Pritisnite da nastavite."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice prepoznato. Pritisnite da nastavite."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice prepoznato. Pritisnite ikonu za otklj. da nastavite."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nije moguće sačuvati. Pokušajte ponovo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nije moguće sačuvati."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Koristite najmanje 4 znaka"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Koristite manje od <xliff:g id="LENGTH">%1$d</xliff:g> znak(ov)a"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Broj verzije je kopiran u međumemoriju."</string>
<string name="basic_status" msgid="2315371112182658176">"Otvoreni razgovor"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Saznajte više"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Saznajte više na <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otvori aplikaciju <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikacija je postavljena"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Najmanje jedna kartica je dodana u Novčanik"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Instalirajte aplikaciju kamere"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Aplikacija je postavljena"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Dostupan je najmanje jedan uređaj"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Odaberite zadanu aplikaciju za bilješke da koristite prečicu za zapisivanje bilješki"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Za dodavanje aplikacije Wallet kao prečaca provjerite je li instalirana"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Provjerite je li dodana barem jedna kartica kako biste dodali aplikaciju Wallet kao prečac"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Provjerite je li instalirana aplikacija kamere kako biste dodali čitač QR koda kao prečac"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Provjerite je li aplikacija Home instalirana kako biste je dodali kao prečac"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Dostupan je najmanje jedan uređaj"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Odaberite zadanu aplikaciju za bilješke da biste koristili prečac za pisanje bilježaka"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Odaberi aplikaciju"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Dodirnite i zadržite prečicu"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Otkaži"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Način rada Prioriteti je uključen"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Pažnja Asistenta je uključena"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Postavite zadanu aplikaciju za bilješke u Postavkama"</string>
+ <string name="install_app" msgid="5066668100199613936">"Instaliraj aplikaciju"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 74b557b624e5..cca1904717fd 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Cara autenticada"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmat"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirma per completar"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"S\'ha desbloquejat amb la cara"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"S\'ha desbloquejat amb la cara. Prem per continuar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"S\'ha reconegut la cara. Prem per continuar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"S\'ha reconegut la cara. Prem la icona per continuar."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"No es pot desar. Torna-ho a provar."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"No es pot desar."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utilitza 4 caràcters com a mínim"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Utilitza menys de <xliff:g id="LENGTH">%1$d</xliff:g> caràcters"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilació"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"El número de compilació s\'ha copiat al porta-retalls."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversa oberta"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Més informació"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Més informació a <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Obre <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• L\'aplicació està configurada."</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Almenys s\'ha afegit una targeta a Wallet."</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Tens una aplicació de càmera."</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• L\'aplicació està configurada."</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Almenys un dispositiu està disponible."</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Selecciona una aplicació de notes predeterminada per utilitzar la drecera de presa de notes"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Selecciona una aplicació"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Mantén premuda la drecera"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancel·la"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"El mode Prioritat està activat"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"L\'Assistent està activat"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Defineix l\'aplicació de notes predeterminada a Configuració"</string>
+ <string name="install_app" msgid="5066668100199613936">"Instal·la l\'aplicació"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 97bf39f19223..404779f24e3e 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Obličej byl ověřen"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrzeno"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ověření dokončíte klepnutím na Potvrdit"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Odemknuto obličejem"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odemknuto obličejem. Pokračujte stisknutím."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Obličej rozpoznán. Pokračujte stisknutím."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Obličej rozpoznán. Klepněte na ikonu odemknutí."</string>
@@ -307,7 +306,7 @@
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je vypnuto"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je zapnuto"</string>
- <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Záznam obrazovky"</string>
+ <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Rekordér obrazovky"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Spustit"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ukončit"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Režim jedné ruky"</string>
@@ -419,7 +418,7 @@
<string name="manage_notifications_text" msgid="6885645344647733116">"Spravovat"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Historie"</string>
<string name="notification_section_header_incoming" msgid="850925217908095197">"Nové"</string>
- <string name="notification_section_header_gentle" msgid="6804099527336337197">"Tichá oznámení"</string>
+ <string name="notification_section_header_gentle" msgid="6804099527336337197">"Tichý režim"</string>
<string name="notification_section_header_alerting" msgid="5581175033680477651">"Oznámení"</string>
<string name="notification_section_header_conversations" msgid="821834744538345661">"Konverzace"</string>
<string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Vymazat všechna tichá oznámení"</string>
@@ -563,7 +562,7 @@
<string name="inline_done_button" msgid="6043094985588909584">"Hotovo"</string>
<string name="inline_ok_button" msgid="603075490581280343">"Použít"</string>
<string name="inline_turn_off_notifications" msgid="8543989584403106071">"Vypnout oznámení"</string>
- <string name="notification_silence_title" msgid="8608090968400832335">"Tiché"</string>
+ <string name="notification_silence_title" msgid="8608090968400832335">"Tichý režim"</string>
<string name="notification_alert_title" msgid="3656229781017543655">"Výchozí"</string>
<string name="notification_automatic_title" msgid="3745465364578762652">"Automaticky"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Žádný zvuk ani vibrace"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Uložení se nezdařilo. Zkuste to znovu."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Uložení se nezdařilo."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Heslo musí mít alespoň 4 znaky"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Použijte méně než <xliff:g id="LENGTH">%1$d</xliff:g> znaků"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo sestavení"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Číslo sestavení bylo zkopírováno do schránky."</string>
<string name="basic_status" msgid="2315371112182658176">"Otevřít konverzaci"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Další informace"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Další informace najdete na adrese <xliff:g id="URL">%s</xliff:g>."</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otevřít <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikace je nastavena"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Do Peněženky byla přidána alespoň jedna karta"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Je nainstalována aplikace pro fotoaparát"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Aplikace je nastavena"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Je k dispozici alespoň jedno zařízení"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Vyberte výchozí aplikaci k psaní poznámek, ke které přidružíte zkratku pro poznámky"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Vyberte aplikaci"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Podržte zkratku"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Zrušit"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Režim priority je zapnutý"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Pozornost Asistenta je zapnutá"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Výchozí aplikaci pro poznámky nastavíte v Nastavení"</string>
+ <string name="install_app" msgid="5066668100199613936">"Nainstalovat aplikaci"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 7388fbf6d8a8..ededbd39c5d6 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ansigtet er godkendt"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekræftet"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tryk på Bekræft for at udføre"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Låst op via ansigtsgenkendelse"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Låst op ved hjælp af ansigt. Tryk for at fortsætte."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansigt genkendt. Tryk for at fortsætte."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansigt genkendt. Tryk på oplåsningsikonet for at fortsætte."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Der kan ikke gemmes. Prøv igen."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Der kan ikke gemmes."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Angiv mindst 4 tegn"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Angiv færre end <xliff:g id="LENGTH">%1$d</xliff:g> tegn"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildnummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Buildnummeret blev kopieret til udklipsholderen."</string>
<string name="basic_status" msgid="2315371112182658176">"Åben samtale"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Få flere oplysninger"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Få flere oplysninger på <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Åbn <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Appen er konfigureret"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Mindst ét kort er føjet til Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Installer en kameraapp"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Appen er konfigureret"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Mindst én enhed er tilgængelig"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Vælg en standardapp til noter for at bruge genvejen til notetagning"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Vælg app"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Hold fingeren på genvejen"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Annuller"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritetstilstand er aktiveret"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent lytter"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Angiv standardapp til noter i Indstillinger"</string>
+ <string name="install_app" msgid="5066668100199613936">"Installer app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 7608509fdbbd..d987120554c1 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Gesicht authentifiziert"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bestätigt"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Zum Abschließen auf \"Bestätigen\" tippen"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Mit Gesicht entsperrt"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Gerät mit dem Gesicht entsperrt. Tippe, um fortzufahren."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gesicht erkannt. Tippe, um fortzufahren."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gesicht erkannt. Tippe zum Fortfahren auf das Symbol „Entsperren“."</string>
@@ -453,9 +452,9 @@
<string name="monitoring_subtitle_ca_certificate" msgid="8588092029755175800">"CA-Zertifikate"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Richtlinien ansehen"</string>
<string name="monitoring_button_view_controls" msgid="8316440345340701117">"Jugendschutzeinstellungen"</string>
- <string name="monitoring_description_named_management" msgid="505833016545056036">"Dieses Gerät gehört <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nDein IT-Administrator kann Einstellungen, Zugriffsrechte im Unternehmen, Apps, mit diesem Gerät verknüpfte Daten und die Standortdaten deines Geräts sehen und verwalten.\n\nWeitere Informationen erhältst du von deinem IT-Administrator."</string>
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Dieses Gerät gehört <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nIhr IT-Administrator kann Einstellungen, Zugriffsrechte im Unternehmen, Apps, mit diesem Gerät verknüpfte Daten und die Standortdaten Ihres Geräts sehen und verwalten.\n\nWeitere Informationen erhalten Sie von Ihrem IT-Administrator."</string>
<string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> kann möglicherweise auf die Daten zugreifen, die mit diesem Gerät verknüpft sind, Apps verwalten und die Geräteeinstellungen ändern.\n\nFalls du Fragen hast, wende dich an <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>."</string>
- <string name="monitoring_description_management" msgid="4308879039175729014">"Dieses Gerät gehört deiner Organisation.\n\nDein IT-Administrator kann Einstellungen, Zugriffsrechte im Unternehmen, Apps, mit diesem Gerät verknüpfte Daten und die Standortdaten deines Geräts sehen und verwalten.\n\nWeitere Informationen erhältst du von deinem IT-Administrator."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Dieses Gerät gehört Ihrer Organisation.\n\nIhr IT-Administrator kann Einstellungen, Zugriffsrechte im Unternehmen, Apps, mit diesem Gerät verknüpfte Daten und die Standortdaten Ihres Geräts sehen und verwalten.\n\nWeitere Informationen erhalten Sie von Ihrem IT-Administrator."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Deine Organisation hat ein Zertifikat einer Zertifizierungsstelle auf deinem Gerät installiert. Eventuell wird dein sicherer Netzwerkverkehr überwacht oder bearbeitet."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Deine Organisation hat ein Zertifikat einer Zertifizierungsstelle in deinem Arbeitsprofil installiert. Eventuell wird dein sicherer Netzwerkverkehr überwacht oder bearbeitet."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Auf dem Gerät ist das Zertifikat einer Zertifizierungsstelle installiert. Eventuell wird dein sicherer Netzwerkverkehr überwacht oder bearbeitet."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Speichern nicht möglich. Versuche es noch einmal."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Speichern nicht möglich."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gib mindestens vier Zeichen ein"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Maximal <xliff:g id="LENGTH">%1$d</xliff:g> Zeichen möglich"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build-Nummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build-Nummer in Zwischenablage kopiert."</string>
<string name="basic_status" msgid="2315371112182658176">"Offene Unterhaltung"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Weitere Informationen"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Weitere Informationen unter <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> öffnen"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Die App ist eingerichtet"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet wurde mindestens eine Karte hinzugefügt"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Kamera-App ist installiert"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Die App ist eingerichtet"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Mindestens ein Gerät ist verfügbar"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Wähle eine Standard-App für Notizen aus, die du für die Verknüpfung verwenden möchtest"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"App wählen"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Verknüpfung berühren &amp; halten"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Abbrechen"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritätsmodus an"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant-Aktivierung an"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Standard-Notizen-App in den Einstellungen einrichten"</string>
+ <string name="install_app" msgid="5066668100199613936">"App installieren"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index e4187543b335..a863cc73a3dd 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Έγινε έλεγχος ταυτότητας προσώπου"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Επιβεβαιώθηκε"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Πατήστε Επιβεβαίωση για ολοκλήρωση"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Ξεκλειδώθηκε με αναγνώριση προσώπου"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ξεκλείδωμα με αναγνώριση προσώπου. Πατήστε για συνέχεια."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Το πρόσωπο αναγνωρίστηκε. Πατήστε για συνέχεια."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Το πρόσωπο αναγνωρ. Πατήστε το εικον. ξεκλειδ. για συνέχεια."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Δεν είναι δυνατή η αποθήκευση. Δοκιμάστε ξανά."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Δεν είναι δυνατή η αποθήκευση."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Χρησιμοποιήστε τουλάχιστον 4 χαρακτήρες"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Χρησιμοποιήστε λιγότερους από <xliff:g id="LENGTH">%1$d</xliff:g> χαρακτήρες"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Αριθμός έκδοσης"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Ο αριθμός έκδοσης αντιγράφηκε στο πρόχειρο."</string>
<string name="basic_status" msgid="2315371112182658176">"Άνοιγμα συνομιλίας"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Μάθετε περισσότερα"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Μάθετε περισσότερα στο <xliff:g id="URL">%s</xliff:g>."</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Άνοιγμα <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Η εφαρμογή έχει ρυθμιστεί"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Έχει προστεθεί τουλάχιστον μία κάρτα στο Πορτοφόλι"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Επιλέξτε μια προεπιλεγμένη εφαρμογή σημειώσεων για να χρησιμοποιήσετε τη συντόμευση δημιουργίας σημειώσεων"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Επιλογή εφαρμογής"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Παρατεταμένο άγγιγμα συντόμευσης"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Ακύρωση"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Η λειτουργία προτεραιότητας είναι ενεργοποιημένη"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Ο Βοηθός βρίσκεται σε αναμονή"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ορίστε την προεπιλεγμένη εφαρμογή σημειώσεων στις Ρυθμίσεις"</string>
+ <string name="install_app" msgid="5066668100199613936">"Εγκατάσταση εφαρμογής"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 524864a1bc53..afadffb57928 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Unlocked by face"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string>
@@ -451,11 +450,11 @@
<string name="monitoring_subtitle_vpn" msgid="800485258004629079">"VPN"</string>
<string name="monitoring_subtitle_network_logging" msgid="2444199331891219596">"Network logging"</string>
<string name="monitoring_subtitle_ca_certificate" msgid="8588092029755175800">"CA certificates"</string>
- <string name="monitoring_button_view_policies" msgid="3869724835853502410">"View Policies"</string>
+ <string name="monitoring_button_view_policies" msgid="3869724835853502410">"View policies"</string>
<string name="monitoring_button_view_controls" msgid="8316440345340701117">"View controls"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> may be able to access data associated with this device, manage apps and change this device\'s settings.\n\nIf you have questions, contact <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>."</string>
- <string name="monitoring_description_management" msgid="4308879039175729014">"This device belongs to your organisation.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"This device belongs to your organisation.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Your organisation installed a certificate authority on this device. Your secure network traffic may be monitored or modified."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Your organisation installed a certificate authority in your work profile. Your secure network traffic may be monitored or modified."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"A certificate authority is installed on this device. Your secure network traffic may be monitored or modified."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Can’t save. Try again."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Can’t save."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use at least four characters"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Use fewer than <xliff:g id="LENGTH">%1$d</xliff:g> characters"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
<string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Learn more"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Learn more at <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Open <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• The app is set up"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• At least one card has been added to Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Install a camera app"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• The app is set up"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• At least one device is available"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Select a default notes app to use the note-taking shortcut"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Select app"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Touch &amp; hold shortcut"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancel"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Priority mode on"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant attention on"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Set default notes app in Settings"</string>
+ <string name="install_app" msgid="5066668100199613936">"Install app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index d8971ba0d30d..4f46c007ef1b 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -450,11 +450,11 @@
<string name="monitoring_subtitle_vpn" msgid="800485258004629079">"VPN"</string>
<string name="monitoring_subtitle_network_logging" msgid="2444199331891219596">"Network logging"</string>
<string name="monitoring_subtitle_ca_certificate" msgid="8588092029755175800">"CA certificates"</string>
- <string name="monitoring_button_view_policies" msgid="3869724835853502410">"View Policies"</string>
+ <string name="monitoring_button_view_policies" msgid="3869724835853502410">"View policies"</string>
<string name="monitoring_button_view_controls" msgid="8316440345340701117">"View controls"</string>
- <string name="monitoring_description_named_management" msgid="505833016545056036">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> may be able to access data associated with this device, manage apps, and change this devices settings.\n\nIf you have questions, contact <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>."</string>
- <string name="monitoring_description_management" msgid="4308879039175729014">"This device belongs to your organization.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"This device belongs to your organization.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Your organization installed a certificate authority on this device. Your secure network traffic may be monitored or modified."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Your organization installed a certificate authority in your work profile. Your secure network traffic may be monitored or modified."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"A certificate authority is installed on this device. Your secure network traffic may be monitored or modified."</string>
@@ -1003,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Can’t save. Try again."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Can’t save."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use at least 4 characters"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Use fewer than <xliff:g id="LENGTH">%1$d</xliff:g> characters"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
<string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -1124,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Learn more"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Learn more at <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Open <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• The app is set up"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• At least one card has been added to Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Install a camera app"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• The app is set up"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• At least one device is available"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Select a default notes app to use the notetaking shortcut"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"To add the Wallet app as a shortcut, make sure the app is installed"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"To add the Wallet app as a shortcut, make sure at least one card has been added"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"To add the QR code scanner as a shortcut, make sure a camera app is installed"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"To add the Home app as a shortcut, make sure the app is installed"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• At least one device is available"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Select a default notes app to use the notetaking shortcut"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Select app"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Touch and hold shortcut"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancel"</string>
@@ -1158,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Priority mode on"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant attention on"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Set default notes app in Settings"</string>
+ <string name="install_app" msgid="5066668100199613936">"Install app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 524864a1bc53..afadffb57928 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Unlocked by face"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string>
@@ -451,11 +450,11 @@
<string name="monitoring_subtitle_vpn" msgid="800485258004629079">"VPN"</string>
<string name="monitoring_subtitle_network_logging" msgid="2444199331891219596">"Network logging"</string>
<string name="monitoring_subtitle_ca_certificate" msgid="8588092029755175800">"CA certificates"</string>
- <string name="monitoring_button_view_policies" msgid="3869724835853502410">"View Policies"</string>
+ <string name="monitoring_button_view_policies" msgid="3869724835853502410">"View policies"</string>
<string name="monitoring_button_view_controls" msgid="8316440345340701117">"View controls"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> may be able to access data associated with this device, manage apps and change this device\'s settings.\n\nIf you have questions, contact <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>."</string>
- <string name="monitoring_description_management" msgid="4308879039175729014">"This device belongs to your organisation.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"This device belongs to your organisation.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Your organisation installed a certificate authority on this device. Your secure network traffic may be monitored or modified."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Your organisation installed a certificate authority in your work profile. Your secure network traffic may be monitored or modified."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"A certificate authority is installed on this device. Your secure network traffic may be monitored or modified."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Can’t save. Try again."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Can’t save."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use at least four characters"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Use fewer than <xliff:g id="LENGTH">%1$d</xliff:g> characters"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
<string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Learn more"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Learn more at <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Open <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• The app is set up"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• At least one card has been added to Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Install a camera app"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• The app is set up"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• At least one device is available"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Select a default notes app to use the note-taking shortcut"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Select app"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Touch &amp; hold shortcut"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancel"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Priority mode on"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant attention on"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Set default notes app in Settings"</string>
+ <string name="install_app" msgid="5066668100199613936">"Install app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 524864a1bc53..afadffb57928 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Face authenticated"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmed"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tap Confirm to complete"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Unlocked by face"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Unlocked by face. Press to continue."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Face recognised. Press to continue."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Face recognised. Press the unlock icon to continue."</string>
@@ -451,11 +450,11 @@
<string name="monitoring_subtitle_vpn" msgid="800485258004629079">"VPN"</string>
<string name="monitoring_subtitle_network_logging" msgid="2444199331891219596">"Network logging"</string>
<string name="monitoring_subtitle_ca_certificate" msgid="8588092029755175800">"CA certificates"</string>
- <string name="monitoring_button_view_policies" msgid="3869724835853502410">"View Policies"</string>
+ <string name="monitoring_button_view_policies" msgid="3869724835853502410">"View policies"</string>
<string name="monitoring_button_view_controls" msgid="8316440345340701117">"View controls"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> may be able to access data associated with this device, manage apps and change this device\'s settings.\n\nIf you have questions, contact <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>."</string>
- <string name="monitoring_description_management" msgid="4308879039175729014">"This device belongs to your organisation.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"This device belongs to your organisation.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Your organisation installed a certificate authority on this device. Your secure network traffic may be monitored or modified."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Your organisation installed a certificate authority in your work profile. Your secure network traffic may be monitored or modified."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"A certificate authority is installed on this device. Your secure network traffic may be monitored or modified."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Can’t save. Try again."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Can’t save."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use at least four characters"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Use fewer than <xliff:g id="LENGTH">%1$d</xliff:g> characters"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
<string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Learn more"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Learn more at <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Open <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• The app is set up"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• At least one card has been added to Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Install a camera app"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• The app is set up"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• At least one device is available"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Select a default notes app to use the note-taking shortcut"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Select app"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Touch &amp; hold shortcut"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancel"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Priority mode on"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant attention on"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Set default notes app in Settings"</string>
+ <string name="install_app" msgid="5066668100199613936">"Install app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 368632b12250..c95d6aa8b466 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -1003,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‏‎‏‏‎‎‏‎Can’t save. Try again.‎‏‎‎‏‎"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‎‏‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‎‎‏‏‎Can’t save.‎‏‎‎‏‎"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‏‎‎‏‏‏‎‎‏‎Use at least 4 characters‎‏‎‎‏‎"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‎‎‏‏‏‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‏‏‎‏‏‎‏‎‏‎‏‏‏‏‎‎‎‎‏‎‎Use fewer than ‎‏‎‎‏‏‎<xliff:g id="LENGTH">%1$d</xliff:g>‎‏‎‎‏‏‏‎ characters‎‏‎‎‏‎"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‎‎‎‎‎‏‏‏‎‎‎‎‎‎‏‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎Build number‎‏‎‎‏‎"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‎Build number copied to clipboard.‎‏‎‎‏‎"</string>
<string name="basic_status" msgid="2315371112182658176">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‎‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‎‎‎‎‎Open conversation‎‏‎‎‏‎"</string>
@@ -1124,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‎‎‎‎‎‎‏‏‎‏‏‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎Learn more‎‏‎‎‏‎"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‎‎‏‏‏‏‎‎‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎‎‎‎‏‎Learn more at ‎‏‎‎‏‏‎<xliff:g id="URL">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‎‎‎Open ‎‏‎‎‏‏‎<xliff:g id="APPNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‏‎‏‏‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‏‏‏‎‎• The app is set up‎‏‎‎‏‎"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‏‏‎‎‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‏‏‎• At least one card has been added to Wallet‎‏‎‎‏‎"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‎‏‏‏‏‏‎‏‏‏‏‎• Install a camera app‎‏‎‎‏‎"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‎‎‏‎• The app is set up‎‏‎‎‏‎"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‏‎‎‏‎‎‏‏‏‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎• At least one device is available‎‏‎‎‏‎"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‏‎‎‎‏‏‏‎Select a default notes app to use the notetaking shortcut‎‏‎‎‏‎"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‎‎‏‏‎‏‎‏‎‏‏‎‎‏‏‎‎‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‏‎‎‎‎‎To add the Wallet app as a shortcut, make sure the app is installed‎‏‎‎‏‎"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎‏‎‎‏‏‎‎‏‎‏‎‎‏‏‏‎‏‎‎‏‏‎‏‎‎‏‏‎‏‎‏‎‎To add the Wallet app as a shortcut, make sure at least one card has been added‎‏‎‎‏‎"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎To add the QR code scanner as a shortcut, make sure a camera app is installed‎‏‎‎‏‎"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‎‎‏‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‏‎‏‏‎‎‎‎To add the Home app as a shortcut, make sure the app is installed‎‏‎‎‏‎"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‏‎‏‏‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‎‏‏‎‎‏‏‏‎• At least one device is available‎‏‎‎‏‎"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‏‎‏‎‏‎‏‎‎‏‏‎‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎‎‎‏‎‎Select a default notes app to use the notetaking shortcut‎‏‎‎‏‎"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‎‎‏‎‏‎‏‏‎‏‏‎‏‎‏‏‎‎‎‏‏‏‏‏‎‎Select app‎‏‎‎‏‎"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‎‎‏‏‎‎‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎‎Touch &amp; hold shortcut‎‏‎‎‏‎"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‏‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎‏‏‎‏‏‏‎‏‏‎‎‎‎‎‎‎Cancel‎‏‎‎‏‎"</string>
@@ -1158,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‏‎‎‏‎‎‏‎‎‎‎Priority mode on‎‏‎‎‏‎"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‏‏‎‏‏‎Assistant attention on‎‏‎‎‏‎"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎‏‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎‎‎‏‎Set default notes app in Settings‎‏‎‎‏‎"</string>
+ <string name="install_app" msgid="5066668100199613936">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‎‎Install app‎‏‎‎‏‎"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 06647b79ce78..e2ac0ff7c47c 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Se autenticó el rostro"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmado"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Presiona Confirmar para completar"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Se desbloqueó con el rostro"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueo con rostro. Presiona para continuar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rostro reconocido. Presiona para continuar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rostro reconocido. Presiona el desbloqueo para continuar."</string>
@@ -537,7 +536,7 @@
<string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Actualizando"</string>
<string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
<string name="wallet_error_generic" msgid="257704570182963611">"Ocurrió un problema al obtener las tarjetas; vuelve a intentarlo más tarde"</string>
- <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuración de pantalla de bloqueo"</string>
+ <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuración de la pantalla de bloqueo"</string>
<string name="qr_code_scanner_title" msgid="1938155688725760702">"Escáner de código QR"</string>
<string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Actualizando"</string>
<string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabajo"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"No se puede guardar. Vuelve a intentarlo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"No se puede guardar."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Usa al menos 4 caracteres"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Usa menos de <xliff:g id="LENGTH">%1$d</xliff:g> caracteres"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Se copió el número de compilación en el portapapeles."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversación abierta"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Más información"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Más información en <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Se configuró la app."</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Se agregó al menos una tarjeta a la Billetera."</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Se instaló la app de Cámara."</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Se configuró la app."</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Hay al menos un dispositivo disponible."</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Selecciona una app de notas predeterminada para usar el atajo de toma de notas"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Para agregar la app de Billetera como acceso directo, asegúrate de haber instalado la app"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Para agregar la app de Billetera como acceso directo, asegúrate de haber agregado al menos una tarjeta"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Para agregar el escáner de código QR como acceso directo, asegúrate de haber instalado la app de la cámara"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Para agregar la app de Home como acceso directo, asegúrate de haber instalado la app"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Hay al menos un dispositivo disponible"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Selecciona una app de notas predeterminada para usar el acceso directo de toma de notas"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Seleccionar app"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Mantener presionado atajo"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"El modo de prioridad está activado"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistente está prestando atención"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Configura la app de notas predeterminada en Configuración"</string>
+ <string name="install_app" msgid="5066668100199613936">"Instalar app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index c6b8d5081fae..f25e0182e6e9 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Cara autenticada"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirmar para completar la acción"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Desbloqueado con la cara"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado con la cara. Pulsa para continuar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Cara reconocida. Pulsa para continuar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Cara reconocida. Pulsa el icono de desbloquear para continuar."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"No se puede guardar. Inténtalo de nuevo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"No se puede guardar."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Usa 4 caracteres como mínimo"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Usa menos de <xliff:g id="LENGTH">%1$d</xliff:g> caracteres"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número de compilación copiado en el portapapeles."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversación abierta"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Más información"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Más información en <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• La aplicación debe estar configurada"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Se debe haber añadido al menos una tarjeta a Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Debes instalar una aplicación de cámara"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• La aplicación debe estar configurada"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Al menos un dispositivo debe estar disponible"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Selecciona una aplicación de notas predeterminada para usar el acceso directo de toma de notas"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Seleccionar aplicación"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Mantén pulsado el acceso directo"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modo Prioridad activado"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"El Asistente está activado"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Configura la aplicación de notas predeterminada en Ajustes"</string>
+ <string name="install_app" msgid="5066668100199613936">"Instalar aplicación"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index bb9198eeeaf6..e13fe919d1c1 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Nägu on autenditud"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Kinnitatud"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Lõpuleviimiseks puudutage nuppu Kinnita"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Avati näoga"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Avati näoga. Vajutage jätkamiseks."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Nägu tuvastati. Vajutage jätkamiseks."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Nägu tuvastati. Jätkamiseks vajutage avamise ikooni."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ei saa salvestada. Proovige uuesti."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ei saa salvestada."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Kasutage vähemalt 4 tähemärki"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Kasutage vähem kui <xliff:g id="LENGTH">%1$d</xliff:g> tähemärki"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Järgunumber"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Järgunumber kopeeriti lõikelauale."</string>
<string name="basic_status" msgid="2315371112182658176">"Avage vestlus"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Lisateave"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Lisateave: <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ava <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Rakendus on seadistatud"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Vähemalt üks kaart on Walletisse lisatud"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Installige kaamerarakendus"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Rakendus on seadistatud"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Vähemalt üks seade on saadaval"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Valige märkmete tegemise vaikerakendus, et kasutada märkmete tegemise otseteed"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Valige rakendus"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Pikalt puudutamise otsetee"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Tühista"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteetne režiim on sisse lülitatud"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent on aktiveeritud"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Määrake seadetes märkmete vaikerakendus."</string>
+ <string name="install_app" msgid="5066668100199613936">"Installi rakendus"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index a24dfef0cf1b..d80ff83bc0da 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Autentifikatu da aurpegia"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Berretsita"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Amaitzeko, sakatu \"Berretsi\""</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Aurpegiaren bidez desblokeatu da"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Aurpegiaren bidez desblokeatu da. Sakatu aurrera egiteko."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ezagutu da aurpegia. Sakatu aurrera egiteko."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ezagutu da aurpegia. Aurrera egiteko, sakatu desblokeatzeko ikonoa."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ezin da gorde. Saiatu berriro."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ezin da gorde."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Erabili lau karaktere gutxienez"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Erabili <xliff:g id="LENGTH">%1$d</xliff:g> karaktere baino gutxiago"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Konpilazio-zenbakia"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Kopiatu da konpilazio-zenbakia arbelean."</string>
<string name="basic_status" msgid="2315371112182658176">"Elkarrizketa irekia"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Lortu informazio gehiago"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Lortu informazio gehiago <xliff:g id="URL">%s</xliff:g> helbidean"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ireki <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikazioa konfiguratuta dago."</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Diru-zorroa zerbitzuan gutxienez txartel bat gehitu da."</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Kamera-aplikazio bat instalatu da."</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Aplikazioa konfiguratuta dago."</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Gutxienez gailu bat erabilgarri dago."</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Oharrak idazteko lasterbidea erabiltzeko, hautatu oharretarako aplikazio lehenetsia."</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Hautatu aplikazioa"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Eduki sakatuta lasterbidea"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Utzi"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Lehentasun modua aktibatuta dago"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Laguntzailea zerbitzuak arreta jarrita dauka"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ezarri oharren aplikazio lehenetsia ezarpenetan"</string>
+ <string name="install_app" msgid="5066668100199613936">"Instalatu aplikazioa"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 1b029051fa00..456d91fc2f46 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"چهره اصالت‌سنجی شد"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تأیید شد"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"برای تکمیل، روی تأیید ضربه بزنید"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"قفل با چهره باز شد"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"قفلْ با چهره باز شد. برای ادامه، فشار دهید."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"چهره شناسایی شد. برای ادامه، فشار دهید."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"چهره شناسایی شد. برای ادامه، نماد قفل‌گشایی را فشار دهید."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ذخیره نشد. دوباره امتحان کنید."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ذخیره نشد."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"حداقل از ۴ نویسه استفاده کنید"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"از کمتر از <xliff:g id="LENGTH">%1$d</xliff:g> نویسه استفاده کنید"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"شماره ساخت"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"شماره ساخت در بریده‌دان کپی شد."</string>
<string name="basic_status" msgid="2315371112182658176">"باز کردن مکالمه"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"بیشتر بدانید"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"در <xliff:g id="URL">%s</xliff:g> اطلاعات بیشتری دریافت کنید"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"باز کردن <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• برنامه راه‌اندازی شده باشد"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• حداقل یک کارت به «کیف پول» اضافه شده باشد"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"برنامه یادداشت پیش‌فرضی را برای میان‌بر یادداشت‌برداری انتخاب کنید"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"برای افزودن برنامه «کیف پول» به‌عنوان میان‌بر، مطمئن شوید این برنامه نصب شده باشد"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"برای افزودن برنامه «کیف پول» به‌عنوان میان‌بر، مطمئن شوید حداقل یک کارت اضافه شده باشد"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"برای افزودن «کدخوان پاسخ‌سریع» به‌عنوان میان‌بر، مطمئن شوید برنامه دوربین نصب شده باشد"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"‏برای افزودن برنامه Home به‌عنوان میان‌بر، مطمئن شوید این برنامه نصب شده باشد"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• حداقل یک دستگاه دردسترس باشد"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"برای استفاده از میان‌بر یادداشت‌برداری، برنامه یادداشت پیش‌فرضی را انتخاب کنید"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"انتخاب برنامه"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"میان‌بر را لمس کنید و نگه دارید"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"لغو کردن"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"حالت اولویت روشن است"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"توجه «دستیار» روشن است"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"برنامه پیش‌فرض یادداشت را در «تنظیمات» تنظیم کنید"</string>
+ <string name="install_app" msgid="5066668100199613936">"نصب برنامه"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 91b074d1396f..598bc888f4fc 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Kasvot tunnistettu"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Vahvistettu"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Valitse lopuksi Vahvista"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Avattu kasvojen avulla"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Avattu kasvojen avulla. Jatka painamalla."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Kasvot tunnistettu. Jatka painamalla."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Kasvot tunnistettu. Jatka lukituksen avauskuvakkeella."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Tallennus ei onnistu. Yritä uudelleen."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Tallennus ei onnistu."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Käytä vähintään 4 merkkiä"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Käytä alle <xliff:g id="LENGTH">%1$d</xliff:g> merkkiä"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Koontiversion numero"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Koontiversion numero kopioitu leikepöydälle"</string>
<string name="basic_status" msgid="2315371112182658176">"Avaa keskustelu"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Lue lisää"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Lue lisää: <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Avaa <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Sovellus on otettu käyttöön"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Ainakin yksi kortti on lisätty Walletiin"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Asenna kamerasovellus"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Sovellus on otettu käyttöön"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ainakin yksi laite on käytettävissä"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Valitse muistiinpanojen tekemisen oletussovellus, jota käytetään pikanäppäimen avulla"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Valitse sovellus"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Kosketa pikakuvaketta pitkään"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Peru"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Tärkeät-tila on päällä"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant on aktiivinen"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Aseta oletusmuistiinpanosovellus Asetuksista"</string>
+ <string name="install_app" msgid="5066668100199613936">"Asenna sovellus"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 7d2d92abf954..848774b4ecfc 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Visage authentifié"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmé"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Touchez Confirmer pour terminer"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Déverrouillé avec le visage"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Déverr. par reconnaissance faciale. Appuyez pour continuer."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Visage reconnu. Appuyez pour continuer."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Visage reconnu. Appuyez sur Déverrouiller pour continuer."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Impossible d\'enregistrer. Réessayez."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Impossible d\'enregistrer."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utilisez au moins 4 caractères"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Utilisez moins de <xliff:g id="LENGTH">%1$d</xliff:g> caractères"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de version"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Le numéro de version a été copié dans le presse-papiers."</string>
<string name="basic_status" msgid="2315371112182658176">"Ouvrir la conversation"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"En savoir plus"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"En savoir plus : <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ouvrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• que cette application est configurée;"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• qu\'au moins une carte a été ajoutée à Portefeuille."</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• qu\'une application de caméra est installée;"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• que cette application est configurée;"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• qu\'au moins un appareil est utilisable;"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Sélectionnez une application de prise de notes par défaut pour utiliser le raccourci de prise de notes"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Sélectionner l\'application"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Maintenir le doigt sur raccourci"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Annuler"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mode Priorité activé"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant à l\'écoute"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Définir l\'application de prise de notes par défaut dans les Paramètres"</string>
+ <string name="install_app" msgid="5066668100199613936">"Installer l\'application"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 496ae69342d5..90847ad69b2e 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Visage authentifié"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmé"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Appuyez sur \"Confirmer\" pour terminer"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Déverrouillé par le visage"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Déverrouillé par visage. Appuyez pour continuer."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Visage reconnu. Appuyez pour continuer."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Visage reconnu. Appuyez sur l\'icône de déverrouillage pour continuer."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Impossible d\'enregistrer. Réessayez."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Impossible d\'enregistrer."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utilisez au moins quatre caractères"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Utilisez moins de <xliff:g id="LENGTH">%1$d</xliff:g> caractères"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numéro de build copié dans le presse-papiers."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversation ouverte"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"En savoir plus"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Pour en savoir plus, rendez-vous sur <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ouvrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• L\'appli est configurée"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Au moins une carte a été ajoutée à Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Installer une appli d\'appareil photo"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• L\'appli est configurée"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Au moins un appareil est disponible"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Sélectionnez une appli de notes par défaut pour utiliser le raccourci de prise de notes"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Pour ajouter l\'appli Wallet comme raccourci, vérifiez que l\'appli est installée"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Pour ajouter l\'appli Wallet comme raccourci, assurez-vous qu\'au moins une carte a été ajoutée"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Pour ajouter le lecteur de code QR comme raccourci, assurez-vous qu\'une appli d\'appareil photo est installée"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Pour ajouter l\'application Home comme raccourci, vérifiez que l\'appli est installée"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Au moins un appareil est disponible"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Sélectionnez une appli de notes par défaut pour utiliser le raccourci de prise de notes"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Sélectionner une appli"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Appuyez de manière prolongée sur raccourci"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Annuler"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mode Prioritaire activé"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant à l\'écoute"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Définir une appli de notes par défaut dans les paramètres"</string>
+ <string name="install_app" msgid="5066668100199613936">"Installer l\'appli"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index bca8d5173deb..325d880cce89 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -98,7 +98,7 @@
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Engadir a unha nota"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Gravadora da pantalla"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando gravación pantalla"</string>
- <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación en curso sobre unha sesión de gravación de pantalla"</string>
+ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación de actividade en curso sobre unha sesión de gravación de pantalla"</string>
<string name="screenrecord_permission_dialog_title" msgid="303380743267672953">"Queres iniciar a gravación?"</string>
<string name="screenrecord_permission_dialog_warning_entire_screen" msgid="4152602778470789965">"Durante a gravación, Android ten acceso a todo o que se vexa na pantalla ou se reproduza no teu dispositivo. Polo tanto, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como o contido de audio e de vídeo."</string>
<string name="screenrecord_permission_dialog_warning_single_app" msgid="6818309727772146138">"Durante a gravación dunha aplicación, Android ten acceso a todo o que se vexa ou se reproduza nela. Polo tanto, debes ter coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como o contido de audio e de vídeo."</string>
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Autenticouse a cara"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toca Confirmar para completar o proceso"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Usouse o desbloqueo facial"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Usouse o desbloqueo facial. Preme para continuar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Recoñeceuse a cara. Preme para continuar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Recoñeceuse a cara. Preme a icona de desbloquear."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Non se puido gardar a información. Téntao de novo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Non se pode gardar a información."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utiliza como mínimo 4 caracteres"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Utiliza menos de <xliff:g id="LENGTH">%1$d</xliff:g> caracteres"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Copiouse o número de compilación no portapapeis."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversa aberta"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Máis información"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Máis información en <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• A aplicación debe estar configurada"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Ten que haber polo menos unha tarxeta engadida a Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Debes instalar a aplicación de cámara"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• A aplicación debe estar configurada"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ten que haber polo menos un dispositivo dispoñible"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Selecciona unha aplicación de notas predeterminada para usar o atallo de tomar notas"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Seleccionar aplicación"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Mantén premido o atallo"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"O modo de prioridade está activado"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"A atención do Asistente está activada"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Establece a aplicación de notas predeterminada en Configuración"</string>
+ <string name="install_app" msgid="5066668100199613936">"Instalar aplicación"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 8f86401574e0..639c6c3c8cea 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ચહેરાનું પ્રમાણીકરણ થયું"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"પુષ્ટિ કરી"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"પરીક્ષણ પૂર્ણ કરવા કન્ફર્મ કરોને ટૅપ કરો"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"ચહેરા દ્વારા અનલૉક કર્યું"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ચહેરા દ્વારા અનલૉક કર્યું. આગળ વધવા માટે દબાવો."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ચહેરો ઓળખ્યો. આગળ વધવા માટે દબાવો."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ચહેરો ઓળખ્યો. આગળ વધવા \'અનલૉક કરો\' આઇકન દબાવો."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"સાચવી શકતા નથી. ફરી પ્રયાસ કરો."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"સાચવી શકતા નથી."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ઓછામાં ઓછા 4 અક્ષરનો ઉપયોગ કરો"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g> કરતાં ઓછા અક્ષરનો ઉપયોગ કરો"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"બિલ્ડ નંબર"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"બિલ્ડ નંબર ક્લિપબૉર્ડ પર કૉપિ કર્યો."</string>
<string name="basic_status" msgid="2315371112182658176">"વાતચીત ખોલો"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"વધુ જાણો"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g> પરથી વધુ જાણો"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ખોલો"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ઍપનું સેટઅપ કરેલું છે"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• ઓછામાં ઓછું એક કાર્ડ વૉલેટમાં ઉમેરેલું છે"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"નોંધ લેવાના શૉર્ટકટનો ઉપયોગ કરવા માટે, નોંધ લેનારી કોઈ ડિફૉલ્ટ ઍપ પસંદ કરો"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Wallet ઍપને શૉર્ટકટ તરીકે ઉમેરવા માટે, ખાતરી કરો કે ઍપ ઇન્સ્ટૉલ કરેલી હોય"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Wallet ઍપને શૉર્ટકટ તરીકે ઉમેરવા માટે, ખાતરી કરો કે ઓછામાં ઓછું એક કાર્ડ ઉમેરવામાં આવ્યું હોય"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"QR કોડ સ્કૅનરને શૉર્ટકટ તરીકે ઉમેરવા માટે, ખાતરી કરો કે કૅમેરા ઍપ ઇન્સ્ટૉલ કરેલી હોય"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Home ઍપને શૉર્ટકટ તરીકે ઉમેરવા માટે, ખાતરી કરો કે ઍપ ઇન્સ્ટૉલ કરેલી હોય"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• ઓછામાં ઓછું એક ડિવાઇસ ઉપલબ્ધ છે"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"નોંધ લેવાના શૉર્ટકટનો ઉપયોગ કરવા માટે, નોંધ માટેની ડિફૉલ્ટ ઍપ પસંદ કરો"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"ઍપ પસંદ કરો"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"શૉર્ટકટને ટચ વડે પળભર દબાવી રાખો"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"રદ કરો"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"પ્રાધાન્યતા મોડ ચાલુ છે"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant સક્રિય છે"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"સેટિંગમાં નોંધની ડિફૉલ્ટ ઍપ સેટ કરો"</string>
+ <string name="install_app" msgid="5066668100199613936">"ઍપ ઇન્સ્ટૉલ કરો"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index b2d4b883f359..6b9d1f53756c 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -1004,8 +1004,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"सेव नहीं किया जा सका. फिर से कोशिश करें."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"सेव नहीं किया जा सका."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"कम से कम चार वर्ण इस्तेमाल करें"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g> वर्ण से कम इस्तेमाल करें"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नंबर को क्लिपबोर्ड पर कॉपी किया गया."</string>
<string name="basic_status" msgid="2315371112182658176">"ऐसी बातचीत जिसमें इंटरैक्शन डेटा मौजूद नहीं है"</string>
@@ -1125,12 +1124,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"ज़्यादा जानें"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"ज़्यादा जानने के लिए <xliff:g id="URL">%s</xliff:g> पर जाएं"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> खोलें"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ऐप्लिकेशन को सेट अप किया गया है"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet में कम से कम एक कार्ड जोड़ा गया है"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"नोट लेने से जुड़ा शॉर्टकट इस्तेमाल करने के लिए, नोट लेने का डिफ़ॉल्ट ऐप्लिकेशन चुनें"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Wallet ऐप्लिकेशन को शॉर्टकट के तौर पर जोड़ने के लिए, पक्का करें कि ऐप्लिकेशन इंस्टॉल किया गया हो"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Wallet ऐप्लिकेशन को शॉर्टकट के तौर पर जोड़ने के लिए, पक्का करें कि कम से कम एक कार्ड जोड़ा गया हो"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"क्यूआर कोड स्कैनर को शॉर्टकट के तौर पर जोड़ने के लिए, पक्का करें कि कैमरा ऐप्लिकेशन इंस्टॉल किया गया हो"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Home ऐप्लिकेशन को शॉर्टकट के तौर पर जोड़ने के लिए, पक्का करें कि ऐप्लिकेशन इंस्टॉल किया गया हो"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• कम से कम एक डिवाइस उपलब्ध है"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"नोट लेने से जुड़ा शॉर्टकट इस्तेमाल करने के लिए, नोट लेने का डिफ़ॉल्ट ऐप्लिकेशन चुनें"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"ऐप्लिकेशन चुनें"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"शॉर्टकट को दबाकर रखें"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"रद्द करें"</string>
@@ -1159,4 +1158,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"प्राथमिकता मोड चालू है"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant आपकी बातें सुन रही है"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"सेटिंग में जाकर, नोट लेने की सुविधा देने वाले ऐप्लिकेशन को डिफ़ॉल्ट के तौर पर सेट करें"</string>
+ <string name="install_app" msgid="5066668100199613936">"ऐप्लिकेशन इंस्टॉल करें"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 54d87f282d11..7fed2dca0a0a 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -142,12 +142,11 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Lice je autentificirano"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrđeno"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Dodirnite Potvrdi za dovršetak"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Otključano licem"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Otključano pomoću lica. Pritisnite da biste nastavili."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Lice je prepoznato. Pritisnite da biste nastavili."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Lice je prepoznato. Pritisnite ikonu otključavanja da biste nastavili."</string>
- <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentičnost provjerena"</string>
+ <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autentifikacija izvršena"</string>
<string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Koristite PIN"</string>
<string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Koristite uzorak"</string>
<string name="biometric_dialog_use_password" msgid="3445033859393474779">"Koristite zaporku"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Spremanje nije uspjelo. Pokušajte ponovo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Spremanje nije uspjelo."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Upotrijebite barem četiri znaka"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Upotrijebite manje od ovoliko znakova: <xliff:g id="LENGTH">%1$d</xliff:g>"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj međuverzije"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Broj međuverzije kopiran je u međuspremnik."</string>
<string name="basic_status" msgid="2315371112182658176">"Otvoreni razgovor"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Saznajte više"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Saznajte više na <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otvorite <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikacija je postavljena"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Najmanje jedna kartica dodana je u Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Instalirajte aplikaciju fotoaparata"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Aplikacija je postavljena"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Dostupan je najmanje jedan uređaj"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Odaberite zadanu aplikaciju za bilješke da biste koristili prečac za pisanje bilježaka"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Za dodavanje aplikacije Wallet kao prečaca provjerite je li instalirana"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Provjerite je li dodana barem jedna kartica kako biste dodali aplikaciju Wallet kao prečac"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Provjerite je li instalirana aplikacija kamere kako biste dodali čitač QR koda kao prečac"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Provjerite je li aplikacija Home instalirana kako biste je dodali kao prečac"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Dostupan je najmanje jedan uređaj"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Odaberite zadanu aplikaciju za bilješke da biste koristili prečac za pisanje bilježaka"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Odaberite aplikaciju"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Prečac za dodirnuti i zadržati"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Odustani"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Uključen je prioritetni način rada"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Pažnja Asistenta je aktivirana"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Postavite zadanu aplikaciju za bilješke u postavkama"</string>
+ <string name="install_app" msgid="5066668100199613936">"Instalacija"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 25b30a77e51e..7b5c9433d25c 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Arc hitelesítve"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Megerősítve"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Koppintson a Megerősítés lehetőségre"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Zárolás arccal feloldva"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Zárolás arccal feloldva. Koppintson a folytatáshoz."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Arc felismerve. Koppintson a folytatáshoz."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Arc felismerve. A folytatáshoz koppintson a Feloldásra."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"A mentés nem sikerült. Próbálja újra."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"A mentés nem sikerült."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Legalább négy karaktert használjon"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Legfeljebb <xliff:g id="LENGTH">%1$d</xliff:g> karaktert használhat"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildszám"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Buildszám a vágólapra másolva."</string>
<string name="basic_status" msgid="2315371112182658176">"Beszélgetés megnyitása"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"További információ"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"További információ: <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"A(z) <xliff:g id="APPNAME">%1$s</xliff:g> megnyitása"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Az alkalmazás be van állítva"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Legalább egy kártya hozzá lett adva a Wallethez"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Kameraalkalmazás telepítése"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Az alkalmazás be van állítva"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Legalább egy eszköz rendelkezésre áll"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Válassza ki az alapértelmezett jegyzetkészítő alkalmazást, amelyet a jegyzetelési gyorsparancshoz szeretne használni"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Ha szeretné felvenni Wallet alkalmazást gyorsparancsként, gondoskodjon az app telepítéséről"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Ha szeretné felvenni Wallet alkalmazást gyorsparancsként, győződjön meg róla, hogy hozzáadott legalább egy kártyát a szolgáltatáshoz"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Ha szeretné felvenni a QR-kód-szkennelőt gyorsparancsként, győződjön meg róla, hogy van az eszközre telepítve kameraalkalmazás"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Ha szeretné felvenni Home appot gyorsparancsként, gondoskodjon az alkalmazás telepítéséről"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Legalább egy eszköz rendelkezésre áll"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Válassza ki az alapértelmezett jegyzetkészítő alkalmazást, amelyet a jegyzetelési gyorsparancshoz szeretne használni"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Alkalmazás kiválasztása"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Tartsa nyomva a parancsikont"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Mégse"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritás mód bekapcsolva"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"A Segéd figyel"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Állítson be alapértelmezett jegyzetkészítő alkalmazást a Beállításokban"</string>
+ <string name="install_app" msgid="5066668100199613936">"Alkalmazás telepítése"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 14326af3f2e9..f25dc487df5c 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Դեմքը ճանաչվեց"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Հաստատվեց"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ավարտելու համար հպեք «Հաստատել»"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Ապակողպվեց դեմքով"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ապակողպվել է դեմքով։ Սեղմեք շարունակելու համար։"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Դեմքը ճանաչվեց։ Սեղմեք շարունակելու համար։"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Դեմքը ճանաչվեց։ Սեղմեք ապակողպման պատկերակը։"</string>
@@ -361,7 +360,7 @@
<string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"Դեմքը ճանաչվեց"</string>
<string name="keyguard_retry" msgid="886802522584053523">"Սահեցրեք վերև՝ նորից փորձելու համար"</string>
<string name="require_unlock_for_nfc" msgid="1305686454823018831">"Ապակողպեք՝ NFC-ն օգտագործելու համար"</string>
- <string name="do_disclosure_generic" msgid="4896482821974707167">"Այս սարքը պատկանում է ձեր կազմակերպությանը"</string>
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"Այս սարքը պատկանում է ձեր ընկերությանը"</string>
<string name="do_disclosure_with_name" msgid="2091641464065004091">"Այս սարքը պատկանում է «<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>» կազմակերպությանը"</string>
<string name="do_financed_disclosure_with_name" msgid="6723004643314467864">"Այս սարքը տրամադրվել է «<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>» կազմակերպության կողմից"</string>
<string name="phone_hint" msgid="6682125338461375925">"Սահահարվածեք հեռախոսի պատկերակից"</string>
@@ -432,11 +431,11 @@
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Ձեր կազմակերպությունը այս սարքի սեփականատերն է և կարող է վերահսկել ցանցային թրաֆիկը"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"«<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>» կազմակերպությունը այս սարքի սեփականատերն է և կարող է վերահսկել ցանցային թրաֆիկը"</string>
<string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"Այս սարքը տրամադրվել է <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> կազմակերպության կողմից"</string>
- <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"Այս սարքը պատկանում է ձեր կազմակերպությանը և համացանցին միացած է <xliff:g id="VPN_APP">%1$s</xliff:g>-ի միջոցով"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"Այս սարքը պատկանում է ձեր ընկերությանը և համացանցին միացած է <xliff:g id="VPN_APP">%1$s</xliff:g>-ի միջոցով"</string>
<string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"Այս սարքը պատկանում է <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> կազմակերպությանը և համացանցին միացած է <xliff:g id="VPN_APP">%2$s</xliff:g>-ի միջոցով"</string>
- <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Այս սարքը պատկանում է ձեր կազմակերպությանը"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"Այս սարքը պատկանում է ձեր ընկերությանը"</string>
<string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"Այս սարքը պատկանում է «<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>» կազմակերպությանը"</string>
- <string name="quick_settings_disclosure_management_vpns" msgid="929181757984262902">"Այս սարքը պատկանում է ձեր կազմակերպությանը և համացանցին միացած է VPN-ների միջոցով"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="929181757984262902">"Այս սարքը պատկանում է ձեր ընկերությանը և համացանցին միացած է VPN-ների միջոցով"</string>
<string name="quick_settings_disclosure_named_management_vpns" msgid="3312645578322079185">"Այս սարքը պատկանում է <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> կազմակերպությանը և համացանցին միացած է VPN-ների միջոցով"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="1423899084754272514">"Ձեր կազմակերպությունը կարող է վերահսկել ձեր աշխատանքային պրոֆիլի ցանցային թրաֆիկը"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8321469176706219860">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> կազմակերպությունը կարող է վերահսկել ձեր աշխատանքային պրոֆիլի ցանցային թրաֆիկը"</string>
@@ -455,7 +454,7 @@
<string name="monitoring_button_view_controls" msgid="8316440345340701117">"Դիտել կառավարման տարրերը"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Այս սարքը պատկանում է «<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>» կազմակերպությանը։\n\nՁեր ՏՏ ադմինիստրատորը կարող է վերահսկել և կառավարել կարգավորումները, կորպորատիվ ռեսուրսներից օգտվելու թույլտվությունները, հավելվածները, սարքի հետ կապված տվյալները և սարքի տեղադրության տվյալները։\n\nԼրացուցիչ տեղեկությունների համար դիմեք ձեր ՏՏ ադմինիստրատորին։"</string>
<string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> կազմակերպությունը կարող է ստանալ այս սարքի հետ կապված տվյալների օգտագործման թույլտվություն, փոփոխել դրա կարգավորումներն ու կառավարել հավելվածները։\n\nԱվելին իմանալու համար դիմեք <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g> ընկերությանը։"</string>
- <string name="monitoring_description_management" msgid="4308879039175729014">"Այս սարքը պատկանում է ձեր կազմակերպությանը։\n\nՁեր ՏՏ ադմինիստրատորը կարող է վերահսկել և կառավարել կարգավորումները, կորպորատիվ ռեսուրսներից օգտվելու թույլտվությունները, հավելվածները, սարքի հետ կապված տվյալները և սարքի տեղադրության տվյալները։\n\nԼրացուցիչ տեղեկությունների համար դիմեք ձեր ՏՏ ադմինիստրատորին։"</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Այս սարքը պատկանում է ձեր ընկերությանը։\n\nՁեր ՏՏ ադմինիստրատորը կարող է վերահսկել և կառավարել կարգավորումները, կորպորատիվ ռեսուրսներից օգտվելու թույլտվությունները, հավելվածները, սարքի հետ կապված տվյալները և սարքի տեղադրության տվյալները։\n\nԼրացուցիչ տեղեկությունների համար դիմեք ձեր ՏՏ ադմինիստրատորին։"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Ձեր կազմակերպությունը այս սարքում տեղադրել է վկայագրման կենտրոն։ Ձեր ցանցի ապահով թրաֆիկը կարող է վերահսկվել կամ փոփոխվել։"</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Ձեր կազմակերպությունը ձեր աշխատանքային պրոֆիլում տեղադրել է վկայագրման կենտրոն։ Ձեր ցանցի ապահով թրաֆիկը կարող է վերահսկվել կամ փոփոխվել։"</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Այս սարքում տեղադրված է վկայագրման կենտրոն։ Ձեր ցանցի ապահով թրաֆիկը կարող է վերահսկվել կամ փոփոխվել։"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Չհաջողվեց պահել։ Նորից փորձեք։"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Չհաջողվեց պահել։"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Օգտագործեք առնվազն 4 նիշ"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Օգտագործեք մինչև <xliff:g id="LENGTH">%1$d</xliff:g> նիշ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Կառուցման համարը"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Կառուցման համարը պատճենվեց սեղմատախտակին։"</string>
<string name="basic_status" msgid="2315371112182658176">"Բաց զրույց"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Իմանալ ավելին"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Իմացեք ավելին <xliff:g id="URL">%s</xliff:g> էջում"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Բացել <xliff:g id="APPNAME">%1$s</xliff:g> հավելվածը"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Հավելվածը կարգավորված է"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Առնվազն մեկ քարտ ավելացված է Wallet-ում"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Ընտրեք նշումների կանխադրված հավելված՝ նշումների ստեղծման դյուրանցումն օգտագործելու համար"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Ընտրել հավելված"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Հպեք դյուրանցմանը և պահեք"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Չեղարկել"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Առաջնահերթության ռեժիմը միացված է"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Օգնականը լսում է"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Կարգավորեք նշումների կանխադրված հավելված Կարգավորումներում"</string>
+ <string name="install_app" msgid="5066668100199613936">"Տեղադրել հավելվածը"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index f402df66558f..88c06e76fd33 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Wajah diautentikasi"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Dikonfirmasi"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ketuk Konfirmasi untuk menyelesaikan"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Kunci dibuka dengan wajah"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Kunci dibuka dengan wajah. Tekan untuk melanjutkan."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Wajah dikenali. Tekan untuk melanjutkan."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Wajah dikenali. Tekan ikon buka kunci untuk melanjutkan."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Tidak dapat menyimpan. Coba lagi."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Tidak dapat menyimpan."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gunakan minimal 4 karakter"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Gunakan kurang dari <xliff:g id="LENGTH">%1$d</xliff:g> karakter"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nomor build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nomor versi disalin ke papan klip."</string>
<string name="basic_status" msgid="2315371112182658176">"Membuka percakapan"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Pelajari lebih lanjut"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Pelajari lebih lanjut di <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Buka <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikasi disiapkan"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Minimal satu kartu telah ditambahkan ke Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Menginstal aplikasi kamera"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Aplikasi disiapkan"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Tersedia minimal satu perangkat"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Pilih aplikasi catatan default untuk menggunakan pintasan pembuatan catatan"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Pilih aplikasi"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Sentuh lama pintasan"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Batal"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mode prioritas diaktifkan"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Asisten sedang memerhatikan"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Setel aplikasi catatan default di Setelan"</string>
+ <string name="install_app" msgid="5066668100199613936">"Instal aplikasi"</string>
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 5b755070ee57..5e3af2b9964a 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Andlit staðfest"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Staðfest"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ýttu á „Staðfesta“ til að ljúka"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Opnað með andliti"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Opnað með andliti. Ýttu til að halda áfram."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Andlitið var greint. Ýttu til að halda áfram."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Andlitið var greint. Ýttu á opnunartáknið til að halda áfr."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ekki hægt að vista. Reyndu aftur."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ekki hægt að vista."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Notaðu að minnsta kosti 4 stafi"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Notaðu færri en <xliff:g id="LENGTH">%1$d</xliff:g> stafi"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Útgáfunúmer smíðar"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Útgáfunúmer smíðar afritað á klippiborð."</string>
<string name="basic_status" msgid="2315371112182658176">"Opna samtal"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Nánar"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Nánar á <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Opna <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Forritið er uppsett"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Að minnsta kosti einu korti var bætt við Veski"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Setja upp myndavélarforrit"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Forritið er uppsett"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Að minnsta kosti eitt tæki er tiltækt"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Veldu sjálfgefið glósuforrit til að nota flýtileið fyrir glósugerð"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Velja forrit"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Haltu flýtilyklinum inni"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Hætta við"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Kveikt er á forgangsstillingu"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Hjálparinn er að hlusta"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Stilltu sjálfgefið glósuforrit í stillingunum"</string>
+ <string name="install_app" msgid="5066668100199613936">"Setja upp forrit"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 8937c212e3ca..9c784b6370a2 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Volto autenticato"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confermato"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tocca Conferma per completare"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Sbloccato con il volto"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Sbloccato con il volto. Premi per continuare."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Volto riconosciuto. Premi per continuare."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Volto riconosciuto. Premi l\'icona Sblocca e continua."</string>
@@ -307,7 +306,7 @@
<string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC non attiva"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC attiva"</string>
- <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Registrazione schermo"</string>
+ <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Registrazione dello schermo"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Inizia"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Interrompi"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modalità a una mano"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Impossibile salvare. Riprova."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Impossibile salvare."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Usa almeno 4 caratteri"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Usa meno di <xliff:g id="LENGTH">%1$d</xliff:g> caratteri"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numero build copiato negli appunti."</string>
<string name="basic_status" msgid="2315371112182658176">"Apri conversazione"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Scopri di più"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Scopri di più all\'indirizzo <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Apri <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• L\'app sia configurata"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Sia stata aggiunta almeno una carta a Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Sia installata un\'app fotocamera"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• L\'app sia configurata"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ci sia almeno un dispositivo disponibile"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Seleziona un\'app per le note predefinita per usare la scorciatoia per l\'aggiunta di note"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Per aggiungere l\'app Wallet come scorciatoia, assicurati che l\'app sia installata"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Per aggiungere l\'app Wallet come scorciatoia, assicurati che sia stata aggiunta almeno una carta"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Per aggiungere lo scanner di codici QR come scorciatoia, assicurati che ci sia un\'app fotocamera installata"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Per aggiungere l\'app Home come scorciatoia, assicurati che l\'app sia installata"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Ci sia almeno un dispositivo disponibile"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Seleziona un\'app per le note predefinita per usare la scorciatoia per l\'aggiunta di note"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Seleziona app"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Tocca scorciatoia/tieni premuto"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Annulla"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modalità priorità attivata"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"L\'assistente è attivo"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Imposta l\'app per le note predefinita nelle Impostazioni"</string>
+ <string name="install_app" msgid="5066668100199613936">"Installa app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 271001dafd4b..168e3e23b8ac 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"זיהוי הפנים בוצע"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"יש אישור"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"יש להקיש על \'אישור\' לסיום התהליך"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"הנעילה בוטלה באמצעות זיהוי הפנים"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"הנעילה בוטלה באמצעות זיהוי הפנים. יש ללחוץ כדי להמשיך."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"הפנים זוהו. יש ללחוץ כדי להמשיך."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"הפנים זוהו. להמשך יש ללחוץ על סמל ביטול הנעילה."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"לא ניתן לשמור. כדאי לנסות שוב."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"לא ניתן לשמור."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"יש להזין 4 תווים לפחות"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"אפשר להזין עד <xliff:g id="LENGTH">%1$d</xliff:g> תווים"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"‏מספר Build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"‏מספר ה-Build הועתק ללוח."</string>
<string name="basic_status" msgid="2315371112182658176">"פתיחת שיחה"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"מידע נוסף"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"מידע נוסף זמין בכתובת <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"פתיחת <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• האפליקציה מוגדרת"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"‏• לפחות כרטיס אחד נוסף ל-Wallet"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"צריך לבחור אפליקציית פתקים שתיפתח כברירת מחדל כשייעשה שימוש במקש הקיצור לכתיבת פתקים"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"‏כדי להוסיף את אפליקציית Wallet כקיצור דרך, צריך לוודא שהאפליקציה מותקנת"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"‏כדי להוסיף את אפליקציית Wallet כקיצור דרך, צריך לוודא שנוסף לפחות כרטיס אחד"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"‏כדי להוסיף את סורק קודי ה-QR כקיצור דרך, צריך לוודא שמותקנת אפליקציית מצלמה"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"‏כדי להוסיף את אפליקציית Home כקיצור דרך, צריך לוודא שהאפליקציה מותקנת"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• יש לפחות מכשיר אחד זמין"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"צריך לבחור אפליקציית פתקים שתיפתח כברירת מחדל כשייעשה שימוש במקש הקיצור לכתיבת פתקים"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"בחירת אפליקציה"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"מקש קיצור ללחיצה ארוכה"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ביטול"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"מצב \'עדיפות\' מופעל"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"‏Assistant מאזינה"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"צריך להגדיר את אפליקציית ברירת המחדל לפתקים ב\'הגדרות\'"</string>
+ <string name="install_app" msgid="5066668100199613936">"התקנת האפליקציה"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 88d0c600c0ce..f100299ea367 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"顔を認証しました"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"確認しました"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"完了するには [確認] をタップしてください"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"顔でロック解除しました"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"顔でロック解除しました。押して続行してください。"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"顔を認識しました。押して続行してください。"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"顔を認識しました。ロック解除アイコンを押して続行します。"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"保存できません。もう一度お試しください。"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"保存できません。"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"4 文字以上にしてください"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"使用できる文字数は <xliff:g id="LENGTH">%1$d</xliff:g> 文字未満です"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ビルド番号"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ビルド番号をクリップボードにコピーしました。"</string>
<string name="basic_status" msgid="2315371112182658176">"空の会話"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"詳細"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"詳しくは、<xliff:g id="URL">%s</xliff:g> をご覧ください"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> を開く"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• アプリが設定されている"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• ウォーレットに追加されているカードが 1 枚以上ある"</string>
- <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">"• 利用できるデバイスが 1 台以上ある"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"メモのショートカットを使用するデフォルトのメモアプリを選択してください"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"ウォレット アプリをショートカットとして追加するには、アプリがインストールされていることを確認してください"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"ウォレット アプリをショートカットとして追加するには、カードが 1 枚以上追加されていることを確認してください"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"QR コードスキャナをショートカットとして追加するには、カメラアプリがインストールされていることを確認してください"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Google Home アプリをショートカットとして追加するには、アプリがインストールされていることを確認してください"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• 利用できるデバイスが 1 台以上ある"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"メモのショートカットを使用するデフォルトのメモアプリを選択してください"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"アプリを選択"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ショートカットの長押しが必要です"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"キャンセル"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"優先モードは ON です"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"アシスタントは起動済みです"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"[設定] でデフォルトのメモアプリを設定してください"</string>
+ <string name="install_app" msgid="5066668100199613936">"アプリをインストール"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index e7fd9d3e00fa..8ed9c431eaf9 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"სახის ამოცნობილია"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"დადასტურებული"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"დასასრულებლად შეეხეთ „დადასტურებას“"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"განიბლოკა სახით"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"განიბლოკა სახით. დააჭირეთ გასაგრძელებლად."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ამოცნობილია სახით. დააჭირეთ გასაგრძელებლად."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ამოცნობილია სახით. გასაგრძელებლად დააჭირეთ განბლოკვის ხატულას."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"შენახვა ვერ ხერხდება. ცადეთ ხელახლა."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"შენახვა ვერ ხერხდება."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"გამოიყენეთ მინიმუმ 4 სიმბოლო."</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"გამოიყენეთ <xliff:g id="LENGTH">%1$d</xliff:g>-ზე ნაკლები სიმბოლო"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ანაწყობის ნომერი"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ანაწყობის ნომერი დაკოპირებულია გაცვლის ბუფერში."</string>
<string name="basic_status" msgid="2315371112182658176">"მიმოწერის გახსნა"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"შეიტყვეთ მეტი"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"შეიტყვეთ მეტი აქ: <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> აპის გახსნა"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• აპი დაყენებულია"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• საფულეში დამატებულია მინიმუმ ერთი ბარათი"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"აირჩიეთ ნაგულისხმევი ჩანიშვნების აპი, რათა ჩანიშვნების შექმნის მალსახმობი გამოიყენოთ"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"საფულის აპის მალსახმობის დასამატებლად დარწმუნდით, რომ აპი დაინსტალირებულია"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"საფულის აპის მალსახმობის დასამატებლად დარწმუნდით, რომ დამატებულია მინიმუმ ერთი ბარათი"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"QR კოდის სკანერის მალსახმობის დასამატებლად დარწმუნდით, რომ დაინსტალირებულია კამერის აპი"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"მთავარი აპის მალსახმობის დასამატებლად დარწმუნდით, რომ აპი დაინსტალირებულია"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• ხელმისაწვდომია მინიმუმ ერთი მოწყობილობა"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"აირჩიეთ ჩანიშვნების ნაგულისხმევი აპი, რათა ჩანიშვნების შექმნის მალსახმობი გამოიყენოთ"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"აირჩიეთ აპი"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"შეხების დაamp; მოცდის მალსახმობი"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"გაუქმება"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"პრიორიტეტული რეჟიმი ჩართულია"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"ასისტენტის ყურადღების ფუნქცია ჩართულია"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"დააყენეთ ნაგულისხმევი შენიშვნების აპი პარამეტრებში"</string>
+ <string name="install_app" msgid="5066668100199613936">"აპის ინსტალაცია"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 9964f4de7f8b..c8441f441062 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Бет танылды."</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Расталды"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Аяқтау үшін \"Растау\" түймесін түртіңіз."</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Бетпен ашылды."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Бетпен ашылды. Жалғастыру үшін басыңыз."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Бет танылды. Жалғастыру үшін басыңыз."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Бет танылды. Жалғастыру үшін құлыпты ашу белгішесін басыңыз."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Сақталмайды. Қайталап көріңіз."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Сақталмайды."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Кемінде 4 таңба пайдаланыңыз."</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Ең көбі <xliff:g id="LENGTH">%1$d</xliff:g> таңба пайдаланыңыз."</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Құрама нөмірі"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Құрама нөмірі буферге көшірілді."</string>
<string name="basic_status" msgid="2315371112182658176">"Ашық әңгіме"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Толық ақпарат"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Толық ақпарат: <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ашу"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Қолданба реттелген"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet-ке кемінде бір карта қосылған"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Жазба жазу таңбашасын пайдалану үшін әдепкі жазба қолданбаны таңдаңыз."</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Қолданба таңдау"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Таңбашаны басып тұрыңыз."</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Бас тарту"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"\"Маңызды\" режимі қосулы."</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant қосулы."</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Параметрлерден әдепкі жазба қолданбасын орнатыңыз."</string>
+ <string name="install_app" msgid="5066668100199613936">"Қолданбаны орнату"</string>
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 1165ba6e0b7d..02a05e93cf57 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"បានផ្ទៀងផ្ទាត់​មុខ"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"បានបញ្ជាក់"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ចុច \"បញ្ជាក់\" ដើម្បីបញ្ចប់"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"បានដោះសោដោយប្រើមុខ"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"បានដោះសោដោយប្រើមុខ។ សូមចុច ដើម្បីបន្ត។"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"បានស្គាល់មុខ។ សូមចុច ដើម្បីបន្ត។"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"បានស្គាល់មុខ។ សូមចុចរូបដោះសោ ដើម្បីបន្ត។"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"មិនអាច​រក្សាទុក​បានទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"មិនអាច​រក្សាទុក​បានទេ។"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ប្រើយ៉ាងហោចណាស់ 4 តួអក្សរ"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"ប្រើតិចជាង <xliff:g id="LENGTH">%1$d</xliff:g> តួអក្សរ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"លេខ​កំណែបង្កើត"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"បានចម្លងលេខ​កំណែបង្កើតទៅឃ្លីបបត។"</string>
<string name="basic_status" msgid="2315371112182658176">"បើកការសន្ទនា"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"ស្វែងយល់បន្ថែម"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"ស្វែងយល់​បន្ថែម​តាមរយៈ <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"បើក <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• កម្មវិធីត្រូវបានរៀបចំ"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• កាតយ៉ាងតិចមួយត្រូវបានបញ្ចូលទៅក្នុង Wallet"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"ជ្រើសរើសកម្មវិធីកំណត់ចំណាំលំនាំដើម ដើម្បីប្រើផ្លូវកាត់សម្រាប់ការកត់ចំណាំ"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"ដើម្បីបញ្ចូល​កម្មវិធី Wallet ជាផ្លូវកាត់ សូមប្រាកដថា​កម្មវិធីត្រូវបានដំឡើង"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"ដើម្បីបញ្ចូល​កម្មវិធី Wallet ជាផ្លូវកាត់ សូមប្រាកដថា​បានបញ្ចូលកាត​យ៉ាងហោចណាស់មួយ"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"ដើម្បីបញ្ចូលកម្មវិធី​ស្កេនកូដ QR ជាផ្លូវកាត់ សូមប្រាកដថា​កម្មវិធីកាមេរ៉ាត្រូវបានដំឡើង"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"ដើម្បីបញ្ចូល​កម្មវិធី Home ជាផ្លូវកាត់ សូមប្រាកដថា​កម្មវិធីត្រូវបានដំឡើង"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• ឧបករណ៍យ៉ាងតិចមួយអាចប្រើបាន"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"ជ្រើសរើសកម្មវិធីកំណត់ចំណាំលំនាំដើម ដើម្បីប្រើផ្លូវកាត់សម្រាប់ការកត់ចំណាំ"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"ជ្រើសរើសកម្មវិធី"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ចុចឱ្យជាប់លើផ្លូវកាត់"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"បោះបង់"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"មុខងារ​អាទិភាពត្រូវបានបើក"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"ភាពប្រុងប្រៀប​របស់ Google Assistant ត្រូវបានបើក"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"កំណត់កម្មវិធីកំណត់ចំណាំលំនាំដើមនៅក្នុងការកំណត់"</string>
+ <string name="install_app" msgid="5066668100199613936">"ដំឡើង​កម្មវិធី"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 5d8e001e6153..42bfaf77a007 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ಪೂರ್ಣಗೊಳಿಸಲು ದೃಢೀಕರಿಸಿ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"ಮುಖದ ಮೂಲಕ ಅನ್‌ಲಾಕ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ಮುಖವನ್ನು ಬಳಸಿ ಅನ್‌ಲಾಕ್ ಮಾಡಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ಒತ್ತಿ."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ಮುಖ ಗುರುತಿಸಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ಒತ್ತಿ."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ಮುಖ ಗುರುತಿಸಲಾಗಿದೆ. ಮುಂದುವರಿಯಲು ಅನ್‌ಲಾಕ್ ಐಕಾನ್ ಅನ್ನು ಒತ್ತಿ."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ಕನಿಷ್ಠ 4 ಅಕ್ಷರಗಳನ್ನು ಬಳಸಿ"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g> ಕ್ಕಿಂತ ಕಡಿಮೆ ಅಕ್ಷರಗಳನ್ನು ಬಳಸಿ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ಬಿಲ್ಡ್ ಸಂಖ್ಯೆ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ಬಿಲ್ಡ್ ಸಂಖ್ಯೆಯನ್ನು ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ನಲ್ಲಿ ನಕಲಿಸಲಾಗಿದೆ."</string>
<string name="basic_status" msgid="2315371112182658176">"ಸಂಭಾಷಣೆಯನ್ನು ತೆರೆಯಿರಿ"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g> ನಲ್ಲಿ ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಿರಿ"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ಆ್ಯಪ್ ಅನ್ನು ಸೆಟಪ್ ಮಾಡಲಾಗಿದೆ"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• ವಾಲೆಟ್‌ಗೆ ಕನಿಷ್ಠ ಒಂದು ಕಾರ್ಡ್ ಅನ್ನು ಸೇರಿಸಲಾಗಿದೆ"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"ನೋಟ್ಸ್ ಮಾಡಿಕೊಳ್ಳುವಿಕೆ ಶಾರ್ಟ್‌ಕಟ್ ಅನ್ನು ಬಳಸಲು ಡೀಫಾಲ್ಟ್ ಟಿಪ್ಪಣಿಗಳ ಆ್ಯಪ್ ಆಯ್ಕೆಮಾಡಿ"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"ಆ್ಯಪ್‌ ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ಸ್ಪರ್ಶಿಸಿ ಹೋಲ್ಡ್ ಮಾಡಿ ಶಾರ್ಟ್‌ಕಟ್"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ರದ್ದುಗೊಳಿಸಿ"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ಆದ್ಯತೆಯ ಮೋಡ್‌ ಆನ್‌ ಆಗಿದೆ"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant ನಿಮ್ಮ ಮಾತನ್ನು ಆಲಿಸುತ್ತಿದೆ"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಡೀಫಾಲ್ಟ್ ಟಿಪ್ಪಣಿಗಳ ಆ್ಯಪ್ ಅನ್ನು ಸೆಟ್ ಮಾಡಿ"</string>
+ <string name="install_app" msgid="5066668100199613936">"ಆ್ಯಪ್ ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 7329f89ca47e..176f86673bc3 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"얼굴이 인증되었습니다."</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"확인함"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"완료하려면 확인을 탭하세요."</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"얼굴 인식으로 잠금 해제되었습니다."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"얼굴 인식으로 잠금 해제되었습니다. 계속하려면 누르세요."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"얼굴이 인식되었습니다. 계속하려면 누르세요."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"얼굴이 인식되었습니다. 계속하려면 아이콘을 누르세요."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"저장할 수 없습니다. 다시 시도해 주세요."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"저장할 수 없습니다."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"4자 이상 입력하세요."</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g>자 미만이어야 합니다."</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"빌드 번호"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"빌드 번호가 클립보드에 복사되었습니다."</string>
<string name="basic_status" msgid="2315371112182658176">"대화 열기"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"자세히 알아보기"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g>에서 자세히 알아보세요."</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> 열기"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• 앱이 설정되어 있습니다."</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• 1개 이상의 카드가 월렛에 추가되어 있습니다."</string>
- <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">"• 1대 이상의 기기를 사용할 수 있습니다."</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"메모 바로가기를 사용하려면 기본 메모 앱을 선택합니다."</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"앱 선택"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"바로가기를 길게 터치하세요."</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"취소"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"우선순위 모드 설정됨"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"어시스턴트가 대기 중임"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"설정에서 기본 메모 앱 설정"</string>
+ <string name="install_app" msgid="5066668100199613936">"앱 설치"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 751c98c9b3fa..96389dfae88c 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Жүздүн аныктыгы текшерилди"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Ырасталды"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Бүтүрүү үчүн \"Ырастоо\" баскычын басыңыз"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Түзмөгүңүздү жүзүңүз менен ачтыңыз"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Кулпуну жүзүңүз менен ачтыңыз. Улантуу үчүн басыңыз."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Жүз таанылды. Улантуу үчүн басыңыз."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Жүз таанылды. Улантуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Сакталган жок. Кайталап көрүңүз."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Сакталган жок."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Кеминде 4 символдон турушу керек"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g> символдон ашпашы керек"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Курама номери"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Курама номери алмашуу буферине көчүрүлдү."</string>
<string name="basic_status" msgid="2315371112182658176">"Ачык сүйлөшүү"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Кеңири маалымат"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Кеңири маалымат: <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ачуу"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Колдонмо туураланды"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Капчыкка кеминде бир карта кошулду"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Эскертме жазуу ыкчам баскычын колдонуу үчүн демейки эскертме жазуу колдонмосун тандаңыз"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Колдонмо тандоо"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Ыкчам баскычты басып туруңуз"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Токтотуу"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Маанилүү сүйлөшүүлөр режими күйүк"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Жардамчы иштетилди"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Параметрлерден демейки кыска жазуулар колдонмосун тууралаңыз"</string>
+ <string name="install_app" msgid="5066668100199613936">"Колдонмону орнотуу"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index e075dba9c37a..925dfcebc85f 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ພິສູດຢືນຢັນໃບໜ້າແລ້ວ"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ຢືນຢັນແລ້ວ"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ແຕະຢືນຢັນເພື່ອສຳເລັດ"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"ປົດລັອກດ້ວຍໃບໜ້າແລ້ວ"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ປົດລັອກດ້ວຍໜ້າແລ້ວ. ກົດເພື່ອສືບຕໍ່."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດເພື່ອສືບຕໍ່."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ຈຳແນກໜ້າໄດ້ແລ້ວ. ກົດໄອຄອນປົດລັອກເພື່ອສືບຕໍ່."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ບໍ່ສາມາດບັນທຶກໄດ້. ກະລຸນາລອງໃໝ່."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ບໍ່ສາມາດບັນທຶກໄດ້."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ໃຊ້ຢ່າງໜ້ອຍ 4 ຕົວອັກສອນ"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"ໃຊ້ໜ້ອຍກວ່າ <xliff:g id="LENGTH">%1$d</xliff:g> ຕົວອັກສອນ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ໝາຍເລກສ້າງ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ສຳເນົາໝາຍເລກສ້າງໄປໃສ່ຄລິບບອດແລ້ວ."</string>
<string name="basic_status" msgid="2315371112182658176">"ເປີດການສົນທະນາ"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"ສຶກສາເພີ່ມເຕີມ"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"ສຶກສາເພີ່ມເຕີມຢູ່ <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"ເປີດ <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ແອັບໄດ້ຮັບການຕັ້ງຄ່າແລ້ວ"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• ມີການເພີ່ມຢ່າງໜ້ອຍ 1 ບັດໃສ່ໃນ Wallet"</string>
- <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">"• ມີຢ່າງໜ້ອຍ 1 ອຸປະກອນພ້ອມໃຫ້ນຳໃຊ້"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"ເລືອກແອັບບັນທຶກເລີ່ມຕົ້ນເພື່ອໃຊ້ທາງລັດການຈົດບັນທຶກ"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"ເລືອກແອັບ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ແຕະທາງລັດຄ້າງໄວ້"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ຍົກເລີກ"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ໂໝດຄວາມສຳຄັນເປີດຢູ່"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"ການເອີ້ນໃຊ້ຜູ້ຊ່ວຍເປີດຢູ່"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ຕັ້ງຄ່າແອັບຈົດບັນທຶກເລີ່ມຕົ້ນໃນການຕັ້ງຄ່າ"</string>
+ <string name="install_app" msgid="5066668100199613936">"ຕິດຕັ້ງແອັບ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 57bb64e60073..28da6950febc 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Veidas autentifikuotas"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Patvirtinta"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Paliesk. „Patvirtinti“, kad užbaigtumėte"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Atrakinta pagal veidą"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Atrakinta pagal veidą. Paspauskite, jei norite tęsti."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Veidas atpažintas. Paspauskite, jei norite tęsti."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Veidas atpažintas. Tęskite paspaudę atrakinimo piktogramą."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nepavyko išsaugoti. Bandykite dar kartą."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nepavyko išsaugoti."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Naudokite bent 4 simbolius"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Naudokite daugiausia <xliff:g id="LENGTH">%1$d</xliff:g> simb."</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijos numeris"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versijos numeris nukopijuotas į iškarpinę."</string>
<string name="basic_status" msgid="2315371112182658176">"Atidaryti pokalbį"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Sužinokite daugiau"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Sužinokite daugiau adresu <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Atidaryti „<xliff:g id="APPNAME">%1$s</xliff:g>“"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Programa nustatyta"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Prie „Wallet“ pridėta bent viena kortelė"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Įdiekite Fotoaparato programą"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Programa nustatyta"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Pasiekiamas bent vienas įrenginys"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Pasirinkite numatytąją užrašų programą, naudotiną su užrašų kūrimo sparčiuoju klavišu"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Pasirinkite programą"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Paliesk. ir palaik. spart. klav."</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Atšaukti"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteto režimas įjungtas"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Padėjėjas klauso"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Nustatykite numatytąją užrašų programą Nustatymuose"</string>
+ <string name="install_app" msgid="5066668100199613936">"Įdiegti programą"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 78fc7b3761b6..0038e9c3181c 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Seja autentificēta"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Apstiprināts"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Lai pabeigtu, pieskarieties Apstiprināt"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Ierīce atbloķēta ar seju"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ierīce atbloķēta ar seju. Nospiediet, lai turpinātu."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Seja atpazīta. Nospiediet, lai turpinātu."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Seja atpazīta. Lai turpinātu, nospiediet atbloķēšanas ikonu."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nevar saglabāt. Mēģiniet vēlreiz."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nevar saglabāt."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Izmantojiet vismaz 4 rakstzīmes"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Izmantojiet mazāk nekā <xliff:g id="LENGTH">%1$d</xliff:g> rakstzīmes."</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijas numurs"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versijas numurs ir kopēts starpliktuvē."</string>
<string name="basic_status" msgid="2315371112182658176">"Atvērt sarunu"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Uzzināt vairāk"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Uzziniet vairāk vietnē <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Atvērt lietotni <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Lietotne ir iestatīta."</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Makam ir pievienota vismaz viena karte."</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Atlasiet noklusējuma piezīmju lietotni, lai izmantotu piezīmju pierakstīšanas saīsni."</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Atlasīt lietotni"</string>
<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>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritātes režīms ir ieslēgts"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistents klausās"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Iestatījumos iestatiet noklusējuma piezīmju lietotni."</string>
+ <string name="install_app" msgid="5066668100199613936">"Instalēt lietotni"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 6ddd15c3b9f1..45707680d3d3 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лицето е проверено"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потврдено"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Допрете „Потврди“ за да се заврши"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Отклучено со лик"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Отклучено со лик. Притиснете за да продолжите."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицето е препознаено. Притиснете за да продолжите."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицето е препознаено. Притиснете ја иконата за отклучување за да продолжите."</string>
@@ -210,7 +209,7 @@
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панел за известување"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Брзи поставки."</string>
<string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"„Брзи поставки“ и „Панел со известувања“."</string>
- <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заклучи екран."</string>
+ <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заклучен екран."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Работен заклучен екран"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Затвори"</string>
<string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"целосна тишина"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не може да се зачува. Обидете се повторно."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не може да се зачува."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Употребете најмалку 4 знаци"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Употребете помалку од <xliff:g id="LENGTH">%1$d</xliff:g> знаци"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Број на верзија"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Бројот на верзијата е копиран во привремената меморија."</string>
<string name="basic_status" msgid="2315371112182658176">"Започни разговор"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Дознајте повеќе"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Дознајте повеќе на <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Отворете ја <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• апликацијата е поставена"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• најмалку една картичка е додадена во Wallet"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Изберете стандардна апликација за белешки за да ја користите кратенката за фаќање белешки"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Изберете апликација"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Допрете и задржете ја кратенката"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Откажи"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Приоритетниот режим е вклучен"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Вниманието на „Помошникот“ е вклучено"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Поставете стандардна апликација за белешки во „Поставки“"</string>
+ <string name="install_app" msgid="5066668100199613936">"Инсталирајте ја апликацијата"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 467720ae18be..ec1d42cfb9d3 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"സ്ഥിരീകരിച്ചു"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"പൂർത്തിയാക്കാൻ സ്ഥിരീകരിക്കുക ടാപ്പ് ചെയ്യൂ"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്‌തു"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"മുഖം ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്‌തു. തുടരാൻ അമർത്തുക."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"മുഖം തിരിച്ചറിഞ്ഞു. തുടരാൻ അമർത്തുക."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"മുഖം തിരിച്ചറിഞ്ഞു. തുടരാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"സംരക്ഷിക്കാൻ കഴിയില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"സംരക്ഷിക്കാൻ കഴിയില്ല."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"കുറഞ്ഞത് 4 പ്രതീകങ്ങളെങ്കിലും ഉപയോഗിക്കുക"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g>-ൽ കുറവ് പ്രതീകങ്ങൾ ഉപയോഗിക്കുക"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ബിൽഡ് നമ്പർ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ക്ലിപ്പ്ബോർഡിലേക്ക് ബിൽഡ് നമ്പർ പകർത്തി."</string>
<string name="basic_status" msgid="2315371112182658176">"സംഭാഷണം തുറക്കുക"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"കൂടുതലറിയുക"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g> എന്നതിൽ കൂടുതലറിയുക"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> തുറക്കുക"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ആപ്പ് സജ്ജീകരിച്ചിട്ടുണ്ട്"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet-ലേക്ക് ഒരു കാർഡെങ്കിലും ചേർത്തിട്ടുണ്ട്"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"കുറിപ്പ് രേഖപ്പെടുത്തൽ കുറുക്കുവഴി ഉപയോഗിക്കുന്നതിന് ഒരു ഡിഫോൾട്ട് കുറിപ്പ് ആപ്പ് തിരഞ്ഞെടുക്കുക"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"കുറുക്കുവഴിയായി Wallet ആപ്പ് ചേർക്കാൻ, ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്തിട്ടുണ്ടെന്ന് ഉറപ്പാക്കുക"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"കുറുക്കുവഴിയായി Wallet ആപ്പ് ചേർക്കാൻ, ഒരു കാർഡെങ്കിലും ചേർത്തിട്ടുണ്ടെന്ന് ഉറപ്പാക്കുക"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"കുറുക്കുവഴിയായി QR കോഡ് സ്‌കാനർ ചേർക്കാൻ, ക്യാമറാ ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്തിട്ടുണ്ടെന്ന് ഉറപ്പാക്കുക"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"കുറുക്കുവഴിയായി Home ആപ്പ് ചേർക്കാൻ, ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്തിട്ടുണ്ടെന്ന് ഉറപ്പാക്കുക"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• ഒരു ഉപകരണമെങ്കിലും ലഭ്യമാണ്"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"കുറിപ്പ് രേഖപ്പെടുത്തൽ കുറുക്കുവഴി ഉപയോഗിക്കുന്നതിന് ഒരു ഡിഫോൾട്ട് കുറിപ്പ് ആപ്പ് തിരഞ്ഞെടുക്കുക"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"ആപ്പ് തിരഞ്ഞെടുക്കുക"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"സ്പർശിച്ച് പിടിക്കുക കുറുക്കുവഴി"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"റദ്ദാക്കുക"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"മുൻഗണനാ മോഡ് ഓണാണ്"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant സജീവമാണ്"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ക്രമീകരണത്തിൽ കുറിപ്പുകൾക്കുള്ള ഡിഫോൾട്ട് ആപ്പ് സജ്ജീകരിക്കുക"</string>
+ <string name="install_app" msgid="5066668100199613936">"ആപ്പ് ഇൻസ്റ്റാൾ ചെയ്യൂ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index d17933aff733..d978c7099c0a 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Царайг баталгаажууллаа"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Баталгаажсан"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Дуусгахын тулд баталгаажуулахыг товших"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Царайгаар түгжээг тайлсан"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Царайгаар түгжээг тайлсан. Үргэлжлүүлэхийн тулд дарна уу."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Царайг таньсан. Үргэлжлүүлэхийн тулд дарна уу."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Царайг таньсан. Үргэлжлүүлэх бол түгжээг тайлах дүрсийг дар."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Хадгалах боломжгүй. Дахин оролдоно уу."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Хадгалах боломжгүй."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Дор хаяж 4 тэмдэгт ашиглана уу."</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g>-с цөөн тэмдэгт ашиглана уу"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Хийцийн дугаар"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Хийцийн дугаарыг түр санах ойд хуулсан."</string>
<string name="basic_status" msgid="2315371112182658176">"Харилцан яриаг нээх"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Нэмэлт мэдээлэл авах"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g>-с нэмэлт мэдээлэл авна уу"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g>-г нээх"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Аппыг тохируулсан"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Дор хаяж нэг картыг Wallet-д нэмсэн"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Тэмдэглэл хөтлөх товчлолыг ашиглахын тулд тэмдэглэлийн өгөгдмөл аппыг сонгоно уу"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Апп сонгох"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Товчлолд хүрээд удаан дарна уу"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Цуцлах"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Чухал горим асаалттай байна"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Туслах анхаарлаа хандуулж байна"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Тохиргоонд тэмдэглэлийн өгөгдмөл апп тохируулна уу"</string>
+ <string name="install_app" msgid="5066668100199613936">"Аппыг суулгах"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index b1825e9e6096..ace116c08f23 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"चेहरा ऑथेंटिकेशन केलेला आहे"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"निश्चित केले"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"पूर्ण करण्यासाठी खात्री करा वर टॅप करा"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"चेहऱ्याने अनलॉक केले आहे"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"चेहऱ्याने अनलॉक केले आहे. पुढे सुरू ठेवण्यासाठी प्रेस करा."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"चेहरा ओळखला आहे. पुढे सुरू ठेवण्यासाठी प्रेस करा."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"चेहरा ओळखला आहे. पुढे सुरू ठेवण्यासाठी अनलॉक करा आयकन प्रेस करा."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"सेव्ह करू शकत नाही. पुन्हा प्रयत्न करा."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"सेव्ह करू शकत नाही."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"किमान चार वर्ण वापरा"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g> वर्णांपेक्षा कमी वर्ण वापरा"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नंबर क्लिपबोर्डवर कॉपी केला."</string>
<string name="basic_status" msgid="2315371112182658176">"संभाषण उघडा"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"अधिक जाणून घ्या"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g> येथे अधिक जाणून घ्या"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> उघडा"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• अ‍ॅप सेट करणे"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet मध्ये किमान एक कार्ड जोडणे"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"टिपा घेण्याशी संबंधित शॉर्टकट वापरण्याकरिता टिपांसाठीचे डीफॉल्ट अ‍ॅप निवडा"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Wallet ॲप शॉर्टकट म्हणून जोडण्यासाठी ॲप इंस्टॉल केले असल्याची खात्री करा"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Wallet ॲप शॉर्टकट म्हणून जोडण्यासाठी किमान एक कार्ड जोडले असल्याची खात्री करा"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"QR कोड स्कॅनर शॉर्टकट म्हणून जोडण्यासाठी कॅमेरा ॲप इंस्टॉल केले असल्याची खात्री करा"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Home अ‍ॅप शॉर्टकट म्हणून जोडण्यासाठी ॲप इंस्टॉल केले असल्याची खात्री करा"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• किमान एक डिव्हाइस उपलब्ध करणे"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"टिपा घेण्यासंबंधित शॉर्टकट वापरण्याकरिता टिपांसाठीचे डीफॉल्ट अ‍ॅप निवडा"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"अ‍ॅप निवडा"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"स्पर्श करा आणि धरून ठेवा शॉर्टकट"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"रद्द करा"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"प्राधान्य मोड सुरू आहे"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant चे लक्ष हे आता अ‍ॅक्टिव्ह आहे"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"सेटिंग्ज मध्ये डीफॉल्ट टिपा अ‍ॅप सेट करा"</string>
+ <string name="install_app" msgid="5066668100199613936">"अ‍ॅप इंस्टॉल करा"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index f12b476a4cab..9153f1f5a884 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Wajah disahkan"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Disahkan"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Ketik Sahkan untuk menyelesaikan"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Dibuka kunci dengan wajah"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Dibuka kunci dengan wajah. Tekan untuk meneruskan."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Wajah dicam. Tekan untuk meneruskan."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Wajah dicam. Tekan ikon buka kunci untuk meneruskan."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Tidak dapat disimpan. Cuba lagi."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Tidak dapat disimpan."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gunakan sekurang-kurangnya 4 aksara"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Gunakan kurang daripada <xliff:g id="LENGTH">%1$d</xliff:g> aksara"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nombor binaan"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nombor binaan disalin ke papan keratan."</string>
<string name="basic_status" msgid="2315371112182658176">"Buka perbualan"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Ketahui lebih lanjut"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Ketahui lebih lanjut di <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Buka <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Apl disediakan"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Sekurang-kurangnya satu kad telah ditambahkan pada Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Pasang apl kamera"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Apl disediakan"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Sekurang-kurangnya satu peranti tersedia"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Pilih apl nota lalai untuk menggunakan pintasan pengambilan nota"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Untuk menambahkan apl Wallet sebagai pintasan, pastikan apl telah dipasang"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Untuk menambahkan apl Wallet sebagai pintasan, pastikan sekurang-kurangnya satu kad telah ditambahkan"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Untuk menambahkan pengimbas kod QR sebagai pintasan, pastikan apl kamera telah dipasang"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Untuk menambahkan apl Home sebagai pintasan, pastikan apl telah dipasang"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Sekurang-kurangnya satu peranti tersedia"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Pilih apl nota lalai untuk menggunakan pintasan pengambilan nota"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Pilih apl"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Pintasan sentuh &amp; tahan"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Batal"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mod keutamaan dihidupkan"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Perhatian pembantu dihidupkan"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Tetapkan apl nota lalai dalam Tetapan"</string>
+ <string name="install_app" msgid="5066668100199613936">"Pasang apl"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 1d85be1fca86..729ff60df5e5 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"အတည်ပြုပြီးပြီ"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"အပြီးသတ်ရန်အတွက် \'အတည်ပြုရန်\' ကို တို့ပါ"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"မျက်နှာဖြင့် ဖွင့်ထားသည်"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"မျက်နှာဖြင့် ဖွင့်ထားသည်။ ရှေ့ဆက်ရန် နှိပ်ပါ။"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"မျက်နှာ မှတ်မိသည်။ ရှေ့ဆက်ရန် နှိပ်ပါ။"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"မျက်နှာ မှတ်မိသည်။ ရှေ့ဆက်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ။"</string>
@@ -414,7 +413,7 @@
<string name="media_projection_entry_generic_permission_dialog_warning_single_app" msgid="3454859977888159495">"အက်ပ်တစ်ခုဖြင့် မျှဝေ၊ ရုပ်သံဖမ်း (သို့) ကာစ်လုပ်သည့်အခါ Android သည် ယင်းအက်ပ်တွင် ပြထားသည့် (သို့) ဖွင့်ထားသည့် အရာအားလုံးကို တွေ့နိုင်သည်။ ထို့ကြောင့် စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့အရာများကို ဂရုစိုက်ပါ။"</string>
<string name="media_projection_entry_generic_permission_dialog_continue" msgid="8640381403048097116">"စတင်ရန်"</string>
<string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"သင်၏ IT စီမံခန့်ခွဲသူက ပိတ်ထားသည်"</string>
- <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ကိရိယာဆိုင်ရာ မူဝါဒက ဖန်သားပြင်ပုံဖမ်းခြင်းကို ပိတ်ထားသည်"</string>
+ <string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"ကိရိယာ မူဝါဒက ဖန်သားပြင်ပုံဖမ်းခြင်းကို ပိတ်ထားသည်"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"အားလုံးရှင်းရန်"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"စီမံရန်"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"မှတ်တမ်း"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"သိမ်း၍မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"သိမ်း၍မရပါ။"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"အနည်းဆုံး အက္ခရာ ၄ လုံး သုံးရန်"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"အက္ခရာ <xliff:g id="LENGTH">%1$d</xliff:g> လုံးအောက် သုံးရန်"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"တည်ဆောက်မှုနံပါတ်"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"တည်ဆောက်မှုနံပါတ်ကို ကလစ်ဘုတ်သို့ မိတ္တူကူးပြီးပါပြီ။"</string>
<string name="basic_status" msgid="2315371112182658176">"စကားဝိုင်းကို ဖွင့်ရန်"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"ပိုမိုလေ့လာရန်"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g> တွင် ပိုမိုလေ့လာရန်"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ဖွင့်ရန်"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• အက်ပ်ကို စနစ်ထည့်သွင်းထားရမည်"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet တွင် အနည်းဆုံးကတ်တစ်ခု ထည့်ထားရမည်"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"မှတ်စုရေးသည့် ဖြတ်လမ်းလင့်ခ်သုံးရန်အတွက် မူရင်းမှတ်စုများအက်ပ် ရွေးရန်"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Wallet အက်ပ်ကို ဖြတ်လမ်းလင့်ခ်အဖြစ်ထည့်ရန် ၎င်းအားထည့်သွင်းထားကြောင်း သေချာပါစေ"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Wallet အက်ပ်ကို ဖြတ်လမ်းလင့်ခ်အဖြစ်ထည့်ရန် အနည်းဆုံး ကတ်တစ်ခုထည့်ထားကြောင်း သေချာပါစေ"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"QR ကုဒ် စကင်ဖတ်စနစ်ကို ဖြတ်လမ်းလင့်ခ်အဖြစ်ထည့်ရန် ကင်မရာအက်ပ်အားထည့်သွင်းထားကြောင်း သေချာပါစေ"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Home အက်ပ်ကို ဖြတ်လမ်းလင့်ခ်အဖြစ်ထည့်ရန် ၎င်းအားထည့်သွင်းထားကြောင်း သေချာပါစေ"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• အနည်းဆုံး စက်တစ်ခုသုံးနိုင်ရမည်"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"မှတ်စုရေးသည့် ဖြတ်လမ်းလင့်ခ်သုံးရန်အတွက် မူရင်းမှတ်စုများအက်ပ် ရွေးရန်"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"အက်ပ်ရွေးရန်"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ဖြတ်လမ်းလင့်ခ်ကို ထိပြီးဖိထားပါ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"မလုပ်တော့"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ဦးစားပေးမုဒ် ဖွင့်ထားသည်"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant နားထောင်နေသည်"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ဆက်တင်များတွင် မူရင်းမှတ်စုများအက်ပ် သတ်မှတ်ပါ"</string>
+ <string name="install_app" msgid="5066668100199613936">"အက်ပ် ထည့်သွင်းရန်"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 2363a689777b..e5d1315f343b 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ansiktet er autentisert"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekreftet"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Trykk på Bekreft for å fullføre"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Låst opp med ansiktet"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Låst opp med ansiktet. Trykk for å fortsette."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansiktet er gjenkjent. Trykk for å fortsette."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansiktet er gjenkjent. Trykk på lås opp-ikon for å fortsette"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kan ikke lagre. Prøv på nytt."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kan ikke lagre."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Bruk minst 4 tegn"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Bruk færre enn <xliff:g id="LENGTH">%1$d</xliff:g> tegn"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Delversjonsnummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Delversjonsnummeret er kopiert til utklippstavlen."</string>
<string name="basic_status" msgid="2315371112182658176">"Åpen samtale"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Finn ut mer"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Finn ut mer på <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Åpne <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• appen er konfigurert"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• minst ett kort er lagt til i Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• en kameraapp er installert"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• appen er konfigurert"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• minst én enhet er tilgjengelig"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Velg en standard notatapp du vil bruke med notatsnarveien"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Velg app"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Trykk på og hold inne snarveien"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Avbryt"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteringsmodus er på"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistentoppmerksomhet er på"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Du kan velge en standardapp for notater i Innstillinger"</string>
+ <string name="install_app" msgid="5066668100199613936">"Installer appen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 2f99cc73979f..b8d807d50df0 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"अनुहार प्रमाणीकरण गरियो"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"पुष्टि भयो"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"पूरा गर्नका लागि पुष्टि गर्नुहोस् नामक विकल्पमा ट्याप गर्नुहोस्"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"अनुहार प्रयोग गरी अनलक गरियो"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"अनुहार प्रयोग गरी अनलक गरियो। जारी राख्न थिच्नुहोस्।"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"अनुहार पहिचान गरियो। जारी राख्न थिच्नुहोस्।"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"अनुहार पहिचान गरियो। जारी राख्न अनलक आइकनमा थिच्नुहोस्।"</string>
@@ -463,8 +462,8 @@
<string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"तपाईंका एड्मिनले \'नेटवर्क लगिङ\' सुविधा अन गर्नुभएको छ। यो सुविधाले तपाईंको कार्य प्रोफाइलको ट्राफिक अनुगमन गर्छ तर व्यक्तिगत प्रोफाइलको ट्राफिक भने अनुगमन गर्दैन।"</string>
<string name="monitoring_description_named_vpn" msgid="8220190039787149671">"यो डिभाइस <xliff:g id="VPN_APP">%1$s</xliff:g> मार्फत इन्टरनेटमा कनेक्ट गरिएको छ। तपाईंको VPN प्रदायकले इमेल र ब्राउजिङ डेटालगायतका नेटवर्कसम्बन्धी गतिविधि हेर्न सक्छ।"</string>
<string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"यो डिभाइस <xliff:g id="VPN_APP">%1$s</xliff:g> मार्फत इन्टरनेटमा कनेक्ट गरिएको छ। तपाईंका IT एड्मिन इमेल र ब्राउजिङ डेटालगायतका नेटवर्कसम्बन्धी गतिविधि हेर्न सक्नुहुन्छ।"</string>
- <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"तपाईंको डिभाइस <xliff:g id="VPN_APP_0">%1$s</xliff:g> र <xliff:g id="VPN_APP_1">%2$s</xliff:g> मार्फत इन्टरनेटमा कनेक्ट गरिएको छ। तपाईंको सूचना प्रविधि व्यवस्थापक तपाईंको इमेल र ब्राउजिङ डेटासहित नेटवर्कसम्बन्धी क्रियाकलाप हेर्न सक्छन्।"</string>
- <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"तपाईंका कामसम्बन्धी एपहरू <xliff:g id="VPN_APP">%1$s</xliff:g> मार्फत इन्टरनेटमा कनेक्ट गरिएका छन्। तपाईंको सूचना प्रविधि व्यवस्थापक र VPN प्रदायक कामसम्बन्धी एपहरूमा भएका तपाईंका इमेल र ब्राउजिङ डेटासहित नेटवर्कसम्बन्धी क्रियाकलाप हेर्न सक्छन्।"</string>
+ <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"तपाईंको डिभाइस <xliff:g id="VPN_APP_0">%1$s</xliff:g> र <xliff:g id="VPN_APP_1">%2$s</xliff:g> मार्फत इन्टरनेटमा कनेक्ट गरिएको छ। तपाईंका IT एड्मिन तपाईंका इमेल र ब्राउजिङ डेटासहित नेटवर्कसम्बन्धी क्रियाकलाप हेर्न सक्छन्।"</string>
+ <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"तपाईंका कामसम्बन्धी एपहरू <xliff:g id="VPN_APP">%1$s</xliff:g> मार्फत इन्टरनेटमा कनेक्ट गरिएका छन्। तपाईंको IT एड्मिन र VPN प्रदायक कामसम्बन्धी एपहरूमा भएका तपाईंका इमेल र ब्राउजिङ डेटासहित नेटवर्कसम्बन्धी क्रियाकलाप हेर्न सक्छन्।"</string>
<string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"तपाईंका व्यक्तिगत एपहरू <xliff:g id="VPN_APP">%1$s</xliff:g> मार्फत इन्टरनेटमा कनेक्ट गरिएका छन्। तपाईंको VPN प्रदायक तपाईंको इमेल र ब्राउजिङ डेटासहित नेटवर्कसम्बन्धी क्रियाकलाप हेर्न सक्छन्।"</string>
<string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
<string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"VPN सम्बन्धी सेटिङहरू खोल्नुहोस्"</string>
@@ -676,7 +675,7 @@
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"एपहरू"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"सहायता"</string>
<string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"ब्राउजर (डिफल्ट ब्राउजर: Chrome)"</string>
- <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"सम्पर्कहरू"</string>
+ <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"कन्ट्याक्टहरू"</string>
<string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"इमेल (डिफल्ट एप: Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"सङ्गीत"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"सेभ गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"सेभ गर्न सकिएन।"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"कम्तीमा ४ वटा वर्ण प्रयोग गर्नुहोस्"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g> वटा भन्दा कम वर्ण प्रयोग गर्नुहोस्"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नम्बर"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नम्बर कपी गरी क्लिपबोर्डमा सारियो।"</string>
<string name="basic_status" msgid="2315371112182658176">"वार्तालाप खोल्नुहोस्"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"थप जान्नुहोस्"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g> मा गई थप जान्नुहोस्"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> खोल्नुहोस्"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• एप सेटअप गरिएको छ"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet मा कम्तीमा एउटा कार्ड हालिएको छ"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"नोट बनाउने गर्ने सर्टकट प्रयोग गर्न नोट बनाउने डिफल्ट एप चयन गर्नुहोस्"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"सर्टकटका रूपमा Wallet एप हाल्न उक्त एप इन्स्टल गरिएको छ भन्ने कुरा सुनिश्चित गर्नुहोस्"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"सर्टकटका रूपमा Wallet एप हाल्न कम्तीमा एउटा कार्ड हालिएको छ भन्ने कुरा सुनिश्चित गर्नुहोस्"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"सर्टकटका रूपमा QR कोड स्क्यानर हाल्न क्यामेरा एप इन्स्टल गरिएको छ भन्ने कुरा सुनिश्चित गर्नुहोस्"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Home एपलाई सर्टकटका रूपमा हाल्न उक्त एप इन्स्टल गरिएको छ भन्ने कुरा सुनिश्चित गर्नुहोस्"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• कम्तीमा एउटा डिभाइस उपलब्ध छ"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"नोट बनाउनेसम्बन्धी सर्टकट प्रयोग गर्न नोट बनाउने डिफल्ट एप चयन गर्नुहोस्"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"एप चयन गर्नुहोस्"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"सर्टकट थिचिराख्नुहोस्"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"रद्द गर्नुहोस्"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"प्राथमिकता मोड अन छ"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"सहायकले सुनिरहेको छ"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"सेटिङमा गई नोट बनाउने डिफल्ट एप तोक्नुहोस्"</string>
+ <string name="install_app" msgid="5066668100199613936">"एप इन्स्टल गर्नुहोस्"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 05f7922c6d1c..5e66b1c27b74 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Gezicht geverifieerd"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bevestigd"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tik op Bevestigen om te voltooien"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Ontgrendeld via gezicht"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Ontgrendeld via gezicht. Druk om door te gaan."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Gezicht herkend. Druk om door te gaan."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Gezicht herkend. Druk op het ontgrendelicoon."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kan niet opslaan. Probeer het opnieuw."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kan niet opslaan."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gebruik minstens 4 tekens"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Gebruik minder dan <xliff:g id="LENGTH">%1$d</xliff:g> tekens"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildnummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Buildnummer naar klembord gekopieerd."</string>
<string name="basic_status" msgid="2315371112182658176">"Gesprek openen"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Meer informatie"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Ga voor meer informatie naar <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> openen"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• De app is ingesteld"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Er is ten minste één kaart aan Wallet toegevoegd"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Er moet een camera-app zijn geïnstalleerd"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• De app is ingesteld"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Er is ten minste één apparaat beschikbaar"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Selecteer een standaard notitie-app om de sneltoets voor notities maken te gebruiken"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Als je de Wallet-app wilt toevoegen als sneltoets, zorg je dat de app is geïnstalleerd"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Als je de Wallet-app wilt toevoegen als sneltoets, zorg je dat er minstens één kaart is toegevoegd"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Als je de QR-codescanner wilt toevoegen als sneltoets, zorg je dat er een camera-app is geïnstalleerd"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Als je de Home-app wilt toevoegen als sneltoets, zorg je dat de app is geïnstalleerd"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Er is minstens één apparaat beschikbaar"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Selecteer een standaard notitie-app om de sneltoets voor notities maken te gebruiken"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"App selecteren"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Houd de sneltoets ingedrukt"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Annuleren"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteitsmodus aan"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent-aandacht aan"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Standaard notitie-app instellen in Instellingen"</string>
+ <string name="install_app" msgid="5066668100199613936">"App installeren"</string>
</resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 7f443de1898f..1cac0ed7ea90 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ମୁହଁ ପ୍ରାମାଣିକତା ହୋଇଛି"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ସୁନିଶ୍ଚିତ କରାଯାଇଛି"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ସମ୍ପୂର୍ଣ୍ଣ କରିବାକୁ ସୁନିଶ୍ଚିତ କରନ୍ତୁରେ ଟାପ୍ କରନ୍ତୁ"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"ଫେସ ମାଧ୍ୟମରେ ଅନଲକ କରାଯାଇଛି"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ଫେସ ମାଧ୍ୟମରେ ଅନଲକ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ ଦବାନ୍ତୁ।"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ଫେସ ଚିହ୍ନଟ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ ଦବାନ୍ତୁ।"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ଫେସ ଚିହ୍ନଟ କରାଯାଇଛି। ଜାରି ରଖିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ।"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ସେଭ କରାଯାଇପାରିଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ସେଭ କରାଯାଇପାରିଲା ନାହିଁ।"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ଅତିକମରେ 4ଟି କେରେକ୍ଟର ବ୍ୟବହାର କରନ୍ତୁ"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g>ଟିରୁ କମ କେରେକ୍ଟର ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ବିଲ୍ଡ ନମ୍ୱର"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"କ୍ଲିପବୋର୍ଡକୁ କପି କରାଯାଇଥିବା ବିଲ୍ଡ ନମ୍ୱର।"</string>
<string name="basic_status" msgid="2315371112182658176">"ବାର୍ତ୍ତାଳାପ ଖୋଲନ୍ତୁ"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g>ରେ ଅଧିକ ଜାଣନ୍ତୁ"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ଖୋଲନ୍ତୁ"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ଆପ ସେଟ ଅପ କରାଯାଇଥିବା"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Walletରେ ଅତିକମରେ ଗୋଟିଏ କାର୍ଡ ଯୋଗ କରାଯାଇଥିବା"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"ନୋଟଟେକିଂ ସର୍ଟକଟ ବ୍ୟବହାର କରିବାକୁ ଏକ ଡିଫଲ୍ଟ ନୋଟ୍ସ ଆପ୍ସ ଚୟନ କରନ୍ତୁ"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"ଆପ ଚୟନ କରନ୍ତୁ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ସର୍ଟକଟକୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ବାତିଲ କରନ୍ତୁ"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ପ୍ରାୟୋରିଟି ମୋଡ ଚାଲୁ ଅଛି"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant ଆଟେନସନ ଚାଲୁ ଅଛି"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ସେଟିଂସରେ ଡିଫଲ୍ଟ ନୋଟ୍ସ ଆପ ସେଟ କରନ୍ତୁ"</string>
+ <string name="install_app" msgid="5066668100199613936">"ଆପ ଇନଷ୍ଟଲ କରନ୍ତୁ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index f7bb0c916458..ad1ddcffd864 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ਚਿਹਰਾ ਪ੍ਰਮਾਣੀਕਿਰਤ ਹੋਇਆ"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ਪੁਸ਼ਟੀ ਕੀਤੀ ਗਈ"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"ਪੂਰਾ ਕਰਨ ਲਈ ਪੁਸ਼ਟੀ ਕਰੋ \'ਤੇ ਟੈਪ ਕਰੋ"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"ਚਿਹਰੇ ਰਾਹੀਂ ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ਚਿਹਰੇ ਰਾਹੀਂ ਅਣਲਾਕ ਕੀਤਾ ਗਿਆ। ਜਾਰੀ ਰੱਖਣ ਲਈ ਦਬਾਓ।"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਹੋਈ। ਜਾਰੀ ਰੱਖਣ ਲਈ ਦਬਾਓ।"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਹੋਈ। ਜਾਰੀ ਰੱਖਣ ਲਈ \'ਅਣਲਾਕ ਕਰੋ\' ਪ੍ਰਤੀਕ ਨੂੰ ਦਬਾਓ।"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ਘੱਟੋ-ਘੱਟ 4 ਅੱਖਰ-ਚਿੰਨ੍ਹ ਵਰਤੋ"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g> ਤੋਂ ਘੱਟ ਅੱਖਰ-ਚਿੰਨ੍ਹ ਵਰਤੋ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ਬਿਲਡ ਨੰਬਰ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ਬਿਲਡ ਨੰਬਰ ਨੂੰ ਕਲਿੱਪਬੋਰਡ \'ਤੇ ਕਾਪੀ ਕੀਤਾ ਗਿਆ।"</string>
<string name="basic_status" msgid="2315371112182658176">"ਗੱਲਬਾਤ ਖੋਲ੍ਹੋ"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"ਹੋਰ ਜਾਣੋ"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g> \'ਤੇ ਹੋਰ ਜਾਣੋ"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ਖੋਲ੍ਹੋ"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ਐਪ ਦਾ ਸੈੱਟਅੱਪ ਹੋ ਗਿਆ ਹੈ"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• ਘੱਟੋ-ਘੱਟ ਇੱਕ ਕਾਰਡ ਨੂੰ Wallet ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"ਨੋਟ- ਬਣਾਉਣ ਵਾਲੇ ਸ਼ਾਰਟਕੱਟ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਨੋਟ ਐਪ ਚੁਣੋ"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"ਐਪ ਚੁਣੋ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਸਪਰਸ਼ ਕਰ ਕੇ ਰੱਖੋ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ਰੱਦ ਕਰੋ"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ਤਰਜੀਹ ਮੋਡ ਚਾਲੂ ਹੈ"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant ਧਿਆਨ ਸੁਵਿਧਾ ਨੂੰ ਚਾਲੂ ਹੈ"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਨੋਟ ਐਪ ਨੂੰ ਸੈੱਟ ਕਰੋ"</string>
+ <string name="install_app" msgid="5066668100199613936">"ਐਪ ਸਥਾਪਤ ਕਰੋ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index e6af3fcf5f90..e42fd393cb29 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Twarz rozpoznana"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potwierdzono"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Aby zakończyć, kliknij Potwierdź"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Odblokowano skanem twarzy"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odblokowano rozpoznawaniem twarzy. Kliknij, aby kontynuować."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Twarz rozpoznana. Kliknij, aby kontynuować."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Twarz rozpoznana. Aby kontynuować, kliknij ikonę odblokowywania."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nie można zapisać. Spróbuj ponownie."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nie można zapisać."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Wpisz co najmniej 4 znaki"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Wpisz mniej znaków niż <xliff:g id="LENGTH">%1$d</xliff:g>"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numer kompilacji"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numer kompilacji został skopiowany do schowka."</string>
<string name="basic_status" msgid="2315371112182658176">"Otwarta rozmowa"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Więcej informacji"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Więcej informacji: <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otwórz: <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikacja została skonfigurowana."</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Do Portfela została dodana co najmniej 1 karta."</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Zainstalowano aplikację aparatu."</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Aplikacja została skonfigurowana."</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Dostępne jest co najmniej 1 urządzenie."</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Wybierz domyślną aplikację do obsługi notatek, której skrótu będziesz używać do funkcji notowania"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Wybierz aplikację"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Skrót – naciśnij i przytrzymaj"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Anuluj"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Tryb priorytetowy jest włączony"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Asystent jest aktywny"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ustaw domyślną aplikację do obsługi notatek w Ustawieniach"</string>
+ <string name="install_app" msgid="5066668100199613936">"Zainstaluj aplikację"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index b9df66103f3f..579a9bdfdf8c 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Rosto autenticado"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em \"Confirmar\" para concluir"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Desbloqueado pelo rosto"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado pelo rosto. Pressione para continuar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Pressione para continuar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Pressione o ícone para continuar."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Falha ao salvar. Tente de novo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Falha ao salvar."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use pelo menos 4 caracteres"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Use menos de <xliff:g id="LENGTH">%1$d</xliff:g> caracteres"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número da versão copiado para a área de transferência."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversa aberta"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Saiba mais"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Saiba mais em <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• O app está disponível"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Pelo menos um cartão foi adicionado à Carteira"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Um app de câmera está instalado"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• O app está disponível"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Pelo menos um dispositivo está disponível"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Selecione um app de notas padrão para usar o atalho de anotações"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Para adicionar o app Carteira como um atalho, verifique se ele está instalado"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Para adicionar o app Carteira como um atalho, verifique se pelo menos um cartão foi adicionado"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Para adicionar o leitor de código QR como um atalho, verifique se algum app de câmera está instalado"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Para adicionar o app Home como um atalho, verifique se ele está instalado"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Pelo menos um dispositivo está disponível"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Selecione um app de notas padrão para usar o atalho de anotações"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Selecionar app"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Toque e pressione o atalho"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
@@ -1147,7 +1145,7 @@
<string name="video_camera" msgid="7654002575156149298">"Filmadora"</string>
<string name="call_from_work_profile_title" msgid="5418253516453177114">"Não é possível fazer ligações de um app pessoal"</string>
<string name="call_from_work_profile_text" msgid="2856337395968118274">"Sua organização só permite fazer ligações usando apps de trabalho"</string>
- <string name="call_from_work_profile_action" msgid="2937701298133010724">"Alternar para o perfil de trabalho"</string>
+ <string name="call_from_work_profile_action" msgid="2937701298133010724">"Mudar para o perfil de trabalho"</string>
<string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instalar um app de telefone no perfil de trabalho"</string>
<string name="call_from_work_profile_close" msgid="5830072964434474143">"Cancelar"</string>
<string name="lock_screen_settings" msgid="6152703934761402399">"Personalizar a tela de bloqueio"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modo de prioridade ativado"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Atenção do Assistente ativada"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Defina o app de notas padrão nas Configurações"</string>
+ <string name="install_app" msgid="5066668100199613936">"Instalar o app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 9c11d6150cd8..aca644fa3f85 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Rosto autenticado"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmado"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em Confirmar para concluir."</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Desbloqueado com o rosto"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado com o rosto. Prima para continuar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Prima para continuar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Prima ícone de desbloqueio para continuar"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Não é possível guardar. Tente novamente."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Não é possível guardar."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use, pelo menos, 4 carateres"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Use menos de <xliff:g id="LENGTH">%1$d</xliff:g> carateres"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da compilação"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número da compilação copiado para a área de transferência."</string>
<string name="basic_status" msgid="2315371112182658176">"Abrir conversa"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Saiba mais"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Saiba mais em <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• A app está configurada"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Foi adicionado, pelo menos, um cartão à Carteira"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Instale uma app de câmara"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• A app está configurada"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Está disponível, pelo menos, um dispositivo"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Selecione uma app de notas predefinida para usar o atalho de anotação"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Para adicionar a app Carteira como um atalho, certifique-se de que a app está instalada"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Para adicionar a app Carteira como um atalho, certifique-se de que foi adicionado, pelo menos, um cartão"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Para adicionar o Leitor de códigos QR como um atalho, certifique-se de que está instalada uma app de câmara"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Para adicionar a app Home como um atalho, certifique-se de que a app está instalada"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Está disponível, pelo menos, um dispositivo"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Selecione uma app de notas predefinida para usar o atalho de anotação"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Selecionar app"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Toque sem soltar no atalho"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modo Prioridade ativado"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Atenção do Assistente ativada"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Predefina a app de notas nas Definições"</string>
+ <string name="install_app" msgid="5066668100199613936">"Instalar app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index b9df66103f3f..579a9bdfdf8c 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Rosto autenticado"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmada"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Toque em \"Confirmar\" para concluir"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Desbloqueado pelo rosto"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Desbloqueado pelo rosto. Pressione para continuar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Rosto reconhecido. Pressione para continuar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Pressione o ícone para continuar."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Falha ao salvar. Tente de novo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Falha ao salvar."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use pelo menos 4 caracteres"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Use menos de <xliff:g id="LENGTH">%1$d</xliff:g> caracteres"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número da versão copiado para a área de transferência."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversa aberta"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Saiba mais"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Saiba mais em <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• O app está disponível"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Pelo menos um cartão foi adicionado à Carteira"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Um app de câmera está instalado"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• O app está disponível"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Pelo menos um dispositivo está disponível"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Selecione um app de notas padrão para usar o atalho de anotações"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Para adicionar o app Carteira como um atalho, verifique se ele está instalado"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Para adicionar o app Carteira como um atalho, verifique se pelo menos um cartão foi adicionado"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Para adicionar o leitor de código QR como um atalho, verifique se algum app de câmera está instalado"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Para adicionar o app Home como um atalho, verifique se ele está instalado"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Pelo menos um dispositivo está disponível"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Selecione um app de notas padrão para usar o atalho de anotações"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Selecionar app"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Toque e pressione o atalho"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
@@ -1147,7 +1145,7 @@
<string name="video_camera" msgid="7654002575156149298">"Filmadora"</string>
<string name="call_from_work_profile_title" msgid="5418253516453177114">"Não é possível fazer ligações de um app pessoal"</string>
<string name="call_from_work_profile_text" msgid="2856337395968118274">"Sua organização só permite fazer ligações usando apps de trabalho"</string>
- <string name="call_from_work_profile_action" msgid="2937701298133010724">"Alternar para o perfil de trabalho"</string>
+ <string name="call_from_work_profile_action" msgid="2937701298133010724">"Mudar para o perfil de trabalho"</string>
<string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instalar um app de telefone no perfil de trabalho"</string>
<string name="call_from_work_profile_close" msgid="5830072964434474143">"Cancelar"</string>
<string name="lock_screen_settings" msgid="6152703934761402399">"Personalizar a tela de bloqueio"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modo de prioridade ativado"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Atenção do Assistente ativada"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Defina o app de notas padrão nas Configurações"</string>
+ <string name="install_app" msgid="5066668100199613936">"Instalar o app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 9667f43a58c7..03a0872c042e 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Chip autentificat"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Confirmat"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Atinge Confirm pentru a finaliza"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"S-a deblocat folosind fața"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"S-a deblocat cu ajutorul feței. Apasă pentru a continua."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Chipul a fost recunoscut. Apasă pentru a continua."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Chip recunoscut. Apasă pictograma Deblocare ca să continui."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nu se poate salva. Încearcă din nou."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nu se poate salva."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Folosește minimum 4 caractere."</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Folosește maximum <xliff:g id="LENGTH">%1$d</xliff:g> caractere"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numărul versiunii"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numărul versiunii s-a copiat în clipboard."</string>
<string name="basic_status" msgid="2315371112182658176">"Deschide conversația"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Află mai multe"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Află mai multe la <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Deschide <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplicația este configurată"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Cel puțin un card a fost adăugat în Portofel"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Instalează o aplicație pentru camera foto"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Aplicația este configurată"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Este disponibil cel puțin un dispozitiv"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Selectează o aplicație prestabilită pentru note ca să folosești comanda rapidă de luat note"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Pentru a adăuga aplicația Portofel drept comandă rapidă, asigură-te că aplicația este instalată"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Pentru a adăuga aplicația Portofel drept comandă rapidă, asigură-te că ai adăugat cel puțin un card"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Pentru a adăuga Scanner de coduri QR drept comandă rapidă, asigură-te că este instalată o aplicație pentru camera foto"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Pentru a adăuga aplicația Home drept comandă rapidă, asigură-te că aplicația este instalată"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Este disponibil cel puțin un dispozitiv"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Selectează o aplicație prestabilită pentru note ca să folosești comanda rapidă de luat note"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Selectează aplicația"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Atinge lung comanda rapidă"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Anulează"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modul Cu prioritate este activat"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistentul este atent"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Setează aplicația prestabilită de note din Setări"</string>
+ <string name="install_app" msgid="5066668100199613936">"Instalează aplicația"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 8945e34232b1..58563d50688a 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лицо распознано"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Подтверждено"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Нажмите \"Подтвердить\""</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Разблокировано сканированием лица"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Разблокировано сканированием лица. Нажмите, чтобы продолжить."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лицо распознано. Нажмите, чтобы продолжить."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лицо распознано. Нажмите на значок разблокировки."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не удалось сохранить. Повторите попытку."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не удалось сохранить."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Минимальное количество символов – 4"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Максимальное количество символов – <xliff:g id="LENGTH">%1$d</xliff:g>."</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер сборки"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Номер сборки скопирован в буфер обмена."</string>
<string name="basic_status" msgid="2315371112182658176">"Открытый чат"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Подробнее"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Подробнее: <xliff:g id="URL">%s</xliff:g>."</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Открыть \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Приложение установлено."</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• В Кошельке есть хотя бы одна карта."</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Выберите стандартное приложение для заметок, которое будет открываться при нажатии кнопки быстрого доступа."</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Выбрать приложение"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Нажмите и удерживайте ярлык"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Отмена"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Режим \"Только важные\" включен"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Ассистент готов слушать"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Задайте стандартное приложение для заметок в настройках."</string>
+ <string name="install_app" msgid="5066668100199613936">"Установить приложение"</string>
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index ef291cba38e8..69ebc3fd091b 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"මුහුණ සත්‍යාපන කළා"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"තහවුරු කළා"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"සම්පූර්ණ කිරීමට තහවුරු කරන්න තට්ටු කර."</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"මුහුණ මගින් අගුළු හරින ලදි"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"මුහුණ මගින් අගුලු හරින ලදි. ඉදිරියට යාමට ඔබන්න."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"මුහුණ හඳුනා ගන්නා ලදි. ඉදිරියට යාමට ඔබන්න."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"මුහුණ හඳුනා ගන්නා ලදි. ඉදිරියට යාමට අගුලු හැරීමේ නිරූපකය ඔබන්න."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"සුරැකිය නොහැකිය. නැවත උත්සාහ කරන්න."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"සුරැකිය නොහැකිය."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"අවම වශයෙන් අනුලකුණු 4ක් භාවිතා කරන්න"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"අනුලකුණු <xliff:g id="LENGTH">%1$d</xliff:g>කට වඩා අඩුවෙන් භාවිතා කරන්න"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"නිමැවුම් අංකය"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"නිමැවුම් අංකය පසුරු පුවරුවට පිටපත් කරන ලදි."</string>
<string name="basic_status" msgid="2315371112182658176">"සංවාදය විවෘත කරන්න"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"තව දැන ගන්න"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g> තුළින් තව දැන ගන්න"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> විවෘත කරන්න"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• යෙදුම සකසා ඇත"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Wallet වෙත අවම වශයෙන් එක කාඩ්පතක් එක් කර ඇත"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"සටහන් ගැනීමේ කෙටිමඟ භාවිතා කිරීමට පෙරනිමි සටහන් යෙදුමක් තෝරන්න"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"යෙදුම තෝරන්න"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ස්පර්ශ කර අල්ලා සිටීමේ කෙටිමඟ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"අවලංගු කරන්න"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ප්‍රමුඛතා මාදිලිය සක්‍රීයයි"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"සහයක අවධානය යොමු කරයි"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"සැකසීම් තුළ පෙරනිමි සටහන් යෙදුම සකසන්න"</string>
+ <string name="install_app" msgid="5066668100199613936">"යෙදුම ස්ථාපනය කරන්න"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 2544505e4d4b..7c356ded7502 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Tvár bola overená"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potvrdené"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Overenie dokončíte klepnutím na Potvrdiť"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Odomknuté tvárou"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odomknuté tvárou. Pokračujte stlačením."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Tvár bola rozpoznaná. Pokračujte stlačením."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Tvár bola rozpoznaná. Pokračujte stlačením ikony odomknutia"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nedá sa uložiť. Skúste to znova."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nedá sa uložiť."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Použite aspoň štyri znaky"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Použite menej znakov než <xliff:g id="LENGTH">%1$d</xliff:g>"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo zostavy"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Číslo zostavy bolo skopírované do schránky."</string>
<string name="basic_status" msgid="2315371112182658176">"Otvorená konverzácia"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Ďalšie informácie"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Viac sa dozviete na <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otvoriť <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikácia je nastavená"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Do Peňaženky bola pridaná minimálne jedna karta"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Vyberte predvolenú aplikáciu na písanie poznámok, ku ktorej priradíte skratku pre poznámky"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Výber aplikácie"</string>
<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>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Režim priority je zapnutý"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Pozornosť Asistenta je zapnutá"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Nastavte predvolenú aplikáciu na poznámky v Nastaveniach"</string>
+ <string name="install_app" msgid="5066668100199613936">"Inštalovať aplikáciu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 9a9676fec3e3..96ad5baab5ab 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Pristnost obraza je potrjena"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Potrjeno"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Za dokončanje se dotaknite »Potrdite«"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Odklenjeno z obrazom"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Odklenjeno z obrazom. Pritisnite za nadaljevanje."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Obraz je prepoznan. Pritisnite za nadaljevanje."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Obraz je prepoznan. Za nadaljevanje pritisnite ikono za odklepanje."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ni mogoče shraniti. Poskusite znova."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ni mogoče shraniti."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Uporabite vsaj 4 znake."</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Uporabite manj kot <xliff:g id="LENGTH">%1$d</xliff:g> znakov."</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Delovna različica"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Delovna različica je bila kopirana v odložišče."</string>
<string name="basic_status" msgid="2315371112182658176">"Odprt pogovor"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Več o tem"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Več informacij je na voljo na strani <xliff:g id="URL">%s</xliff:g>."</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Odpri aplikacijo <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikacija mora biti nastavljena."</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Vsaj ena kartica mora biti dodana v Denarnico."</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Namestite fotografsko aplikacijo."</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Aplikacija mora biti nastavljena."</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Na voljo mora biti vsaj ena naprava."</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Izberite privzeto aplikacijo za zapiske, ki jo želite povezati z bližnjico do ustvarjanja zapiskov."</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Če želite aplikacijo Denarnica dodati kot bližnjico, poskrbite, da je aplikacija nameščena."</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Če želite aplikacijo Denarnica dodati kot bližnjico, poskrbite, da je dodana vsaj ena kartica."</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Če želite optični bralnik kod QR dodati kot bližnjico, poskrbite, da je nameščena fotografska aplikacija."</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Če želite aplikacijo Home dodati kot bližnjico, poskrbite, da je aplikacija nameščena."</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Na voljo mora biti vsaj ena naprava."</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Izberite privzeto aplikacijo za zapiske, ki jo želite povezati z bližnjico do ustvarjanja zapiskov."</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Izbira aplikacije"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Pridržite bližnjico"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Prekliči"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prednostni način je vklopljen."</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Zaznavanje pomočnika je vklopljeno."</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Nastavite privzeto aplikacijo za zapiske v nastavitvah."</string>
+ <string name="install_app" msgid="5066668100199613936">"Namesti aplikacijo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index d477aa415067..181756afeccf 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Fytyra u vërtetua"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Konfirmuar"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Trokit \"Konfirmo\" për ta përfunduar"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"U shkyç me fytyrë"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"U shkyç me fytyrë. Shtyp për të vazhduar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Fytyra u njoh. Shtyp për të vazhduar."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Fytyra u njoh. Shtyp ikonën e shkyçjes për të vazhduar."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nuk mund të ruhet. Provo përsëri."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nuk mund të ruhet."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Përdor të paktën 4 karaktere"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Përdor më pak se <xliff:g id="LENGTH">%1$d</xliff:g> karaktere"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numri i ndërtimit"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numri i ndërtimit u kopjua te kujtesa e fragmenteve"</string>
<string name="basic_status" msgid="2315371112182658176">"Hap bisedën"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Mëso më shumë"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Mëso më shumë në <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Hap \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Aplikacioni është konfiguruar"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Të paktën një kartë të jetë shtuar në \"Portofol\""</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Zgjidh një aplikacion të parazgjedhur shënimesh për të përdorur shkurtoren e mbajtjes së shënimeve"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Zgjidh aplikacionin"</string>
<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>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modaliteti i përparësisë aktiv"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Vëmendja e \"Asistentit\" aktive"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Cakto aplikacionin e parazgjedhur të shënimeve te \"Cilësimet\""</string>
+ <string name="install_app" msgid="5066668100199613936">"Instalo aplikacionin"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index b293e6aaae02..798b4643164e 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Лице је потврђено"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Потврђено"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Додирните Потврди да бисте завршили"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Откључано је лицем"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Откључано је лицем. Притисните да бисте наставили."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Лице је препознато. Притисните да бисте наставили."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Лице препознато. Притисните икону откључавања за наставак."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Чување није успело. Пробајте поново."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Чување није успело."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Користите бар 4 знака"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Користите мањи број знакова од <xliff:g id="LENGTH">%1$d</xliff:g>"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Број верзије"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Број верзије је копиран у привремену меморију."</string>
<string name="basic_status" msgid="2315371112182658176">"Отворите конверзацију"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Сазнајте више"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Сазнајте више на <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Отворите: <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• да је апликација подешена"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• да је у Новчаник додата барем једна картица"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Изаберите подразумевану апликацију за белешке да бисте користили пречицу за прављење белешки"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Изабери апликацију"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Додирните и задржите пречицу"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Откажи"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Приоритетни режим је укључен"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Помоћник је у активном стању"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Подесите подразумевану апликацију за белешке у Подешавањима"</string>
+ <string name="install_app" msgid="5066668100199613936">"Инсталирај апликацију"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 00a2e3c158bb..ba56ab40645a 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ansiktet har autentiserats"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Bekräftat"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Slutför genom att trycka på Bekräfta"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Upplåst med ansiktslås"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Upplåst med ansiktslås. Tryck för att fortsätta."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ansiktet har identifierats. Tryck för att fortsätta."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ansiktet har identifierats. Tryck på ikonen lås upp."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Det gick inte att spara. Försök igen."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Det gick inte att spara."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Använd minst 4 tecken"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Använd färre än <xliff:g id="LENGTH">%1$d</xliff:g> tecken"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versionsnummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versionsnumret har kopierats till urklipp."</string>
<string name="basic_status" msgid="2315371112182658176">"Öppen konversation"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Läs mer"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Läs mer på <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Öppna <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• appen har konfigurerats"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• minst ett kort har lagts till i Wallet"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Välj en standardapp för anteckningar om du vill använda genvägen för anteckningar"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Välj app"</string>
<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>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritetsläge är aktiverat"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistenten är aktiverad"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ställ in en standardapp för anteckningar i inställningarna"</string>
+ <string name="install_app" msgid="5066668100199613936">"Installera appen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index af90c67aefb9..e4d3e56ae119 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Uso umethibitishwa"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Imethibitishwa"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Gusa Thibitisha ili ukamilishe"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Inafunguliwa kwa kutumia uso"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Imefunguliwa kwa kutumia uso wako. Bonyeza ili uendelee."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Uso umetambuliwa. Bonyeza ili uendelee."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Uso umetambuliwa. Bonyeza aikoni ya kufungua ili uendelee."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Imeshindwa kuhifadhi. Jaribu tena."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Imeshindwa kuhifadhi."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Tumia angalau herufi 4"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Hupaswi kuzidi herufi <xliff:g id="LENGTH">%1$d</xliff:g>"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nambari ya muundo"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nambari ya muundo imewekwa kwenye ubao wa kunakili."</string>
<string name="basic_status" msgid="2315371112182658176">"Fungua mazungumzo"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Pata maelezo zaidi"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Pata maelezo zaidi katika <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Fungua <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Programu hii imewekewa mipangilio"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Angalau kadi moja imewekwa kwenye Pochi"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Chagua programu chaguomsingi ya madokezo ili utumie njia ya mkato ya kuandika madokezo"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Ili uweke programu ya Pochi kuwa njia ya mkato, hakikisha umesakinisha programu hiyo"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Ili uweke programu ya Pochi kuwa njia ya mkato, hakikisha umeweka angalau kadi moja"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Ili uweke kichanganuzi cha msimbo wa QR kuwa njia ya mkato, hakikisha umesakinisha programu ya kamera"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Ili uweke programu ya Google Home kuwa njia ya mkato, hakikisha umesakinisha programu hiyo"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Angalau kifaa kimoja kinapatikana"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Chagua programu chaguomsingi ya madokezo ili utumie njia ya mkato ya kuandika madokezo"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Chagua programu"</string>
<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>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Hali ya kipaumbele imewashwa"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Programu ya Mratibu imewashwa"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Teua programu chaguomsingi ya madokezo katika Mipangilio"</string>
+ <string name="install_app" msgid="5066668100199613936">"Sakinisha programu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index fd33af97be2c..125adc826932 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"முகம் அங்கீகரிக்கப்பட்டது"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"உறுதிப்படுத்தப்பட்டது"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"முடிக்க \'உறுதிப்படுத்துக\' என்பதை தட்டவும்"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"முகத்தால் அன்லாக் செய்யப்பட்டது"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"முகம் மூலம் அன்லாக் செய்யப்பட்டது. தொடர அழுத்தவும்."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"முகம் அங்கீகரிக்கப்பட்டது. தொடர அழுத்தவும்."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"முகம் அங்கீகரிக்கப்பட்டது. தொடர அன்லாக் ஐகானை அழுத்தவும்."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"சேமிக்க முடியவில்லை. மீண்டும் முயலவும்."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"சேமிக்க முடியவில்லை."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"குறைந்தது 4 எழுத்துகளைப் பயன்படுத்துங்கள்"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g> எழுத்துகளுக்குக் குறைவாகப் பயன்படுத்துங்கள்"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"பதிப்பு எண்"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"பதிப்பு எண் கிளிப்போர்டுக்கு நகலெடுக்கப்பட்டது."</string>
<string name="basic_status" msgid="2315371112182658176">"திறந்தநிலை உரையாடல்"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"மேலும் அறிக"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"மேலும் அறிக: <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> ஆப்ஸைத் திற"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• இந்த ஆப்ஸ் அமைக்கப்பட்டிருக்க வேண்டும்"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Walletடில் குறைந்தபட்சம் ஒரு கார்டாவது சேர்க்கப்பட்டிருக்க வேண்டும்"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"குறிப்பெடுத்தல் ஷார்ட்கட்டைப் பயன்படுத்த, குறிப்பெடுப்பதற்கான இயல்புநிலை ஆப்ஸைத் தேர்ந்தெடுக்கவும்"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"ஆப்ஸைத் தேர்ந்தெடு"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ஷார்ட்கட்டை தொட்டுப் பிடிக்கவும்"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ரத்துசெய்"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"முன்னுரிமைப் பயன்முறை இயக்கத்தில் உள்ளது"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"அசிஸ்டண்ட்டின் கவனம் இயக்கத்தில் உள்ளது"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"குறிப்பு எடுப்பதற்கான இயல்புநிலை ஆப்ஸை அமைப்புகளில் அமையுங்கள்"</string>
+ <string name="install_app" msgid="5066668100199613936">"ஆப்ஸை நிறுவுங்கள்"</string>
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 63fc9e03bfce..25bf52817ffd 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -132,7 +132,7 @@
<string name="accessibility_unlock_button" msgid="3613812140816244310">"అన్‌లాక్ చేయబడింది"</string>
<string name="accessibility_lock_icon" msgid="661492842417875775">"పరికరం లాక్ చేయబడింది"</string>
<string name="accessibility_scanning_face" msgid="3093828357921541387">"ముఖాన్ని స్కాన్ చేస్తోంది"</string>
- <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"పంపు"</string>
+ <string name="accessibility_send_smart_reply" msgid="8885032190442015141">"పంపండి"</string>
<string name="cancel" msgid="1089011503403416730">"రద్దు చేయండి"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"నిర్ధారించండి"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"మళ్లీ ట్రై చేయండి"</string>
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ముఖం ప్రామాణీకరించబడింది"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"నిర్ధారించబడింది"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"పూర్తి చేయడానికి \"నిర్ధారించు\" నొక్కండి"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"ముఖం ద్వారా అన్‌లాక్ చేయబడింది"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ముఖం ద్వారా అన్‌లాక్ చేయబడింది. కొనసాగించడానికి నొక్కండి."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"ముఖం గుర్తించబడింది. కొనసాగించడానికి నొక్కండి."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"ముఖం గుర్తించబడింది. కొనసాగడానికి అన్‌లాక్ చిహ్నం నొక్కండి."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"సేవ్ చేయడం సాధ్యపడదు. మళ్లీ ట్రై చేయండి."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"సేవ్ చేయడం సాధ్యపడదు."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"కనీసం 4 అక్షరాలను ఉపయోగించండి"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g> కంటే తక్కువ అక్షరాలను ఉపయోగించండి"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"బిల్డ్ నంబర్"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"బిల్డ్ నంబర్, క్లిప్‌బోర్డ్‌కు కాపీ చేయబడింది."</string>
<string name="basic_status" msgid="2315371112182658176">"సంభాషణను తెరవండి"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"మరింత తెలుసుకోండి"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g>‌లో మరింత తెలుసుకోండి"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g>‌ను తెరవండి"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• యాప్ సెటప్ చేయబడి ఉందని"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Walletకు కనీసం ఒక కార్డ్ అయినా జోడించబడి ఉందని"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"నోట్‌టేకింగ్ షార్ట్‌కట్‌ను ఉపయోగించడానికి ఆటోమేటిక్ సెట్టింగ్ నోట్స్ యాప్‌ను ఎంచుకోండి"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Wallet యాప్‌ను షార్ట్‌కట్‌గా జోడించడానికి, యాప్ ఇన్‌స్టాల్ చేయబడిందని నిర్ధారించుకోండి"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Wallet యాప్‌ను షార్ట్‌కట్‌గా జోడించడానికి, కనీసం ఒక కార్డ్ జోడించబడిందని నిర్ధారించుకోండి"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"QR కోడ్ స్కానర్‌ను షార్ట్‌కట్‌గా జోడించడానికి, కెమెరా యాప్ ఇన్‌స్టాల్ చేయబడిందని నిర్ధారించుకోండి"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Home యాప్‌ను షార్ట్‌కట్‌గా జోడించడానికి, యాప్ ఇన్‌స్టాల్ చేయబడిందని నిర్ధారించుకోండి"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• కనీసం ఒక పరికరమైనా అందుబాటులో ఉందని"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"నోట్‌టేకింగ్ షార్ట్‌కట్‌ను ఉపయోగించడానికి ఆటోమేటిక్ సెట్టింగ్ నోట్స్ యాప్‌ను ఎంచుకోండి"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"యాప్‌ను ఎంచుకోండి"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"షార్ట్‌కట్‌ను తాకి, నొక్కి ఉంచు"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"రద్దు చేయండి"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ప్రయారిటీ మోడ్ ఆన్‌లో ఉంది"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant అటెన్షన్ ఆన్‌లో ఉంది"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"సెట్టింగ్‌లలో ఆటోమేటిక్‌గా ఉండేలా ఒక నోట్స్ యాప్‌ను సెట్ చేసుకోండి"</string>
+ <string name="install_app" msgid="5066668100199613936">"యాప్‌ను ఇన్‌స్టాల్ చేయండి"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 49f0f2a85802..578c843f1258 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"ตรวจสอบสิทธิ์ใบหน้าแล้ว"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"ยืนยันแล้ว"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"แตะยืนยันเพื่อดำเนินการให้เสร็จสมบูรณ์"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"ปลดล็อกด้วยใบหน้าแล้ว"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"ปลดล็อกด้วยใบหน้าแล้ว กดเพื่อดำเนินการต่อ"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"จดจำใบหน้าได้ กดเพื่อดำเนินการต่อ"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"จดจำใบหน้าได้ กดไอคอนปลดล็อกเพื่อดำเนินการต่อ"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"บันทึกไม่ได้ โปรดลองอีกครั้ง"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"บันทึกไม่ได้"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ใช้อักขระอย่างน้อย 4 ตัว"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"ใช้อักขระไม่เกิน <xliff:g id="LENGTH">%1$d</xliff:g> ตัว"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"หมายเลขบิลด์"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"คัดลอกหมายเลขบิลด์ไปยังคลิปบอร์ดแล้ว"</string>
<string name="basic_status" msgid="2315371112182658176">"เปิดการสนทนา"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"ดูข้อมูลเพิ่มเติม"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"ดูข้อมูลเพิ่มเติมที่ <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"เปิด <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• แอปได้รับการตั้งค่าแล้ว"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• มีการเพิ่มบัตรลงใน Wallet อย่างน้อย 1 รายการ"</string>
- <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">"• มีอุปกรณ์พร้อมใช้งานอย่างน้อย 1 รายการ"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"เลือกแอปโน้ตเริ่มต้นเพื่อใช้ทางลัดการจดบันทึก"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"หากต้องการเพิ่มแอป Wallet เป็นทางลัด โปรดตรวจสอบว่าได้ติดตั้งแอปแล้ว"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"หากต้องการเพิ่มแอป Wallet เป็นทางลัด โปรดตรวจสอบว่าได้เพิ่มบัตรอย่างน้อย 1 ใบแล้ว"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"หากต้องการเพิ่มเครื่องมือสแกนคิวอาร์โค้ดเป็นทางลัด โปรดตรวจสอบว่าได้ติดตั้งแอปกล้องแล้ว"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"หากต้องการเพิ่มแอป Home เป็นทางลัด โปรดตรวจสอบว่าได้ติดตั้งแอปแล้ว"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• มีอุปกรณ์พร้อมใช้งานอย่างน้อย 1 รายการ"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"เลือกแอปโน้ตเริ่มต้นเพื่อใช้ทางลัดการจดบันทึก"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"เลือกแอป"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"แตะแป้นพิมพ์ลัดค้างไว้"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ยกเลิก"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"โหมดลำดับความสำคัญเปิดอยู่"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"การเรียกใช้งาน Assistant เปิดอยู่"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"กำหนดแอปการจดบันทึกเริ่มต้นในการตั้งค่า"</string>
+ <string name="install_app" msgid="5066668100199613936">"ติดตั้งแอป"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 755c87207b9a..81a78c9c11c4 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Na-authenticate ang mukha"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Nakumpirma"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"I-tap ang Kumpirmahin para kumpletuhin"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Na-unlock gamit ang mukha"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Na-unlock gamit ang mukha. Pindutin para magpatuloy."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Nakilala ang mukha. Pindutin para magpatuloy."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Nakilala ang mukha. Pindutin ang unlock para magpatuloy."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Hindi ma-save. Subukan ulit."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Hindi ma-save."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gumamit ng hindi bababa sa 4 na character"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Gumamit ng mas kaunti sa <xliff:g id="LENGTH">%1$d</xliff:g> (na) character"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero ng build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nakopya sa clipboard ang numero ng build."</string>
<string name="basic_status" msgid="2315371112182658176">"Buksan ang pag-uusap"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Matuto pa"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Matuto pa sa <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Buksan ang <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Na-set up ang app"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• May kahit isang card na idinagdag sa Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Mag-install ng camera app"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Na-set up ang app"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• May kahit isang device na available"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Pumili ng default na notes app para magamit ang shortcut sa pagtatala"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Para maidagdag ang Wallet app bilang shortcut, siguraduhing naka-install ang app"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Para maidagdag ang Wallet app bilang shortcut, siguraduhing may naidagdag na kahit isang card man lang"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Para maidagdag ang scanner ng QR code bilang shortcut, siguraduhing may naka-install na camera app"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Para maidagdag ang Home app bilang shortcut, siguraduhing naka-install ang app"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• May kahit isang device na available"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Pumili ng default na app ng mga tala para magamit ang shortcut sa paggawa ng tala"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Pumili ng app"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Pindutin nang matagal: shortcut"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Kanselahin"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Naka-on ang Priority mode"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Naka-on ang atensyon ng Assistant"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Magtakda ng default na app sa pagtatala sa Mga Setting"</string>
+ <string name="install_app" msgid="5066668100199613936">"I-install ang app"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 72c2d436d9b8..77570df8655a 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Yüz kimliği doğrulandı"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Onaylandı"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tamamlamak için Onayla\'ya dokunun"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Cihazın kilidini yüzünüzle açtınız"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Cihazın kilidini yüzünüzle açtınız. Devam etmek için basın."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Yüzünüz tanındı. Devam etmek için basın."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Yüzünüz tanındı. Kilit açma simgesine basın."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kaydedilemiyor. Tekrar deneyin."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kaydedilemiyor."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"En az 4 karakter kullanın."</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"En fazla <xliff:g id="LENGTH">%1$d</xliff:g> karakter kullanın"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Derleme numarası"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Derleme numarası panoya kopyalandı."</string>
<string name="basic_status" msgid="2315371112182658176">"Görüşmeyi aç"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Daha fazla bilgi"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Daha fazla bilgiyi <xliff:g id="URL">%s</xliff:g> sayfasında bulabilirsiniz"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> uygulamasını aç"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Uygulama kurulmuş olmalıdır"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Cüzdan\'a en az bir kart eklenmelidir"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Not alma kısayolunu kullanmak için varsayılan bir notlar uygulaması seçin"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Uygulama seçin"</string>
<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>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Öncelik modu etkin"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistan dinliyor"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ayarlar\'ı kullanarak varsayılan notlar ayarlayın"</string>
+ <string name="install_app" msgid="5066668100199613936">"Uygulamayı yükle"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index c1e291d3fce7..9d101fb99b9b 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Обличчя автентифіковано"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Підтверджено"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Щоб завершити, натисніть \"Підтвердити\""</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Розблоковано (фейс-контроль)"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Розблоковано (фейсконтроль). Натисніть, щоб продовжити."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Обличчя розпізнано. Натисніть, щоб продовжити."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Обличчя розпізнано. Натисніть значок розблокування."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не вдалося зберегти. Повторіть спробу."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не вдалося зберегти."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Введіть принаймні 4 символи"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Кількість символів має бути менше ніж <xliff:g id="LENGTH">%1$d</xliff:g>"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер складання"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Номер складання скопійовано в буфер обміну."</string>
<string name="basic_status" msgid="2315371112182658176">"Відкрита розмова"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Докладніше"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Докладніше: <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Відкрити <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Додаток налаштовано"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Принаймні одну картку додано в Гаманець"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Виберіть стандартний додаток для нотаток, щоб створювати їх за допомогою ярлика"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Вибрати додаток"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Натисніть і утримуйте ярлик"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Скасувати"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Режим пріоритету ввімкнено"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Асистента активовано"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Призначте стандартний додаток для нотаток у налаштуваннях"</string>
+ <string name="install_app" msgid="5066668100199613936">"Установити додаток"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 46596c34a250..fc20a88ba583 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"چہرے کی تصدیق ہو گئی"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"تصدیق شدہ"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"مکمل کرنے کیلئے \'تصدیق کریں\' تھپتھپائیں"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"چہرے سے غیر مقفل کیا گیا"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"چہرے سے انلاک کیا گیا۔ جاری رکھنے کے لیے دبائیں۔"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"چہرے کی شناخت ہو گئی۔ جاری رکھنے کے لیے دبائیں۔"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"چہرے کی شناخت ہو گئی۔ جاری رکھنے کیلئے انلاک آئیکن دبائیں۔"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"محفوظ نہیں کیا جا سکا۔ پھر کوشش کریں۔"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"محفوظ نہیں کیا جا سکا۔"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"کم از کم 4 حروف استعمال کریں"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"<xliff:g id="LENGTH">%1$d</xliff:g> حروف سے کم استعمال کریں"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"بلڈ نمبر"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"بلڈ نمبر کلپ بورڈ میں کاپی ہو گیا۔"</string>
<string name="basic_status" msgid="2315371112182658176">"گفتگو کھولیں"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"مزید جانیں"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"مزید جاننے کیلئے <xliff:g id="URL">%s</xliff:g> ملاحظہ کریں"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> کھولیں"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ایپ سیٹ اپ ہو گئی ہے"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• والٹ میں کم از کم ایک کارڈ شامل کیا گیا ہے"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"نوٹ لینے والے شارٹ کٹ کا استعمال کرنے کے لیے ڈیفالٹ نوٹس ایپ منتخب کریں"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"ایپ منتخب کریں"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"شارٹ کٹ ٹچ کریں اور دبائے رکھیں"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"منسوخ کریں"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ترجیحی موڈ آن ہے"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"اسسٹنٹ کی توجہ آن ہے"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ترتیبات میں ڈیفالٹ نوٹس ایپ سیٹ کریں"</string>
+ <string name="install_app" msgid="5066668100199613936">"ایپ انسٹال کریں"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index ab1fe063a797..31ba2ba23c94 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Yuzingiz aniqlandi"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Tasdiqlangan"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Tasdiqlash uchun tegining"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Yuz bilan ochildi"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Yuz orqali ochildi. Davom etish uchun bosing."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Yuz aniqlandi. Davom etish uchun bosing."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Yuz aniqlandi. Davom etish uchun ochish belgisini bosing."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Saqlanmadi. Qayta urining."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Saqlanmadi."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Parolga kamida 4 ta belgi kiriting."</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Kiritiladigan belgilar <xliff:g id="LENGTH">%1$d</xliff:g> tadan oshmasin"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nashr raqami"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nashr raqami vaqtinchalik xotiraga nusxalandi."</string>
<string name="basic_status" msgid="2315371112182658176">"Suhbatni ochish"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Batafsil"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Batafsil: <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Ochish: <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Ilova sozlangan"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Kamida bitta kartochka Wallet xizmatiga qoʻshilgan"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Kamera ilovasini oʻrnating"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Ilova sozlangan"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Kamida bitta qurilma mavjud"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Qayd yozish yorligʻidan foydalanish uchun birlamchi qayd ilovasini tanlang"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Wallet ilovasini yorliq sifatida qoʻshish uchun ilova oʻrnatilganiga ishonch hosil qiling"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Wallet ilovasini yorliq sifatida qoʻshish uchun kamida bitta karta kiritilganiga ishonch hosil qiling"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"QR kod skanerini yorliq sifatida qoʻshish uchun kamera ilovasi oʻrnatilganiga ishonch hosil qiling"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Home ilovasini yorliq sifatida qoʻshish uchun ilova oʻrnatilganiga ishonch hosil qiling"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Kamida bitta qurilma mavjud"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Qayd yozish yorligʻidan foydalanish uchun birlamchi qayd ilovasini tanlang"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Ilovani tanlang"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Bosib turish yorligʻi"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Bekor qilish"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Imtiyozli rejim yoniq"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent diqqati yoniq"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Standart qaydlar ilovasini Sozlamalar orqali tanlang"</string>
+ <string name="install_app" msgid="5066668100199613936">"Ilovani oʻrnatish"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index e681b1a724a0..d30a488bcaf0 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Đã xác thực khuôn mặt"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Ðã xác nhận"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Nhấn vào Xác nhận để hoàn tất"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Đã mở khoá bằng khuôn mặt"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Đã mở khoá bằng khuôn mặt. Hãy nhấn để tiếp tục."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Đã nhận diện khuôn mặt. Hãy nhấn để tiếp tục."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Đã nhận diện khuôn mặt. Nhấn biểu tượng mở khoá để tiếp tục."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Không lưu được. Hãy thử lại."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Không lưu được."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Sử dụng ít nhất 4 ký tự"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Hãy dùng ít hơn <xliff:g id="LENGTH">%1$d</xliff:g> ký tự"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Số bản dựng"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Đã sao chép số bản dựng vào bảng nhớ tạm."</string>
<string name="basic_status" msgid="2315371112182658176">"Mở cuộc trò chuyện"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Tìm hiểu thêm"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Tìm hiểu thêm tại <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Mở <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• Ứng dụng được thiết lập"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Thêm ít nhất một thẻ vào Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Cài đặt một ứng dụng máy ảnh"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• Ứng dụng được thiết lập"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Có ít nhất một thiết bị đang hoạt động"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Chọn một ứng dụng ghi chú mặc định để dùng lối tắt ghi chú"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Chọn ứng dụng"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Chạm và giữ phím tắt"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Huỷ"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Chế độ ưu tiên đang bật"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Trợ lý đang bật"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Đặt ứng dụng ghi chú mặc định trong phần Cài đặt"</string>
+ <string name="install_app" msgid="5066668100199613936">"Cài đặt ứng dụng"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 5df113b5f5e7..18fc39692b82 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -69,7 +69,7 @@
<string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"启用 USB"</string>
<string name="learn_more" msgid="4690632085667273811">"了解详情"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"屏幕截图"</string>
- <string name="global_action_smart_lock_disabled" msgid="6286551337177954859">"已停用 Extend Unlock"</string>
+ <string name="global_action_smart_lock_disabled" msgid="6286551337177954859">"已停用延长解锁"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"发送了一张图片"</string>
<string name="screenshot_saving_title" msgid="2298349784913287333">"正在保存屏幕截图..."</string>
<string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"正在将屏幕截图保存到工作资料…"</string>
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"面孔身份验证成功"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"已确认"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"点按“确认”即可完成"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"已用面孔解锁"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"已通过面孔识别解锁。点按即可继续。"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"识别出面孔。点按即可继续。"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"识别出面孔。按下解锁图标即可继续。"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"无法保存,请重试。"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"无法保存。"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"必须至少 4 个字符"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"必须少于 <xliff:g id="LENGTH">%1$d</xliff:g> 个字符"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build 号"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"已将 Build 号复制到剪贴板。"</string>
<string name="basic_status" msgid="2315371112182658176">"开放式对话"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"了解详情"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"如需了解详情,请前往 <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"打开<xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• 应用已设置完毕"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• 至少已将一张银行卡添加到钱包"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"选择默认记事应用即可使用记事快捷方式"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"若要将 Google 钱包应用添加为快捷方式,请确保已安装该应用"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"若要将 Google 钱包应用添加为快捷方式,请确保至少已添加一张银行卡"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"若要将二维码扫描器添加为快捷方式,请确保已安装相机应用"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"若要将 Home 应用添加为快捷方式,请确保已安装该应用"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• 至少有一台设备可用"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"选择默认记事应用即可使用记事快捷方式"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"选择应用"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"轻触并按住快捷方式"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"取消"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"已开启优先模式"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"已开启 Google 助理感知功能"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"在设置中设置默认记事应用"</string>
+ <string name="install_app" msgid="5066668100199613936">"安装应用"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index f911d5c2c559..76153b60698a 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"面孔已經驗證"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"已確認"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"輕按 [確定] 以完成"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"已使用面孔解鎖"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"已使用面孔解鎖。按下即可繼續操作。"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"已識別面孔。按下即可繼續操作。"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"已識別面孔。按解鎖圖示即可繼續。"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"無法儲存,請再試一次。"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"無法儲存。"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"請至少使用 4 個字元"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"請使用少於 <xliff:g id="LENGTH">%1$d</xliff:g> 個字元"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"版本號碼"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"版本號碼已複製到剪貼簿。"</string>
<string name="basic_status" msgid="2315371112182658176">"開啟對話"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"瞭解詳情"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"詳情請瀏覽 <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"開啟「<xliff:g id="APPNAME">%1$s</xliff:g>」"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• 應用程式已完成設定"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• 已新增至少一張卡至「錢包」"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"選取筆記快速鍵所用的預設筆記應用程式"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"選取應用程式"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"輕觸並按住快速鍵"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"取消"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"優先模式已開啟"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"「Google 助理」感應功能已開啟"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"在「設定」中指定預設筆記應用程式"</string>
+ <string name="install_app" msgid="5066668100199613936">"安裝應用程式"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 01cd254a4198..a5e00c68c80e 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"臉孔驗證成功"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"確認完畢"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"輕觸 [確認] 完成驗證設定"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"裝置已透過你的臉解鎖"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"裝置已透過你的臉解鎖,按下即可繼續操作。"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"臉孔辨識完成,按下即可繼續操作。"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"臉孔辨識完成,按下「解鎖」圖示即可繼續操作。"</string>
@@ -361,7 +360,7 @@
<string name="keyguard_face_successful_unlock_alt1" msgid="5853906076353839628">"臉孔辨識完成"</string>
<string name="keyguard_retry" msgid="886802522584053523">"向上滑動即可重試"</string>
<string name="require_unlock_for_nfc" msgid="1305686454823018831">"如要使用 NFC,請先解鎖"</string>
- <string name="do_disclosure_generic" msgid="4896482821974707167">"這部裝置的擁有者為貴機構"</string>
+ <string name="do_disclosure_generic" msgid="4896482821974707167">"此裝置屬於貴機構"</string>
<string name="do_disclosure_with_name" msgid="2091641464065004091">"這部裝置的擁有者為「<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>」"</string>
<string name="do_financed_disclosure_with_name" msgid="6723004643314467864">"這是「<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>」提供的裝置"</string>
<string name="phone_hint" msgid="6682125338461375925">"滑動手機圖示即可啟用"</string>
@@ -434,7 +433,7 @@
<string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"這是「<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>」提供的裝置"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"這部裝置的擁有者為貴機構,並已透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」連線到網際網路"</string>
<string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"這部裝置的擁有者為「<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>」,並已透過「<xliff:g id="VPN_APP">%2$s</xliff:g>」連線到網際網路"</string>
- <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"這部裝置的擁有者為貴機構"</string>
+ <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"此裝置屬於貴機構"</string>
<string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"這部裝置的擁有者為「<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>」"</string>
<string name="quick_settings_disclosure_management_vpns" msgid="929181757984262902">"這部裝置的擁有者為貴機構,並已透過 VPN 連線到網際網路"</string>
<string name="quick_settings_disclosure_named_management_vpns" msgid="3312645578322079185">"這部裝置的擁有者為「<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>」,並已透過 VPN 連線到網際網路"</string>
@@ -455,7 +454,7 @@
<string name="monitoring_button_view_controls" msgid="8316440345340701117">"查看監護功能相關資訊"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"這部裝置的擁有者為「<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>」。\n\n你的 IT 管理員可以監控及管理與裝置相關聯的設定、公司系統權限、應用程式和資料,以及裝置的位置資訊。\n\n如要瞭解詳情,請與你的 IT 管理員聯絡。"</string>
<string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"「<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g>」或許可以存取這部裝置的相關資料、管理應用程式及變更裝置設定。\n\n如有任何疑問,請與「<xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>」聯絡。"</string>
- <string name="monitoring_description_management" msgid="4308879039175729014">"這部裝置的擁有者為貴機構。\n\n你的 IT 管理員可以監控及管理與裝置相關聯的設定、公司系統權限、應用程式和資料,以及裝置的位置資訊。\n\n如要瞭解詳情,請與你的 IT 管理員聯絡。"</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"此裝置屬於貴機構。\n\n你的 IT 管理員可以監控及管理與裝置相關聯的設定、公司系統權限、應用程式和資料,以及裝置的位置資訊。\n\n如要瞭解詳情,請與你的 IT 管理員聯絡。"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"貴機構已為這個裝置安裝憑證授權單位憑證。你的安全網路流量可能會受到監控或修改。"</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"貴機構已為你的工作資料夾安裝憑證授權單位憑證。你的安全網路流量可能會受到監控或修改。"</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"這個裝置已安裝憑證授權單位憑證。你的安全網路流量可能會受到監控或修改。"</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"無法儲存,請再試一次。"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"無法儲存。"</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"至少要有 4 個半形字元"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"不得超過 <xliff:g id="LENGTH">%1$d</xliff:g> 個半形字元"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"版本號碼"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"已將版本號碼複製到剪貼簿。"</string>
<string name="basic_status" msgid="2315371112182658176">"開放式對話"</string>
@@ -1125,12 +1123,18 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"瞭解詳情"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"如要瞭解詳情,請前往 <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"開啟「<xliff:g id="APPNAME">%1$s</xliff:g>」"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• 完成應用程式設定"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• 錢包中至少要有一張卡片"</string>
- <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>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"如要使用筆記捷徑,請選取預設的記事應用程式"</string>
+ <!-- no translation found for wallet_quick_affordance_unavailable_install_the_app (7298552910007208368) -->
+ <skip />
+ <!-- no translation found for wallet_quick_affordance_unavailable_configure_the_app (4387433357429873258) -->
+ <skip />
+ <!-- no translation found for qr_scanner_quick_affordance_unavailable_explanation (3049582306241150946) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_install_the_app (6187820778998446168) -->
+ <skip />
+ <!-- no translation found for home_quick_affordance_unavailable_configure_the_app (7953595390775156839) -->
+ <skip />
+ <!-- no translation found for notes_app_quick_affordance_unavailable_explanation (4796955161600178530) -->
+ <skip />
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"選取應用程式"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"按住快速鍵"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"取消"</string>
@@ -1159,4 +1163,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"優先模式已開啟"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Google 助理感知功能已開啟"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"在「設定」中指定預設記事應用程式"</string>
+ <string name="install_app" msgid="5066668100199613936">"安裝應用程式"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 3f89ba951753..74a688407b5a 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -142,8 +142,7 @@
<string name="biometric_dialog_face_icon_description_authenticated" msgid="2242167416140740920">"Ubuso bufakazelwe ubuqiniso"</string>
<string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Kuqinisekisiwe"</string>
<string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Thepha okuthi Qinisekisa ukuze uqedele"</string>
- <!-- no translation found for biometric_dialog_tap_confirm_with_face (2378151312221818694) -->
- <skip />
+ <string name="biometric_dialog_tap_confirm_with_face" msgid="2378151312221818694">"Vula ngobuso"</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_1" msgid="439152621640507113">"Vula ngobuso. Cindezela ukuze uqhubeke."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_2" msgid="8586608186457385108">"Ubuso buyaziwa. Cindezela ukuze uqhubeke."</string>
<string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Ubuso buyaziwa. Cindezela isithonjana sokuvula ukuze uqhubeke."</string>
@@ -1004,8 +1003,7 @@
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ayikwazi ukulondoloza. Zama futhi."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ayikwazi ukulondoloza."</string>
<string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Sebenzisa okungenani izinhlamvu ezi-4"</string>
- <!-- no translation found for media_output_broadcast_edit_hint_no_more_than_max (3923625800037673922) -->
- <skip />
+ <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Sebenzisa isinhlamvu ezimbalwa kuneziyi-<xliff:g id="LENGTH">%1$d</xliff:g>"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Yakha inombolo"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Yakha inombolo ekopishelwe kubhodi yokunamathisela."</string>
<string name="basic_status" msgid="2315371112182658176">"Vula ingxoxo"</string>
@@ -1125,12 +1123,12 @@
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Funda kabanzi"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Funda kabanzi ku-<xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Vula i-<xliff:g id="APPNAME">%1$s</xliff:g>"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• I-app isethiwe"</string>
- <string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• Okungenani ikhadi elilodwa lengeziwe ku-Wallet"</string>
- <string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction" msgid="5355839079232119791">"• Faka i-app yekhamera"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_1" msgid="8438311171750568633">"• I-app isethiwe"</string>
- <string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Okungenani idivayisi eyodwa iyatholakala"</string>
- <string name="keyguard_affordance_enablement_dialog_notes_app_instruction" msgid="2274489846095284167">"Khetha i-app yamanothi azenzakalelayo ukuze usebenzise isinqamuleli sokubhala amanothi"</string>
+ <string name="wallet_quick_affordance_unavailable_install_the_app" msgid="7298552910007208368">"Ukuze ungeze i-app ye-Wallet njengesinqamuleli, qinisekisa ukuthi i-app ifakiwe"</string>
+ <string name="wallet_quick_affordance_unavailable_configure_the_app" msgid="4387433357429873258">"Ukuze ungeze i-app ye-Wallet njengesinqamuleli, qinisekisa ukuthi okungenani ikhadi elilodwa lingeziwe"</string>
+ <string name="qr_scanner_quick_affordance_unavailable_explanation" msgid="3049582306241150946">"Ukuze ungeze Iskena sekhodi ye-QR njengesinqamuleli, qinisekisa ukuthi i-app yekhamera ifakiwe"</string>
+ <string name="home_quick_affordance_unavailable_install_the_app" msgid="6187820778998446168">"Ukuze ungeze i-App yasekhaya njengesinqamuleli, qinisekisa ukuthi i-app ifakiwe"</string>
+ <string name="home_quick_affordance_unavailable_configure_the_app" msgid="7953595390775156839">"• Okungenani idivayisi eyodwa iyatholakala"</string>
+ <string name="notes_app_quick_affordance_unavailable_explanation" msgid="4796955161600178530">"Khetha i-app yamanothi azenzakalelayo ukuze usebenzise isinqamuleli sokubhala amanothi"</string>
<string name="keyguard_affordance_enablement_dialog_notes_app_action" msgid="6821710209675089470">"Khetha i-app"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Thinta futhi ubambe isinqamuleli"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Khansela"</string>
@@ -1159,4 +1157,5 @@
<string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Imodi ebalulekile ivuliwe"</string>
<string name="assistant_attention_content_description" msgid="6830215897604642875">"Ukunaka kwe-Assistant kuvuliwe"</string>
<string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Setha i-app yamanothi azenzakalelayo Kumsethingi"</string>
+ <string name="install_app" msgid="5066668100199613936">"Faka i-app"</string>
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt
index c5979cc50c3c..7a8c82cee32a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt
@@ -65,8 +65,8 @@ class UnfoldConstantTranslateAnimator(
} else {
1
}
- viewsToTranslate.forEach { (view, direction) ->
- view.get()?.translationX = xTrans * direction.multiplier * rtlMultiplier
+ viewsToTranslate.forEach { (view, direction, func) ->
+ view.get()?.let { func(it, xTrans * direction.multiplier * rtlMultiplier) }
}
}
@@ -77,7 +77,7 @@ class UnfoldConstantTranslateAnimator(
.filter { it.shouldBeAnimated() }
.mapNotNull {
parent.findViewById<View>(it.viewId)?.let { view ->
- ViewToTranslate(WeakReference(view), it.direction)
+ ViewToTranslate(WeakReference(view), it.direction, it.translateFunc)
}
}
.toList()
@@ -91,14 +91,19 @@ class UnfoldConstantTranslateAnimator(
data class ViewIdToTranslate(
val viewId: Int,
val direction: Direction,
- val shouldBeAnimated: () -> Boolean = { true }
+ val shouldBeAnimated: () -> Boolean = { true },
+ val translateFunc: (View, Float) -> Unit = { view, value -> view.translationX = value },
)
/**
* Represents a view whose animation process is in-progress. It should be immutable because the
* started animation should be completed.
*/
- private data class ViewToTranslate(val view: WeakReference<View>, val direction: Direction)
+ private data class ViewToTranslate(
+ val view: WeakReference<View>,
+ val direction: Direction,
+ val translateFunc: (View, Float) -> Unit,
+ )
/** Direction of the animation. */
enum class Direction(val multiplier: Float) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index d9d64ad5a893..376e27c6cf44 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -1,8 +1,14 @@
package com.android.keyguard;
import static android.view.View.ALPHA;
+import static android.view.View.SCALE_X;
+import static android.view.View.SCALE_Y;
import static android.view.View.TRANSLATION_Y;
+import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_X_CLOCK_DESIGN;
+import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_Y_CLOCK_DESIGN;
+import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_Y_CLOCK_SIZE;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -17,6 +23,7 @@ import android.widget.RelativeLayout;
import androidx.annotation.IntDef;
import androidx.annotation.VisibleForTesting;
+import androidx.core.content.res.ResourcesCompat;
import com.android.app.animation.Interpolators;
import com.android.keyguard.dagger.KeyguardStatusViewScope;
@@ -44,6 +51,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
private static final long STATUS_AREA_START_DELAY_MILLIS = 0;
private static final long STATUS_AREA_MOVE_UP_MILLIS = 967;
private static final long STATUS_AREA_MOVE_DOWN_MILLIS = 467;
+ private static final float SMARTSPACE_TRANSLATION_CENTER_MULTIPLIER = 1.4f;
@IntDef({LARGE, SMALL})
@Retention(RetentionPolicy.SOURCE)
@@ -88,14 +96,18 @@ public class KeyguardClockSwitch extends RelativeLayout {
private KeyguardClockFrame mLargeClockFrame;
private ClockController mClock;
- private View mStatusArea;
+ private KeyguardStatusAreaView mStatusArea;
private int mSmartspaceTopOffset;
+ private float mWeatherClockSmartspaceScaling = 1f;
+ private int mWeatherClockSmartspaceTranslateX = 0;
+ private int mWeatherClockSmartspaceTranslateY = 0;
private int mDrawAlpha = 255;
/**
* Maintain state so that a newly connected plugin can be initialized.
*/
private float mDarkAmount;
+ private boolean mSplitShadeCentered = false;
/**
* Indicates which clock is currently displayed - should be one of {@link ClockSize}.
@@ -105,7 +117,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
@VisibleForTesting AnimatorSet mClockInAnim = null;
@VisibleForTesting AnimatorSet mClockOutAnim = null;
- private AnimatorSet mStatusAreaAnim = null;
+ @VisibleForTesting AnimatorSet mStatusAreaAnim = null;
private int mClockSwitchYAmount;
@VisibleForTesting boolean mChildrenAreLaidOut = false;
@@ -117,13 +129,30 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
/**
- * Apply dp changes on font/scale change
+ * Apply dp changes on configuration change
*/
- public void onDensityOrFontScaleChanged() {
+ public void onConfigChanged() {
mClockSwitchYAmount = mContext.getResources().getDimensionPixelSize(
R.dimen.keyguard_clock_switch_y_shift);
mSmartspaceTopOffset = mContext.getResources().getDimensionPixelSize(
R.dimen.keyguard_smartspace_top_offset);
+ mWeatherClockSmartspaceScaling = ResourcesCompat.getFloat(
+ mContext.getResources(), R.dimen.weather_clock_smartspace_scale);
+ mWeatherClockSmartspaceTranslateX = mContext.getResources().getDimensionPixelSize(
+ R.dimen.weather_clock_smartspace_translateX);
+ mWeatherClockSmartspaceTranslateY = mContext.getResources().getDimensionPixelSize(
+ R.dimen.weather_clock_smartspace_translateY);
+ updateStatusArea(/* animate= */false);
+ }
+
+ /**
+ * Enable or disable split shade specific positioning
+ */
+ public void setSplitShadeCentered(boolean splitShadeCentered) {
+ if (mSplitShadeCentered != splitShadeCentered) {
+ mSplitShadeCentered = splitShadeCentered;
+ updateStatusArea(/* animate= */true);
+ }
}
@Override
@@ -134,7 +163,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
mLargeClockFrame = findViewById(R.id.lockscreen_clock_view_large);
mStatusArea = findViewById(R.id.keyguard_status_area);
- onDensityOrFontScaleChanged();
+ onConfigChanged();
}
@Override
@@ -182,6 +211,13 @@ public class KeyguardClockSwitch extends RelativeLayout {
mSmallClockFrame.addView(clock.getSmallClock().getView());
mLargeClockFrame.addView(clock.getLargeClock().getView());
updateClockTargetRegions();
+ updateStatusArea(/* animate= */false);
+ }
+
+ private void updateStatusArea(boolean animate) {
+ if (mDisplayedClockSize != null && mChildrenAreLaidOut) {
+ updateClockViews(mDisplayedClockSize == LARGE, animate);
+ }
}
void updateClockTargetRegions() {
@@ -230,13 +266,25 @@ public class KeyguardClockSwitch extends RelativeLayout {
mStatusAreaAnim = null;
View in, out;
- float statusAreaYTranslation, clockInYTranslation, clockOutYTranslation;
+ float statusAreaYTranslation, statusAreaClockScale = 1f;
+ float statusAreaClockTranslateX = 0f, statusAreaClockTranslateY = 0f;
+ float clockInYTranslation, clockOutYTranslation;
if (useLargeClock) {
out = mSmallClockFrame;
in = mLargeClockFrame;
if (indexOfChild(in) == -1) addView(in, 0);
statusAreaYTranslation = mSmallClockFrame.getTop() - mStatusArea.getTop()
+ mSmartspaceTopOffset;
+ // TODO: Load from clock config when less risky
+ if (mClock != null
+ && mClock.getLargeClock().getConfig().getHasCustomWeatherDataDisplay()) {
+ statusAreaClockScale = mWeatherClockSmartspaceScaling;
+ statusAreaClockTranslateX = mWeatherClockSmartspaceTranslateX;
+ statusAreaClockTranslateY = mWeatherClockSmartspaceTranslateY;
+ if (mSplitShadeCentered) {
+ statusAreaClockTranslateX *= SMARTSPACE_TRANSLATION_CENTER_MULTIPLIER;
+ }
+ }
clockInYTranslation = 0;
clockOutYTranslation = 0; // Small clock translation is handled with statusArea
} else {
@@ -258,7 +306,12 @@ public class KeyguardClockSwitch extends RelativeLayout {
in.setAlpha(1f);
in.setTranslationY(clockInYTranslation);
in.setVisibility(View.VISIBLE);
- mStatusArea.setTranslationY(statusAreaYTranslation);
+ mStatusArea.setScaleX(statusAreaClockScale);
+ mStatusArea.setScaleY(statusAreaClockScale);
+ mStatusArea.setTranslateXFromClockDesign(statusAreaClockTranslateX);
+ mStatusArea.setTranslateYFromClockDesign(statusAreaClockTranslateY);
+ mStatusArea.setTranslateYFromClockSize(statusAreaYTranslation);
+ mSmallClockFrame.setTranslationY(statusAreaYTranslation);
return;
}
@@ -295,8 +348,15 @@ public class KeyguardClockSwitch extends RelativeLayout {
useLargeClock ? STATUS_AREA_MOVE_UP_MILLIS : STATUS_AREA_MOVE_DOWN_MILLIS);
mStatusAreaAnim.setInterpolator(Interpolators.EMPHASIZED);
mStatusAreaAnim.playTogether(
- ObjectAnimator.ofFloat(mStatusArea, TRANSLATION_Y, statusAreaYTranslation),
- ObjectAnimator.ofFloat(mSmallClockFrame, TRANSLATION_Y, statusAreaYTranslation));
+ ObjectAnimator.ofFloat(mStatusArea, TRANSLATE_Y_CLOCK_SIZE.getProperty(),
+ statusAreaYTranslation),
+ ObjectAnimator.ofFloat(mSmallClockFrame, TRANSLATION_Y, statusAreaYTranslation),
+ ObjectAnimator.ofFloat(mStatusArea, SCALE_X, statusAreaClockScale),
+ ObjectAnimator.ofFloat(mStatusArea, SCALE_Y, statusAreaClockScale),
+ ObjectAnimator.ofFloat(mStatusArea, TRANSLATE_X_CLOCK_DESIGN.getProperty(),
+ statusAreaClockTranslateX),
+ ObjectAnimator.ofFloat(mStatusArea, TRANSLATE_Y_CLOCK_DESIGN.getProperty(),
+ statusAreaClockTranslateY));
mStatusAreaAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
mStatusAreaAnim = null;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 99e25745dda7..41c1eda42e83 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -330,10 +330,10 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
}
/**
- * Apply dp changes on font/scale change
+ * Apply dp changes on configuration change
*/
- public void onDensityOrFontScaleChanged() {
- mView.onDensityOrFontScaleChanged();
+ public void onConfigChanged() {
+ mView.onConfigChanged();
mKeyguardSmallClockTopMargin =
mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
mKeyguardLargeClockTopMargin =
@@ -344,6 +344,12 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
setDateWeatherVisibility();
}
+ /**
+ * Enable or disable split shade center specific positioning
+ */
+ public void setSplitShadeCentered(boolean splitShadeCentered) {
+ mView.setSplitShadeCentered(splitShadeCentered);
+ }
/**
* Set which clock should be displayed on the keyguard. The other one will be automatically
@@ -407,7 +413,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
scale, props, animate);
if (mStatusArea != null) {
- PropertyAnimator.setProperty(mStatusArea, AnimatableProperty.TRANSLATION_X,
+ PropertyAnimator.setProperty(mStatusArea, KeyguardStatusAreaView.TRANSLATE_X_AOD,
x, props, animate);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
index 0332c9f57136..363dd014beb6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
@@ -208,7 +208,7 @@ public class KeyguardMessageAreaController<T extends KeyguardMessageArea>
@Override
public void run() {
final View host = mHost.get();
- if (host != null) {
+ if (host != null && host.isVisibleToUser()) {
host.announceForAccessibility(mTextToAnnounce);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index b5e54209dab2..74b29a77aad4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -264,13 +264,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
*/
@Override
public void finish(boolean fromPrimaryAuth, int targetUserId) {
- if (!mKeyguardStateController.canDismissLockScreen() && !fromPrimaryAuth) {
- Log.e(TAG,
- "Tried to dismiss keyguard when lockscreen is not dismissible and user "
- + "was not authenticated with a primary security method "
- + "(pin/password/pattern).");
- return;
- }
// If there's a pending runnable because the user interacted with a widget
// and we're leaving keyguard, then run it.
boolean deferKeyguardDone = false;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusAreaView.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusAreaView.kt
new file mode 100644
index 000000000000..e7da2b977379
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusAreaView.kt
@@ -0,0 +1,118 @@
+package com.android.keyguard
+
+import android.content.Context
+import android.util.AttributeSet
+import android.util.FloatProperty
+import android.widget.LinearLayout
+import com.android.systemui.R
+import com.android.systemui.statusbar.notification.AnimatableProperty
+
+class KeyguardStatusAreaView(
+ context: Context,
+ attrs: AttributeSet? = null,
+) : LinearLayout(context, attrs) {
+ var translateXFromClockDesign = 0f
+ get() = field
+ set(value) {
+ field = value
+ translationX = translateXFromAod + translateXFromClockDesign + translateXFromUnfold
+ }
+
+ var translateXFromAod = 0f
+ get() = field
+ set(value) {
+ field = value
+ translationX = translateXFromAod + translateXFromClockDesign + translateXFromUnfold
+ }
+
+ var translateXFromUnfold = 0F
+ get() = field
+ set(value) {
+ field = value
+ translationX = translateXFromAod + translateXFromClockDesign + translateXFromUnfold
+ }
+
+ var translateYFromClockSize = 0f
+ get() = field
+ set(value) {
+ field = value
+ translationY = value + translateYFromClockDesign
+ }
+
+ var translateYFromClockDesign = 0f
+ get() = field
+ set(value) {
+ field = value
+ translationY = value + translateYFromClockSize
+ }
+
+ companion object {
+ @JvmField
+ val TRANSLATE_X_CLOCK_DESIGN =
+ AnimatableProperty.from(
+ object : FloatProperty<KeyguardStatusAreaView>("TranslateXClockDesign") {
+ override fun setValue(view: KeyguardStatusAreaView, value: Float) {
+ view.translateXFromClockDesign = value
+ }
+
+ override fun get(view: KeyguardStatusAreaView): Float {
+ return view.translateXFromClockDesign
+ }
+ },
+ R.id.translate_x_clock_design_animator_tag,
+ R.id.translate_x_clock_design_animator_start_tag,
+ R.id.translate_x_clock_design_animator_end_tag
+ )
+
+ @JvmField
+ val TRANSLATE_X_AOD =
+ AnimatableProperty.from(
+ object : FloatProperty<KeyguardStatusAreaView>("TranslateXAod") {
+ override fun setValue(view: KeyguardStatusAreaView, value: Float) {
+ view.translateXFromAod = value
+ }
+
+ override fun get(view: KeyguardStatusAreaView): Float {
+ return view.translateXFromAod
+ }
+ },
+ R.id.translate_x_aod_animator_tag,
+ R.id.translate_x_aod_animator_start_tag,
+ R.id.translate_x_aod_animator_end_tag
+ )
+
+ @JvmField
+ val TRANSLATE_Y_CLOCK_SIZE =
+ AnimatableProperty.from(
+ object : FloatProperty<KeyguardStatusAreaView>("TranslateYClockSize") {
+ override fun setValue(view: KeyguardStatusAreaView, value: Float) {
+ view.translateYFromClockSize = value
+ }
+
+ override fun get(view: KeyguardStatusAreaView): Float {
+ return view.translateYFromClockSize
+ }
+ },
+ R.id.translate_y_clock_size_animator_tag,
+ R.id.translate_y_clock_size_animator_start_tag,
+ R.id.translate_y_clock_size_animator_end_tag
+ )
+
+ @JvmField
+ val TRANSLATE_Y_CLOCK_DESIGN =
+ AnimatableProperty.from(
+ object : FloatProperty<KeyguardStatusAreaView>("TranslateYClockDesign") {
+ override fun setValue(view: KeyguardStatusAreaView, value: Float) {
+ view.translateYFromClockDesign = value
+ }
+
+ override fun get(view: KeyguardStatusAreaView): Float {
+ return view.translateYFromClockDesign
+ }
+ },
+ R.id.translate_y_clock_design_animator_tag,
+ R.id.translate_y_clock_design_animator_start_tag,
+ R.id.translate_y_clock_design_animator_end_tag
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 835cc13bebb1..00500d617766 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -24,6 +24,7 @@ import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_CL
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.transition.ChangeBounds;
import android.transition.Transition;
@@ -280,8 +281,8 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
}
@Override
- public void onDensityOrFontScaleChanged() {
- mKeyguardClockSwitchController.onDensityOrFontScaleChanged();
+ public void onConfigChanged(Configuration newConfig) {
+ mKeyguardClockSwitchController.onConfigChanged();
}
};
@@ -329,6 +330,7 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
boolean splitShadeEnabled,
boolean shouldBeCentered,
boolean animate) {
+ mKeyguardClockSwitchController.setSplitShadeCentered(splitShadeEnabled && shouldBeCentered);
if (mStatusViewCentered == shouldBeCentered) {
return;
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt
index edd150c293f6..ca64ae059093 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt
@@ -53,7 +53,10 @@ constructor(
UnfoldConstantTranslateAnimator(
viewsIdToTranslate =
setOf(
- ViewIdToTranslate(R.id.keyguard_status_area, START, filterKeyguard),
+ ViewIdToTranslate(R.id.keyguard_status_area, START, filterKeyguard,
+ { view, value ->
+ (view as? KeyguardStatusAreaView)?.translateXFromUnfold = value
+ }),
ViewIdToTranslate(
R.id.lockscreen_clock_view_large, START, filterKeyguardAndSplitShadeOnly),
ViewIdToTranslate(R.id.lockscreen_clock_view, START, filterKeyguard),
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 83c317fe3061..c7e817e5781a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -2090,6 +2090,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
state = TelephonyManager.SIM_STATE_PIN_REQUIRED;
} else if (Intent.SIM_LOCKED_ON_PUK.equals(lockedReason)) {
state = TelephonyManager.SIM_STATE_PUK_REQUIRED;
+ } else if (Intent.SIM_ABSENT_ON_PERM_DISABLED.equals(lockedReason)) {
+ state = TelephonyManager.SIM_STATE_PERM_DISABLED;
} else {
state = TelephonyManager.SIM_STATE_UNKNOWN;
}
@@ -3668,7 +3670,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mLogger.logSimState(subId, slotId, state);
boolean becameAbsent = false;
- if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)
+ && state != TelephonyManager.SIM_STATE_UNKNOWN) {
mLogger.w("invalid subId in handleSimStateChange()");
/* Only handle No SIM(ABSENT) and Card Error(CARD_IO_ERROR) due to
* handleServiceStateChange() handle other case */
@@ -3703,7 +3706,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
data.subId = subId;
data.slotId = slotId;
}
- if ((changed || becameAbsent) && state != TelephonyManager.SIM_STATE_UNKNOWN) {
+ if ((changed || becameAbsent) || state == TelephonyManager.SIM_STATE_UNKNOWN) {
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 7cedecc33a02..239a0cc01c45 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -326,7 +326,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
}
if (!Objects.equals(prevContentDescription, mView.getContentDescription())
- && mView.getContentDescription() != null) {
+ && mView.getContentDescription() != null && mView.isVisibleToUser()) {
mView.announceForAccessibility(mView.getContentDescription());
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
index 4557b3418e19..500910c910c3 100644
--- a/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
@@ -30,6 +30,7 @@ import android.transition.TransitionManager;
import android.transition.TransitionValues;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
@@ -51,12 +52,30 @@ public class PinShapeNonHintingView extends LinearLayout implements PinShapeInpu
private int mPosition = 0;
private final PinShapeAdapter mPinShapeAdapter;
private ValueAnimator mValueAnimator = ValueAnimator.ofFloat(1f, 0f);
+ private Rect mFirstChildVisibleRect = new Rect();
public PinShapeNonHintingView(Context context, AttributeSet attrs) {
super(context, attrs);
mPinShapeAdapter = new PinShapeAdapter(context);
}
@Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ if (getChildCount() > 0) {
+ View firstChild = getChildAt(0);
+ boolean isVisible = firstChild.getLocalVisibleRect(mFirstChildVisibleRect);
+ boolean clipped = mFirstChildVisibleRect.left > 0
+ || mFirstChildVisibleRect.right < firstChild.getWidth();
+ if (!isVisible || clipped) {
+ setGravity(Gravity.END | Gravity.CENTER_VERTICAL);
+ return;
+ }
+ }
+
+ setGravity(Gravity.CENTER);
+ }
+
+ @Override
public void append() {
int size = getResources().getDimensionPixelSize(R.dimen.password_shape_size);
ImageView pinDot = new ImageView(getContext());
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 8af92ce4bcb1..806d1aff3a30 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -34,6 +34,7 @@ import android.app.PendingIntent;
import android.content.res.Resources;
import android.graphics.RectF;
import android.os.Handler;
+import android.os.Trace;
import android.util.ArrayMap;
import android.util.Log;
import android.view.MotionEvent;
@@ -277,9 +278,11 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
// invalidate the view's own bounds all the way up the view hierarchy
public static void invalidateGlobalRegion(View view) {
+ Trace.beginSection("SwipeHelper.invalidateGlobalRegion");
invalidateGlobalRegion(
view,
new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()));
+ Trace.endSection();
}
// invalidate a rectangle relative to the view's coordinate system all the way up the view
@@ -492,7 +495,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
}
if (!mCancelled || wasRemoved) {
mCallback.onChildDismissed(animView);
- resetSwipeOfView(animView);
+ resetViewIfSwiping(animView);
}
if (endAction != null) {
endAction.accept(mCancelled);
@@ -547,7 +550,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
if (!cancelled) {
updateSwipeProgressFromOffset(animView, canBeDismissed);
- resetSwipeOfView(animView);
+ resetViewIfSwiping(animView);
// Clear the snapped view after success, assuming it's not being swiped now
if (animView == mTouchedView && !mIsSwiping) {
mTouchedView = null;
@@ -811,7 +814,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
return mIsSwiping ? mTouchedView : null;
}
- protected void resetSwipeOfView(View view) {
+ protected void resetViewIfSwiping(View view) {
if (getSwipedView() == view) {
resetSwipeState();
}
@@ -825,6 +828,12 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
resetSwipeStates(/* resetAll= */ true);
}
+ public void forceResetSwipeState(@NonNull View view) {
+ if (view.getTranslationX() == 0) return;
+ setTranslation(view, 0);
+ updateSwipeProgressFromOffset(view, /* dismissable= */ true, 0);
+ }
+
/** This method resets the swipe state, and if `resetAll` is true, also resets the snap state */
private void resetSwipeStates(boolean resetAll) {
final View touchedView = mTouchedView;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index c5e7e0d99286..ee046c27d72e 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -34,13 +34,11 @@ import com.android.systemui.complication.ComplicationLayoutParams.POSITION_TOP
import com.android.systemui.complication.ComplicationLayoutParams.Position
import com.android.systemui.dreams.dagger.DreamOverlayModule
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel
-import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel.Companion.DREAM_ANIMATION_DURATION
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.statusbar.BlurUtils
import com.android.systemui.statusbar.CrossFadeHelper
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
-import com.android.systemui.util.concurrency.DelayableExecutor
import javax.inject.Inject
import javax.inject.Named
import kotlinx.coroutines.flow.MutableStateFlow
@@ -129,6 +127,12 @@ constructor(
)
}
}
+
+ launch {
+ transitionViewModel.transitionEnded.collect { _ ->
+ mOverlayStateController.setExitAnimationsRunning(false)
+ }
+ }
}
configController.removeCallback(configCallback)
@@ -251,9 +255,9 @@ constructor(
}
/** Starts the dream content and dream overlay exit animations. */
- fun wakeUp(doneCallback: Runnable, executor: DelayableExecutor) {
+ fun wakeUp() {
cancelAnimations()
- executor.executeDelayed(doneCallback, DREAM_ANIMATION_DURATION.inWholeMilliseconds)
+ mOverlayStateController.setExitAnimationsRunning(true)
}
/** Cancels the dream content and dream overlay animations, if they're currently running. */
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
index c22019e96d74..ff07bb620a44 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
@@ -31,8 +31,6 @@ import android.util.MathUtils;
import android.view.View;
import android.view.ViewGroup;
-import androidx.annotation.NonNull;
-
import com.android.app.animation.Interpolators;
import com.android.dream.lowlight.LowLightTransitionCoordinator;
import com.android.systemui.R;
@@ -46,7 +44,6 @@ import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInt
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.statusbar.BlurUtils;
import com.android.systemui.util.ViewController;
-import com.android.systemui.util.concurrency.DelayableExecutor;
import java.util.Arrays;
@@ -302,20 +299,15 @@ public class DreamOverlayContainerViewController extends
/**
* Handle the dream waking up and run any necessary animations.
- *
- * @param onAnimationEnd Callback to trigger once animations are finished.
- * @param callbackExecutor Executor to execute the callback on.
*/
- public void wakeUp(@NonNull Runnable onAnimationEnd,
- @NonNull DelayableExecutor callbackExecutor) {
+ public void wakeUp() {
// When swiping causes wakeup, do not run any animations as the dream should exit as soon
// as possible.
if (mWakingUpFromSwipe) {
- onAnimationEnd.run();
return;
}
- mDreamOverlayAnimationsController.wakeUp(onAnimationEnd, callbackExecutor);
+ mDreamOverlayAnimationsController.wakeUp();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index 1da7900e985b..d509015bde1d 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -116,6 +116,17 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
}
};
+ private final DreamOverlayStateController.Callback mExitAnimationFinishedCallback =
+ new DreamOverlayStateController.Callback() {
+ @Override
+ public void onStateChanged() {
+ if (!mStateController.areExitAnimationsRunning()) {
+ mStateController.removeCallback(mExitAnimationFinishedCallback);
+ resetCurrentDreamOverlayLocked();
+ }
+ }
+ };
+
private final DreamOverlayStateController mStateController;
@VisibleForTesting
@@ -257,10 +268,10 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
}
@Override
- public void onWakeUp(@NonNull Runnable onCompletedCallback) {
+ public void onWakeUp() {
if (mDreamOverlayContainerViewController != null) {
mDreamOverlayCallbackController.onWakeUp();
- mDreamOverlayContainerViewController.wakeUp(onCompletedCallback, mExecutor);
+ mDreamOverlayContainerViewController.wakeUp();
}
}
@@ -329,6 +340,11 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
}
private void resetCurrentDreamOverlayLocked() {
+ if (mStateController.areExitAnimationsRunning()) {
+ mStateController.addCallback(mExitAnimationFinishedCallback);
+ return;
+ }
+
if (mStarted && mWindow != null) {
try {
mWindowManager.removeView(mWindow.getDecorView());
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 1fbbe1cce480..da7bf4e7bae8 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -93,7 +93,7 @@ object Flags {
// TODO(b/277338665): Tracking Bug
@JvmField
val NOTIFICATION_SHELF_REFACTOR =
- unreleasedFlag(271161129, "notification_shelf_refactor", teamfood = true)
+ unreleasedFlag(271161129, "notification_shelf_refactor")
@JvmField
val ANIMATED_NOTIFICATION_SHADE_INSETS =
@@ -263,6 +263,11 @@ object Flags {
@JvmField
val FP_LISTEN_OCCLUDING_APPS = unreleasedFlag(237, "fp_listen_occluding_apps")
+ /** Flag meant to guard the talkback fix for the KeyguardIndicationTextView */
+ // TODO(b/286563884): Tracking bug
+ @JvmField
+ val KEYGUARD_TALKBACK_FIX = unreleasedFlag(238, "keyguard_talkback_fix")
+
// 300 - power menu
// TODO(b/254512600): Tracking Bug
@JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite")
@@ -743,4 +748,10 @@ object Flags {
@JvmField
val BIGPICTURE_NOTIFICATION_LAZY_LOADING =
unreleasedFlag(283447257, "bigpicture_notification_lazy_loading")
+
+ // 2900 - CentralSurfaces-related flags
+
+ // TODO(b/285174336): Tracking Bug
+ @JvmField
+ val USE_REPOS_FOR_BOUNCER_SHOWING = unreleasedFlag(2900, "use_repos_for_bouncer_showing")
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
index 8c0cfba5aea8..aa4c88af4690 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
@@ -16,6 +16,8 @@
package com.android.systemui.keyguard;
+import static com.android.systemui.flags.Flags.KEYGUARD_TALKBACK_FIX;
+
import android.annotation.Nullable;
import android.content.res.ColorStateList;
import android.graphics.Color;
@@ -28,6 +30,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.keyguard.logging.KeyguardLogger;
import com.android.systemui.Dumpable;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
@@ -75,6 +78,7 @@ public class KeyguardIndicationRotateTextViewController extends
// Executor that will show the next message after a delay
private final DelayableExecutor mExecutor;
+ private final FeatureFlags mFeatureFlags;
@VisibleForTesting
@Nullable ShowNextIndication mShowNextIndicationRunnable;
@@ -91,7 +95,8 @@ public class KeyguardIndicationRotateTextViewController extends
KeyguardIndicationTextView view,
@Main DelayableExecutor executor,
StatusBarStateController statusBarStateController,
- KeyguardLogger logger
+ KeyguardLogger logger,
+ FeatureFlags flags
) {
super(view);
mMaxAlpha = view.getAlpha();
@@ -100,12 +105,14 @@ public class KeyguardIndicationRotateTextViewController extends
? mView.getTextColors() : ColorStateList.valueOf(Color.WHITE);
mStatusBarStateController = statusBarStateController;
mLogger = logger;
+ mFeatureFlags = flags;
init();
}
@Override
protected void onViewAttached() {
mStatusBarStateController.addCallback(mStatusBarStateListener);
+ mView.setAlwaysAnnounceEnabled(mFeatureFlags.isEnabled(KEYGUARD_TALKBACK_FIX));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 94227bccfced..a2c940bd298c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -187,10 +187,10 @@ public class KeyguardService extends Service {
final IRemoteAnimationRunner runner, final boolean lockscreenLiveWallpaperEnabled) {
return new IRemoteTransition.Stub() {
+ @GuardedBy("mLeashMap")
private final ArrayMap<SurfaceControl, SurfaceControl> mLeashMap = new ArrayMap<>();
private final CounterRotator mCounterRotator = new CounterRotator();
-
@GuardedBy("mLeashMap")
private IRemoteTransitionFinishedCallback mFinishCallback = null;
@@ -200,40 +200,38 @@ public class KeyguardService extends Service {
throws RemoteException {
Slog.d(TAG, "Starts IRemoteAnimationRunner: info=" + info);
+ final RemoteAnimationTarget[] apps;
+ final RemoteAnimationTarget[] wallpapers;
+ final RemoteAnimationTarget[] nonApps = new RemoteAnimationTarget[0];
synchronized (mLeashMap) {
- final RemoteAnimationTarget[] apps =
- wrap(info, false /* wallpapers */, t, mLeashMap, mCounterRotator);
- final RemoteAnimationTarget[] wallpapers =
- wrap(info, true /* wallpapers */, t, mLeashMap, mCounterRotator);
- final RemoteAnimationTarget[] nonApps = new RemoteAnimationTarget[0];
-
- // Set alpha back to 1 for the independent changes because we will be animating
- // children instead.
- for (TransitionInfo.Change chg : info.getChanges()) {
- if (TransitionInfo.isIndependent(chg, info)) {
- t.setAlpha(chg.getLeash(), 1.f);
- }
- }
- initAlphaForAnimationTargets(t, apps);
- if (lockscreenLiveWallpaperEnabled) {
- initAlphaForAnimationTargets(t, wallpapers);
- }
- t.apply();
+ apps = wrap(info, false /* wallpapers */, t, mLeashMap, mCounterRotator);
+ wallpapers = wrap(info, true /* wallpapers */, t, mLeashMap, mCounterRotator);
mFinishCallback = finishCallback;
- runner.onAnimationStart(
- getTransitionOldType(info.getType(), info.getFlags(), apps),
- apps, wallpapers, nonApps,
- new IRemoteAnimationFinishedCallback.Stub() {
- @Override
- public void onAnimationFinished() throws RemoteException {
- synchronized (mLeashMap) {
- Slog.d(TAG, "Finish IRemoteAnimationRunner.");
- finish();
- }
- }
- }
- );
}
+
+ // Set alpha back to 1 for the independent changes because we will be animating
+ // children instead.
+ for (TransitionInfo.Change chg : info.getChanges()) {
+ if (TransitionInfo.isIndependent(chg, info)) {
+ t.setAlpha(chg.getLeash(), 1.f);
+ }
+ }
+ initAlphaForAnimationTargets(t, apps);
+ if (lockscreenLiveWallpaperEnabled) {
+ initAlphaForAnimationTargets(t, wallpapers);
+ }
+ t.apply();
+
+ runner.onAnimationStart(
+ getTransitionOldType(info.getType(), info.getFlags(), apps),
+ apps, wallpapers, nonApps,
+ new IRemoteAnimationFinishedCallback.Stub() {
+ @Override
+ public void onAnimationFinished() throws RemoteException {
+ Slog.d(TAG, "Finish IRemoteAnimationRunner.");
+ finish();
+ }
+ });
}
public void mergeAnimation(IBinder candidateTransition, TransitionInfo candidateInfo,
@@ -247,10 +245,8 @@ public class KeyguardService extends Service {
}
try {
- synchronized (mLeashMap) {
- runner.onAnimationCancelled();
- finish();
- }
+ runner.onAnimationCancelled();
+ finish();
} catch (RemoteException e) {
// nothing, we'll just let it finish on its own I guess.
}
@@ -264,18 +260,22 @@ public class KeyguardService extends Service {
}
}
- @GuardedBy("mLeashMap")
private void finish() throws RemoteException {
+ IRemoteTransitionFinishedCallback finishCallback = null;
SurfaceControl.Transaction finishTransaction = null;
- if (mCounterRotator.getSurface() != null
- && mCounterRotator.getSurface().isValid()) {
- finishTransaction = new SurfaceControl.Transaction();
- mCounterRotator.cleanUp(finishTransaction);
+
+ synchronized (mLeashMap) {
+ if (mCounterRotator.getSurface() != null
+ && mCounterRotator.getSurface().isValid()) {
+ finishTransaction = new SurfaceControl.Transaction();
+ mCounterRotator.cleanUp(finishTransaction);
+ }
+ mLeashMap.clear();
+ finishCallback = mFinishCallback;
+ mFinishCallback = null;
}
- mLeashMap.clear();
- final IRemoteTransitionFinishedCallback finishCallback = mFinishCallback;
+
if (finishCallback != null) {
- mFinishCallback = null;
finishCallback.onTransitionFinished(null /* wct */, finishTransaction);
} else if (finishTransaction != null) {
finishTransaction.apply();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 6948c8d4e563..97244c8fa313 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -18,6 +18,7 @@ package com.android.systemui.keyguard;
import static android.app.StatusBarManager.SESSION_KEYGUARD;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT;
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
@@ -34,8 +35,8 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STR
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE;
import static com.android.systemui.DejankUtils.whitelistIpcs;
-import static com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel.LOCKSCREEN_ANIMATION_DURATION_MS;
import static com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel.DREAMING_ANIMATION_DURATION_MS;
+import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -87,9 +88,11 @@ import android.util.SparseIntArray;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl.Transaction;
import android.view.SyncRtSurfaceTransactionApplier;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewRootImpl;
import android.view.WindowManager;
import android.view.WindowManagerPolicyConstants;
import android.view.animation.Animation;
@@ -127,12 +130,14 @@ import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.LaunchAnimator;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.dagger.KeyguardModule;
+import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -162,6 +167,9 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+import kotlinx.coroutines.CoroutineDispatcher;
/**
* Mediates requests related to the keyguard. This includes queries about the
@@ -435,11 +443,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
private final int mDreamOpenAnimationDuration;
/**
- * The duration in milliseconds of the dream close animation.
- */
- private final int mDreamCloseAnimationDuration;
-
- /**
* The animation used for hiding keyguard. This is used to fetch the animation timings if
* WindowManager is not providing us with them.
*/
@@ -697,6 +700,9 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
}
}
break;
+ case TelephonyManager.SIM_STATE_UNKNOWN:
+ mPendingPinLock = false;
+ break;
default:
if (DEBUG_SIM_STATES) Log.v(TAG, "Unspecific state: " + simState);
break;
@@ -1125,49 +1131,57 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
return;
}
- final RemoteAnimationTarget primary = apps[0];
+ mRemoteAnimationTarget = apps[0];
final boolean isDream = (apps[0].taskInfo != null
&& apps[0].taskInfo.topActivityType
== WindowConfiguration.ACTIVITY_TYPE_DREAM);
- final SyncRtSurfaceTransactionApplier applier =
- new SyncRtSurfaceTransactionApplier(
- mKeyguardViewControllerLazy.get().getViewRootImpl().getView());
+ final View localView = mKeyguardViewControllerLazy.get()
+ .getViewRootImpl().getView();
+ final SyncRtSurfaceTransactionApplier applier =
+ new SyncRtSurfaceTransactionApplier(localView);
mContext.getMainExecutor().execute(() -> {
if (mUnoccludeAnimator != null) {
mUnoccludeAnimator.cancel();
}
+ if (isDream) {
+ initAlphaForAnimationTargets(wallpapers);
+ getRemoteSurfaceAlphaApplier().accept(0.0f);
+ mDreamingToLockscreenTransitionViewModel.get()
+ .startTransition();
+ return;
+ }
+
mUnoccludeAnimator = ValueAnimator.ofFloat(1f, 0f);
- mUnoccludeAnimator.setDuration(isDream ? mDreamCloseAnimationDuration
- : UNOCCLUDE_ANIMATION_DURATION);
+ mUnoccludeAnimator.setDuration(UNOCCLUDE_ANIMATION_DURATION);
mUnoccludeAnimator.setInterpolator(Interpolators.TOUCH_RESPONSE);
mUnoccludeAnimator.addUpdateListener(
animation -> {
final float animatedValue =
(float) animation.getAnimatedValue();
- final float surfaceHeight = primary.screenSpaceBounds.height();
+ final float surfaceHeight =
+ mRemoteAnimationTarget.screenSpaceBounds.height();
// Fade for all types of activities.
SyncRtSurfaceTransactionApplier.SurfaceParams.Builder
paramsBuilder =
new SyncRtSurfaceTransactionApplier.SurfaceParams
- .Builder(primary.leash)
+ .Builder(mRemoteAnimationTarget.leash)
.withAlpha(animatedValue);
- // Set translate if the occluding activity isn't Dream.
- if (!isDream) {
- mUnoccludeMatrix.setTranslate(
- 0f,
- (1f - animatedValue)
- * surfaceHeight
- * UNOCCLUDE_TRANSLATE_DISTANCE_PERCENT);
-
- paramsBuilder.withMatrix(mUnoccludeMatrix).withCornerRadius(
- mWindowCornerRadius);
- }
+
+ mUnoccludeMatrix.setTranslate(
+ 0f,
+ (1f - animatedValue)
+ * surfaceHeight
+ * UNOCCLUDE_TRANSLATE_DISTANCE_PERCENT);
+
+ paramsBuilder.withMatrix(mUnoccludeMatrix).withCornerRadius(
+ mWindowCornerRadius);
+
applier.scheduleApply(paramsBuilder.build());
});
mUnoccludeAnimator.addListener(new AnimatorListenerAdapter() {
@@ -1189,6 +1203,34 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
}
};
+ private static void initAlphaForAnimationTargets(
+ @android.annotation.NonNull RemoteAnimationTarget[] targets
+ ) {
+ for (RemoteAnimationTarget target : targets) {
+ if (target.mode != MODE_OPENING) continue;
+
+ try (Transaction t = new Transaction()) {
+ t.setAlpha(target.leash, 1.f);
+ t.apply();
+ }
+ }
+ }
+
+ private Consumer<Float> getRemoteSurfaceAlphaApplier() {
+ return (Float alpha) -> {
+ if (mRemoteAnimationTarget == null) return;
+ final View localView = mKeyguardViewControllerLazy.get().getViewRootImpl().getView();
+ final SyncRtSurfaceTransactionApplier applier =
+ new SyncRtSurfaceTransactionApplier(localView);
+ SyncRtSurfaceTransactionApplier.SurfaceParams
+ params =
+ new SyncRtSurfaceTransactionApplier.SurfaceParams
+ .Builder(mRemoteAnimationTarget.leash)
+ .withAlpha(alpha).build();
+ applier.scheduleApply(params);
+ };
+ }
+
private DeviceConfigProxy mDeviceConfig;
private DozeParameters mDozeParameters;
@@ -1218,6 +1260,10 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
private FeatureFlags mFeatureFlags;
private final UiEventLogger mUiEventLogger;
private final SessionTracker mSessionTracker;
+ private final CoroutineDispatcher mMainDispatcher;
+ private final Lazy<DreamingToLockscreenTransitionViewModel>
+ mDreamingToLockscreenTransitionViewModel;
+ private RemoteAnimationTarget mRemoteAnimationTarget;
/**
* Injected constructor. See {@link KeyguardModule}.
@@ -1253,7 +1299,9 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
Lazy<NotificationShadeWindowController> notificationShadeWindowControllerLazy,
Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
Lazy<ScrimController> scrimControllerLazy,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags,
+ @Main CoroutineDispatcher mainDispatcher,
+ Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel) {
mContext = context;
mUserTracker = userTracker;
mFalsingCollector = falsingCollector;
@@ -1308,11 +1356,13 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
mWindowCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context);
mDreamOpenAnimationDuration = (int) DREAMING_ANIMATION_DURATION_MS;
- mDreamCloseAnimationDuration = (int) LOCKSCREEN_ANIMATION_DURATION_MS;
mFeatureFlags = featureFlags;
mUiEventLogger = uiEventLogger;
mSessionTracker = sessionTracker;
+
+ mMainDispatcher = mainDispatcher;
+ mDreamingToLockscreenTransitionViewModel = dreamingToLockscreenTransitionViewModel;
}
public void userActivity() {
@@ -1431,6 +1481,13 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
mUpdateMonitor.registerCallback(mUpdateCallback);
adjustStatusBarLocked();
mDreamOverlayStateController.addCallback(mDreamOverlayStateCallback);
+
+ ViewRootImpl viewRootImpl = mKeyguardViewControllerLazy.get().getViewRootImpl();
+ if (viewRootImpl != null) {
+ collectFlow(viewRootImpl.getView(),
+ mDreamingToLockscreenTransitionViewModel.get().getDreamOverlayAlpha(),
+ getRemoteSurfaceAlphaApplier(), mMainDispatcher);
+ }
}
// Most services aren't available until the system reaches the ready state, so we
// send it here when the device first boots.
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index d7c039d9b519..ab79c8067cd5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -37,6 +37,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.classifier.FalsingModule;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dump.DumpManager;
@@ -51,6 +52,7 @@ import com.android.systemui.keyguard.domain.interactor.StartKeyguardTransitionMo
import com.android.systemui.keyguard.domain.quickaffordance.KeyguardQuickAffordanceModule;
import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger;
import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLoggerImpl;
+import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.settings.UserTracker;
@@ -72,6 +74,8 @@ import dagger.Provides;
import java.util.concurrent.Executor;
+import kotlinx.coroutines.CoroutineDispatcher;
+
/**
* Dagger Module providing keyguard.
*/
@@ -128,7 +132,9 @@ public class KeyguardModule {
Lazy<NotificationShadeWindowController> notificationShadeWindowController,
Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
Lazy<ScrimController> scrimControllerLazy,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags,
+ @Main CoroutineDispatcher mainDispatcher,
+ Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel) {
return new KeyguardViewMediator(
context,
uiEventLogger,
@@ -162,7 +168,9 @@ public class KeyguardModule {
notificationShadeWindowController,
activityLaunchAnimator,
scrimControllerLazy,
- featureFlags);
+ featureFlags,
+ mainDispatcher,
+ dreamingToLockscreenTransitionViewModel);
}
/** */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
index 100bc596103d..358ab0147049 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
@@ -160,35 +160,28 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
// An animator was provided, so use it to run the transition
animator.setFloatValues(startingValue, 1f)
animator.duration = ((1f - startingValue) * animator.duration).toLong()
- val updateListener =
- object : AnimatorUpdateListener {
- override fun onAnimationUpdate(animation: ValueAnimator) {
- emitTransition(
- TransitionStep(
- info,
- (animation.getAnimatedValue() as Float),
- TransitionState.RUNNING
- )
- )
- }
- }
+ val updateListener = AnimatorUpdateListener { animation ->
+ emitTransition(
+ TransitionStep(
+ info,
+ (animation.animatedValue as Float),
+ TransitionState.RUNNING
+ )
+ )
+ }
val adapter =
object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator) {
emitTransition(TransitionStep(info, startingValue, TransitionState.STARTED))
}
override fun onAnimationCancel(animation: Animator) {
- endAnimation(animation, lastStep.value, TransitionState.CANCELED)
+ endAnimation(lastStep.value, TransitionState.CANCELED)
}
override fun onAnimationEnd(animation: Animator) {
- endAnimation(animation, 1f, TransitionState.FINISHED)
+ endAnimation(1f, TransitionState.FINISHED)
}
- private fun endAnimation(
- animation: Animator,
- value: Float,
- state: TransitionState
- ) {
+ private fun endAnimation(value: Float, state: TransitionState) {
emitTransition(TransitionStep(info, value, state))
animator.removeListener(this)
animator.removeUpdateListener(updateListener)
@@ -201,7 +194,7 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
return@startTransition null
}
?: run {
- emitTransition(TransitionStep(info, 0f, TransitionState.STARTED))
+ emitTransition(TransitionStep(info, startingValue, TransitionState.STARTED))
// No animator, so it's manual. Provide a mechanism to callback
updateTransitionId = UUID.randomUUID()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
index 323fc317ebe1..ee2c2df41624 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
@@ -52,7 +52,7 @@ constructor(
.sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
.collect { (wakefulnessModel, lastStartedTransition) ->
if (
- wakefulnessModel.isStartingToWake() &&
+ wakefulnessModel.isStartingToWakeOrAwake() &&
lastStartedTransition.to == KeyguardState.DOZING
) {
keyguardTransitionRepository.startTransition(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
index 36c8eb186924..ccf4bc1588f6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
@@ -23,7 +23,6 @@ import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.DozeStateModel
-import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionInfo
import com.android.systemui.util.kotlin.Utils.Companion.toTriple
@@ -48,39 +47,23 @@ constructor(
) : TransitionInteractor(FromDreamingTransitionInteractor::class.simpleName!!) {
override fun start() {
- listenForDreamingToLockscreen()
listenForDreamingToOccluded()
listenForDreamingToGone()
listenForDreamingToDozing()
}
- private fun listenForDreamingToLockscreen() {
+ fun startToLockscreenTransition() {
scope.launch {
- keyguardInteractor.isAbleToDream
- .sample(
- combine(
- keyguardInteractor.dozeTransitionModel,
- keyguardTransitionInteractor.startedKeyguardTransitionStep,
- ::Pair
- ),
- ::toTriple
+ if (keyguardTransitionInteractor.startedKeyguardState.value == KeyguardState.DREAMING) {
+ keyguardTransitionRepository.startTransition(
+ TransitionInfo(
+ name,
+ KeyguardState.DREAMING,
+ KeyguardState.LOCKSCREEN,
+ getAnimator(TO_LOCKSCREEN_DURATION),
+ )
)
- .collect { (isDreaming, dozeTransitionModel, lastStartedTransition) ->
- if (
- !isDreaming &&
- isDozeOff(dozeTransitionModel.to) &&
- lastStartedTransition.to == KeyguardState.DREAMING
- ) {
- keyguardTransitionRepository.startTransition(
- TransitionInfo(
- name,
- KeyguardState.DREAMING,
- KeyguardState.LOCKSCREEN,
- getAnimator(TO_LOCKSCREEN_DURATION),
- )
- )
- }
- }
+ }
}
}
@@ -173,6 +156,6 @@ constructor(
companion object {
private val DEFAULT_DURATION = 500.milliseconds
- val TO_LOCKSCREEN_DURATION = 1183.milliseconds
+ val TO_LOCKSCREEN_DURATION = 1167.milliseconds
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 3cf9a9ec5a9c..c44435ee2be0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -111,7 +111,7 @@ constructor(
isDreaming && isDozeOff(dozeTransitionModel.to)
}
.sample(wakefulnessModel) { isAbleToDream, wakefulnessModel ->
- isAbleToDream && wakefulnessModel.isStartingToWake()
+ isAbleToDream && wakefulnessModel.isStartingToWakeOrAwake()
}
.flatMapLatest { isAbleToDream ->
flow {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
index da0ada160518..42f12f82d9a7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
@@ -18,6 +18,7 @@
package com.android.systemui.keyguard.domain.interactor
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
@@ -29,10 +30,14 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.stateIn
/** Encapsulates business-logic related to the keyguard transitions. */
@SysUISingleton
@@ -40,6 +45,7 @@ class KeyguardTransitionInteractor
@Inject
constructor(
private val repository: KeyguardTransitionRepository,
+ @Application val scope: CoroutineScope,
) {
/** (any)->GONE transition information */
val anyStateToGoneTransition: Flow<TransitionStep> =
@@ -108,10 +114,17 @@ constructor(
val finishedKeyguardTransitionStep: Flow<TransitionStep> =
repository.transitions.filter { step -> step.transitionState == TransitionState.FINISHED }
- /** The last completed [KeyguardState] transition */
- val finishedKeyguardState: Flow<KeyguardState> =
- finishedKeyguardTransitionStep.map { step -> step.to }
+ /** The destination state of the last started transition */
+ val startedKeyguardState: StateFlow<KeyguardState> =
+ startedKeyguardTransitionStep
+ .map { step -> step.to }
+ .stateIn(scope, SharingStarted.Eagerly, KeyguardState.OFF)
+ /** The last completed [KeyguardState] transition */
+ val finishedKeyguardState: StateFlow<KeyguardState> =
+ finishedKeyguardTransitionStep
+ .map { step -> step.to }
+ .stateIn(scope, SharingStarted.Eagerly, LOCKSCREEN)
/**
* The amount of transition into or out of the given [KeyguardState].
*
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt
index 7ca90ba63fda..52e15bece2df 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt
@@ -29,6 +29,8 @@ data class WakefulnessModel(
fun isStartingToSleepOrAsleep() = isStartingToSleep() || state == WakefulnessState.ASLEEP
+ fun isStartingToWakeOrAwake() = isStartingToWake() || state == WakefulnessState.AWAKE
+
fun isStartingToSleepFromPowerButton() =
isStartingToSleep() && lastWakeReason == WakeSleepReason.POWER_BUTTON
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
index db231092d7a5..1c2e85b0fd3a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
@@ -404,8 +404,7 @@ constructor(
val darkClockColor = wallpaperColorScheme?.accent2?.s600
/** Note that when [wallpaperColors] is null, isWallpaperDark is true. */
val isWallpaperDark: Boolean =
- (wallpaperColors?.colorHints?.and(WallpaperColors.HINT_SUPPORTS_DARK_TEXT)) !=
- WallpaperColors.HINT_SUPPORTS_DARK_TEXT
+ (wallpaperColors?.colorHints?.and(WallpaperColors.HINT_SUPPORTS_DARK_TEXT)) == 0
clock.events.onSeedColorChanged(
if (isWallpaperDark) lightClockColor else darkClockColor
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
index 2c9a9b3271e6..9ca4bd62b6fe 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
@@ -16,15 +16,17 @@
package com.android.systemui.keyguard.ui.viewmodel
-import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
-import com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE
+import com.android.app.animation.Interpolators.EMPHASIZED
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filter
/**
* Breaks down DREAMING->LOCKSCREEN transition into discrete steps for corresponding views to
@@ -34,22 +36,32 @@ import kotlinx.coroutines.flow.Flow
class DreamingToLockscreenTransitionViewModel
@Inject
constructor(
- private val interactor: KeyguardTransitionInteractor,
+ keyguardTransitionInteractor: KeyguardTransitionInteractor,
+ private val fromDreamingTransitionInteractor: FromDreamingTransitionInteractor
) {
+ fun startTransition() = fromDreamingTransitionInteractor.startToLockscreenTransition()
+
private val transitionAnimation =
KeyguardTransitionAnimationFlow(
transitionDuration = TO_LOCKSCREEN_DURATION,
- transitionFlow = interactor.dreamingToLockscreenTransition,
+ transitionFlow = keyguardTransitionInteractor.dreamingToLockscreenTransition,
)
+ val transitionEnded =
+ keyguardTransitionInteractor.dreamingToLockscreenTransition.filter { step ->
+ step.transitionState == TransitionState.FINISHED ||
+ step.transitionState == TransitionState.CANCELED
+ }
+
/** Dream overlay y-translation on exit */
fun dreamOverlayTranslationY(translatePx: Int): Flow<Float> {
return transitionAnimation.createFlow(
- duration = 600.milliseconds,
+ duration = TO_LOCKSCREEN_DURATION,
onStep = { it * translatePx },
- interpolator = EMPHASIZED_ACCELERATE,
+ interpolator = EMPHASIZED,
)
}
+
/** Dream overlay views alpha - fade out */
val dreamOverlayAlpha: Flow<Float> =
transitionAnimation.createFlow(
@@ -65,7 +77,7 @@ constructor(
// Reset on cancel or finish
onFinish = { 0f },
onCancel = { 0f },
- interpolator = EMPHASIZED_DECELERATE,
+ interpolator = EMPHASIZED,
)
}
@@ -76,12 +88,4 @@ constructor(
duration = 250.milliseconds,
onStep = { it },
)
-
- companion object {
- /* Length of time before ending the dream activity, in order to start unoccluding */
- val DREAM_ANIMATION_DURATION = 250.milliseconds
- @JvmField
- val LOCKSCREEN_ANIMATION_DURATION_MS =
- (TO_LOCKSCREEN_DURATION - DREAM_ANIMATION_DURATION).inWholeMilliseconds
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
index c6187dde035b..a3ae67d906bd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
@@ -33,7 +33,7 @@ import kotlinx.coroutines.flow.Flow
class LockscreenToDreamingTransitionViewModel
@Inject
constructor(
- private val interactor: KeyguardTransitionInteractor,
+ interactor: KeyguardTransitionInteractor,
) {
private val transitionAnimation =
KeyguardTransitionAnimationFlow(
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 14386c1c0fd6..0819d0d36e9a 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
@@ -248,9 +248,9 @@ public class MediaControlPanel {
private final FeatureFlags mFeatureFlags;
private final GlobalSettings mGlobalSettings;
- // TODO(b/281032715): Consider making this as a final variable. For now having a null check
- // due to unit test failure. (Perhaps missing some setup)
private TurbulenceNoiseAnimationConfig mTurbulenceNoiseAnimationConfig;
+ private boolean mWasPlaying = false;
+ private boolean mButtonClicked = false;
private ContentObserver mAnimationScaleObserver = new ContentObserver(null) {
@Override
@@ -582,6 +582,25 @@ public class MediaControlPanel {
if (!mMetadataAnimationHandler.isRunning()) {
mMediaViewController.refreshState();
}
+
+ // Turbulence noise
+ if (shouldPlayTurbulenceNoise()) {
+ if (mTurbulenceNoiseAnimationConfig == null) {
+ mTurbulenceNoiseAnimationConfig =
+ createTurbulenceNoiseAnimation();
+ }
+ // Color will be correctly updated in ColorSchemeTransition.
+ mTurbulenceNoiseController.play(
+ mTurbulenceNoiseAnimationConfig
+ );
+ mMainExecutor.executeDelayed(
+ mTurbulenceNoiseController::finish,
+ TURBULENCE_NOISE_PLAY_DURATION
+ );
+ }
+ mButtonClicked = false;
+ mWasPlaying = isPlaying();
+
Trace.endSection();
}
@@ -1155,21 +1174,14 @@ public class MediaControlPanel {
if (!mFalsingManager.isFalseTap(FalsingManager.MODERATE_PENALTY)) {
mLogger.logTapAction(button.getId(), mUid, mPackageName, mInstanceId);
logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT);
+ // Used to determine whether to play turbulence noise.
+ mWasPlaying = isPlaying();
+ mButtonClicked = true;
+
action.run();
+
if (mFeatureFlags.isEnabled(Flags.UMO_SURFACE_RIPPLE)) {
mMultiRippleController.play(createTouchRippleAnimation(button));
- if (mFeatureFlags.isEnabled(Flags.UMO_TURBULENCE_NOISE)) {
- if (mTurbulenceNoiseAnimationConfig == null) {
- mTurbulenceNoiseAnimationConfig =
- createTurbulenceNoiseAnimation();
- }
- // Color will be correctly updated in ColorSchemeTransition.
- mTurbulenceNoiseController.play(mTurbulenceNoiseAnimationConfig);
- mMainExecutor.executeDelayed(
- mTurbulenceNoiseController::finish,
- TURBULENCE_NOISE_PLAY_DURATION
- );
- }
}
if (icon instanceof Animatable) {
@@ -1208,6 +1220,11 @@ public class MediaControlPanel {
);
}
+ private boolean shouldPlayTurbulenceNoise() {
+ return mFeatureFlags.isEnabled(Flags.UMO_TURBULENCE_NOISE) && mButtonClicked && !mWasPlaying
+ && isPlaying();
+ }
+
private TurbulenceNoiseAnimationConfig createTurbulenceNoiseAnimation() {
return new TurbulenceNoiseAnimationConfig(
/* gridCount= */ 2.14f,
@@ -1218,12 +1235,12 @@ public class MediaControlPanel {
/* color= */ mColorSchemeTransition.getAccentPrimary().getCurrentColor(),
/* backgroundColor= */ Color.BLACK,
/* opacity= */ 51,
- /* width= */ mMediaViewHolder.getMultiRippleView().getWidth(),
- /* height= */ mMediaViewHolder.getMultiRippleView().getHeight(),
+ /* width= */ mMediaViewHolder.getTurbulenceNoiseView().getWidth(),
+ /* height= */ mMediaViewHolder.getTurbulenceNoiseView().getHeight(),
TurbulenceNoiseAnimationConfig.DEFAULT_MAX_DURATION_IN_MILLIS,
/* easeInDuration= */ 1350f,
/* easeOutDuration= */ 1350f,
- this.getContext().getResources().getDisplayMetrics().density,
+ getContext().getResources().getDisplayMetrics().density,
BlendMode.SCREEN,
/* onAnimationEnd= */ null,
/* lumaMatteBlendFactor= */ 0.26f,
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index 88ffa8da666b..318cd99a06ed 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -24,7 +24,6 @@ import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -175,9 +174,8 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
mCurrentActivePosition = position;
updateFullItemClickListener(v -> onItemClick(v, device));
setSingleLineLayout(getItemTitle(device));
- initMutingExpectedDevice();
- } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
- && device.hasSubtext()) {
+ initFakeActiveDevice();
+ } else if (device.hasSubtext()) {
boolean isActiveWithOngoingSession =
(device.hasOngoingSession() && (currentlyConnected || isDeviceIncluded(
mController.getSelectedMediaDevice(), device)));
@@ -267,6 +265,27 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
setUpDeviceIcon(device);
updateFullItemClickListener(v -> cancelMuteAwaitConnection());
setSingleLineLayout(getItemTitle(device));
+ } else if (device.hasOngoingSession()) {
+ mCurrentActivePosition = position;
+ if (device.isHostForOngoingSession()) {
+ updateTitleIcon(R.drawable.media_output_icon_volume,
+ mController.getColorItemContent());
+ updateEndClickAreaAsSessionEditing(device);
+ mEndClickIcon.setVisibility(View.VISIBLE);
+ setSingleLineLayout(getItemTitle(device), true /* showSeekBar */,
+ false /* showProgressBar */, false /* showCheckBox */,
+ true /* showEndTouchArea */);
+ initSeekbar(device, isCurrentSeekbarInvisible);
+ } else {
+ updateDeviceStatusIcon(mContext.getDrawable(
+ R.drawable.ic_sound_bars_anim));
+ mStatusIcon.setVisibility(View.VISIBLE);
+ updateSingleLineLayoutContentAlpha(
+ updateClickActionBasedOnSelectionBehavior(device)
+ ? DEVICE_CONNECTED_ALPHA : DEVICE_DISCONNECTED_ALPHA);
+ setSingleLineLayout(getItemTitle(device));
+ initFakeActiveDevice();
+ }
} else if (mController.isCurrentConnectedDeviceRemote()
&& !mController.getSelectableMediaDevice().isEmpty()) {
//If device is connected and there's other selectable devices, layout as
@@ -351,7 +370,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
ColorStateList.valueOf(mController.getColorItemContent()));
mEndClickIcon.setOnClickListener(
v -> mController.tryToLaunchInAppRoutingIntent(device.getId(), v));
- mEndTouchArea.setOnClickListener(v -> mCheckBox.performClick());
+ mEndTouchArea.setOnClickListener(v -> mEndClickIcon.performClick());
}
public void updateEndClickAreaColor(int color) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index 01f790422bc3..b88eba9081f7 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -188,6 +188,7 @@ public abstract class MediaOutputBaseAdapter extends
mContainerLayout.setContentDescription(null);
mTitleText.setTextColor(mController.getColorItemContent());
mSubTitleText.setTextColor(mController.getColorItemContent());
+ mSubTitleText.setSelected(true);
mTwoLineTitleText.setTextColor(mController.getColorItemContent());
mVolumeValueText.setTextColor(mController.getColorItemContent());
mSeekBar.setProgressTintList(
@@ -417,7 +418,7 @@ public abstract class MediaOutputBaseAdapter extends
mIconAreaLayout.setOnClickListener(listener);
}
- void initMutingExpectedDevice() {
+ void initFakeActiveDevice() {
disableSeekBar();
updateTitleIcon(R.drawable.media_output_icon_volume,
mController.getColorItemContent());
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index e52418912e1f..8b3d7a653232 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -15,8 +15,6 @@
*/
package com.android.systemui.navigationbar.gestural;
-import static android.view.InputDevice.SOURCE_MOUSE;
-import static android.view.InputDevice.SOURCE_TOUCHPAD;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION;
import static com.android.systemui.classifier.Classifier.BACK_GESTURE;
@@ -951,12 +949,10 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
mMLResults = 0;
mLogGesture = false;
mInRejectedExclusion = false;
- // Trackpad back gestures don't have zones, so we don't need to check if the down event
- // is within insets. Also we don't allow back for button press from the trackpad, and
- // yet we do with a mouse.
boolean isWithinInsets = isWithinInsets((int) ev.getX(), (int) ev.getY());
+ // Trackpad back gestures don't have zones, so we don't need to check if the down event
+ // is within insets.
mAllowGesture = !mDisabledForQuickstep && mIsBackGestureAllowed
- && !isButtonPressFromTrackpad(ev)
&& (isTrackpadMultiFingerSwipe || isWithinInsets)
&& !mGestureBlockingActivityRunning
&& !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
@@ -1069,11 +1065,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
mProtoTracer.scheduleFrameUpdate();
}
- private boolean isButtonPressFromTrackpad(MotionEvent ev) {
- int sources = InputManager.getInstance().getInputDevice(ev.getDeviceId()).getSources();
- return (sources & (SOURCE_MOUSE | SOURCE_TOUCHPAD)) == sources && ev.getButtonState() != 0;
- }
-
private void dispatchToBackAnimation(MotionEvent event) {
if (mBackAnimation != null) {
mVelocityTracker.addMovement(event);
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index 25272ae097a1..ccfbaf1da7b6 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -215,7 +215,7 @@ constructor(
debugLog { "onShowNoteTask - opened as app bubble: $info" }
}
is NoteTaskLaunchMode.Activity -> {
- if (activityManager.isInForeground(info.packageName)) {
+ if (info.isKeyguardLocked && activityManager.isInForeground(info.packageName)) {
// Force note task into background by calling home.
val intent = createHomeIntent()
context.startActivityAsUser(intent, user)
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt
index fae325cc3147..442000281862 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt
@@ -25,12 +25,14 @@ import com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity
* An entry point represents where the note task has ben called from. In rare cases, it may
* represent a "re-entry" (i.e., [APP_CLIPS]).
*/
-enum class
-NoteTaskEntryPoint {
+enum class NoteTaskEntryPoint {
/** @see [LaunchNoteTaskActivity] */
WIDGET_PICKER_SHORTCUT,
+ /** @see [LaunchNoteTaskActivity] */
+ WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE,
+
/** @see [NoteTaskQuickAffordanceConfig] */
QUICK_AFFORDANCE,
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt
index 48a5933a6030..a79057e5464b 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt
@@ -22,6 +22,8 @@ import com.android.systemui.notetask.NoteTaskEntryPoint.KEYBOARD_SHORTCUT
import com.android.systemui.notetask.NoteTaskEntryPoint.QUICK_AFFORDANCE
import com.android.systemui.notetask.NoteTaskEntryPoint.TAIL_BUTTON
import com.android.systemui.notetask.NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT
+import com.android.systemui.notetask.NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent
import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT
import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
@@ -41,40 +43,45 @@ class NoteTaskEventLogger @Inject constructor(private val uiEventLogger: UiEvent
/** Logs a [NoteTaskInfo] as an **open** [NoteTaskUiEvent], including package name and uid. */
fun logNoteTaskOpened(info: NoteTaskInfo) {
val event =
- when (info.entryPoint) {
- TAIL_BUTTON -> {
- if (info.isKeyguardLocked) {
- NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED
- } else {
- NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
+ when (info.entryPoint) {
+ TAIL_BUTTON -> {
+ if (info.isKeyguardLocked) {
+ NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+ } else {
+ NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
+ }
}
+
+ WIDGET_PICKER_SHORTCUT,
+ WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE -> NOTE_OPENED_VIA_SHORTCUT
+
+ QUICK_AFFORDANCE -> NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
+ APP_CLIPS,
+ KEYBOARD_SHORTCUT,
+ null -> return
}
- WIDGET_PICKER_SHORTCUT -> NOTE_OPENED_VIA_SHORTCUT
- QUICK_AFFORDANCE -> NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
- APP_CLIPS -> return
- KEYBOARD_SHORTCUT -> return
- null -> return
- }
uiEventLogger.log(event, info.uid, info.packageName)
}
/** Logs a [NoteTaskInfo] as a **closed** [NoteTaskUiEvent], including package name and uid. */
fun logNoteTaskClosed(info: NoteTaskInfo) {
val event =
- when (info.entryPoint) {
- TAIL_BUTTON -> {
- if (info.isKeyguardLocked) {
- NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED
- } else {
- NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON
+ when (info.entryPoint) {
+ TAIL_BUTTON -> {
+ if (info.isKeyguardLocked) {
+ NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+ } else {
+ NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON
+ }
}
+
+ WIDGET_PICKER_SHORTCUT,
+ WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE,
+ QUICK_AFFORDANCE,
+ APP_CLIPS,
+ KEYBOARD_SHORTCUT,
+ null -> return
}
- WIDGET_PICKER_SHORTCUT -> return
- QUICK_AFFORDANCE -> return
- APP_CLIPS -> return
- KEYBOARD_SHORTCUT -> return
- null -> return
- }
uiEventLogger.log(event, info.uid, info.packageName)
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt
index a75834760d30..269eb870686c 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt
@@ -16,6 +16,7 @@
package com.android.systemui.notetask
import android.os.UserHandle
+import com.android.systemui.notetask.NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE
/** Contextual information required to launch a Note Task by [NoteTaskController]. */
data class NoteTaskInfo(
@@ -27,7 +28,7 @@ data class NoteTaskInfo(
) {
val launchMode: NoteTaskLaunchMode =
- if (isKeyguardLocked) {
+ if (isKeyguardLocked || entryPoint == WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE) {
NoteTaskLaunchMode.Activity
} else {
NoteTaskLaunchMode.AppBubble
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskRoleManagerExt.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskRoleManagerExt.kt
index 441b9f5d0181..754c3650a5ed 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskRoleManagerExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskRoleManagerExt.kt
@@ -51,7 +51,8 @@ internal object NoteTaskRoleManagerExt {
val icon = Icon.createWithResource(context, R.drawable.ic_note_task_shortcut_widget)
return ShortcutInfo.Builder(context, NoteTaskController.SHORTCUT_ID)
- .setIntent(LaunchNoteTaskActivity.newIntent(context = context))
+ .setIntent(LaunchNoteTaskActivity.createIntent(context))
+ .setActivity(LaunchNoteTaskActivity.createComponent(context))
.setShortLabel(context.getString(R.string.note_task_button_label))
.setLongLived(true)
.setIcon(icon)
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
index 8ca13b9776bb..7ef149de2794 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
@@ -16,6 +16,7 @@
package com.android.systemui.notetask.shortcut
+import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.Bundle
@@ -72,7 +73,13 @@ constructor(
controller.startNoteTaskProxyActivityForUser(mainUser)
}
} else {
- controller.showNoteTask(entryPoint = NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT)
+ val entryPoint =
+ if (isInMultiWindowMode) {
+ NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE
+ } else {
+ NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT
+ }
+ controller.showNoteTask(entryPoint)
}
finish()
}
@@ -80,11 +87,14 @@ constructor(
companion object {
/** Creates a new [Intent] set to start [LaunchNoteTaskActivity]. */
- fun newIntent(context: Context): Intent {
- return Intent(context, LaunchNoteTaskActivity::class.java).apply {
+ fun createIntent(context: Context): Intent =
+ Intent(context, LaunchNoteTaskActivity::class.java).apply {
// Intent's action must be set in shortcuts, or an exception will be thrown.
action = Intent.ACTION_CREATE_NOTE
}
- }
+
+ /** Creates a new [ComponentName] for [LaunchNoteTaskActivity]. */
+ fun createComponent(context: Context): ComponentName =
+ ComponentName(context, LaunchNoteTaskActivity::class.java)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordingAdapter.java b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordingAdapter.java
index 3e78489e5707..9962c914b476 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordingAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordingAdapter.java
@@ -16,10 +16,6 @@
package com.android.systemui.screenrecord;
-import static com.android.systemui.screenrecord.ScreenRecordingAudioSource.INTERNAL;
-import static com.android.systemui.screenrecord.ScreenRecordingAudioSource.MIC;
-import static com.android.systemui.screenrecord.ScreenRecordingAudioSource.MIC_AND_INTERNAL;
-
import android.content.Context;
import android.content.res.Resources;
import android.view.LayoutInflater;
@@ -40,9 +36,6 @@ public class ScreenRecordingAdapter extends ArrayAdapter<ScreenRecordingAudioSou
private LinearLayout mSelectedMic;
private LinearLayout mSelectedInternal;
private LinearLayout mSelectedMicAndInternal;
- private LinearLayout mMicOption;
- private LinearLayout mMicAndInternalOption;
- private LinearLayout mInternalOption;
public ScreenRecordingAdapter(Context context, int resource,
List<ScreenRecordingAudioSource> objects) {
@@ -54,28 +47,21 @@ public class ScreenRecordingAdapter extends ArrayAdapter<ScreenRecordingAudioSou
mSelectedInternal = getSelected(R.string.screenrecord_device_audio_label);
mSelectedMic = getSelected(R.string.screenrecord_mic_label);
mSelectedMicAndInternal = getSelected(R.string.screenrecord_device_audio_and_mic_label);
-
- mMicOption = getOption(R.string.screenrecord_mic_label, Resources.ID_NULL);
- mMicOption.removeViewAt(1);
-
- mMicAndInternalOption = getOption(
- R.string.screenrecord_device_audio_and_mic_label, Resources.ID_NULL);
- mMicAndInternalOption.removeViewAt(1);
-
- mInternalOption = getOption(R.string.screenrecord_device_audio_label,
- R.string.screenrecord_device_audio_description);
}
private LinearLayout getOption(int label, int description) {
- LayoutInflater inflater = (LayoutInflater) getContext()
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ LayoutInflater inflater = LayoutInflater.from(getContext());
LinearLayout layout = (LinearLayout) inflater
.inflate(R.layout.screen_record_dialog_audio_source, null, false);
((TextView) layout.findViewById(R.id.screen_recording_dialog_source_text))
.setText(label);
- if (description != Resources.ID_NULL)
- ((TextView) layout.findViewById(R.id.screen_recording_dialog_source_description))
- .setText(description);
+ TextView descriptionView = layout.findViewById(
+ R.id.screen_recording_dialog_source_description);
+ if (description != Resources.ID_NULL) {
+ descriptionView.setText(description);
+ } else {
+ descriptionView.setVisibility(View.GONE);
+ }
return layout;
}
@@ -92,11 +78,13 @@ public class ScreenRecordingAdapter extends ArrayAdapter<ScreenRecordingAudioSou
public View getDropDownView(int position, View convertView, ViewGroup parent) {
switch (getItem(position)) {
case INTERNAL:
- return mInternalOption;
+ return getOption(R.string.screenrecord_device_audio_label,
+ R.string.screenrecord_device_audio_description);
case MIC_AND_INTERNAL:
- return mMicAndInternalOption;
+ return getOption(
+ R.string.screenrecord_device_audio_and_mic_label, Resources.ID_NULL);
case MIC:
- return mMicOption;
+ return getOption(R.string.screenrecord_mic_label, Resources.ID_NULL);
default:
return super.getDropDownView(position, convertView, parent);
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ImageCaptureImpl.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ImageCaptureImpl.kt
index 2e47ab6417ae..24fe7d593b3d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ImageCaptureImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ImageCaptureImpl.kt
@@ -42,8 +42,8 @@ open class ImageCaptureImpl @Inject constructor(
.setSourceCrop(crop)
.build()
val syncScreenCapture = ScreenCapture.createSyncCaptureListener()
- windowManager.captureDisplay(displayId, captureArgs, syncScreenCapture.first)
- val buffer = syncScreenCapture.second.get()
+ windowManager.captureDisplay(displayId, captureArgs, syncScreenCapture)
+ val buffer = syncScreenCapture.getBuffer()
return buffer?.asBitmap()
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java
index 83ff020362f1..4c013151c464 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java
@@ -20,7 +20,7 @@ import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.window.ScreenCapture.ScreenshotHardwareBuffer;
-import android.window.ScreenCapture.ScreenshotSync;
+import android.window.ScreenCapture.SynchronousScreenCaptureListener;
import androidx.annotation.Nullable;
@@ -54,9 +54,9 @@ public class AppClipsScreenshotHelperService extends Service {
return null;
}
- ScreenshotSync screenshotSync =
+ SynchronousScreenCaptureListener screenshotSync =
mOptionalBubbles.get().getScreenshotExcludingBubble(displayId);
- ScreenshotHardwareBuffer screenshotHardwareBuffer = screenshotSync.get();
+ ScreenshotHardwareBuffer screenshotHardwareBuffer = screenshotSync.getBuffer();
if (screenshotHardwareBuffer == null) {
return null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 17a887019541..d2e94d6a20a5 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -1653,10 +1653,9 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding));
mKeyguardNotificationBottomPadding = bottomPadding;
- float staticTopPadding = mClockPositionAlgorithm.getLockscreenMinStackScrollerPadding()
- // getMinStackScrollerPadding is from the top of the screen,
- // but we need it from the top of the NSSL.
- - mNotificationStackScrollLayoutController.getTop();
+ float staticTopPadding = mClockPositionAlgorithm.getLockscreenNotifPadding(
+ mNotificationStackScrollLayoutController.getTop());
+
mKeyguardNotificationTopPadding = staticTopPadding;
// To debug the available space, enable debug lines in this class. If you change how the
@@ -1670,8 +1669,8 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
Log.i(TAG, "\n");
Log.i(TAG, "staticTopPadding[" + staticTopPadding
+ "] = Clock.padding["
- + mClockPositionAlgorithm.getLockscreenMinStackScrollerPadding()
- + "] - NSSLC.top[" + mNotificationStackScrollLayoutController.getTop()
+ + mClockPositionAlgorithm.getLockscreenNotifPadding(
+ mNotificationStackScrollLayoutController.getTop())
+ "]"
);
Log.i(TAG, "bottomPadding[" + bottomPadding
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java
index 7dff6ea99029..e5b84bd86514 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java
@@ -55,6 +55,7 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout
private Consumer<QS> mQSFragmentAttachedListener = qs -> {};
private QS mQs;
private View mQSContainer;
+ private int mLastQSPaddingBottom;
/**
* These are used to compute the bounding box containing the shade and the notification scrim,
@@ -83,6 +84,10 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout
mQs = (QS) fragment;
mQSFragmentAttachedListener.accept(mQs);
mQSContainer = mQs.getView().findViewById(R.id.quick_settings_container);
+ // We need to restore the bottom padding as the fragment may have been recreated due to
+ // some special Configuration change, so we apply the last known padding (this will be
+ // correct even if it has changed while the fragment was destroyed and re-created).
+ setQSContainerPaddingBottom(mLastQSPaddingBottom);
}
@Override
@@ -109,6 +114,7 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout
}
public void setQSContainerPaddingBottom(int paddingBottom) {
+ mLastQSPaddingBottom = paddingBottom;
if (mQSContainer != null) {
mQSContainer.setPadding(
mQSContainer.getPaddingLeft(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 12420ff5f481..b847fb6ded83 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -91,6 +91,7 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.KeyguardIndication;
import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController;
import com.android.systemui.keyguard.ScreenLifecycle;
@@ -224,6 +225,7 @@ public class KeyguardIndicationController {
// triggered while the device is asleep
private final AlarmTimeout mHideTransientMessageHandler;
private final AlarmTimeout mHideBiometricMessageHandler;
+ private FeatureFlags mFeatureFlags;
/**
* Creates a new KeyguardIndicationController and registers callbacks.
@@ -253,7 +255,8 @@ public class KeyguardIndicationController {
KeyguardLogger keyguardLogger,
AlternateBouncerInteractor alternateBouncerInteractor,
AlarmManager alarmManager,
- UserTracker userTracker
+ UserTracker userTracker,
+ FeatureFlags flags
) {
mContext = context;
mBroadcastDispatcher = broadcastDispatcher;
@@ -278,6 +281,7 @@ public class KeyguardIndicationController {
mScreenLifecycle.addObserver(mScreenObserver);
mAlternateBouncerInteractor = alternateBouncerInteractor;
mUserTracker = userTracker;
+ mFeatureFlags = flags;
mFaceAcquiredMessageDeferral = faceHelpMessageDeferral;
mCoExFaceAcquisitionMsgIdsToShow = new HashSet<>();
@@ -342,7 +346,8 @@ public class KeyguardIndicationController {
mLockScreenIndicationView,
mExecutor,
mStatusBarStateController,
- mKeyguardLogger
+ mKeyguardLogger,
+ mFeatureFlags
);
updateDeviceEntryIndication(false /* animate */);
updateOrganizedOwnedDevice();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
index 23b5241b79ef..314566eaf8d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
@@ -633,12 +633,17 @@ class HeadsUpCoordinator @Inject constructor(
mFSIUpdateCandidates.removeAll(toRemoveForFSI)
}
- /** When an action is pressed on a notification, end HeadsUp lifetime extension. */
+ /**
+ * When an action is pressed on a notification, make sure we don't lifetime-extend it in the
+ * future by informing the HeadsUpManager, and make sure we don't keep lifetime-extending it if
+ * we already are.
+ *
+ * @see HeadsUpManager.setUserActionMayIndirectlyRemove
+ * @see HeadsUpManager.canRemoveImmediately
+ */
private val mActionPressListener = Consumer<NotificationEntry> { entry ->
- if (mNotifsExtendingLifetime.contains(entry)) {
- val removeInMillis = mHeadsUpManager.getEarliestRemovalTime(entry.key)
- mExecutor.executeDelayed({ endNotifLifetimeExtensionIfExtended(entry) }, removeInMillis)
- }
+ mHeadsUpManager.setUserActionMayIndirectlyRemove(entry)
+ mExecutor.execute { endNotifLifetimeExtensionIfExtended(entry) }
}
private val mLifetimeExtender = object : NotifLifetimeExtender {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index f7c6594e3a70..df6fe3d5e434 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -4011,7 +4011,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mCentralSurfaces.resetUserExpandedStates();
clearTemporaryViews();
clearUserLockedViews();
- cancelActiveSwipe();
+ resetAllSwipeState();
}
}
@@ -4077,7 +4077,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mGroupExpansionManager.collapseGroups();
mExpandHelper.cancelImmediately();
if (!mIsExpansionChanging) {
- cancelActiveSwipe();
+ resetAllSwipeState();
}
finalizeClearAllAnimation();
}
@@ -4406,7 +4406,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
boolean nowHiddenAtAll = mAmbientState.isHiddenAtAll();
if (nowFullyHidden != wasFullyHidden) {
updateVisibility();
- mSwipeHelper.resetTouchState();
+ resetAllSwipeState();
}
if (!wasHiddenAtAll && nowHiddenAtAll) {
resetExposedMenuView(true /* animate */, true /* animate */);
@@ -5866,9 +5866,14 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
}
}
- private void cancelActiveSwipe() {
+ private void resetAllSwipeState() {
+ Trace.beginSection("NSSL.resetAllSwipeState()");
mSwipeHelper.resetTouchState();
+ for (int i = 0; i < getChildCount(); i++) {
+ mSwipeHelper.forceResetSwipeState(getChildAt(i));
+ }
updateContinuousShadowDrawing();
+ Trace.endSection();
}
void updateContinuousShadowDrawing() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 6f1c378f429d..efb7926b8b8b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -315,7 +315,8 @@ public class StackScrollAlgorithm {
float newNotificationEnd = newYTranslation + newHeight;
boolean isHeadsUp = (child instanceof ExpandableNotificationRow) && child.isPinned();
if (mClipNotificationScrollToTop
- && ((isHeadsUp && !firstHeadsUp) || child.isHeadsUpAnimatingAway())
+ && !firstHeadsUp
+ && (isHeadsUp || child.isHeadsUpAnimatingAway())
&& newNotificationEnd > firstHeadsUpEnd
&& !ambientState.isShadeExpanded()) {
// The bottom of this view is peeking out from under the previous view.
@@ -619,13 +620,12 @@ public class StackScrollAlgorithm {
updateViewWithShelf(view, viewState, shelfStart);
}
}
- // Avoid pulsing notification flicker during AOD to LS
- // A pulsing notification is already expanded, no need to expand it again with animation
- if (ambientState.isPulsingRow(view)) {
- expansionFraction = 1.0f;
+ viewState.height = getMaxAllowedChildHeight(view);
+ if (!view.isPinned() && !view.isHeadsUpAnimatingAway()
+ && !ambientState.isPulsingRow(view)) {
+ // The expansion fraction should not affect HUNs or pulsing notifications.
+ viewState.height *= expansionFraction;
}
- // Clip height of view right before shelf.
- viewState.height = (int) (getMaxAllowedChildHeight(view) * expansionFraction);
}
algorithmState.mCurrentYPosition +=
@@ -785,6 +785,8 @@ public class StackScrollAlgorithm {
}
}
if (row.isPinned()) {
+ // Make sure row yTranslation is at maximum the HUN yTranslation,
+ // which accounts for AmbientState.stackTopMargin in split-shade.
childState.setYTranslation(
Math.max(childState.getYTranslation(), headsUpTranslation));
childState.height = Math.max(row.getIntrinsicHeight(), childState.height);
@@ -809,7 +811,11 @@ public class StackScrollAlgorithm {
}
}
if (row.isHeadsUpAnimatingAway()) {
- childState.setYTranslation(Math.max(childState.getYTranslation(), mHeadsUpInset));
+ // Make sure row yTranslation is at maximum the HUN yTranslation,
+ // which accounts for AmbientState.stackTopMargin in split-shade.
+ childState.setYTranslation(
+ Math.max(childState.getYTranslation(), headsUpTranslation));
+ // keep it visible for the animation
childState.hidden = false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 561bd91b964f..fc3c85a0807b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -229,12 +229,18 @@ public class KeyguardClockPositionAlgorithm {
}
}
- public float getLockscreenMinStackScrollerPadding() {
+ /**
+ * @param nsslTop NotificationStackScrollLayout top, which is below top of the srceen.
+ * @return Distance from nsslTop to top of the first view in the lockscreen shade.
+ */
+ public float getLockscreenNotifPadding(float nsslTop) {
if (mBypassEnabled) {
- return mUnlockedStackScrollerPadding;
+ return mUnlockedStackScrollerPadding - nsslTop;
} else if (mIsSplitShade) {
- return mSplitShadeTargetTopMargin + mUserSwitchHeight;
+ return mSplitShadeTargetTopMargin + mUserSwitchHeight - nsslTop;
} else {
+ // Non-bypass portrait shade already uses values from nsslTop
+ // so we don't need to subtract it here.
return mMinTopMargin + mKeyguardStatusHeight;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
index 61c1cc82482a..29a249fcaa41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
@@ -51,6 +51,7 @@ public class KeyguardIndicationTextView extends TextView {
private KeyguardIndication mKeyguardIndicationInfo;
private Animator mLastAnimator;
+ private boolean mAlwaysAnnounceText;
public KeyguardIndicationTextView(Context context) {
super(context);
@@ -104,6 +105,19 @@ public class KeyguardIndicationTextView extends TextView {
}
/**
+ * Controls whether the text displayed in the indication area will be announced always.
+ */
+ public void setAlwaysAnnounceEnabled(boolean enabled) {
+ this.mAlwaysAnnounceText = enabled;
+ if (mAlwaysAnnounceText) {
+ // We will announce the text programmatically anyway.
+ setAccessibilityLiveRegion(ACCESSIBILITY_LIVE_REGION_NONE);
+ } else {
+ setAccessibilityLiveRegion(ACCESSIBILITY_LIVE_REGION_POLITE);
+ }
+ }
+
+ /**
* Updates the text with an optional animation.
*
* @param text The text to show.
@@ -227,6 +241,9 @@ public class KeyguardIndicationTextView extends TextView {
setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null);
}
setText(mMessage);
+ if (mAlwaysAnnounceText) {
+ announceForAccessibility(mMessage);
+ }
}
private AnimatorSet getInAnimator() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt
index 2b4f51c63043..4c6374b75f82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapter.kt
@@ -35,7 +35,10 @@ protected constructor(
) : BaseAdapter() {
protected open val users: List<UserRecord>
- get() = controller.users.filter { !controller.isKeyguardShowing || !it.isRestricted }
+ get() = controller.users.filter {
+ (!controller.isKeyguardShowing || !it.isRestricted) &&
+ (controller.isUserSwitcherEnabled || it.isCurrent)
+ }
init {
controller.addAdapter(WeakReference(this))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index ed8050a031d8..92a78541d744 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -393,6 +393,31 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
}
}
+ /**
+ * Notes that the user took an action on an entry that might indirectly cause the system or the
+ * app to remove the notification.
+ *
+ * @param entry the entry that might be indirectly removed by the user's action
+ *
+ * @see com.android.systemui.statusbar.notification.collection.coordinator.HeadsUpCoordinator#mActionPressListener
+ * @see #canRemoveImmediately(String)
+ */
+ public void setUserActionMayIndirectlyRemove(@NonNull NotificationEntry entry) {
+ HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.getKey());
+ if (headsUpEntry != null) {
+ headsUpEntry.userActionMayIndirectlyRemove = true;
+ }
+ }
+
+ @Override
+ public boolean canRemoveImmediately(@NonNull String key) {
+ HeadsUpEntry headsUpEntry = getHeadsUpEntry(key);
+ if (headsUpEntry != null && headsUpEntry.userActionMayIndirectlyRemove) {
+ return true;
+ }
+ return super.canRemoveImmediately(key);
+ }
+
@NonNull
@Override
protected HeadsUpEntry createAlertEntry() {
@@ -421,6 +446,8 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
*/
protected class HeadsUpEntry extends AlertEntry {
public boolean remoteInputActive;
+ public boolean userActionMayIndirectlyRemove;
+
protected boolean expanded;
protected boolean wasUnpinned;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
index 1e223b1920ed..f88339a4d077 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
@@ -67,6 +67,9 @@ constructor(
val isSimpleUserSwitcher: Boolean
get() = userInteractor.isSimpleUserSwitcher
+ val isUserSwitcherEnabled: Boolean
+ get() = userInteractor.isUserSwitcherEnabled
+
/** The [UserRecord] of the current user or `null` when none. */
val currentUserRecord: UserRecord?
get() = userInteractor.selectedUserRecord.value
diff --git a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
index a0b56aa6f5c3..3de75ca2ed87 100644
--- a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
@@ -105,6 +105,8 @@ interface UserRepository {
fun getSelectedUserInfo(): UserInfo
fun isSimpleUserSwitcher(): Boolean
+
+ fun isUserSwitcherEnabled(): Boolean
}
@SysUISingleton
@@ -206,6 +208,10 @@ constructor(
return _userSwitcherSettings.value.isSimpleUserSwitcher
}
+ override fun isUserSwitcherEnabled(): Boolean {
+ return _userSwitcherSettings.value.isUserSwitcherEnabled
+ }
+
private fun observeUserSwitching() {
conflatedCallbackFlow {
val callback =
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
index 27c348ba329a..a487f538e59c 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
@@ -294,6 +294,10 @@ constructor(
val isSimpleUserSwitcher: Boolean
get() = repository.isSimpleUserSwitcher()
+
+ val isUserSwitcherEnabled: Boolean
+ get() = repository.isUserSwitcherEnabled()
+
val keyguardUpdateMonitorCallback =
object : KeyguardUpdateMonitorCallback() {
override fun onKeyguardGoingAway() {
@@ -370,6 +374,7 @@ constructor(
}
pw.println("isSimpleUserSwitcher=$isSimpleUserSwitcher")
+ pw.println("isUserSwitcherEnabled=$isUserSwitcherEnabled")
pw.println("isGuestUserAutoCreated=$isGuestUserAutoCreated")
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 109c1cfdcf0f..7456d349a933 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -390,8 +390,6 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
public void init(int windowType, Callback callback) {
initDialog(mActivityManager.getLockTaskModeState());
- mAccessibility.init();
-
mController.addCallback(mControllerCallbackH, mHandler);
mController.getState();
@@ -478,8 +476,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
- mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
@@ -677,6 +674,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
initRingerH();
initSettingsH(lockTaskModeState);
initODICaptionsH();
+ mAccessibility.init();
}
private boolean isWindowGravityLeft() {
@@ -930,7 +928,6 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
showRingerDrawer();
}
});
- updateSelectedRingerContainerDescription(mIsRingerDrawerOpen);
mRingerDrawerVibrate.setOnClickListener(
new RingerDrawerItemClickListener(RINGER_MODE_VIBRATE));
@@ -993,18 +990,6 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
: 0;
}
- @VisibleForTesting String getSelectedRingerContainerDescription() {
- return mSelectedRingerContainer.getContentDescription().toString();
- }
-
- @VisibleForTesting void toggleRingerDrawer(boolean show) {
- if (show) {
- showRingerDrawer();
- } else {
- hideRingerDrawer();
- }
- }
-
/** Animates in the ringer drawer. */
private void showRingerDrawer() {
if (mIsRingerDrawerOpen) {
@@ -1082,7 +1067,12 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
.start();
}
- updateSelectedRingerContainerDescription(true);
+ // When the ringer drawer is open, tapping the currently selected ringer will set the ringer
+ // to the current ringer mode. Change the content description to that, instead of the 'tap
+ // to change ringer mode' default.
+ mSelectedRingerContainer.setContentDescription(
+ mContext.getString(getStringDescriptionResourceForRingerMode(
+ mState.ringerModeInternal)));
mIsRingerDrawerOpen = true;
}
@@ -1128,38 +1118,14 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
.translationY(0f)
.start();
- updateSelectedRingerContainerDescription(false);
+ // When the drawer is closed, tapping the selected ringer drawer will open it, allowing the
+ // user to change the ringer.
+ mSelectedRingerContainer.setContentDescription(
+ mContext.getString(R.string.volume_ringer_change));
mIsRingerDrawerOpen = false;
}
-
- /**
- * @param open false to set the description when drawer is closed
- */
- private void updateSelectedRingerContainerDescription(boolean open) {
- if (mState == null) return;
-
- String currentMode = mContext.getString(getStringDescriptionResourceForRingerMode(
- mState.ringerModeInternal));
- String tapToSelect;
-
- if (open) {
- // When the ringer drawer is open, tapping the currently selected ringer will set the
- // ringer to the current ringer mode. Change the content description to that, instead of
- // the 'tap to change ringer mode' default.
- tapToSelect = "";
-
- } else {
- // When the drawer is closed, tapping the selected ringer drawer will open it, allowing
- // the user to change the ringer. The user needs to know that, and also the current mode
- currentMode += ", ";
- tapToSelect = mContext.getString(R.string.volume_ringer_change);
- }
-
- mSelectedRingerContainer.setContentDescription(currentMode + tapToSelect);
- }
-
private void initSettingsH(int lockTaskModeState) {
if (mSettingsView != null) {
mSettingsView.setVisibility(
@@ -1735,7 +1701,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
});
}
- @VisibleForTesting int getStringDescriptionResourceForRingerMode(int mode) {
+ private int getStringDescriptionResourceForRingerMode(int mode) {
switch (mode) {
case RINGER_MODE_SILENT:
return R.string.volume_ringer_status_silent;
@@ -1817,7 +1783,6 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
updateVolumeRowH(row);
}
updateRingerH();
- updateSelectedRingerContainerDescription(mIsRingerDrawerOpen);
mWindow.setTitle(composeWindowTitle());
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index 3f1560bc5fce..e9a9f3a6b007 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -47,6 +47,7 @@ import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.yield
import org.junit.Assert.assertEquals
import org.junit.Before
@@ -118,7 +119,7 @@ class ClockEventControllerTest : SysuiTestCase() {
featureFlags = featureFlags,
bouncerRepository = bouncerRepository,
),
- KeyguardTransitionInteractor(repository = transitionRepository),
+ KeyguardTransitionInteractor(transitionRepository, TestScope().backgroundScope),
broadcastDispatcher,
batteryController,
keyguardUpdateMonitor,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index 254f9531ef83..061340e385a5 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -72,6 +72,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
private FrameLayout mSmallClockFrame;
private FrameLayout mLargeClockFrame;
+ private KeyguardStatusAreaView mStatusArea;
KeyguardClockSwitch mKeyguardClockSwitch;
@@ -109,6 +110,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
(KeyguardClockSwitch) layoutInflater.inflate(R.layout.keyguard_clock_switch, null);
mSmallClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view);
mLargeClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view_large);
+ mStatusArea = mKeyguardClockSwitch.findViewById(R.id.keyguard_status_area);
mKeyguardClockSwitch.mChildrenAreLaidOut = true;
}
@@ -185,6 +187,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
mKeyguardClockSwitch.mClockInAnim.end();
mKeyguardClockSwitch.mClockOutAnim.end();
+ mKeyguardClockSwitch.mStatusAreaAnim.end();
assertThat(mLargeClockFrame.getAlpha()).isEqualTo(1);
assertThat(mLargeClockFrame.getVisibility()).isEqualTo(VISIBLE);
@@ -206,6 +209,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
mKeyguardClockSwitch.mClockInAnim.end();
mKeyguardClockSwitch.mClockOutAnim.end();
+ mKeyguardClockSwitch.mStatusAreaAnim.end();
assertThat(mSmallClockFrame.getAlpha()).isEqualTo(1);
assertThat(mSmallClockFrame.getVisibility()).isEqualTo(VISIBLE);
@@ -226,6 +230,31 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
}
@Test
+ public void switchingToSmallClockAnimation_resetsStatusArea() {
+ mKeyguardClockSwitch.switchToClock(SMALL, true);
+
+ mKeyguardClockSwitch.mClockInAnim.end();
+ mKeyguardClockSwitch.mClockOutAnim.end();
+ mKeyguardClockSwitch.mStatusAreaAnim.end();
+
+ assertThat(mStatusArea.getTranslationX()).isEqualTo(0);
+ assertThat(mStatusArea.getTranslationY()).isEqualTo(0);
+ assertThat(mStatusArea.getScaleX()).isEqualTo(1);
+ assertThat(mStatusArea.getScaleY()).isEqualTo(1);
+ }
+
+ @Test
+ public void switchingToSmallClockNoAnimation_resetsStatusArea() {
+ mKeyguardClockSwitch.switchToClock(SMALL, false);
+
+ assertThat(mStatusArea.getTranslationX()).isEqualTo(0);
+ assertThat(mStatusArea.getTranslationY()).isEqualTo(0);
+ assertThat(mStatusArea.getScaleX()).isEqualTo(1);
+ assertThat(mStatusArea.getScaleY()).isEqualTo(1);
+ }
+
+
+ @Test
public void switchingToBigClock_returnsTrueOnlyWhenItWasNotVisibleBefore() {
assertThat(mKeyguardClockSwitch.switchToClock(LARGE, /* animate */ true)).isTrue();
assertThat(mKeyguardClockSwitch.switchToClock(LARGE, /* animate */ true)).isFalse();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index d2e5a45c3a93..2f20f76ccc50 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -585,21 +585,6 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
}
@Test
- public void testSecurityCallbackFinish() {
- when(mKeyguardStateController.canDismissLockScreen()).thenReturn(true);
- when(mKeyguardUpdateMonitor.isUserUnlocked(0)).thenReturn(true);
- mKeyguardSecurityContainerController.finish(true, 0);
- verify(mViewMediatorCallback).keyguardDone(anyBoolean(), anyInt());
- }
-
- @Test
- public void testSecurityCallbackFinish_cannotDismissLockScreenAndNotStrongAuth() {
- when(mKeyguardStateController.canDismissLockScreen()).thenReturn(false);
- mKeyguardSecurityContainerController.finish(false, 0);
- verify(mViewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt());
- }
-
- @Test
public void testOnStartingToHide() {
mKeyguardSecurityContainerController.onStartingToHide();
verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class),
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt
new file mode 100644
index 000000000000..e6b696454d42
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt
@@ -0,0 +1,44 @@
+package com.android.keyguard
+
+import android.test.suitebuilder.annotation.SmallTest
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import com.android.systemui.SysuiTestCase
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper(setAsMainLooper = true)
+class KeyguardStatusAreaViewTest : SysuiTestCase() {
+
+ private lateinit var view: KeyguardStatusAreaView
+
+ @Before
+ fun setUp() {
+ view = KeyguardStatusAreaView(context)
+ }
+
+ @Test
+ fun checkTranslationX_AddedTotals() {
+ view.translateXFromClockDesign = 10f
+ assertEquals(10f, view.translationX)
+
+ view.translateXFromAod = 20f
+ assertEquals(30f, view.translationX)
+
+ view.translateXFromUnfold = 30f
+ assertEquals(60f, view.translationX)
+ }
+
+ @Test
+ fun checkTranslationY_AddedTotals() {
+ view.translateYFromClockSize = 10f
+ assertEquals(10f, view.translationY)
+
+ view.translateYFromClockDesign = 20f
+ assertEquals(30f, view.translationY)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 419d045885a8..de306d669476 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -2800,6 +2800,16 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
);
}
+ @Test
+ public void testOnSimStateChanged_Unknown() {
+ KeyguardUpdateMonitorCallback keyguardUpdateMonitorCallback = spy(
+ KeyguardUpdateMonitorCallback.class);
+ mKeyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback);
+ mKeyguardUpdateMonitor.handleSimStateChange(-1, 0, TelephonyManager.SIM_STATE_UNKNOWN);
+ verify(keyguardUpdateMonitorCallback).onSimStateChanged(-1, 0,
+ TelephonyManager.SIM_STATE_UNKNOWN);
+ }
+
private void verifyFingerprintAuthenticateNeverCalled() {
verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), any());
verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
index 456702b65091..84e58be2150f 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
@@ -159,7 +159,8 @@ public class LockIconViewControllerBaseTest extends SysuiTestCase {
mVibrator,
mAuthRippleController,
mResources,
- new KeyguardTransitionInteractor(mTransitionRepository),
+ new KeyguardTransitionInteractor(mTransitionRepository,
+ TestScopeProvider.getTestScope().getBackgroundScope()),
new KeyguardInteractor(
new FakeKeyguardRepository(),
mCommandQueue,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/TestScopeProvider.kt b/packages/SystemUI/tests/src/com/android/keyguard/TestScopeProvider.kt
new file mode 100644
index 000000000000..073c7feb25e3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/TestScopeProvider.kt
@@ -0,0 +1,25 @@
+/*
+ * 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.keyguard
+
+import kotlinx.coroutines.test.TestScope
+
+class TestScopeProvider {
+ companion object {
+ @JvmStatic fun getTestScope() = TestScope()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt
index 57a355f4e127..5e1a8e1432dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt
@@ -37,7 +37,7 @@ class FontInterpolatorTest : SysuiTestCase() {
private fun assertSameAxes(expect: Font, actual: Font) {
val expectAxes = expect.axes?.also { it.sortBy { axis -> axis.tag } }
val actualAxes = actual.axes?.also { it.sortBy { axis -> axis.tag } }
- assertThat(expectAxes).isEqualTo(actualAxes)
+ assertThat(actualAxes).isEqualTo(expectAxes)
}
private fun assertSameAxes(expectVarSettings: String, actual: Font) {
@@ -46,7 +46,7 @@ class FontInterpolatorTest : SysuiTestCase() {
it.sortBy { axis -> axis.tag }
}
val actualAxes = actual.axes?.also { it.sortBy { axis -> axis.tag } }
- assertThat(expectAxes).isEqualTo(actualAxes)
+ assertThat(actualAxes).isEqualTo(expectAxes)
}
@Test
@@ -61,7 +61,7 @@ class FontInterpolatorTest : SysuiTestCase() {
val interp = FontInterpolator()
assertSameAxes(startFont, interp.lerp(startFont, endFont, 0f))
assertSameAxes(endFont, interp.lerp(startFont, endFont, 1f))
- assertSameAxes("'wght' 496, 'ital' 0.5, 'GRAD' 450", interp.lerp(startFont, endFont, 0.5f))
+ assertSameAxes("'wght' 500, 'ital' 0.5, 'GRAD' 450", interp.lerp(startFont, endFont, 0.5f))
}
@Test
@@ -74,7 +74,7 @@ class FontInterpolatorTest : SysuiTestCase() {
.build()
val interp = FontInterpolator()
- assertSameAxes("'wght' 249, 'ital' 0.5", interp.lerp(startFont, endFont, 0.5f))
+ assertSameAxes("'wght' 250, 'ital' 0.5", interp.lerp(startFont, endFont, 0.5f))
}
@Test
@@ -118,7 +118,7 @@ class FontInterpolatorTest : SysuiTestCase() {
.setFontVariationSettings("'wght' 1")
.build()
val resultFont = interp.lerp(startFont, endFont, 0.5f)
- for (i in 0..FONT_CACHE_MAX_ENTRIES + 1) {
+ for (i in 0..interp.cacheMaxEntries + 1) {
val f1 = Font.Builder(sFont)
.setFontVariationSettings("'wght' ${i * 100}")
.build()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractorImplTest.kt
index 1f2b64d7adbd..263ce1a2e9f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractorImplTest.kt
@@ -56,6 +56,7 @@ class LogContextInteractorImplTest : SysuiTestCase() {
foldProvider,
KeyguardTransitionInteractor(
keyguardTransitionRepository,
+ testScope.backgroundScope
),
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
index 039682c88498..a00e5456b711 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
@@ -11,7 +11,6 @@ import com.android.systemui.complication.ComplicationHostViewController
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel
import com.android.systemui.statusbar.BlurUtils
import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
@@ -23,9 +22,7 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mock
-import org.mockito.Mockito.anyLong
import org.mockito.Mockito.atLeastOnce
-import org.mockito.Mockito.eq
import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
@@ -92,16 +89,10 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
}
@Test
- fun testWakeUpCallsExecutor() {
- val mockExecutor: DelayableExecutor = mock()
- val mockCallback: Runnable = mock()
+ fun testWakeUpSetsExitAnimationsRunning() {
+ controller.wakeUp()
- controller.wakeUp(
- doneCallback = mockCallback,
- executor = mockExecutor,
- )
-
- verify(mockExecutor).executeDelayed(eq(mockCallback), anyLong())
+ verify(stateController).setExitAnimationsRunning(true)
}
@Test
@@ -112,10 +103,7 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
verify(mockStartAnimator, never()).cancel()
- controller.wakeUp(
- doneCallback = mock(),
- executor = mock(),
- )
+ controller.wakeUp()
// Verify that we cancelled the start animator in favor of the exit
// animator.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
index cfd51e3901bd..d0d348d53405 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -23,7 +23,6 @@ import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -498,18 +497,14 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
true /*shouldShowComplication*/);
mMainExecutor.runAllReady();
- final Runnable callback = mock(Runnable.class);
- mService.onWakeUp(callback);
- mMainExecutor.runAllReady();
- verify(mDreamOverlayContainerViewController).wakeUp(callback, mMainExecutor);
+ mService.onWakeUp();
+ verify(mDreamOverlayContainerViewController).wakeUp();
verify(mDreamOverlayCallbackController).onWakeUp();
}
@Test
public void testWakeUpBeforeStartDoesNothing() {
- final Runnable callback = mock(Runnable.class);
- mService.onWakeUp(callback);
- mMainExecutor.runAllReady();
- verify(mDreamOverlayContainerViewController, never()).wakeUp(callback, mMainExecutor);
+ mService.onWakeUp();
+ verify(mDreamOverlayContainerViewController, never()).wakeUp();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java
index d934f761f7c5..39fcd417ec7a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard;
+import static com.android.systemui.flags.Flags.KEYGUARD_TALKBACK_FIX;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_DISCLOSURE;
@@ -42,6 +43,7 @@ import androidx.test.filters.SmallTest;
import com.android.keyguard.logging.KeyguardLogger;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -81,8 +83,10 @@ public class KeyguardIndicationRotateTextViewControllerTest extends SysuiTestCas
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mView.getTextColors()).thenReturn(ColorStateList.valueOf(Color.WHITE));
+ FakeFeatureFlags flags = new FakeFeatureFlags();
+ flags.set(KEYGUARD_TALKBACK_FIX, true);
mController = new KeyguardIndicationRotateTextViewController(mView, mExecutor,
- mStatusBarStateController, mLogger);
+ mStatusBarStateController, mLogger, flags);
mController.onViewAttached();
verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
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 f31ac00051f6..1f353e1090d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -71,6 +71,7 @@ import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.flags.Flags;
+import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.settings.UserTracker;
@@ -105,6 +106,9 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import kotlinx.coroutines.CoroutineDispatcher;
+import kotlinx.coroutines.flow.Flow;
+
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@SmallTest
@@ -156,6 +160,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
private @Mock CentralSurfaces mCentralSurfaces;
private @Mock UiEventLogger mUiEventLogger;
private @Mock SessionTracker mSessionTracker;
+ private @Mock CoroutineDispatcher mDispatcher;
+ private @Mock DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
private FakeFeatureFlags mFeatureFlags;
@@ -171,6 +177,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
final ViewRootImpl testViewRoot = mock(ViewRootImpl.class);
when(testViewRoot.getView()).thenReturn(mock(View.class));
when(mStatusBarKeyguardViewManager.getViewRootImpl()).thenReturn(testViewRoot);
+ when(mDreamingToLockscreenTransitionViewModel.getDreamOverlayAlpha())
+ .thenReturn(mock(Flow.class));
mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext,
mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
mConfigurationController, mViewMediator, mKeyguardBypassController,
@@ -186,6 +194,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
}
@Test
+ @TestableLooper.RunWithLooper(setAsMainLooper = true)
public void onLockdown_showKeyguard_evenIfKeyguardIsNotEnabledExternally() {
// GIVEN keyguard is not enabled and isn't showing
mViewMediator.onSystemReady();
@@ -629,7 +638,9 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
() -> mNotificationShadeWindowController,
() -> mActivityLaunchAnimator,
() -> mScrimController,
- mFeatureFlags);
+ mFeatureFlags,
+ mDispatcher,
+ () -> mDreamingToLockscreenTransitionViewModel);
mViewMediator.start();
mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null, null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt
index 78a65a8473db..644736899b6c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ResourceTrimmerTest.kt
@@ -70,7 +70,10 @@ class ResourceTrimmerTest : SysuiTestCase() {
resourceTrimmer =
ResourceTrimmer(
keyguardInteractor,
- KeyguardTransitionInteractor(keyguardTransitionRepository),
+ KeyguardTransitionInteractor(
+ keyguardTransitionRepository,
+ testScope.backgroundScope
+ ),
globalWindowManager,
testScope.backgroundScope,
testDispatcher,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index e61620beeff3..1090c15d8625 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -215,7 +215,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
)
keyguardTransitionRepository = FakeKeyguardTransitionRepository()
val keyguardTransitionInteractor =
- KeyguardTransitionInteractor(keyguardTransitionRepository)
+ KeyguardTransitionInteractor(keyguardTransitionRepository, testScope.backgroundScope)
return DeviceEntryFaceAuthRepositoryImpl(
mContext,
fmOverride,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
index 6af122051afc..71e73cbd768f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
@@ -82,7 +82,8 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
bouncerRepository = FakeKeyguardBouncerRepository()
faceAuthRepository = FakeDeviceEntryFaceAuthRepository()
keyguardTransitionRepository = FakeKeyguardTransitionRepository()
- keyguardTransitionInteractor = KeyguardTransitionInteractor(keyguardTransitionRepository)
+ keyguardTransitionInteractor =
+ KeyguardTransitionInteractor(keyguardTransitionRepository, testScope.backgroundScope)
underTest =
SystemUIKeyguardFaceAuthInteractor(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt
index 5de24e4fc322..f63be610fd11 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt
@@ -292,7 +292,8 @@ class KeyguardLongPressInteractorTest : SysuiTestCase() {
scope = testScope.backgroundScope,
transitionInteractor =
KeyguardTransitionInteractor(
- repository = keyguardTransitionRepository,
+ keyguardTransitionRepository,
+ testScope.backgroundScope
),
repository = keyguardRepository,
logger = logger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
index d66e42009348..fa4941cbb895 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
@@ -27,11 +27,14 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
+import com.android.systemui.keyguard.shared.model.KeyguardState.OFF
+import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -46,11 +49,12 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
private lateinit var underTest: KeyguardTransitionInteractor
private lateinit var repository: FakeKeyguardTransitionRepository
+ private val testScope = TestScope()
@Before
fun setUp() {
repository = FakeKeyguardTransitionRepository()
- underTest = KeyguardTransitionInteractor(repository)
+ underTest = KeyguardTransitionInteractor(repository, testScope.backgroundScope)
}
@Test
@@ -108,17 +112,39 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
}
@Test
- fun keyguardStateTests() = runTest {
+ fun finishedKeyguardStateTests() = testScope.runTest {
val finishedSteps by collectValues(underTest.finishedKeyguardState)
+ runCurrent()
+ val steps = mutableListOf<TransitionStep>()
+
+ steps.add(TransitionStep(AOD, PRIMARY_BOUNCER, 0f, STARTED))
+ steps.add(TransitionStep(AOD, PRIMARY_BOUNCER, 0.5f, RUNNING))
+ steps.add(TransitionStep(AOD, PRIMARY_BOUNCER, 1f, FINISHED))
+ steps.add(TransitionStep(PRIMARY_BOUNCER, AOD, 0f, STARTED))
+ steps.add(TransitionStep(PRIMARY_BOUNCER, AOD, 0.9f, RUNNING))
+ steps.add(TransitionStep(PRIMARY_BOUNCER, AOD, 1f, FINISHED))
+ steps.add(TransitionStep(AOD, GONE, 1f, STARTED))
+ steps.forEach {
+ repository.sendTransitionStep(it)
+ runCurrent()
+ }
+
+ assertThat(finishedSteps).isEqualTo(listOf(LOCKSCREEN, PRIMARY_BOUNCER, AOD))
+ }
+
+ @Test
+ fun startedKeyguardStateTests() = testScope.runTest {
+ val finishedSteps by collectValues(underTest.startedKeyguardState)
+ runCurrent()
val steps = mutableListOf<TransitionStep>()
- steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
- steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
- steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
- steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
- steps.add(TransitionStep(LOCKSCREEN, AOD, 0.9f, RUNNING))
- steps.add(TransitionStep(LOCKSCREEN, AOD, 1f, FINISHED))
+ steps.add(TransitionStep(AOD, PRIMARY_BOUNCER, 0f, STARTED))
+ steps.add(TransitionStep(AOD, PRIMARY_BOUNCER, 0.5f, RUNNING))
+ steps.add(TransitionStep(AOD, PRIMARY_BOUNCER, 1f, FINISHED))
+ steps.add(TransitionStep(PRIMARY_BOUNCER, AOD, 0f, STARTED))
+ steps.add(TransitionStep(PRIMARY_BOUNCER, AOD, 0.9f, RUNNING))
+ steps.add(TransitionStep(PRIMARY_BOUNCER, AOD, 1f, FINISHED))
steps.add(TransitionStep(AOD, GONE, 1f, STARTED))
steps.forEach {
@@ -126,7 +152,7 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
runCurrent()
}
- assertThat(finishedSteps).isEqualTo(listOf(LOCKSCREEN, AOD))
+ assertThat(finishedSteps).isEqualTo(listOf(OFF, PRIMARY_BOUNCER, AOD, GONE))
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index 603f199b468b..30dba23ba394 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -110,7 +110,8 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
keyguardInteractor = createKeyguardInteractor(featureFlags),
shadeRepository = shadeRepository,
keyguardTransitionRepository = mockTransitionRepository,
- keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+ keyguardTransitionInteractor =
+ KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
)
fromLockscreenTransitionInteractor.start()
@@ -119,7 +120,8 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
scope = testScope,
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardTransitionRepository = mockTransitionRepository,
- keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+ keyguardTransitionInteractor =
+ KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
)
fromDreamingTransitionInteractor.start()
@@ -128,7 +130,8 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
scope = testScope,
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardTransitionRepository = mockTransitionRepository,
- keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+ keyguardTransitionInteractor =
+ KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
)
fromAodTransitionInteractor.start()
@@ -137,7 +140,8 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
scope = testScope,
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardTransitionRepository = mockTransitionRepository,
- keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+ keyguardTransitionInteractor =
+ KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
)
fromGoneTransitionInteractor.start()
@@ -146,7 +150,8 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
scope = testScope,
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardTransitionRepository = mockTransitionRepository,
- keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+ keyguardTransitionInteractor =
+ KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
)
fromDozingTransitionInteractor.start()
@@ -155,7 +160,8 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
scope = testScope,
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardTransitionRepository = mockTransitionRepository,
- keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+ keyguardTransitionInteractor =
+ KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
)
fromOccludedTransitionInteractor.start()
@@ -164,7 +170,8 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
scope = testScope,
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardTransitionRepository = mockTransitionRepository,
- keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+ keyguardTransitionInteractor =
+ KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
)
fromAlternateBouncerTransitionInteractor.start()
@@ -173,48 +180,14 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
scope = testScope,
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardTransitionRepository = mockTransitionRepository,
- keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+ keyguardTransitionInteractor =
+ KeyguardTransitionInteractor(transitionRepository, testScope.backgroundScope),
keyguardSecurityModel = keyguardSecurityModel,
)
fromPrimaryBouncerTransitionInteractor.start()
}
@Test
- fun dreamingToLockscreen() =
- testScope.runTest {
- // GIVEN a device is dreaming
- keyguardRepository.setDreamingWithOverlay(true)
- keyguardRepository.setWakefulnessModel(startingToWake())
- runCurrent()
-
- // GIVEN a prior transition has run to DREAMING
- runTransition(KeyguardState.LOCKSCREEN, KeyguardState.DREAMING)
-
- // WHEN doze is complete
- keyguardRepository.setDozeTransitionModel(
- DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
- )
- // AND dreaming has stopped
- keyguardRepository.setDreamingWithOverlay(false)
- advanceUntilIdle()
- // AND then occluded has stopped
- keyguardRepository.setKeyguardOccluded(false)
- advanceUntilIdle()
-
- val info =
- withArgCaptor<TransitionInfo> {
- verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
- }
- // THEN a transition to BOUNCER should occur
- assertThat(info.ownerName).isEqualTo("FromDreamingTransitionInteractor")
- assertThat(info.from).isEqualTo(KeyguardState.DREAMING)
- assertThat(info.to).isEqualTo(KeyguardState.LOCKSCREEN)
- assertThat(info.animator).isNotNull()
-
- coroutineContext.cancelChildren()
- }
-
- @Test
fun lockscreenToPrimaryBouncerViaBouncerShowingCall() =
testScope.runTest {
// GIVEN a device that has at least woken up
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
index 4440946a2383..08e99dc6b7d0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
@@ -29,6 +29,7 @@ import com.android.systemui.statusbar.LightRevealEffect
import com.android.systemui.statusbar.LightRevealScrim
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
@@ -45,7 +46,7 @@ class LightRevealScrimInteractorTest : SysuiTestCase() {
private val fakeLightRevealScrimRepository = FakeLightRevealScrimRepository()
private val keyguardTransitionInteractor =
- KeyguardTransitionInteractor(fakeKeyguardTransitionRepository)
+ KeyguardTransitionInteractor(fakeKeyguardTransitionRepository, TestScope().backgroundScope)
private lateinit var underTest: LightRevealScrimInteractor
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
index cdd06acf4370..a3413466d62e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
@@ -25,11 +25,12 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.util.mockito.mock
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -42,13 +43,12 @@ import org.junit.runner.RunWith
class DreamingToLockscreenTransitionViewModelTest : SysuiTestCase() {
private lateinit var underTest: DreamingToLockscreenTransitionViewModel
private lateinit var repository: FakeKeyguardTransitionRepository
- private lateinit var transitionAnimation: KeyguardTransitionAnimationFlow
@Before
fun setUp() {
repository = FakeKeyguardTransitionRepository()
- val interactor = KeyguardTransitionInteractor(repository)
- underTest = DreamingToLockscreenTransitionViewModel(interactor)
+ val interactor = KeyguardTransitionInteractor(repository, TestScope().backgroundScope)
+ underTest = DreamingToLockscreenTransitionViewModel(interactor, mock())
}
@Test
@@ -60,17 +60,15 @@ class DreamingToLockscreenTransitionViewModelTest : SysuiTestCase() {
val job =
underTest.dreamOverlayTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
- // Should start running here...
repository.sendTransitionStep(step(0f, TransitionState.STARTED))
repository.sendTransitionStep(step(0f))
repository.sendTransitionStep(step(0.3f))
repository.sendTransitionStep(step(0.5f))
repository.sendTransitionStep(step(0.6f))
- // ...up to here
repository.sendTransitionStep(step(0.8f))
repository.sendTransitionStep(step(1f))
- assertThat(values.size).isEqualTo(5)
+ assertThat(values.size).isEqualTo(7)
values.forEach { assertThat(it).isIn(Range.closed(0f, 100f)) }
job.cancel()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
index 40511a06d486..694539b0cbfe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
@@ -29,6 +29,7 @@ import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -45,7 +46,7 @@ class GoneToDreamingTransitionViewModelTest : SysuiTestCase() {
@Before
fun setUp() {
repository = FakeKeyguardTransitionRepository()
- val interactor = KeyguardTransitionInteractor(repository)
+ val interactor = KeyguardTransitionInteractor(repository, TestScope().backgroundScope)
underTest = GoneToDreamingTransitionViewModel(interactor)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
index 73fe380f01c7..b6368cf57f9e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
@@ -219,6 +219,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
transitionInteractor =
KeyguardTransitionInteractor(
repository = FakeKeyguardTransitionRepository(),
+ scope = testScope.backgroundScope
),
repository = repository,
logger = UiEventLoggerFake(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
index c98058dd22a7..ea17751782c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
@@ -29,6 +29,7 @@ import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -45,7 +46,7 @@ class LockscreenToDreamingTransitionViewModelTest : SysuiTestCase() {
@Before
fun setUp() {
repository = FakeKeyguardTransitionRepository()
- val interactor = KeyguardTransitionInteractor(repository)
+ val interactor = KeyguardTransitionInteractor(repository, TestScope().backgroundScope)
underTest = LockscreenToDreamingTransitionViewModel(interactor)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
index 031b7fb13d26..bf56a981fa31 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
@@ -29,6 +29,7 @@ import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -45,7 +46,7 @@ class LockscreenToOccludedTransitionViewModelTest : SysuiTestCase() {
@Before
fun setUp() {
repository = FakeKeyguardTransitionRepository()
- val interactor = KeyguardTransitionInteractor(repository)
+ val interactor = KeyguardTransitionInteractor(repository, TestScope().backgroundScope)
underTest = LockscreenToOccludedTransitionViewModel(interactor)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
index c7ff8826a17c..34da26ecc0bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
@@ -29,6 +29,7 @@ import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -45,7 +46,7 @@ class OccludedToLockscreenTransitionViewModelTest : SysuiTestCase() {
@Before
fun setUp() {
repository = FakeKeyguardTransitionRepository()
- val interactor = KeyguardTransitionInteractor(repository)
+ val interactor = KeyguardTransitionInteractor(repository, TestScope().backgroundScope)
underTest = OccludedToLockscreenTransitionViewModel(interactor)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
index db251a0b2258..65b2ef767afe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
@@ -33,6 +33,7 @@ import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -54,7 +55,7 @@ class PrimaryBouncerToGoneTransitionViewModelTest : SysuiTestCase() {
fun setUp() {
MockitoAnnotations.initMocks(this)
repository = FakeKeyguardTransitionRepository()
- val interactor = KeyguardTransitionInteractor(repository)
+ val interactor = KeyguardTransitionInteractor(repository, TestScope().backgroundScope)
underTest =
PrimaryBouncerToGoneTransitionViewModel(
interactor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
index 07f7c158fc4d..2aff90c47189 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
@@ -63,6 +63,7 @@ import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -146,7 +147,7 @@ class MediaCarouselControllerTest : SysuiTestCase() {
debugLogger,
mediaFlags,
keyguardUpdateMonitor,
- KeyguardTransitionInteractor(repository = transitionRepository),
+ KeyguardTransitionInteractor(transitionRepository, TestScope().backgroundScope),
)
verify(configurationController).addCallback(capture(configListener))
verify(mediaDataManager).addListener(capture(listener))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
index 7b673bc2b31e..f6075add6afe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
@@ -2420,7 +2420,6 @@ public class MediaControlPanelTest : SysuiTestCase() {
@Test
fun playTurbulenceNoise_finishesAfterDuration() {
- fakeFeatureFlag.set(Flags.UMO_SURFACE_RIPPLE, true)
fakeFeatureFlag.set(Flags.UMO_TURBULENCE_NOISE, true)
val semanticActions =
@@ -2452,6 +2451,29 @@ public class MediaControlPanelTest : SysuiTestCase() {
}
@Test
+ fun playTurbulenceNoise_whenPlaybackStateIsNotPlaying_doesNotPlayTurbulence() {
+ fakeFeatureFlag.set(Flags.UMO_TURBULENCE_NOISE, true)
+
+ val semanticActions =
+ MediaButton(
+ custom0 =
+ MediaAction(
+ icon = null,
+ action = {},
+ contentDescription = "custom0",
+ background = null
+ ),
+ )
+ val data = mediaData.copy(semanticActions = semanticActions)
+ player.attachPlayer(viewHolder)
+ player.bindPlayer(data, KEY)
+
+ viewHolder.action0.callOnClick()
+
+ assertThat(turbulenceNoiseView.visibility).isEqualTo(View.INVISIBLE)
+ }
+
+ @Test
fun outputSwitcher_hasCustomIntent_openOverLockscreen() {
// When the device for a media player has an intent that opens over lockscreen
val pendingIntent = mock(PendingIntent::class.java)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 6d8c9b106881..7df54d44e69e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -280,6 +280,50 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
}
@Test
+ public void onBindViewHolder_bindConnectedRemoteDeviceWithOnGoingSession_verifyView() {
+ when(mMediaDevice1.hasOngoingSession()).thenReturn(true);
+ when(mMediaOutputController.getSelectableMediaDevice()).thenReturn(
+ ImmutableList.of());
+ when(mMediaOutputController.isCurrentConnectedDeviceRemote()).thenReturn(true);
+ mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
+ .onCreateViewHolder(new LinearLayout(mContext), 0);
+ mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
+
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_1);
+ assertThat(mViewHolder.mStatusIcon.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mEndTouchArea.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onBindViewHolder_bindConnectedRemoteDeviceWithHostOnGoingSession_verifyView() {
+ when(mMediaDevice1.hasOngoingSession()).thenReturn(true);
+ when(mMediaDevice1.isHostForOngoingSession()).thenReturn(true);
+ when(mMediaOutputController.getSelectableMediaDevice()).thenReturn(
+ ImmutableList.of());
+ when(mMediaOutputController.isCurrentConnectedDeviceRemote()).thenReturn(true);
+ mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
+ .onCreateViewHolder(new LinearLayout(mContext), 0);
+ mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
+
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_1);
+ assertThat(mViewHolder.mStatusIcon.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mEndClickIcon.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mEndTouchArea.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
public void onBindViewHolder_bindConnectedDeviceWithMutingExpectedDeviceExist_verifyView() {
when(mMediaOutputController.hasMutingExpectedDevice()).thenReturn(true);
when(mMediaOutputController.isCurrentConnectedDeviceRemote()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java
index 9dba9b5b3c3e..f8971fd7c99c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogTest.java
@@ -136,7 +136,10 @@ public class MediaOutputBroadcastDialogTest extends SysuiTestCase {
@After
public void tearDown() {
- mMediaOutputBroadcastDialog.dismissDialog();
+ if (mMediaOutputBroadcastDialog.mAlertDialog != null){
+ mMediaOutputBroadcastDialog.mAlertDialog.dismiss();
+ }
+ mMediaOutputBroadcastDialog.dismiss();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/multishade/domain/interactor/MultiShadeMotionEventInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/multishade/domain/interactor/MultiShadeMotionEventInteractorTest.kt
index 19f9960558b2..9e5422470d8b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/multishade/domain/interactor/MultiShadeMotionEventInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/multishade/domain/interactor/MultiShadeMotionEventInteractorTest.kt
@@ -99,6 +99,7 @@ class MultiShadeMotionEventInteractorTest : SysuiTestCase() {
keyguardTransitionInteractor =
KeyguardTransitionInteractor(
repository = keyguardTransitionRepository,
+ scope = testScope.backgroundScope
),
falsingManager = falsingManager,
shadeController = shadeController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
index e99f8b6aa47b..0954f6f0ffaf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -72,6 +72,7 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
+import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.doNothing
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
@@ -227,12 +228,15 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
// region showNoteTask
@Test
- fun showNoteTask_keyguardIsLocked_shouldStartActivityAndLogUiEvent() {
- val expectedInfo = NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = true)
+ fun showNoteTaskAsUser_keyguardIsLocked_shouldStartActivityWithExpectedUserAndLogUiEvent() {
+ val user10 = UserHandle.of(/* userId= */ 10)
+ val expectedInfo =
+ NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = true, user = user10)
whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
- createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
+ createNoteTaskController()
+ .showNoteTaskAsUser(entryPoint = expectedInfo.entryPoint!!, user = user10)
val intentCaptor = argumentCaptor<Intent>()
val userCaptor = argumentCaptor<UserHandle>()
@@ -245,21 +249,18 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
hasFlags(FLAG_ACTIVITY_NEW_DOCUMENT)
extras().bool(EXTRA_USE_STYLUS_MODE).isTrue()
}
- assertThat(userCaptor.value).isEqualTo(userTracker.userHandle)
+ assertThat(userCaptor.value).isEqualTo(user10)
verify(eventLogger).logNoteTaskOpened(expectedInfo)
verifyZeroInteractions(bubbles)
}
@Test
- fun showNoteTaskWithUser_keyguardIsLocked_shouldStartActivityWithExpectedUserAndLogUiEvent() {
- val user10 = UserHandle.of(/* userId= */ 10)
- val expectedInfo =
- NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = true, user = user10)
+ fun showNoteTask_keyguardIsLocked_notesIsClosed_shouldStartActivityAndLogUiEvent() {
+ val expectedInfo = NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = true)
whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
- createNoteTaskController()
- .showNoteTaskAsUser(entryPoint = expectedInfo.entryPoint!!, user = user10)
+ createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
val intentCaptor = argumentCaptor<Intent>()
val userCaptor = argumentCaptor<UserHandle>()
@@ -272,7 +273,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
hasFlags(FLAG_ACTIVITY_NEW_DOCUMENT)
extras().bool(EXTRA_USE_STYLUS_MODE).isTrue()
}
- assertThat(userCaptor.value).isEqualTo(user10)
+ assertThat(userCaptor.value).isEqualTo(userTracker.userHandle)
verify(eventLogger).logNoteTaskOpened(expectedInfo)
verifyZeroInteractions(bubbles)
}
@@ -301,15 +302,31 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
}
@Test
- fun showNoteTask_keyguardIsUnlocked_shouldStartBubblesWithoutLoggingUiEvent() {
+ fun showNoteTask_keyguardIsUnlocked_noteIsClosed_shouldStartBubblesWithoutLoggingUiEvent() {
+ val expectedInfo = NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = false)
+ whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
+
+ createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
+
+ // Context package name used to create bubble icon from drawable resource id
+ verify(context, atLeastOnce()).packageName
+ verifyNoteTaskOpenInBubbleInUser(userTracker.userHandle)
+ verifyZeroInteractions(eventLogger)
+ }
+
+ @Test
+ fun showNoteTask_keyguardIsUnlocked_noteIsOpen_shouldStartBubblesWithoutLoggingUiEvent() {
val expectedInfo = NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = false)
whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
+ whenever(activityManager.getRunningTasks(anyInt()))
+ .thenReturn(listOf(NOTE_RUNNING_TASK_INFO))
createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
// Context package name used to create bubble icon from drawable resource id
- verify(context).packageName
+ verify(context, atLeastOnce()).packageName
verifyNoteTaskOpenInBubbleInUser(userTracker.userHandle)
verifyZeroInteractions(eventLogger)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
index 34354504abf0..24f39d187f88 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
@@ -16,37 +16,47 @@
package com.android.systemui.notetask
import android.os.UserHandle
-import android.test.suitebuilder.annotation.SmallTest
-import androidx.test.runner.AndroidJUnit4
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.notetask.NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
/** atest SystemUITests:NoteTaskInfoTest */
@SmallTest
-@RunWith(AndroidJUnit4::class)
+@RunWith(AndroidTestingRunner::class)
internal class NoteTaskInfoTest : SysuiTestCase() {
- private fun createNoteTaskInfo(): NoteTaskInfo =
- NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID, UserHandle.of(0))
-
@Test
fun launchMode_keyguardLocked_launchModeActivity() {
- val underTest = createNoteTaskInfo().copy(isKeyguardLocked = true)
+ val underTest = DEFAULT_INFO.copy(isKeyguardLocked = true)
assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.Activity)
}
@Test
- fun launchMode_keyguardUnlocked_launchModeActivity() {
- val underTest = createNoteTaskInfo().copy(isKeyguardLocked = false)
+ fun launchMode_multiWindowMode_launchModeActivity() {
+ val underTest = DEFAULT_INFO.copy(entryPoint = WIDGET_PICKER_SHORTCUT_IN_MULTI_WINDOW_MODE)
+
+ assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.Activity)
+ }
+
+ @Test
+ fun launchMode_keyguardUnlocked_launchModeAppBubble() {
+ val underTest = DEFAULT_INFO.copy(isKeyguardLocked = false)
assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.AppBubble)
}
private companion object {
- const val NOTES_PACKAGE_NAME = "com.android.note.app"
- const val NOTES_UID = 123456
+
+ val DEFAULT_INFO =
+ NoteTaskInfo(
+ packageName = "com.android.note.app",
+ uid = 123456,
+ user = UserHandle.of(0),
+ )
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperServiceTest.java
index ab321f1b5341..ba3d39248762 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperServiceTest.java
@@ -26,7 +26,7 @@ import android.hardware.HardwareBuffer;
import android.os.RemoteException;
import android.view.Display;
import android.window.ScreenCapture.ScreenshotHardwareBuffer;
-import android.window.ScreenCapture.ScreenshotSync;
+import android.window.ScreenCapture.SynchronousScreenCaptureListener;
import androidx.test.runner.AndroidJUnit4;
@@ -58,7 +58,7 @@ public final class AppClipsScreenshotHelperServiceTest extends SysuiTestCase {
@Mock private Optional<Bubbles> mBubblesOptional;
@Mock private Bubbles mBubbles;
@Mock private ScreenshotHardwareBuffer mScreenshotHardwareBuffer;
- @Mock private ScreenshotSync mScreenshotSync;
+ @Mock private SynchronousScreenCaptureListener mScreenshotSync;
private AppClipsScreenshotHelperService mAppClipsScreenshotHelperService;
@@ -80,7 +80,7 @@ public final class AppClipsScreenshotHelperServiceTest extends SysuiTestCase {
when(mBubblesOptional.isEmpty()).thenReturn(false);
when(mBubblesOptional.get()).thenReturn(mBubbles);
when(mBubbles.getScreenshotExcludingBubble(DEFAULT_DISPLAY)).thenReturn(mScreenshotSync);
- when(mScreenshotSync.get()).thenReturn(null);
+ when(mScreenshotSync.getBuffer()).thenReturn(null);
assertThat(getInterface().takeScreenshot(DEFAULT_DISPLAY)).isNull();
}
@@ -90,7 +90,7 @@ public final class AppClipsScreenshotHelperServiceTest extends SysuiTestCase {
when(mBubblesOptional.isEmpty()).thenReturn(false);
when(mBubblesOptional.get()).thenReturn(mBubbles);
when(mBubbles.getScreenshotExcludingBubble(DEFAULT_DISPLAY)).thenReturn(mScreenshotSync);
- when(mScreenshotSync.get()).thenReturn(mScreenshotHardwareBuffer);
+ when(mScreenshotSync.getBuffer()).thenReturn(mScreenshotHardwareBuffer);
when(mScreenshotHardwareBuffer.getHardwareBuffer()).thenReturn(FAKE_HARDWARE_BUFFER);
when(mScreenshotHardwareBuffer.getColorSpace()).thenReturn(FAKE_COLOR_SPACE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index 16277de850d6..3995e71d24d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -103,8 +103,8 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
@Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
@Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
@Mock lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
- @Mock
- private lateinit var unfoldTransitionProgressProvider: Optional<UnfoldTransitionProgressProvider>
+ @Mock private lateinit var unfoldTransitionProgressProvider:
+ Optional<UnfoldTransitionProgressProvider>
@Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
@Mock
lateinit var primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel
@@ -184,6 +184,7 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
keyguardTransitionInteractor =
KeyguardTransitionInteractor(
repository = FakeKeyguardTransitionRepository(),
+ scope = testScope.backgroundScope
),
falsingManager = FalsingManagerFake(),
shadeController = shadeController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
index 16af208fd531..fe9574251ddb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
@@ -59,6 +59,7 @@ import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
+import java.util.Optional
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.test.TestScope
@@ -72,7 +73,6 @@ import org.mockito.Mock
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
-import java.util.Optional
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidTestingRunner::class)
@@ -106,7 +106,8 @@ class NotificationShadeWindowViewTest : SysuiTestCase() {
@Mock
private lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
@Mock
- private lateinit var unfoldTransitionProgressProvider: Optional<UnfoldTransitionProgressProvider>
+ private lateinit var unfoldTransitionProgressProvider:
+ Optional<UnfoldTransitionProgressProvider>
@Mock private lateinit var notificationInsetsController: NotificationInsetsController
@Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
@Mock
@@ -195,6 +196,7 @@ class NotificationShadeWindowViewTest : SysuiTestCase() {
keyguardTransitionInteractor =
KeyguardTransitionInteractor(
repository = FakeKeyguardTransitionRepository(),
+ scope = testScope.backgroundScope
),
falsingManager = FalsingManagerFake(),
shadeController = shadeController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQuickSettingsContainerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQuickSettingsContainerTest.kt
new file mode 100644
index 000000000000..8bb8f6247e25
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQuickSettingsContainerTest.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade
+
+import android.testing.AndroidTestingRunner
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.qs.QSFragment
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class NotificationsQuickSettingsContainerTest : SysuiTestCase() {
+
+ @Mock private lateinit var qsFrame: View
+ @Mock private lateinit var stackScroller: View
+ @Mock private lateinit var keyguardStatusBar: View
+ @Mock private lateinit var qsFragment: QSFragment
+
+ private lateinit var qsView: ViewGroup
+ private lateinit var qsContainer: View
+
+ private lateinit var underTest: NotificationsQuickSettingsContainer
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ underTest = NotificationsQuickSettingsContainer(context, null)
+
+ setUpViews()
+ underTest.onFinishInflate()
+ underTest.onFragmentViewCreated("QS", qsFragment)
+ }
+
+ @Test
+ fun qsContainerPaddingSetAgainAfterQsRecreated() {
+ val padding = 100
+ underTest.setQSContainerPaddingBottom(padding)
+
+ assertThat(qsContainer.paddingBottom).isEqualTo(padding)
+
+ // We reset the padding before "creating" a new QSFragment
+ qsContainer.setPadding(0, 0, 0, 0)
+ underTest.onFragmentViewCreated("QS", qsFragment)
+
+ assertThat(qsContainer.paddingBottom).isEqualTo(padding)
+ }
+
+ private fun setUpViews() {
+ qsView = FrameLayout(context)
+ qsContainer = View(context)
+ qsContainer.id = R.id.quick_settings_container
+ qsView.addView(qsContainer)
+
+ whenever(qsFrame.findViewById<View>(R.id.qs_frame)).thenReturn(qsFrame)
+ whenever(stackScroller.findViewById<View>(R.id.notification_stack_scroller))
+ .thenReturn(stackScroller)
+ whenever(keyguardStatusBar.findViewById<View>(R.id.keyguard_header))
+ .thenReturn(keyguardStatusBar)
+ whenever(qsFragment.view).thenReturn(qsView)
+
+ val layoutParams = ConstraintLayout.LayoutParams(0, 0)
+ whenever(qsFrame.layoutParams).thenReturn(layoutParams)
+ whenever(stackScroller.layoutParams).thenReturn(layoutParams)
+ whenever(keyguardStatusBar.layoutParams).thenReturn(layoutParams)
+
+ underTest.addView(qsFrame)
+ underTest.addView(stackScroller)
+ underTest.addView(keyguardStatusBar)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 542e0cb728a3..cd0c135264ae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -26,6 +26,7 @@ import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIME
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED;
+import static com.android.systemui.flags.Flags.KEYGUARD_TALKBACK_FIX;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE;
@@ -99,6 +100,7 @@ import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.FaceHelpMessageDeferral;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dock.DockManager;
+import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.keyguard.KeyguardIndication;
import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController;
import com.android.systemui.keyguard.ScreenLifecycle;
@@ -285,6 +287,8 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
Looper.prepare();
}
+ FakeFeatureFlags flags = new FakeFeatureFlags();
+ flags.set(KEYGUARD_TALKBACK_FIX, true);
mController = new KeyguardIndicationController(
mContext,
mTestableLooper.getLooper(),
@@ -297,7 +301,8 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
mFaceHelpMessageDeferral, mock(KeyguardLogger.class),
mAlternateBouncerInteractor,
mAlarmManager,
- mUserTracker
+ mUserTracker,
+ flags
);
mController.init();
mController.setIndicationArea(mIndicationArea);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
index 283efe263f04..257cc5b1b85c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
@@ -221,16 +221,35 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
}
@Test
- fun hunExtensionCancelledWhenHunActionPressed() {
+ fun actionPressCancelsExistingLifetimeExtension() {
whenever(headsUpManager.isSticky(anyString())).thenReturn(true)
addHUN(entry)
+
whenever(headsUpManager.canRemoveImmediately(anyString())).thenReturn(false)
whenever(headsUpManager.getEarliestRemovalTime(anyString())).thenReturn(1000L)
- assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, 0))
+ assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, /* reason = */ 0))
+
actionPressListener.accept(entry)
- executor.advanceClockToLast()
executor.runAllReady()
- verify(headsUpManager, times(1)).removeNotification(eq(entry.key), eq(true))
+ verify(endLifetimeExtension, times(1)).onEndLifetimeExtension(notifLifetimeExtender, entry)
+
+ collectionListener.onEntryRemoved(entry, /* reason = */ 0)
+ verify(headsUpManager, times(1)).removeNotification(eq(entry.key), any())
+ }
+
+ @Test
+ fun actionPressPreventsFutureLifetimeExtension() {
+ whenever(headsUpManager.isSticky(anyString())).thenReturn(true)
+ addHUN(entry)
+
+ actionPressListener.accept(entry)
+ verify(headsUpManager, times(1)).setUserActionMayIndirectlyRemove(entry)
+
+ whenever(headsUpManager.canRemoveImmediately(anyString())).thenReturn(true)
+ assertFalse(notifLifetimeExtender.maybeExtendLifetime(entry, 0))
+
+ collectionListener.onEntryRemoved(entry, /* reason = */ 0)
+ verify(headsUpManager, times(1)).removeNotification(eq(entry.key), any())
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
index 7632d01d4d43..df65c09eb8a9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
@@ -29,6 +30,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.animation.Animator;
@@ -670,6 +672,28 @@ public class NotificationSwipeHelperTest extends SysuiTestCase {
}
@Test
+ public void testForceResetSwipeStateDoesNothingIfTranslationIsZero() {
+ doReturn(FAKE_ROW_WIDTH).when(mNotificationRow).getMeasuredWidth();
+ doReturn(0f).when(mNotificationRow).getTranslationX();
+
+ mSwipeHelper.forceResetSwipeState(mNotificationRow);
+
+ verify(mNotificationRow).getTranslationX();
+ verifyNoMoreInteractions(mNotificationRow);
+ }
+
+ @Test
+ public void testForceResetSwipeStateResetsTranslationAndAlpha() {
+ doReturn(FAKE_ROW_WIDTH).when(mNotificationRow).getMeasuredWidth();
+ doReturn(10f).when(mNotificationRow).getTranslationX();
+
+ mSwipeHelper.forceResetSwipeState(mNotificationRow);
+
+ verify(mNotificationRow).setTranslation(eq(0f));
+ verify(mNotificationRow).setContentAlpha(eq(1f));
+ }
+
+ @Test
public void testContentAlphaRemainsUnchangedWhenFeatureFlagIsDisabled() {
// Returning true prevents alpha fade. In an unmocked scenario the callback is instantiated
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index e12d179c5aa5..88b1eb3d565c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -35,7 +35,6 @@ import org.mockito.Mockito.`when` as whenever
@SmallTest
class StackScrollAlgorithmTest : SysuiTestCase() {
-
@JvmField @Rule
var expect: Expect = Expect.create()
@@ -82,26 +81,58 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
fun resetViewStates_defaultHun_yTranslationIsInset() {
whenever(notificationRow.isPinned).thenReturn(true)
whenever(notificationRow.isHeadsUp).thenReturn(true)
-
- stackScrollAlgorithm.resetViewStates(ambientState, 0)
-
- assertThat(notificationRow.viewState.yTranslation)
- .isEqualTo(stackScrollAlgorithm.mHeadsUpInset)
+ resetViewStates_hunYTranslationIsInset()
}
@Test
- fun resetViewStates_stackMargin_changesHunYTranslation() {
+ fun resetViewStates_defaultHunWithStackMargin_changesHunYTranslation() {
whenever(notificationRow.isPinned).thenReturn(true)
whenever(notificationRow.isHeadsUp).thenReturn(true)
- val minHeadsUpTranslation = context.resources
- .getDimensionPixelSize(R.dimen.notification_side_paddings)
+ resetViewStates_stackMargin_changesHunYTranslation()
+ }
- // split shade case with top margin introduced by shade's status bar
- ambientState.stackTopMargin = 100
- stackScrollAlgorithm.resetViewStates(ambientState, 0)
+ @Test
+ fun resetViewStates_hunAnimatingAway_yTranslationIsInset() {
+ whenever(notificationRow.isHeadsUpAnimatingAway).thenReturn(true)
+ resetViewStates_hunYTranslationIsInset()
+ }
- // top margin presence should decrease heads up translation up to minHeadsUpTranslation
- assertThat(notificationRow.viewState.yTranslation).isEqualTo(minHeadsUpTranslation)
+ @Test
+ fun resetViewStates_hunAnimatingAway_StackMarginChangesHunYTranslation() {
+ whenever(notificationRow.isHeadsUpAnimatingAway).thenReturn(true)
+ resetViewStates_stackMargin_changesHunYTranslation()
+ }
+
+ @Test
+ fun resetViewStates_hunAnimatingAway_bottomNotClipped() {
+ whenever(notificationRow.isHeadsUpAnimatingAway).thenReturn(true)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ assertThat(notificationRow.viewState.clipBottomAmount).isEqualTo(0)
+ }
+
+ @Test
+ fun resetViewStates_hunsOverlapping_bottomHunClipped() {
+ val topHun = mockExpandableNotificationRow()
+ val bottomHun = mockExpandableNotificationRow()
+ whenever(topHun.isHeadsUp).thenReturn(true)
+ whenever(topHun.isPinned).thenReturn(true)
+ whenever(bottomHun.isHeadsUp).thenReturn(true)
+ whenever(bottomHun.isPinned).thenReturn(true)
+
+ resetViewStates_hunsOverlapping_bottomHunClipped(topHun, bottomHun)
+ }
+
+ @Test
+ fun resetViewStates_hunsOverlappingAndBottomHunAnimatingAway_bottomHunClipped() {
+ val topHun = mockExpandableNotificationRow()
+ val bottomHun = mockExpandableNotificationRow()
+ whenever(topHun.isHeadsUp).thenReturn(true)
+ whenever(topHun.isPinned).thenReturn(true)
+ whenever(bottomHun.isHeadsUpAnimatingAway).thenReturn(true)
+
+ resetViewStates_hunsOverlapping_bottomHunClipped(topHun, bottomHun)
}
@Test
@@ -855,6 +886,57 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
ambientState.stackHeight = ambientState.stackEndHeight * fraction
}
+ private fun resetViewStates_hunYTranslationIsInset() {
+ stackScrollAlgorithm.resetViewStates(ambientState, 0)
+
+ assertThat(notificationRow.viewState.yTranslation)
+ .isEqualTo(stackScrollAlgorithm.mHeadsUpInset)
+ }
+
+ private fun resetViewStates_stackMargin_changesHunYTranslation() {
+ val stackTopMargin = 50
+ val headsUpTranslationY = stackScrollAlgorithm.mHeadsUpInset - stackTopMargin
+
+ // we need the shelf to mock the real-life behaviour of StackScrollAlgorithm#updateChild
+ ambientState.shelf = notificationShelf
+
+ // split shade case with top margin introduced by shade's status bar
+ ambientState.stackTopMargin = stackTopMargin
+ stackScrollAlgorithm.resetViewStates(ambientState, 0)
+
+ // heads up translation should be decreased by the top margin
+ assertThat(notificationRow.viewState.yTranslation).isEqualTo(headsUpTranslationY)
+ }
+
+ private fun resetViewStates_hunsOverlapping_bottomHunClipped(
+ topHun: ExpandableNotificationRow,
+ bottomHun: ExpandableNotificationRow
+ ) {
+ val topHunHeight = mContext.resources.getDimensionPixelSize(
+ R.dimen.notification_content_min_height)
+ val bottomHunHeight = mContext.resources.getDimensionPixelSize(
+ R.dimen.notification_max_heads_up_height)
+ whenever(topHun.intrinsicHeight).thenReturn(topHunHeight)
+ whenever(bottomHun.intrinsicHeight).thenReturn(bottomHunHeight)
+
+ // we need the shelf to mock the real-life behaviour of StackScrollAlgorithm#updateChild
+ ambientState.shelf = notificationShelf
+
+ // add two overlapping HUNs
+ hostView.removeAllViews()
+ hostView.addView(topHun)
+ hostView.addView(bottomHun)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ // the height shouldn't change
+ assertThat(topHun.viewState.height).isEqualTo(topHunHeight)
+ assertThat(bottomHun.viewState.height).isEqualTo(bottomHunHeight)
+ // the HUN at the bottom should be clipped
+ assertThat(topHun.viewState.clipBottomAmount).isEqualTo(0)
+ assertThat(bottomHun.viewState.clipBottomAmount).isEqualTo(bottomHunHeight - topHunHeight)
+ }
+
private fun resetViewStates_expansionChanging_notificationAlphaUpdated(
expansionFraction: Float,
expectedAlpha: Float,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index 7e69efaaa640..5d2b59b6e00e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -67,6 +67,8 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
private float mQsExpansion;
private int mCutoutTopInset = 0;
private boolean mIsSplitShade = false;
+ private boolean mBypassEnabled = false;
+ private int mUnlockedStackScrollerPadding = 0;
private float mUdfpsTop = -1;
private float mClockBottom = SCREEN_HEIGHT / 2;
private boolean mClockTopAligned;
@@ -339,15 +341,52 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
}
@Test
- public void notifMinPaddingAlignedWithClockInSplitShadeMode() {
+ public void notifPadding_splitShade() {
givenLockScreen();
mIsSplitShade = true;
mKeyguardStatusHeight = 200;
// WHEN the position algorithm is run
positionClock();
// THEN the padding DOESN'T adjust for keyguard status height.
- assertThat(mClockPositionAlgorithm.getLockscreenMinStackScrollerPadding())
- .isEqualTo(mKeyguardStatusBarHeaderHeight);
+ assertThat(mClockPositionAlgorithm.getLockscreenNotifPadding(/* nsslTop= */ 10))
+ .isEqualTo(mKeyguardStatusBarHeaderHeight - 10);
+ }
+
+ @Test
+ public void notifPadding_portraitShade_bypassOff() {
+ givenLockScreen();
+ mIsSplitShade = false;
+ mBypassEnabled = false;
+
+ // mMinTopMargin = 100 = 80 + max(20, 0)
+ mKeyguardStatusBarHeaderHeight = 80;
+ mUserSwitchHeight = 20;
+ when(mResources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin))
+ .thenReturn(0);
+
+ mKeyguardStatusHeight = 200;
+
+ // WHEN the position algorithm is run
+ positionClock();
+
+ // THEN padding = 300 = mMinTopMargin(100) + mKeyguardStatusHeight(200)
+ assertThat(mClockPositionAlgorithm.getLockscreenNotifPadding(/* nsslTop= */ 50))
+ .isEqualTo(300);
+ }
+
+ @Test
+ public void notifPadding_portraitShade_bypassOn() {
+ givenLockScreen();
+ mIsSplitShade = false;
+ mBypassEnabled = true;
+ mUnlockedStackScrollerPadding = 200;
+
+ // WHEN the position algorithm is run
+ positionClock();
+
+ // THEN padding = 150 = mUnlockedStackScrollerPadding(200) - nsslTop(50)
+ assertThat(mClockPositionAlgorithm.getLockscreenNotifPadding(/* nsslTop= */ 50))
+ .isEqualTo(150);
}
@Test
@@ -589,8 +628,8 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
0 /* userSwitchPreferredY */,
mDark,
ZERO_DRAG,
- false /* bypassEnabled */,
- 0 /* unlockedStackScrollerPadding */,
+ mBypassEnabled,
+ mUnlockedStackScrollerPadding,
mQsExpansion,
mCutoutTopInset,
mIsSplitShade,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java
index 6068f0d17720..5cea931e2070 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java
@@ -16,6 +16,9 @@
package com.android.systemui.statusbar.phone;
+import static android.view.View.ACCESSIBILITY_LIVE_REGION_NONE;
+import static android.view.View.ACCESSIBILITY_LIVE_REGION_POLITE;
+
import static com.google.common.truth.Truth.assertThat;
import android.testing.AndroidTestingRunner;
@@ -57,6 +60,22 @@ public class KeyguardIndicationTextViewTest extends SysuiTestCase {
}
@Test
+ public void alwaysAnnounce_setsLiveRegionToNone() {
+ mKeyguardIndicationTextView.setAlwaysAnnounceEnabled(true);
+
+ assertThat(mKeyguardIndicationTextView.getAccessibilityLiveRegion()).isEqualTo(
+ ACCESSIBILITY_LIVE_REGION_NONE);
+ }
+
+ @Test
+ public void alwaysAnnounce_setsLiveRegionToDefaultPolite_whenDisabled() {
+ mKeyguardIndicationTextView.setAlwaysAnnounceEnabled(false);
+
+ assertThat(mKeyguardIndicationTextView.getAccessibilityLiveRegion()).isEqualTo(
+ ACCESSIBILITY_LIVE_REGION_POLITE);
+ }
+
+ @Test
public void switchIndication_emptyText_hideIndication() {
mKeyguardIndicationTextView.switchIndication("" /* text */, null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
index c8c24a770a7a..6301fa0be463 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
@@ -47,7 +47,8 @@ class CollapsedStatusBarViewModelImplTest : SysuiTestCase() {
testScope = TestScope(UnconfinedTestDispatcher())
keyguardTransitionRepository = FakeKeyguardTransitionRepository()
- val interactor = KeyguardTransitionInteractor(keyguardTransitionRepository)
+ val interactor =
+ KeyguardTransitionInteractor(keyguardTransitionRepository, testScope.backgroundScope)
underTest = CollapsedStatusBarViewModelImpl(interactor, testScope.backgroundScope)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt
index 67727ae21641..d1c38f6cbea7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseUserSwitcherAdapterTest.kt
@@ -77,6 +77,7 @@ class BaseUserSwitcherAdapterTest : SysuiTestCase() {
)
whenever(controller.users).thenAnswer { users }
+ whenever(controller.isUserSwitcherEnabled).thenReturn(true)
underTest =
object : BaseUserSwitcherAdapter(controller) {
@@ -162,6 +163,19 @@ class BaseUserSwitcherAdapterTest : SysuiTestCase() {
}
@Test
+ fun count_onlyShowsCurrentUserWhenMultiUserDisabled() {
+ whenever(controller.isUserSwitcherEnabled).thenReturn(false)
+ assertThat(underTest.count).isEqualTo(1)
+ assertThat(underTest.getItem(0).isCurrent).isTrue()
+ }
+
+ @Test
+ fun count_doesNotIgnoreAllOtherUsersWhenMultiUserEnabled() {
+ whenever(controller.isUserSwitcherEnabled).thenReturn(true)
+ assertThat(underTest.count).isEqualTo(users.size)
+ }
+
+ @Test
fun getItem() {
assertThat((0 until underTest.count).map { position -> underTest.getItem(position) })
.isEqualTo(users)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
index 487d26d21824..a797e032a353 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
@@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertNotSame;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -346,4 +345,17 @@ public class HeadsUpManagerTest extends AlertingNotificationManagerTest {
assertEquals(HeadsUpManager.NotificationPeekEvent.NOTIFICATION_PEEK.getId(),
mUiEventLoggerFake.eventId(0));
}
+
+ @Test
+ public void testSetUserActionMayIndirectlyRemove() {
+ NotificationEntry notifEntry = new NotificationEntryBuilder()
+ .setSbn(createNewNotification(/* id= */ 0))
+ .build();
+
+ mHeadsUpManager.showNotification(notifEntry);
+ assertFalse(mHeadsUpManager.canRemoveImmediately(notifEntry.getKey()));
+
+ mHeadsUpManager.setUserActionMayIndirectlyRemove(notifEntry);
+ assertTrue(mHeadsUpManager.canRemoveImmediately(notifEntry.getKey()));
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
index 8290dab19bdf..1ab62d00d307 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
@@ -29,6 +29,7 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.qs.tiles.UserDetailItemView
import com.android.systemui.user.data.source.UserRecord
+import com.android.systemui.util.mockito.whenever
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
@@ -68,6 +69,8 @@ class KeyguardUserSwitcherAdapterTest : SysuiTestCase() {
fun setUp() {
MockitoAnnotations.initMocks(this)
+ whenever(userSwitcherController.isUserSwitcherEnabled).thenReturn(true)
+
mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, layoutInflater)
`when`(layoutInflater.inflate(anyInt(), any(ViewGroup::class.java), anyBoolean()))
.thenReturn(inflatedUserDetailItemView)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index 2ea6368ab402..8f725bebfb16 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -16,16 +16,11 @@
package com.android.systemui.volume;
-import static android.media.AudioManager.RINGER_MODE_NORMAL;
-import static android.media.AudioManager.RINGER_MODE_SILENT;
-import static android.media.AudioManager.RINGER_MODE_VIBRATE;
-
import static com.android.systemui.volume.Events.DISMISS_REASON_UNKNOWN;
import static com.android.systemui.volume.Events.SHOW_REASON_UNKNOWN;
import static com.android.systemui.volume.VolumeDialogControllerImpl.STREAMS;
import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotSame;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -298,7 +293,7 @@ public class VolumeDialogImplTest extends SysuiTestCase {
@Test
public void testSelectVibrateFromDrawer() {
final State initialUnsetState = new State();
- initialUnsetState.ringerModeInternal = RINGER_MODE_NORMAL;
+ initialUnsetState.ringerModeInternal = AudioManager.RINGER_MODE_NORMAL;
mDialog.onStateChangedH(initialUnsetState);
mActiveRinger.performClick();
@@ -312,7 +307,7 @@ public class VolumeDialogImplTest extends SysuiTestCase {
@Test
public void testSelectMuteFromDrawer() {
final State initialUnsetState = new State();
- initialUnsetState.ringerModeInternal = RINGER_MODE_NORMAL;
+ initialUnsetState.ringerModeInternal = AudioManager.RINGER_MODE_NORMAL;
mDialog.onStateChangedH(initialUnsetState);
mActiveRinger.performClick();
@@ -334,7 +329,7 @@ public class VolumeDialogImplTest extends SysuiTestCase {
// Make sure we've actually changed the ringer mode.
verify(mVolumeDialogController, times(1)).setRingerMode(
- RINGER_MODE_NORMAL, false);
+ AudioManager.RINGER_MODE_NORMAL, false);
}
/**
@@ -516,85 +511,6 @@ public class VolumeDialogImplTest extends SysuiTestCase {
}
}
- private enum RingerDrawerState {INIT, OPEN, CLOSE}
-
- @Test
- public void ringerModeNormal_ringerContainerDescribesItsState() {
- assertRingerContainerDescribesItsState(RINGER_MODE_NORMAL, RingerDrawerState.INIT);
- }
-
- @Test
- public void ringerModeSilent_ringerContainerDescribesItsState() {
- assertRingerContainerDescribesItsState(RINGER_MODE_SILENT, RingerDrawerState.INIT);
- }
-
- @Test
- public void ringerModeVibrate_ringerContainerDescribesItsState() {
- assertRingerContainerDescribesItsState(RINGER_MODE_VIBRATE, RingerDrawerState.INIT);
- }
-
- @Test
- public void ringerModeNormal_openDrawer_ringerContainerDescribesItsState() {
- assertRingerContainerDescribesItsState(RINGER_MODE_NORMAL, RingerDrawerState.OPEN);
- }
-
- @Test
- public void ringerModeSilent_openDrawer_ringerContainerDescribesItsState() {
- assertRingerContainerDescribesItsState(RINGER_MODE_SILENT, RingerDrawerState.OPEN);
- }
-
- @Test
- public void ringerModeVibrate_openDrawer_ringerContainerDescribesItsState() {
- assertRingerContainerDescribesItsState(RINGER_MODE_VIBRATE, RingerDrawerState.OPEN);
- }
-
- @Test
- public void ringerModeNormal_closeDrawer_ringerContainerDescribesItsState() {
- assertRingerContainerDescribesItsState(RINGER_MODE_NORMAL, RingerDrawerState.CLOSE);
- }
-
- @Test
- public void ringerModeSilent_closeDrawer_ringerContainerDescribesItsState() {
- assertRingerContainerDescribesItsState(RINGER_MODE_SILENT, RingerDrawerState.CLOSE);
- }
-
- @Test
- public void ringerModeVibrate_closeDrawer_ringerContainerDescribesItsState() {
- assertRingerContainerDescribesItsState(RINGER_MODE_VIBRATE, RingerDrawerState.CLOSE);
- }
-
- /**
- * The content description should include ringer state, and the correct one.
- */
- private void assertRingerContainerDescribesItsState(int ringerMode,
- RingerDrawerState drawerState) {
- State state = createShellState();
- state.ringerModeInternal = ringerMode;
- mDialog.onStateChangedH(state);
-
- mDialog.show(SHOW_REASON_UNKNOWN);
-
- if (drawerState != RingerDrawerState.INIT) {
- // in both cases we first open the drawer
- mDialog.toggleRingerDrawer(true);
-
- if (drawerState == RingerDrawerState.CLOSE) {
- mDialog.toggleRingerDrawer(false);
- }
- }
-
- String ringerContainerDescription = mDialog.getSelectedRingerContainerDescription();
- String ringerDescription = mContext.getString(
- mDialog.getStringDescriptionResourceForRingerMode(ringerMode));
-
- if (drawerState == RingerDrawerState.OPEN) {
- assertEquals(ringerDescription, ringerContainerDescription);
- } else {
- assertNotSame(ringerDescription, ringerContainerDescription);
- assertTrue(ringerContainerDescription.startsWith(ringerDescription));
- }
- }
-
@After
public void teardown() {
if (mDialog != null) {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
index fbc2381c3031..61e5b5fc27ea 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
@@ -79,6 +79,10 @@ class FakeUserRepository : UserRepository {
return _userSwitcherSettings.value.isSimpleUserSwitcher
}
+ override fun isUserSwitcherEnabled(): Boolean {
+ return _userSwitcherSettings.value.isUserSwitcherEnabled
+ }
+
fun setUserInfos(infos: List<UserInfo>) {
_userInfos.value = infos
}
diff --git a/packages/overlays/NotesRoleEnabledOverlay/Android.bp b/packages/overlays/NotesRoleEnabledOverlay/Android.bp
index 68ebd9652399..70b783f75ec7 100644
--- a/packages/overlays/NotesRoleEnabledOverlay/Android.bp
+++ b/packages/overlays/NotesRoleEnabledOverlay/Android.bp
@@ -25,6 +25,7 @@ package {
runtime_resource_overlay {
name: "NotesRoleEnabledOverlay",
+ certificate: "platform",
theme: "NotesRoleEnabled",
product_specific: true,
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 1a57bc1b7a0d..ec4203e3390c 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -63,6 +63,7 @@ import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
import android.util.ArrayMap;
import android.util.LocalLog;
+import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -334,7 +335,8 @@ public final class AutofillManagerService
// of time.
synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
if (service != null) {
service.onSwitchInputMethod();
}
@@ -366,11 +368,12 @@ public final class AutofillManagerService
boolean isTemporary) {
mAugmentedAutofillState.setServiceInfo(userId, serviceName, isTemporary);
synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
if (service == null) {
// If we cannot get the service from the services cache, it will call
// updateRemoteAugmentedAutofillService() finally. Skip call this update again.
- getServiceForUserLocked(userId);
+ getServiceForUserWithLocalBinderIdentityLocked(userId);
} else {
service.updateRemoteAugmentedAutofillService();
}
@@ -380,17 +383,46 @@ public final class AutofillManagerService
private void onFieldClassificationServiceNameChanged(
@UserIdInt int userId, @Nullable String serviceName, boolean isTemporary) {
synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
if (service == null) {
// If we cannot get the service from the services cache, it will call
// updateRemoteFieldClassificationService() finally. Skip call this update again.
- getServiceForUserLocked(userId);
+ getServiceForUserWithLocalBinderIdentityLocked(userId);
} else {
service.updateRemoteFieldClassificationService();
}
}
}
+ @GuardedBy("mLock")
+ @Nullable
+ private AutofillManagerServiceImpl getServiceForUserWithLocalBinderIdentityLocked(int userId) {
+ final long token = Binder.clearCallingIdentity();
+ AutofillManagerServiceImpl managerService = null;
+ try {
+ managerService = getServiceForUserLocked(userId);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
+ return managerService;
+ }
+
+ @GuardedBy("mLock")
+ @Nullable
+ private AutofillManagerServiceImpl peekServiceForUserWithLocalBinderIdentityLocked(int userId) {
+ final long token = Binder.clearCallingIdentity();
+ AutofillManagerServiceImpl managerService = null;
+ try {
+ managerService = peekServiceForUserLocked(userId);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
+ return managerService;
+ }
+
@Override // from AbstractMasterSystemService
protected AutofillManagerServiceImpl newServiceLocked(@UserIdInt int resolvedUserId,
boolean disabled) {
@@ -1038,7 +1070,8 @@ public final class AutofillManagerService
mUi.hideAll(null);
synchronized (mLock) {
final AutofillManagerServiceImpl service =
- getServiceForUserLocked(UserHandle.getCallingUserId());
+ getServiceForUserWithLocalBinderIdentityLocked(
+ UserHandle.getCallingUserId());
service.onBackKeyPressed();
}
}
@@ -1537,20 +1570,27 @@ public final class AutofillManagerService
public void addClient(IAutoFillManagerClient client, ComponentName componentName,
int userId, IResultReceiver receiver) {
int flags = 0;
- synchronized (mLock) {
- final int enabledFlags = getServiceForUserLocked(userId).addClientLocked(client,
- componentName);
- if (enabledFlags != 0) {
- flags |= enabledFlags;
- }
- if (sDebug) {
- flags |= AutofillManager.FLAG_ADD_CLIENT_DEBUG;
- }
- if (sVerbose) {
- flags |= AutofillManager.FLAG_ADD_CLIENT_VERBOSE;
+ try {
+ synchronized (mLock) {
+ final int enabledFlags =
+ getServiceForUserWithLocalBinderIdentityLocked(userId)
+ .addClientLocked(client, componentName);
+ if (enabledFlags != 0) {
+ flags |= enabledFlags;
+ }
+ if (sDebug) {
+ flags |= AutofillManager.FLAG_ADD_CLIENT_DEBUG;
+ }
+ if (sVerbose) {
+ flags |= AutofillManager.FLAG_ADD_CLIENT_VERBOSE;
+ }
}
+ } catch (Exception ex) {
+ // Don't do anything, send back default flags
+ Log.wtf(TAG, "addClient(): failed " + ex.toString());
+ } finally {
+ send(receiver, flags);
}
- send(receiver, flags);
}
@Override
@@ -1569,7 +1609,8 @@ public final class AutofillManagerService
public void setAuthenticationResult(Bundle data, int sessionId, int authenticationId,
int userId) {
synchronized (mLock) {
- final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
+ final AutofillManagerServiceImpl service =
+ getServiceForUserWithLocalBinderIdentityLocked(userId);
service.setAuthenticationResultLocked(data, sessionId, authenticationId,
getCallingUid());
}
@@ -1578,7 +1619,8 @@ public final class AutofillManagerService
@Override
public void setHasCallback(int sessionId, int userId, boolean hasIt) {
synchronized (mLock) {
- final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
+ final AutofillManagerServiceImpl service =
+ getServiceForUserWithLocalBinderIdentityLocked(userId);
service.setHasCallback(sessionId, getCallingUid(), hasIt);
}
}
@@ -1608,7 +1650,8 @@ public final class AutofillManagerService
final int taskId = mAm.getTaskIdForActivity(activityToken, false);
final long result;
synchronized (mLock) {
- final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
+ final AutofillManagerServiceImpl service =
+ getServiceForUserWithLocalBinderIdentityLocked(userId);
result = service.startSessionLocked(activityToken, taskId, getCallingUid(),
clientCallback, autofillId, bounds, value, hasCallback, clientActivity,
compatMode, mAllowInstantService, flags);
@@ -1624,51 +1667,72 @@ public final class AutofillManagerService
@Override
public void getFillEventHistory(@NonNull IResultReceiver receiver) throws RemoteException {
+ FillEventHistory fillEventHistory = null;
final int userId = UserHandle.getCallingUserId();
- FillEventHistory fillEventHistory = null;
- synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
- if (service != null) {
- fillEventHistory = service.getFillEventHistory(getCallingUid());
- } else if (sVerbose) {
- Slog.v(TAG, "getFillEventHistory(): no service for " + userId);
+ try {
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
+ if (service != null) {
+ fillEventHistory = service.getFillEventHistory(getCallingUid());
+ } else if (sVerbose) {
+ Slog.v(TAG, "getFillEventHistory(): no service for " + userId);
+ }
}
+ } catch (Exception ex) {
+ // Do not raise the exception, just send back the null response
+ Log.wtf(TAG, "getFillEventHistory(): failed " + ex.toString());
+ } finally {
+ send(receiver, fillEventHistory);
}
- send(receiver, fillEventHistory);
}
@Override
public void getUserData(@NonNull IResultReceiver receiver) throws RemoteException {
+ UserData userData = null;
final int userId = UserHandle.getCallingUserId();
- UserData userData = null;
- synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
- if (service != null) {
- userData = service.getUserData(getCallingUid());
- } else if (sVerbose) {
- Slog.v(TAG, "getUserData(): no service for " + userId);
+ try {
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
+ if (service != null) {
+ userData = service.getUserData(getCallingUid());
+ } else if (sVerbose) {
+ Slog.v(TAG, "getUserData(): no service for " + userId);
+ }
}
+ } catch (Exception ex) {
+ // Do not raise the exception, just send back the null response
+ Log.wtf(TAG, "getUserData(): failed " + ex.toString());
+ } finally {
+ send(receiver, userData);
}
- send(receiver, userData);
}
@Override
public void getUserDataId(@NonNull IResultReceiver receiver) throws RemoteException {
- final int userId = UserHandle.getCallingUserId();
UserData userData = null;
+ final int userId = UserHandle.getCallingUserId();
- synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
- if (service != null) {
- userData = service.getUserData(getCallingUid());
- } else if (sVerbose) {
- Slog.v(TAG, "getUserDataId(): no service for " + userId);
+ try {
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
+ if (service != null) {
+ userData = service.getUserData(getCallingUid());
+ } else if (sVerbose) {
+ Slog.v(TAG, "getUserDataId(): no service for " + userId);
+ }
}
+ } catch (Exception ex) {
+ // Do not raise the exception, just send back the null response
+ Log.wtf(TAG, "getUserDataId(): failed " + ex.toString());
+ } finally {
+ final String userDataId = userData == null ? null : userData.getId();
+ send(receiver, userDataId);
}
- final String userDataId = userData == null ? null : userData.getId();
- send(receiver, userDataId);
}
@Override
@@ -1676,7 +1740,8 @@ public final class AutofillManagerService
final int userId = UserHandle.getCallingUserId();
synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
if (service != null) {
service.setUserData(getCallingUid(), userData);
} else if (sVerbose) {
@@ -1688,124 +1753,171 @@ public final class AutofillManagerService
@Override
public void isFieldClassificationEnabled(@NonNull IResultReceiver receiver)
throws RemoteException {
- final int userId = UserHandle.getCallingUserId();
boolean enabled = false;
+ final int userId = UserHandle.getCallingUserId();
- synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
- if (service != null) {
- enabled = service.isFieldClassificationEnabled(getCallingUid());
- } else if (sVerbose) {
- Slog.v(TAG, "isFieldClassificationEnabled(): no service for " + userId);
+ try {
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
+ if (service != null) {
+ enabled = service.isFieldClassificationEnabled(getCallingUid());
+ } else if (sVerbose) {
+ Slog.v(TAG, "isFieldClassificationEnabled(): no service for " + userId);
+ }
}
+ } catch (Exception ex) {
+ // Do not raise the exception, just send back false
+ Log.wtf(TAG, "isFieldClassificationEnabled(): failed " + ex.toString());
+ } finally {
+ send(receiver, enabled);
}
- send(receiver, enabled);
}
@Override
public void getDefaultFieldClassificationAlgorithm(@NonNull IResultReceiver receiver)
throws RemoteException {
- final int userId = UserHandle.getCallingUserId();
String algorithm = null;
+ final int userId = UserHandle.getCallingUserId();
- synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
- if (service != null) {
- algorithm = service.getDefaultFieldClassificationAlgorithm(getCallingUid());
- } else {
- if (sVerbose) {
- Slog.v(TAG, "getDefaultFcAlgorithm(): no service for " + userId);
+ try {
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
+ if (service != null) {
+ algorithm = service.getDefaultFieldClassificationAlgorithm(getCallingUid());
+ } else {
+ if (sVerbose) {
+ Slog.v(TAG, "getDefaultFcAlgorithm(): no service for " + userId);
+ }
}
- }
+ }
+ } catch (Exception ex) {
+ // Do not raise the exception, just send back null
+ Log.wtf(TAG, "getDefaultFieldClassificationAlgorithm(): failed " + ex.toString());
+ } finally {
+ send(receiver, algorithm);
}
- send(receiver, algorithm);
+
}
@Override
public void setAugmentedAutofillWhitelist(@Nullable List<String> packages,
@Nullable List<ComponentName> activities, @NonNull IResultReceiver receiver)
throws RemoteException {
+ boolean ok = false;
final int userId = UserHandle.getCallingUserId();
- boolean ok;
- synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
- if (service != null) {
- ok = service.setAugmentedAutofillWhitelistLocked(packages, activities,
- getCallingUid());
- } else {
- if (sVerbose) {
- Slog.v(TAG, "setAugmentedAutofillWhitelist(): no service for " + userId);
+ try {
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
+ if (service != null) {
+ ok = service.setAugmentedAutofillWhitelistLocked(packages, activities,
+ getCallingUid());
+ } else {
+ if (sVerbose) {
+ Slog.v(TAG, "setAugmentedAutofillWhitelist(): no service for "
+ + userId);
+ }
}
- ok = false;
}
+ } catch (Exception ex) {
+ // Do not raise the exception, return the default value
+ Log.wtf(TAG, "setAugmentedAutofillWhitelist(): failed " + ex.toString());
+ } finally {
+ send(receiver,
+ ok ? AutofillManager.RESULT_OK
+ : AutofillManager.RESULT_CODE_NOT_SERVICE);
}
- send(receiver,
- ok ? AutofillManager.RESULT_OK : AutofillManager.RESULT_CODE_NOT_SERVICE);
}
@Override
public void getAvailableFieldClassificationAlgorithms(@NonNull IResultReceiver receiver)
throws RemoteException {
- final int userId = UserHandle.getCallingUserId();
String[] algorithms = null;
+ final int userId = UserHandle.getCallingUserId();
- synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
- if (service != null) {
- algorithms = service.getAvailableFieldClassificationAlgorithms(getCallingUid());
- } else {
- if (sVerbose) {
- Slog.v(TAG, "getAvailableFcAlgorithms(): no service for " + userId);
+ try {
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
+ if (service != null) {
+ algorithms = service
+ .getAvailableFieldClassificationAlgorithms(getCallingUid());
+ } else {
+ if (sVerbose) {
+ Slog.v(TAG, "getAvailableFcAlgorithms(): no service for " + userId);
+ }
}
}
+ } catch (Exception ex) {
+ // Do not raise the exception, return null
+ Log.wtf(TAG, "getAvailableFieldClassificationAlgorithms(): failed "
+ + ex.toString());
+ } finally {
+ send(receiver, algorithms);
}
- send(receiver, algorithms);
}
@Override
public void getAutofillServiceComponentName(@NonNull IResultReceiver receiver)
throws RemoteException {
+ ComponentName componentName = null;
final int userId = UserHandle.getCallingUserId();
- ComponentName componentName = null;
- synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
- if (service != null) {
- componentName = service.getServiceComponentName();
- } else if (sVerbose) {
- Slog.v(TAG, "getAutofillServiceComponentName(): no service for " + userId);
+ try {
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
+ if (service != null) {
+ componentName = service.getServiceComponentName();
+ } else if (sVerbose) {
+ Slog.v(TAG, "getAutofillServiceComponentName(): no service for " + userId);
+ }
}
+ } catch (Exception ex) {
+ Log.wtf(TAG, "getAutofillServiceComponentName(): failed " + ex.toString());
+ } finally {
+ send(receiver, componentName);
}
- send(receiver, componentName);
}
@Override
public void restoreSession(int sessionId, @NonNull IBinder activityToken,
@NonNull IBinder appCallback, @NonNull IResultReceiver receiver)
throws RemoteException {
+ boolean restored = false;
final int userId = UserHandle.getCallingUserId();
- Objects.requireNonNull(activityToken, "activityToken");
- Objects.requireNonNull(appCallback, "appCallback");
- boolean restored = false;
- synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
- if (service != null) {
- restored = service.restoreSession(sessionId, getCallingUid(), activityToken,
- appCallback);
- } else if (sVerbose) {
- Slog.v(TAG, "restoreSession(): no service for " + userId);
+ try {
+ Objects.requireNonNull(activityToken, "activityToken");
+ Objects.requireNonNull(appCallback, "appCallback");
+
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
+ if (service != null) {
+ restored = service.restoreSession(sessionId, getCallingUid(), activityToken,
+ appCallback);
+ } else if (sVerbose) {
+ Slog.v(TAG, "restoreSession(): no service for " + userId);
+ }
}
+ } catch (Exception ex) {
+ // Do not propagate exception, send back status
+ Log.wtf(TAG, "restoreSession(): failed " + ex.toString());
+ } finally {
+ send(receiver, restored);
}
- send(receiver, restored);
}
@Override
public void updateSession(int sessionId, AutofillId autoFillId, Rect bounds,
AutofillValue value, int action, int flags, int userId) {
synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
if (service != null) {
service.updateSessionLocked(sessionId, getCallingUid(), autoFillId, bounds,
value, action, flags);
@@ -1818,7 +1930,8 @@ public final class AutofillManagerService
@Override
public void setAutofillFailure(int sessionId, @NonNull List<AutofillId> ids, int userId) {
synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
if (service != null) {
service.setAutofillFailureLocked(sessionId, getCallingUid(), ids);
} else if (sVerbose) {
@@ -1831,7 +1944,8 @@ public final class AutofillManagerService
public void finishSession(int sessionId, int userId,
@AutofillCommitReason int commitReason) {
synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
if (service != null) {
service.finishSessionLocked(sessionId, getCallingUid(), commitReason);
} else if (sVerbose) {
@@ -1843,19 +1957,22 @@ public final class AutofillManagerService
@Override
public void cancelSession(int sessionId, int userId) {
synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
if (service != null) {
service.cancelSessionLocked(sessionId, getCallingUid());
} else if (sVerbose) {
Slog.v(TAG, "cancelSession(): no service for " + userId);
}
}
+
}
@Override
public void disableOwnedAutofillServices(int userId) {
synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
if (service != null) {
service.disableOwnedAutofillServicesLocked(Binder.getCallingUid());
} else if (sVerbose) {
@@ -1867,21 +1984,36 @@ public final class AutofillManagerService
@Override
public void isServiceSupported(int userId, @NonNull IResultReceiver receiver) {
boolean supported = false;
- synchronized (mLock) {
- supported = !isDisabledLocked(userId);
+
+ try {
+ synchronized (mLock) {
+ supported = !isDisabledLocked(userId);
+ }
+ } catch (Exception ex) {
+ // Do not propagate exception
+ Log.wtf(TAG, "isServiceSupported(): failed " + ex.toString());
+ } finally {
+ send(receiver, supported);
}
- send(receiver, supported);
}
@Override
public void isServiceEnabled(int userId, @NonNull String packageName,
@NonNull IResultReceiver receiver) {
boolean enabled = false;
- synchronized (mLock) {
- final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
- enabled = Objects.equals(packageName, service.getServicePackageName());
+
+ try {
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(userId);
+ enabled = Objects.equals(packageName, service.getServicePackageName());
+ }
+ } catch (Exception ex) {
+ // Do not propagate exception
+ Log.wtf(TAG, "isServiceEnabled(): failed " + ex.toString());
+ } finally {
+ send(receiver, enabled);
}
- send(receiver, enabled);
}
@Override
@@ -1891,8 +2023,9 @@ public final class AutofillManagerService
|| operation == AutofillManager.PENDING_UI_OPERATION_RESTORE,
"invalid operation: %d", operation);
synchronized (mLock) {
- final AutofillManagerServiceImpl service = peekServiceForUserLocked(
- UserHandle.getCallingUserId());
+ final AutofillManagerServiceImpl service =
+ peekServiceForUserWithLocalBinderIdentityLocked(
+ UserHandle.getCallingUserId());
if (service != null) {
service.onPendingSaveUi(operation, token);
}
@@ -1907,7 +2040,7 @@ public final class AutofillManagerService
boolean uiOnly = false;
if (args != null) {
for (String arg : args) {
- switch(arg) {
+ switch (arg) {
case "--no-history":
showHistory = false;
break;
@@ -1934,27 +2067,38 @@ public final class AutofillManagerService
try {
sDebug = sVerbose = true;
synchronized (mLock) {
- pw.print("sDebug: "); pw.print(realDebug);
- pw.print(" sVerbose: "); pw.println(realVerbose);
+ pw.print("sDebug: ");
+ pw.print(realDebug);
+ pw.print(" sVerbose: ");
+ pw.println(realVerbose);
pw.print("Flags: ");
synchronized (mFlagLock) {
- pw.print("mPccClassificationEnabled="); pw.print(mPccClassificationEnabled);
+ pw.print("mPccClassificationEnabled=");
+ pw.print(mPccClassificationEnabled);
pw.print(";");
- pw.print("mPccPreferProviderOverPcc="); pw.print(mPccPreferProviderOverPcc);
+ pw.print("mPccPreferProviderOverPcc=");
+ pw.print(mPccPreferProviderOverPcc);
pw.print(";");
- pw.print("mPccUseFallbackDetection="); pw.print(mPccUseFallbackDetection);
+ pw.print("mPccUseFallbackDetection=");
+ pw.print(mPccUseFallbackDetection);
pw.print(";");
- pw.print("mPccProviderHints="); pw.println(mPccProviderHints);
+ pw.print("mPccProviderHints=");
+ pw.println(mPccProviderHints);
}
// Dump per-user services
dumpLocked("", pw);
- mAugmentedAutofillResolver.dumpShort(pw); pw.println();
- pw.print("Max partitions per session: "); pw.println(sPartitionMaxCount);
- pw.print("Max visible datasets: "); pw.println(sVisibleDatasetsMaxCount);
+ mAugmentedAutofillResolver.dumpShort(pw);
+ pw.println();
+ pw.print("Max partitions per session: ");
+ pw.println(sPartitionMaxCount);
+ pw.print("Max visible datasets: ");
+ pw.println(sVisibleDatasetsMaxCount);
if (sFullScreenMode != null) {
- pw.print("Overridden full-screen mode: "); pw.println(sFullScreenMode);
+ pw.print("Overridden full-screen mode: ");
+ pw.println(sFullScreenMode);
}
- pw.println("User data constraints: "); UserData.dumpConstraints(prefix, pw);
+ pw.println("User data constraints: ");
+ UserData.dumpConstraints(prefix, pw);
mUi.dump(pw);
pw.print("Autofill Compat State: ");
mAutofillCompatState.dump(prefix, pw);
@@ -1969,11 +2113,17 @@ public final class AutofillManagerService
pw.print("Augmented Service Request Timeout: ");
pw.println(mAugmentedServiceRequestTimeoutMs);
if (showHistory) {
- pw.println(); pw.println("Requests history:"); pw.println();
+ pw.println();
+ pw.println("Requests history:");
+ pw.println();
mRequestsHistory.reverseDump(fd, pw, args);
- pw.println(); pw.println("UI latency history:"); pw.println();
+ pw.println();
+ pw.println("UI latency history:");
+ pw.println();
mUiLatencyHistory.reverseDump(fd, pw, args);
- pw.println(); pw.println("WTF history:"); pw.println();
+ pw.println();
+ pw.println("WTF history:");
+ pw.println();
mWtfHistory.reverseDump(fd, pw, args);
}
pw.println("Augmented Autofill State: ");
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index 6b55d7ed4d56..cd2f844294e3 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -987,8 +987,12 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
"Virtual device doesn't have a virtual display with ID " + displayId);
}
- releaseOwnedVirtualDisplayResources(virtualDisplayWrapper);
-
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ releaseOwnedVirtualDisplayResources(virtualDisplayWrapper);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
/**
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index e8c85ce68f22..c6e9a7d5e2e5 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -162,6 +162,8 @@ import java.util.concurrent.TimeUnit;
// TODO(b/180451994): ensure all incoming + outgoing calls have a cleared calling identity
public class VcnManagementService extends IVcnManagementService.Stub {
@NonNull private static final String TAG = VcnManagementService.class.getSimpleName();
+ @NonNull private static final String CONTEXT_ATTRIBUTION_TAG = "VCN";
+
private static final long DUMP_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(5);
private static final int LOCAL_LOG_LINE_COUNT = 512;
@@ -223,7 +225,9 @@ public class VcnManagementService extends IVcnManagementService.Stub {
@VisibleForTesting(visibility = Visibility.PRIVATE)
VcnManagementService(@NonNull Context context, @NonNull Dependencies deps) {
- mContext = requireNonNull(context, "Missing context");
+ mContext =
+ requireNonNull(context, "Missing context")
+ .createAttributionContext(CONTEXT_ATTRIBUTION_TAG);
mDeps = requireNonNull(deps, "Missing dependencies");
mLooper = mDeps.getLooper();
@@ -1065,13 +1069,20 @@ public class VcnManagementService extends IVcnManagementService.Stub {
boolean isRestricted = false;
synchronized (mLock) {
final Vcn vcn = mVcns.get(subGrp);
+ final VcnConfig vcnConfig = mConfigs.get(subGrp);
if (vcn != null) {
+ if (vcnConfig == null) {
+ // TODO: b/284381334 Investigate for the root cause of this issue
+ // and handle it properly
+ logWtf("Vcn instance exists but VcnConfig does not for " + subGrp);
+ }
+
if (vcn.getStatus() == VCN_STATUS_CODE_ACTIVE) {
isVcnManagedNetwork = true;
}
final Set<Integer> restrictedTransports = mDeps.getRestrictedTransports(
- subGrp, mLastSnapshot, mConfigs.get(subGrp));
+ subGrp, mLastSnapshot, vcnConfig);
for (int restrictedTransport : restrictedTransports) {
if (ncCopy.hasTransport(restrictedTransport)) {
if (restrictedTransport == TRANSPORT_CELLULAR
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index 9b4f9683d550..0d423d8a0a62 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -80,6 +80,7 @@ import java.util.List;
*/
public class VpnManagerService extends IVpnManager.Stub {
private static final String TAG = VpnManagerService.class.getSimpleName();
+ private static final String CONTEXT_ATTRIBUTION_TAG = "VPN_MANAGER";
@VisibleForTesting
protected final HandlerThread mHandlerThread;
@@ -157,7 +158,7 @@ public class VpnManagerService extends IVpnManager.Stub {
}
public VpnManagerService(Context context, Dependencies deps) {
- mContext = context;
+ mContext = context.createAttributionContext(CONTEXT_ATTRIBUTION_TAG);
mDeps = deps;
mHandlerThread = mDeps.makeHandlerThread();
mHandlerThread.start();
diff --git a/services/core/java/com/android/server/WallpaperUpdateReceiver.java b/services/core/java/com/android/server/WallpaperUpdateReceiver.java
index 2812233815a6..99178920cc52 100644
--- a/services/core/java/com/android/server/WallpaperUpdateReceiver.java
+++ b/services/core/java/com/android/server/WallpaperUpdateReceiver.java
@@ -88,7 +88,7 @@ public class WallpaperUpdateReceiver extends BroadcastReceiver {
} else {
//live wallpaper
ComponentName currCN = info.getComponent();
- ComponentName defaultCN = WallpaperManager.getCmfDefaultWallpaperComponent(context);
+ ComponentName defaultCN = WallpaperManager.getDefaultWallpaperComponent(context);
if (!currCN.equals(defaultCN)) {
return true;
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 6f205636b476..fc84e1386d1f 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -621,7 +621,8 @@ public final class ActiveServices {
try {
final ServiceRecord.StartItem si = r.pendingStarts.get(0);
startServiceInnerLocked(this, si.intent, r, false, true, si.callingId,
- si.mCallingProcessName, r.startRequested, si.mCallingPackageName);
+ si.mCallingProcessName, si.mCallingProcessState,
+ r.startRequested, si.mCallingPackageName);
} catch (TransactionTooLargeException e) {
// Ignore, nobody upstack cares.
}
@@ -977,10 +978,22 @@ public final class ActiveServices {
fgRequired = false;
}
+ final ProcessRecord callingApp;
+ synchronized (mAm.mPidsSelfLocked) {
+ callingApp = mAm.mPidsSelfLocked.get(callingPid);
+ }
+ final String callingProcessName = callingApp != null
+ ? callingApp.processName : callingPackage;
+ final int callingProcessState =
+ callingApp != null && callingApp.getThread() != null && !callingApp.isKilled()
+ ? callingApp.mState.getCurProcState() : ActivityManager.PROCESS_STATE_UNKNOWN;
+ r.updateProcessStateOnRequest();
+
// The package could be frozen (meaning it's doing surgery), defer the actual
// start until the package is unfrozen.
if (deferServiceBringupIfFrozenLocked(r, service, callingPackage, callingFeatureId,
- callingUid, callingPid, fgRequired, callerFg, userId,
+ callingUid, callingPid, callingProcessName,
+ callingProcessState, fgRequired, callerFg, userId,
backgroundStartPrivileges, false, null)) {
return null;
}
@@ -1001,7 +1014,7 @@ public final class ActiveServices {
// what realResult contains.
final ComponentName realResult =
startServiceInnerLocked(r, service, callingUid, callingPid,
- getCallingProcessNameLocked(callingUid, callingPid, callingPackage),
+ callingProcessName, callingProcessState,
fgRequired, callerFg,
backgroundStartPrivileges, callingPackage);
if (res.aliasComponent != null
@@ -1013,17 +1026,9 @@ public final class ActiveServices {
}
}
- private String getCallingProcessNameLocked(int callingUid, int callingPid,
- String callingPackage) {
- synchronized (mAm.mPidsSelfLocked) {
- final ProcessRecord callingApp = mAm.mPidsSelfLocked.get(callingPid);
- return callingApp != null ? callingApp.processName : callingPackage;
- }
- }
-
private ComponentName startServiceInnerLocked(ServiceRecord r, Intent service,
- int callingUid, int callingPid, String callingProcessName, boolean fgRequired,
- boolean callerFg,
+ int callingUid, int callingPid, String callingProcessName,
+ int callingProcessState, boolean fgRequired, boolean callerFg,
BackgroundStartPrivileges backgroundStartPrivileges, String callingPackage)
throws TransactionTooLargeException {
NeededUriGrants neededGrants = mAm.mUgmInternal.checkGrantUriPermissionFromIntent(
@@ -1037,7 +1042,8 @@ public final class ActiveServices {
r.delayedStop = false;
r.fgRequired = fgRequired;
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
- service, neededGrants, callingUid, callingProcessName, callingPackage));
+ service, neededGrants, callingUid, callingProcessName, callingPackage,
+ callingProcessState));
// We want to allow scheduling user-initiated jobs when the app is running a
// foreground service that was started in the same conditions that allows for scheduling
@@ -1140,7 +1146,8 @@ public final class ActiveServices {
r.allowBgActivityStartsOnServiceStart(backgroundStartPrivileges);
}
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting,
- callingUid, callingProcessName, wasStartRequested, callingPackage);
+ callingUid, callingProcessName, callingProcessState,
+ wasStartRequested, callingPackage);
return cmp;
}
@@ -1244,7 +1251,8 @@ public final class ActiveServices {
@GuardedBy("mAm")
private boolean deferServiceBringupIfFrozenLocked(ServiceRecord s, Intent serviceIntent,
String callingPackage, @Nullable String callingFeatureId,
- int callingUid, int callingPid, boolean fgRequired, boolean callerFg, int userId,
+ int callingUid, int callingPid, String callingProcessName,
+ int callingProcessState, boolean fgRequired, boolean callerFg, int userId,
BackgroundStartPrivileges backgroundStartPrivileges,
boolean isBinding, IServiceConnection connection) {
final PackageManagerInternal pm = mAm.getPackageManagerInternal();
@@ -1258,8 +1266,6 @@ public final class ActiveServices {
curPendingBringups = new ArrayList<>();
mPendingBringups.put(s, curPendingBringups);
}
- final String callingProcessName = getCallingProcessNameLocked(
- callingUid, callingPid, callingPackage);
curPendingBringups.add(new Runnable() {
@Override
public void run() {
@@ -1291,7 +1297,7 @@ public final class ActiveServices {
} else { // Starting a service
try {
startServiceInnerLocked(s, serviceIntent, callingUid, callingPid,
- callingProcessName, fgRequired, callerFg,
+ callingProcessName, callingProcessState, fgRequired, callerFg,
backgroundStartPrivileges, callingPackage);
} catch (TransactionTooLargeException e) {
/* ignore - local call */
@@ -1338,7 +1344,8 @@ public final class ActiveServices {
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting, int callingUid, String callingProcessName,
- boolean wasStartRequested, String callingPackage) throws TransactionTooLargeException {
+ int callingProcessState, boolean wasStartRequested, String callingPackage)
+ throws TransactionTooLargeException {
synchronized (mAm.mProcessStats.mLock) {
final ServiceState stracker = r.getTracker();
if (stracker != null) {
@@ -1381,7 +1388,9 @@ public final class ActiveServices {
getShortServiceNameForStats(r),
packageState,
packageName,
- callingPackage);
+ callingPackage,
+ callingProcessState,
+ r.mProcessStateOnRequest);
if (r.startRequested && addToStarting) {
boolean first = smap.mStartingBackground.size() == 0;
@@ -3611,11 +3620,22 @@ public final class ActiveServices {
return 0;
}
+ final ProcessRecord callingApp;
+ synchronized (mAm.mPidsSelfLocked) {
+ callingApp = mAm.mPidsSelfLocked.get(callingPid);
+ }
+ final String callingProcessName = callingApp != null
+ ? callingApp.processName : callingPackage;
+ final int callingProcessState =
+ callingApp != null && callingApp.getThread() != null && !callingApp.isKilled()
+ ? callingApp.mState.getCurProcState() : ActivityManager.PROCESS_STATE_UNKNOWN;
+ s.updateProcessStateOnRequest();
+
// The package could be frozen (meaning it's doing surgery), defer the actual
// binding until the package is unfrozen.
boolean packageFrozen = deferServiceBringupIfFrozenLocked(s, service, callingPackage, null,
- callingUid, callingPid, false, callerFg, userId, BackgroundStartPrivileges.NONE,
- true, connection);
+ callingUid, callingPid, callingProcessName, callingProcessState,
+ false, callerFg, userId, BackgroundStartPrivileges.NONE, true, connection);
// If permissions need a review before any of the app components can run,
// we schedule binding to the service but do not start its process, then
@@ -3756,7 +3776,9 @@ public final class ActiveServices {
getShortServiceNameForStats(s),
packageState,
s.packageName,
- callerApp.info.packageName);
+ callerApp.info.packageName,
+ callerApp.mState.getCurProcState(),
+ s.mProcessStateOnRequest);
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
+ ": received=" + b.intent.received
@@ -5355,7 +5377,7 @@ public final class ActiveServices {
// be called.
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
- null, null, 0, null, null));
+ null, null, 0, null, null, ActivityManager.PROCESS_STATE_UNKNOWN));
}
sendServiceArgsLocked(r, execInFg, true);
@@ -6351,7 +6373,8 @@ public final class ActiveServices {
stopServiceLocked(sr, true);
} else {
sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
- sr.getLastStartId(), baseIntent, null, 0, null, null));
+ sr.getLastStartId(), baseIntent, null, 0, null, null,
+ ActivityManager.PROCESS_STATE_UNKNOWN));
if (sr.app != null && sr.app.getThread() != null) {
// We always run in the foreground, since this is called as
// part of the "remove task" UI operation.
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 44e198b53761..8c31209aeeb4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -1678,9 +1678,9 @@ final class ActivityManagerConstants extends ContentObserver {
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
KEY_KILL_BG_RESTRICTED_CACHED_IDLE_SETTLE_TIME,
DEFAULT_KILL_BG_RESTRICTED_CACHED_IDLE_SETTLE_TIME_MS);
- if (mKillBgRestrictedAndCachedIdleSettleTimeMs != currentSettleTime) {
- mService.mHandler.removeMessages(
- ActivityManagerService.IDLE_UIDS_MSG);
+ if (mKillBgRestrictedAndCachedIdleSettleTimeMs < currentSettleTime) {
+ // Don't remove existing messages in case other IDLE_UIDS_MSG initiators use lower
+ // delays, but send a new message if the settle time has decreased.
mService.mHandler.sendEmptyMessageDelayed(
ActivityManagerService.IDLE_UIDS_MSG,
mKillBgRestrictedAndCachedIdleSettleTimeMs);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 92e73f585466..a7db663191af 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1176,20 +1176,24 @@ public class ActivityManagerService extends IActivityManager.Stub
public Intent intent;
public boolean deferUntilActive;
public int originalCallingUid;
+ /** The snapshot process state of the app who sent this broadcast */
+ public int originalCallingAppProcessState;
public static StickyBroadcast create(Intent intent, boolean deferUntilActive,
- int originalCallingUid) {
+ int originalCallingUid, int originalCallingAppProcessState) {
final StickyBroadcast b = new StickyBroadcast();
b.intent = intent;
b.deferUntilActive = deferUntilActive;
b.originalCallingUid = originalCallingUid;
+ b.originalCallingAppProcessState = originalCallingAppProcessState;
return b;
}
@Override
public String toString() {
return "{intent=" + intent + ", defer=" + deferUntilActive + ", originalCallingUid="
- + originalCallingUid + "}";
+ + originalCallingUid + ", originalCallingAppProcessState="
+ + originalCallingAppProcessState + "}";
}
}
@@ -1522,6 +1526,8 @@ public class ActivityManagerService extends IActivityManager.Stub
*/
int mBootPhase;
+ volatile boolean mDeterministicUidIdle = false;
+
@VisibleForTesting
public WindowManagerService mWindowManager;
WindowManagerInternal mWmInternal;
@@ -1616,6 +1622,8 @@ public class ActivityManagerService extends IActivityManager.Stub
static final int SERVICE_SHORT_FGS_PROCSTATE_TIMEOUT_MSG = 77;
static final int SERVICE_SHORT_FGS_ANR_TIMEOUT_MSG = 78;
static final int UPDATE_CACHED_APP_HIGH_WATERMARK = 79;
+ static final int ADD_UID_TO_OBSERVER_MSG = 80;
+ static final int REMOVE_UID_FROM_OBSERVER_MSG = 81;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1774,6 +1782,12 @@ public class ActivityManagerService extends IActivityManager.Stub
case PUSH_TEMP_ALLOWLIST_UI_MSG: {
pushTempAllowlist();
} break;
+ case ADD_UID_TO_OBSERVER_MSG: {
+ mUidObserverController.addUidToObserverImpl((IBinder) msg.obj, msg.arg1);
+ } break;
+ case REMOVE_UID_FROM_OBSERVER_MSG: {
+ mUidObserverController.removeUidFromObserverImpl((IBinder) msg.obj, msg.arg1);
+ } break;
}
}
}
@@ -14034,7 +14048,8 @@ public class ActivityManagerService extends IActivityManager.Stub
receivers, null, null, 0, null, null, false, true, true, -1,
originalStickyCallingUid, BackgroundStartPrivileges.NONE,
false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */,
- null /* filterExtrasForReceiver */);
+ null /* filterExtrasForReceiver */,
+ broadcast.originalCallingAppProcessState);
queue.enqueueBroadcastLocked(r);
}
}
@@ -14434,6 +14449,8 @@ public class ActivityManagerService extends IActivityManager.Stub
&& !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
Slog.w(TAG, "Skipping broadcast of " + intent
+ ": user " + userId + " and its parent (if any) are stopped");
+ scheduleCanceledResultTo(resultToApp, resultTo, intent, userId,
+ brOptions, callingUid, callerPackage);
return ActivityManager.BROADCAST_FAILED_USER_STOPPED;
}
}
@@ -14505,6 +14522,8 @@ public class ActivityManagerService extends IActivityManager.Stub
isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception", e);
+ scheduleCanceledResultTo(resultToApp, resultTo, intent,
+ userId, brOptions, callingUid, callerPackage);
return ActivityManager.BROADCAST_SUCCESS;
}
@@ -14738,6 +14757,8 @@ public class ActivityManagerService extends IActivityManager.Stub
if (aInfo == null) {
Slog.w(TAG, "Dropping ACTION_PACKAGE_REPLACED for non-existent pkg:"
+ " ssp=" + ssp + " data=" + data);
+ scheduleCanceledResultTo(resultToApp, resultTo, intent,
+ userId, brOptions, callingUid, callerPackage);
return ActivityManager.BROADCAST_SUCCESS;
}
updateAssociationForApp(aInfo);
@@ -14823,6 +14844,8 @@ public class ActivityManagerService extends IActivityManager.Stub
// Apps should now be using ShortcutManager.pinRequestShortcut().
Log.w(TAG, "Broadcast " + action
+ " no longer supported. It will not be delivered.");
+ scheduleCanceledResultTo(resultToApp, resultTo, intent,
+ userId, brOptions, callingUid, callerPackage);
return ActivityManager.BROADCAST_SUCCESS;
case Intent.ACTION_PRE_BOOT_COMPLETED:
timeoutExempt = true;
@@ -14830,6 +14853,8 @@ public class ActivityManagerService extends IActivityManager.Stub
case Intent.ACTION_CLOSE_SYSTEM_DIALOGS:
if (!mAtmInternal.checkCanCloseSystemDialogs(callingPid, callingUid,
callerPackage)) {
+ scheduleCanceledResultTo(resultToApp, resultTo, intent,
+ userId, brOptions, callingUid, callerPackage);
// Returning success seems to be the pattern here
return ActivityManager.BROADCAST_SUCCESS;
}
@@ -14849,6 +14874,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ final int callerAppProcessState = getRealProcessStateLocked(callerApp, realCallingPid);
// Add to the sticky list if requested.
if (sticky) {
if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
@@ -14863,6 +14889,8 @@ public class ActivityManagerService extends IActivityManager.Stub
if (requiredPermissions != null && requiredPermissions.length > 0) {
Slog.w(TAG, "Can't broadcast sticky intent " + intent
+ " and enforce permissions " + Arrays.toString(requiredPermissions));
+ scheduleCanceledResultTo(resultToApp, resultTo, intent,
+ userId, brOptions, callingUid, callerPackage);
return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
}
if (intent.getComponent() != null) {
@@ -14911,12 +14939,13 @@ public class ActivityManagerService extends IActivityManager.Stub
if (intent.filterEquals(list.get(i).intent)) {
// This sticky already exists, replace it.
list.set(i, StickyBroadcast.create(new Intent(intent), deferUntilActive,
- callingUid));
+ callingUid, callerAppProcessState));
break;
}
}
if (i >= stickiesCount) {
- list.add(StickyBroadcast.create(new Intent(intent), deferUntilActive, callingUid));
+ list.add(StickyBroadcast.create(new Intent(intent), deferUntilActive, callingUid,
+ callerAppProcessState));
}
}
@@ -14999,7 +15028,8 @@ public class ActivityManagerService extends IActivityManager.Stub
requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
registeredReceivers, resultToApp, resultTo, resultCode, resultData,
resultExtras, ordered, sticky, false, userId,
- backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver);
+ backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver,
+ callerAppProcessState);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
queue.enqueueBroadcastLocked(r);
registeredReceivers = null;
@@ -15093,7 +15123,8 @@ public class ActivityManagerService extends IActivityManager.Stub
requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
receivers, resultToApp, resultTo, resultCode, resultData, resultExtras,
ordered, sticky, false, userId,
- backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver);
+ backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver,
+ callerAppProcessState);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r);
queue.enqueueBroadcastLocked(r);
@@ -15110,6 +15141,46 @@ public class ActivityManagerService extends IActivityManager.Stub
return ActivityManager.BROADCAST_SUCCESS;
}
+ @GuardedBy("this")
+ private void scheduleCanceledResultTo(ProcessRecord resultToApp, IIntentReceiver resultTo,
+ Intent intent, int userId, BroadcastOptions options, int callingUid,
+ String callingPackage) {
+ if (resultTo == null) {
+ return;
+ }
+ final ProcessRecord app = resultToApp;
+ final IApplicationThread thread = (app != null) ? app.getOnewayThread() : null;
+ if (thread != null) {
+ try {
+ final boolean shareIdentity = (options != null && options.isShareIdentityEnabled());
+ thread.scheduleRegisteredReceiver(
+ resultTo, intent, Activity.RESULT_CANCELED, null, null,
+ false, false, true, userId, app.mState.getReportedProcState(),
+ shareIdentity ? callingUid : Process.INVALID_UID,
+ shareIdentity ? callingPackage : null);
+ } catch (RemoteException e) {
+ final String msg = "Failed to schedule result of " + intent + " via "
+ + app + ": " + e;
+ app.killLocked("Can't schedule resultTo", ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_UNDELIVERED_BROADCAST, true);
+ Slog.d(TAG, msg);
+ }
+ }
+ }
+
+ @GuardedBy("this")
+ private int getRealProcessStateLocked(ProcessRecord app, int pid) {
+ if (app == null) {
+ synchronized (mPidsSelfLocked) {
+ app = mPidsSelfLocked.get(pid);
+ }
+ }
+ if (app != null && app.getThread() != null && !app.isKilled()) {
+ return app.mState.getCurProcState();
+ }
+ return PROCESS_STATE_NONEXISTENT;
+ }
+
@VisibleForTesting
ArrayList<StickyBroadcast> getStickyBroadcasts(String action, int userId) {
final ArrayMap<String, ArrayList<StickyBroadcast>> stickyBroadcasts =
@@ -16464,6 +16535,11 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ @Override
+ public void setDeterministicUidIdle(boolean deterministic) {
+ mDeterministicUidIdle = deterministic;
+ }
+
/** Make the currently active UIDs idle after a certain grace period. */
final void idleUids() {
synchronized (this) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index add22bd6009e..569f55f7890f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -149,7 +149,6 @@ import java.util.Locale;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
@@ -290,6 +289,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
return runKillAll(pw);
case "make-uid-idle":
return runMakeIdle(pw);
+ case "set-deterministic-uid-idle":
+ return runSetDeterministicUidIdle(pw);
case "monitor":
return runMonitor(pw);
case "watch-uids":
@@ -607,15 +608,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
return 1;
}
- AtomicReference<String> mimeType = new AtomicReference<>(intent.getType());
-
- if (mimeType.get() == null && intent.getData() != null
- && "content".equals(intent.getData().getScheme())) {
- mInterface.getMimeTypeFilterAsync(intent.getData(), mUserId,
- new RemoteCallback(result -> {
- mimeType.set(result.getPairValue());
- }));
- }
+ final String mimeType = intent.resolveType(mInternal.mContext);
do {
if (mStopOption) {
@@ -627,7 +620,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
int userIdForQuery = mInternal.mUserController.handleIncomingUser(
Binder.getCallingPid(), Binder.getCallingUid(), mUserId, false,
ALLOW_NON_FULL, "ActivityManagerShellCommand", null);
- List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType.get(),
+ List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType,
0, userIdForQuery).getList();
if (activities == null || activities.size() <= 0) {
getErrPrintWriter().println("Error: Intent does not match any activities: "
@@ -724,12 +717,12 @@ final class ActivityManagerShellCommand extends ShellCommand {
}
if (mWaitOption) {
result = mInternal.startActivityAndWait(null, SHELL_PACKAGE_NAME, null, intent,
- mimeType.get(), null, null, 0, mStartFlags, profilerInfo,
+ mimeType, null, null, 0, mStartFlags, profilerInfo,
options != null ? options.toBundle() : null, mUserId);
res = result.result;
} else {
res = mInternal.startActivityAsUserWithFeature(null, SHELL_PACKAGE_NAME, null,
- intent, mimeType.get(), null, null, 0, mStartFlags, profilerInfo,
+ intent, mimeType, null, null, 0, mStartFlags, profilerInfo,
options != null ? options.toBundle() : null, mUserId);
}
final long endTime = SystemClock.uptimeMillis();
@@ -935,8 +928,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
final int result = mInterface.broadcastIntentWithFeature(null, null, intent, null,
receiver, 0, null, null, requiredPermissions, null, null,
android.app.AppOpsManager.OP_NONE, bundle, true, false, mUserId);
- Slogf.i(TAG, "Broadcasted %s: " + result, intent);
- if (!mAsync) {
+ Slogf.i(TAG, "Enqueued broadcast %s: " + result, intent);
+ if (result == ActivityManager.BROADCAST_SUCCESS && !mAsync) {
receiver.waitForFinish();
}
return 0;
@@ -1520,6 +1513,23 @@ final class ActivityManagerShellCommand extends ShellCommand {
return 0;
}
+ int runSetDeterministicUidIdle(PrintWriter pw) throws RemoteException {
+ int userId = UserHandle.USER_ALL;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ if (opt.equals("--user")) {
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ } else {
+ getErrPrintWriter().println("Error: Unknown option: " + opt);
+ return -1;
+ }
+ }
+ boolean deterministic = Boolean.parseBoolean(getNextArgRequired());
+ mInterface.setDeterministicUidIdle(deterministic);
+ return 0;
+ }
+
static final class MyActivityController extends IActivityController.Stub {
final IActivityManager mInterface;
final PrintWriter mPw;
@@ -4271,6 +4281,11 @@ final class ActivityManagerShellCommand extends ShellCommand {
pw.println(" make-uid-idle [--user <USER_ID> | all | current] <PACKAGE>");
pw.println(" If the given application's uid is in the background and waiting to");
pw.println(" become idle (not allowing background services), do that now.");
+ pw.println(
+ " set-deterministic-uid-idle [--user <USER_ID> | all | current] <true|false>");
+ pw.println(" If true, sets the timing of making UIDs idle consistent and");
+ pw.println(" deterministic. If false, the timing will be variable depending on");
+ pw.println(" other activity on the device. The default is false.");
pw.println(" monitor [--gdb <port>] [-p <TARGET>] [-s] [-c] [-k]");
pw.println(" Start monitoring for crashes or ANRs.");
pw.println(" --gdb: start gdbserv on the given port at crash/ANR");
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
index 4b6d32427d68..a80ad599a3e2 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -106,6 +106,12 @@ class BroadcastProcessQueue {
long lastCpuDelayTime;
/**
+ * Snapshotted value of {@link ProcessStateRecord#getCurProcState()} before
+ * dispatching the current broadcast to the receiver in this process.
+ */
+ int lastProcessState;
+
+ /**
* Ordered collection of broadcasts that are waiting to be dispatched to
* this process, as a pair of {@link BroadcastRecord} and the index into
* {@link BroadcastRecord#receivers} that represents the receiver.
diff --git a/services/core/java/com/android/server/am/BroadcastQueueImpl.java b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
index 8688f25ba002..f13dc89f2bd2 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
@@ -269,7 +269,10 @@ public class BroadcastQueueImpl extends BroadcastQueue {
Activity.RESULT_CANCELED, null, null,
false, false, oldRecord.shareIdentity, oldRecord.userId,
oldRecord.callingUid, r.callingUid, r.callerPackage,
- SystemClock.uptimeMillis() - oldRecord.enqueueTime, 0, 0);
+ SystemClock.uptimeMillis() - oldRecord.enqueueTime, 0, 0,
+ oldRecord.resultToApp != null
+ ? oldRecord.resultToApp.mState.getCurProcState()
+ : ActivityManager.PROCESS_STATE_UNKNOWN);
} catch (RemoteException e) {
Slog.w(TAG, "Failure ["
+ mQueueName + "] sending broadcast result of "
@@ -367,6 +370,7 @@ public class BroadcastQueueImpl extends BroadcastQueue {
}
r.curApp = app;
+ r.curAppLastProcessState = app.mState.getCurProcState();
final ProcessReceiverRecord prr = app.mReceivers;
prr.addCurReceiver(r);
app.mState.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
@@ -418,6 +422,7 @@ public class BroadcastQueueImpl extends BroadcastQueue {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + ": NOT STARTED!");
r.curApp = null;
+ r.curAppLastProcessState = ActivityManager.PROCESS_STATE_UNKNOWN;
prr.removeCurReceiver(r);
}
}
@@ -620,7 +625,8 @@ public class BroadcastQueueImpl extends BroadcastQueue {
r.getDeliveryGroupPolicy(),
r.intent.getFlags(),
BroadcastRecord.getReceiverPriority(curReceiver),
- r.callerProcState);
+ r.callerProcState,
+ r.curAppLastProcessState);
}
if (state == BroadcastRecord.IDLE) {
Slog.w(TAG_BROADCAST, "finishReceiver [" + mQueueName + "] called but state is IDLE");
@@ -682,6 +688,7 @@ public class BroadcastQueueImpl extends BroadcastQueue {
r.curFilter = null;
r.curReceiver = null;
r.curApp = null;
+ r.curAppLastProcessState = ActivityManager.PROCESS_STATE_UNKNOWN;
r.curFilteredExtras = null;
r.mWasReceiverAppStopped = false;
mPendingBroadcast = null;
@@ -751,7 +758,8 @@ public class BroadcastQueueImpl extends BroadcastQueue {
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky, boolean shareIdentity, int sendingUser,
int receiverUid, int callingUid, String callingPackage,
- long dispatchDelay, long receiveDelay, int priority) throws RemoteException {
+ long dispatchDelay, long receiveDelay, int priority,
+ int receiverProcessState) throws RemoteException {
// If the broadcaster opted-in to sharing their identity, then expose package visibility for
// the receiver.
if (shareIdentity) {
@@ -802,7 +810,7 @@ public class BroadcastQueueImpl extends BroadcastQueue {
SERVICE_REQUEST_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL,
app != null ? app.info.packageName : null, callingPackage,
r.calculateTypeForLogging(), r.getDeliveryGroupPolicy(), r.intent.getFlags(),
- priority, r.callerProcState);
+ priority, r.callerProcState, receiverProcessState);
}
}
@@ -849,6 +857,7 @@ public class BroadcastQueueImpl extends BroadcastQueue {
// things that directly call the IActivityManager API, which
// are already core system stuff so don't matter for this.
r.curApp = filter.receiverList.app;
+ r.curAppLastProcessState = r.curApp.mState.getCurProcState();
filter.receiverList.app.mReceivers.addCurReceiver(r);
mService.enqueueOomAdjTargetLocked(r.curApp);
mService.updateOomAdjPendingTargetsLocked(
@@ -883,7 +892,10 @@ public class BroadcastQueueImpl extends BroadcastQueue {
r.resultExtras, r.ordered, r.initialSticky, r.shareIdentity, r.userId,
filter.receiverList.uid, r.callingUid, r.callerPackage,
r.dispatchTime - r.enqueueTime,
- r.receiverTime - r.dispatchTime, filter.getPriority());
+ r.receiverTime - r.dispatchTime, filter.getPriority(),
+ filter.receiverList.app != null
+ ? filter.receiverList.app.mState.getCurProcState()
+ : ActivityManager.PROCESS_STATE_UNKNOWN);
// parallel broadcasts are fire-and-forget, not bookended by a call to
// finishReceiverLocked(), so we manage their activity-start token here
if (filter.receiverList.app != null
@@ -1174,7 +1186,10 @@ public class BroadcastQueueImpl extends BroadcastQueue {
r.resultData, r.resultExtras, false, false, r.shareIdentity,
r.userId, r.callingUid, r.callingUid, r.callerPackage,
r.dispatchTime - r.enqueueTime,
- now - r.dispatchTime, 0);
+ now - r.dispatchTime, 0,
+ r.resultToApp != null
+ ? r.resultToApp.mState.getCurProcState()
+ : ActivityManager.PROCESS_STATE_UNKNOWN);
logBootCompletedBroadcastCompletionLatencyIfPossible(r);
// Set this to null so that the reference
// (local and remote) isn't kept in the mBroadcastHistory.
@@ -1480,6 +1495,7 @@ public class BroadcastQueueImpl extends BroadcastQueue {
r.intent.getAction(), r.getHostingRecordTriggerType()),
isActivityCapable ? ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE : ZYGOTE_POLICY_FLAG_EMPTY,
(r.intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false);
+ r.curAppLastProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
if (r.curApp == null) {
// Ah, this recipient is unavailable. Finish it if necessary,
// and mark the broadcast record as ready for the next.
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 8380308812d5..33e21f1488a0 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -33,6 +33,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.LOG_WRITER_INFO;
import static com.android.server.am.BroadcastProcessQueue.insertIntoRunnableList;
import static com.android.server.am.BroadcastProcessQueue.reasonToString;
import static com.android.server.am.BroadcastProcessQueue.removeFromRunnableList;
+import static com.android.server.am.BroadcastRecord.DELIVERY_DEFERRED;
import static com.android.server.am.BroadcastRecord.deliveryStateToString;
import static com.android.server.am.BroadcastRecord.getReceiverClassName;
import static com.android.server.am.BroadcastRecord.getReceiverPackageName;
@@ -68,6 +69,7 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.text.format.DateUtils;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import android.util.MathUtils;
@@ -213,6 +215,13 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
new AtomicReference<>();
/**
+ * Container for holding the set of broadcast records that satisfied a certain criteria.
+ */
+ @GuardedBy("mService")
+ private final AtomicReference<ArrayMap<BroadcastRecord, Boolean>> mRecordsLookupCache =
+ new AtomicReference<>();
+
+ /**
* Map from UID to its last known "foreground" state. A UID is considered to be in
* "foreground" state when it's procState is {@link ActivityManager#PROCESS_STATE_TOP}.
* <p>
@@ -449,7 +458,17 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
updateWarmProcess(queue);
final boolean processWarm = queue.isProcessWarm();
- if (!processWarm) {
+ if (processWarm) {
+ mService.mOomAdjuster.unfreezeTemporarily(queue.app,
+ CachedAppOptimizer.UNFREEZE_REASON_START_RECEIVER);
+ // The process could be killed as part of unfreezing. So, check again if it
+ // is still warm.
+ if (!queue.isProcessWarm()) {
+ queue = nextQueue;
+ enqueueUpdateRunningList();
+ continue;
+ }
+ } else {
// We only offer to run one cold-start at a time to preserve
// system resources; below we either claim that single slot or
// skip to look for another warm process
@@ -521,6 +540,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
mRunningColdStart.reEnqueueActiveBroadcast();
demoteFromRunningLocked(mRunningColdStart);
clearRunningColdStart();
+ enqueueUpdateRunningList();
}
private void checkPendingColdStartValidity() {
@@ -555,6 +575,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
@Override
public boolean onApplicationAttachedLocked(@NonNull ProcessRecord app)
throws BroadcastDeliveryFailedException {
+ if (DEBUG_BROADCAST) {
+ logv("Process " + app + " is attached");
+ }
// Process records can be recycled, so always start by looking up the
// relevant per-process queue
final BroadcastProcessQueue queue = getProcessQueue(app);
@@ -604,18 +627,21 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
@Override
public void onApplicationCleanupLocked(@NonNull ProcessRecord app) {
- // Process records can be recycled, so always start by looking up the
- // relevant per-process queue
- final BroadcastProcessQueue queue = getProcessQueue(app);
- if (queue != null) {
- setQueueProcess(queue, null);
+ if (DEBUG_BROADCAST) {
+ logv("Process " + app + " is cleaned up");
}
- if ((mRunningColdStart != null) && (mRunningColdStart == queue)) {
+ // This cleanup callback could be for an old process and not for the one we are waiting
+ // on, so explicitly check if this for the same ProcessRecord that a queue has.
+ final BroadcastProcessQueue queue = getProcessQueue(app);
+ if ((mRunningColdStart != null) && (mRunningColdStart == queue)
+ && mRunningColdStart.app == app) {
clearRunningColdStart();
}
- if (queue != null) {
+ if (queue != null && queue.app == app) {
+ setQueueProcess(queue, null);
+
// If queue was running a broadcast, fail it
if (queue.isActive()) {
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
@@ -682,10 +708,10 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
// If this receiver is going to be skipped, skip it now itself and don't even enqueue
// it.
- final boolean wouldBeSkipped = (mSkipPolicy.shouldSkipMessage(r, receiver) != null);
- if (wouldBeSkipped) {
+ final String skipReason = mSkipPolicy.shouldSkipMessage(r, receiver);
+ if (skipReason != null) {
setDeliveryState(null, null, r, i, receiver, BroadcastRecord.DELIVERY_SKIPPED,
- "skipped by policy at enqueue");
+ "skipped by policy at enqueue: " + skipReason);
continue;
}
@@ -742,13 +768,16 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
broadcastConsumer = mBroadcastConsumerSkipAndCanceled;
break;
case BroadcastOptions.DELIVERY_GROUP_POLICY_MERGED:
+ // TODO: Allow applying MERGED policy for broadcasts with more than one receiver.
+ if (r.receivers.size() > 1) {
+ return;
+ }
final BundleMerger extrasMerger = r.options.getDeliveryGroupExtrasMerger();
if (extrasMerger == null) {
// Extras merger is required to be able to merge the extras. So, if it's not
// supplied, then ignore the delivery group policy.
return;
}
- // TODO: Don't merge with the same BroadcastRecord more than once.
broadcastConsumer = (record, recordIndex) -> {
r.intent.mergeExtras(record.intent, extrasMerger);
mBroadcastConsumerSkipAndCanceled.accept(record, recordIndex);
@@ -758,6 +787,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
logw("Unknown delivery group policy: " + policy);
return;
}
+ final ArrayMap<BroadcastRecord, Boolean> recordsLookupCache = getRecordsLookupCache();
forEachMatchingBroadcast(QUEUE_PREDICATE_ANY, (testRecord, testIndex) -> {
// If the receiver is already in a terminal state, then ignore it.
if (isDeliveryStateTerminal(testRecord.getDeliveryState(testIndex))) {
@@ -769,22 +799,44 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|| !r.matchesDeliveryGroup(testRecord)) {
return false;
}
- // TODO: If a process is in a deferred state, we can always apply the policy as long
- // as it is one of the receivers for the new broadcast.
// For ordered broadcast, check if the receivers for the new broadcast is a superset
// of those for the previous one as skipping and removing only one of them could result
// in an inconsistent state.
- if (testRecord.ordered || testRecord.resultTo != null) {
- // TODO: Cache this result in some way so that we don't have to perform the
- // same check for all the broadcast receivers.
- return r.containsAllReceivers(testRecord.receivers);
- } else if (testRecord.prioritized) {
- return r.containsAllReceivers(testRecord.receivers);
+ if (testRecord.ordered || testRecord.prioritized) {
+ return containsAllReceivers(r, testRecord, recordsLookupCache);
+ } else if (testRecord.resultTo != null) {
+ return testRecord.getDeliveryState(testIndex) == DELIVERY_DEFERRED
+ ? r.containsReceiver(testRecord.receivers.get(testIndex))
+ : containsAllReceivers(r, testRecord, recordsLookupCache);
} else {
return r.containsReceiver(testRecord.receivers.get(testIndex));
}
}, broadcastConsumer, true);
+ recordsLookupCache.clear();
+ mRecordsLookupCache.compareAndSet(null, recordsLookupCache);
+ }
+
+ @NonNull
+ private ArrayMap<BroadcastRecord, Boolean> getRecordsLookupCache() {
+ ArrayMap<BroadcastRecord, Boolean> recordsLookupCache =
+ mRecordsLookupCache.getAndSet(null);
+ if (recordsLookupCache == null) {
+ recordsLookupCache = new ArrayMap<>();
+ }
+ return recordsLookupCache;
+ }
+
+ private boolean containsAllReceivers(@NonNull BroadcastRecord record,
+ @NonNull BroadcastRecord testRecord,
+ @NonNull ArrayMap<BroadcastRecord, Boolean> recordsLookupCache) {
+ final int idx = recordsLookupCache.indexOfKey(testRecord);
+ if (idx > 0) {
+ return recordsLookupCache.valueAt(idx);
+ }
+ final boolean containsAll = record.containsAllReceivers(testRecord.receivers);
+ recordsLookupCache.put(testRecord, containsAll);
+ return containsAll;
}
/**
@@ -1002,6 +1054,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
mService.mPackageManagerInt.grantImplicitAccess(r.userId, r.intent,
UserHandle.getAppId(app.uid), r.callingUid, true);
}
+ queue.lastProcessState = app.mState.getCurProcState();
if (receiver instanceof BroadcastFilter) {
notifyScheduleRegisteredReceiver(app, r, (BroadcastFilter) receiver);
thread.scheduleRegisteredReceiver(
@@ -1037,6 +1090,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
// If we were trying to deliver a manifest broadcast, throw the error as we need
// to try redelivering the broadcast to this receiver.
if (receiver instanceof ResolveInfo) {
+ mLocalHandler.removeMessages(MSG_DELIVERY_TIMEOUT_SOFT, queue);
throw new BroadcastDeliveryFailedException(e);
}
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
@@ -1914,12 +1968,16 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
? BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__RUNTIME
: BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST;
final int type;
+ final int receiverProcessState;
if (queue == null) {
type = BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_UNKNOWN;
+ receiverProcessState = ActivityManager.PROCESS_STATE_UNKNOWN;
} else if (queue.getActiveViaColdStart()) {
type = BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD;
+ receiverProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
} else {
type = BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM;
+ receiverProcessState = queue.lastProcessState;
}
// With the new per-process queues, there's no delay between being
// "dispatched" and "scheduled", so we report no "receive delay"
@@ -1934,7 +1992,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
receiverType, type, dispatchDelay, receiveDelay, finishDelay, packageState,
app != null ? app.info.packageName : null, r.callerPackage,
r.calculateTypeForLogging(), r.getDeliveryGroupPolicy(), r.intent.getFlags(),
- BroadcastRecord.getReceiverPriority(receiver), r.callerProcState);
+ BroadcastRecord.getReceiverPriority(receiver), r.callerProcState,
+ receiverProcessState);
}
}
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index 67d43fd30bad..198adcb7606a 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -44,7 +44,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UptimeMillisLong;
-import android.app.ActivityManager;
import android.app.ActivityManager.ProcessState;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
@@ -271,6 +270,8 @@ final class BroadcastRecord extends Binder {
BroadcastFilter curFilter; // the registered receiver currently running.
Bundle curFilteredExtras; // the bundle that has been filtered by the package visibility rules
+ int curAppLastProcessState; // The last process state of the current receiver before receiving
+
boolean mIsReceiverAppRunning; // Was the receiver's app already running.
boolean mWasReceiverAppStopped; // Was the receiver app stopped prior to starting
@@ -432,13 +433,14 @@ final class BroadcastRecord extends Binder {
boolean initialSticky, int userId,
@NonNull BackgroundStartPrivileges backgroundStartPrivileges,
boolean timeoutExempt,
- @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) {
+ @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver,
+ int callerAppProcessState) {
this(queue, intent, callerApp, callerPackage, callerFeatureId, callingPid,
callingUid, callerInstantApp, resolvedType, requiredPermissions,
excludedPermissions, excludedPackages, appOp, options, receivers, resultToApp,
resultTo, resultCode, resultData, resultExtras, serialized, sticky,
initialSticky, userId, -1, backgroundStartPrivileges, timeoutExempt,
- filterExtrasForReceiver);
+ filterExtrasForReceiver, callerAppProcessState);
}
BroadcastRecord(BroadcastQueue _queue,
@@ -453,7 +455,8 @@ final class BroadcastRecord extends Binder {
boolean _initialSticky, int _userId, int originalStickyCallingUid,
@NonNull BackgroundStartPrivileges backgroundStartPrivileges,
boolean timeoutExempt,
- @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver) {
+ @Nullable BiFunction<Integer, Bundle, Bundle> filterExtrasForReceiver,
+ int callerAppProcessState) {
if (_intent == null) {
throw new NullPointerException("Can't construct with a null intent");
}
@@ -465,8 +468,7 @@ final class BroadcastRecord extends Binder {
callerFeatureId = _callerFeatureId;
callingPid = _callingPid;
callingUid = _callingUid;
- callerProcState = callerApp == null ? ActivityManager.PROCESS_STATE_UNKNOWN
- : callerApp.getCurProcState();
+ callerProcState = callerAppProcessState;
callerInstantApp = _callerInstantApp;
callerInstrumented = isCallerInstrumented(_callerApp, _callingUid);
resolvedType = _resolvedType;
@@ -606,7 +608,8 @@ final class BroadcastRecord extends Binder {
requiredPermissions, excludedPermissions, excludedPackages, appOp, options,
splitReceivers, resultToApp, resultTo, resultCode, resultData, resultExtras,
ordered, sticky, initialSticky, userId,
- mBackgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver);
+ mBackgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver,
+ callerProcState);
split.enqueueTime = this.enqueueTime;
split.enqueueRealTime = this.enqueueRealTime;
split.enqueueClockTime = this.enqueueClockTime;
@@ -686,7 +689,7 @@ final class BroadcastRecord extends Binder {
uid2receiverList.valueAt(i), null /* _resultToApp */, null /* _resultTo */,
resultCode, resultData, resultExtras, ordered, sticky, initialSticky, userId,
mBackgroundStartPrivileges, timeoutExempt,
- filterExtrasForReceiver);
+ filterExtrasForReceiver, callerProcState);
br.enqueueTime = this.enqueueTime;
br.enqueueRealTime = this.enqueueRealTime;
br.enqueueClockTime = this.enqueueClockTime;
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index e744eee8b485..3f7d8ba1a120 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -246,9 +246,13 @@ public class ContentProviderHelper {
}
}
+ final int callingProcessState = r != null
+ ? r.mState.getCurProcState() : ActivityManager.PROCESS_STATE_UNKNOWN;
+
if (providerRunning) {
cpi = cpr.info;
+
if (r != null && cpr.canRunHere(r)) {
checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, checkCrossUser,
cpr.name.flattenToShortString(), startTime);
@@ -266,7 +270,8 @@ public class ContentProviderHelper {
r.uid, callingUid,
PROVIDER_ACQUISITION_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM,
PROVIDER_ACQUISITION_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL,
- cpi.packageName, callingPackage);
+ cpi.packageName, callingPackage,
+ callingProcessState, callingProcessState);
return holder;
}
@@ -282,6 +287,8 @@ public class ContentProviderHelper {
checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, checkCrossUser,
cpr.name.flattenToShortString(), startTime);
+ final int providerProcessState = cpr.proc.mState.getCurProcState();
+
final long origId = Binder.clearCallingIdentity();
try {
checkTime(startTime, "getContentProviderImpl: incProviderCountLocked");
@@ -338,7 +345,8 @@ public class ContentProviderHelper {
cpr.proc.uid, callingUid,
PROVIDER_ACQUISITION_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM,
PROVIDER_ACQUISITION_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL,
- cpi.packageName, callingPackage);
+ cpi.packageName, callingPackage,
+ callingProcessState, providerProcessState);
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -516,7 +524,8 @@ public class ContentProviderHelper {
proc.uid, callingUid,
PROVIDER_ACQUISITION_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM,
PROVIDER_ACQUISITION_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL,
- cpi.packageName, callingPackage);
+ cpi.packageName, callingPackage,
+ callingProcessState, proc.mState.getCurProcState());
} else {
final int packageState =
((cpr.appInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0)
@@ -541,7 +550,8 @@ public class ContentProviderHelper {
PROVIDER_ACQUISITION_EVENT_REPORTED,
proc.uid, callingUid,
PROVIDER_ACQUISITION_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD,
- packageState, cpi.packageName, callingPackage);
+ packageState, cpi.packageName, callingPackage,
+ callingProcessState, ActivityManager.PROCESS_STATE_NONEXISTENT);
}
cpr.launchingApp = proc;
mLaunchingProviders.add(cpr);
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index a86c2e362c54..764bbe8bd191 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1471,7 +1471,8 @@ public class OomAdjuster {
if (!ActivityManager.isProcStateBackground(uidRec.getSetProcState())
|| uidRec.isSetAllowListed()) {
uidRec.setLastBackgroundTime(nowElapsed);
- if (!mService.mHandler.hasMessages(IDLE_UIDS_MSG)) {
+ if (mService.mDeterministicUidIdle
+ || !mService.mHandler.hasMessages(IDLE_UIDS_MSG)) {
// Note: the background settle time is in elapsed realtime, while
// the handler time base is uptime. All this means is that we may
// stop background uids later than we had intended, but that only
@@ -3227,7 +3228,8 @@ public class OomAdjuster {
// (for states debouncing to avoid from thrashing).
state.setLastCanKillOnBgRestrictedAndIdleTime(nowElapsed);
// Kick off the delayed checkup message if needed.
- if (!mService.mHandler.hasMessages(IDLE_UIDS_MSG)) {
+ if (mService.mDeterministicUidIdle
+ || !mService.mHandler.hasMessages(IDLE_UIDS_MSG)) {
mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG,
mConstants.mKillBgRestrictedAndCachedIdleSettleTimeMs);
}
@@ -3346,6 +3348,7 @@ public class OomAdjuster {
@GuardedBy("mService")
void idleUidsLocked() {
final int N = mActiveUids.size();
+ mService.mHandler.removeMessages(IDLE_UIDS_MSG);
if (N <= 0) {
return;
}
@@ -3391,7 +3394,6 @@ public class OomAdjuster {
}
}
if (nextTime > 0) {
- mService.mHandler.removeMessages(IDLE_UIDS_MSG);
mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG,
nextTime + mConstants.BACKGROUND_SETTLE_TIME - nowElapsed);
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 4342cb994754..c5776d822c8f 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2572,9 +2572,14 @@ public final class ProcessList {
// and did the cleanup before the actual death notification. Check the dying processes.
predecessor = mDyingProcesses.get(processName, info.uid);
if (predecessor != null) {
- if (app != null) {
+ // The process record could have existed but its pid is set to 0. In this case,
+ // the 'app' and 'predecessor' could end up pointing to the same instance;
+ // so make sure we check this case here.
+ if (app != null && app != predecessor) {
app.mPredecessor = predecessor;
predecessor.mSuccessor = app;
+ } else {
+ app = null;
}
Slog.w(TAG_PROCESSES, predecessor.toString() + " is attached to a previous process "
+ predecessor.getDyingPid());
@@ -5195,6 +5200,8 @@ public final class ProcessList {
mDyingProcesses.remove(app.processName, app.uid);
app.setDyingPid(0);
handlePrecedingAppDiedLocked(app);
+ // Remove from the LRU list if it's still there.
+ removeLruProcessLocked(app);
return true;
}
return false;
@@ -5243,7 +5250,9 @@ public final class ProcessList {
mAppsInBackgroundRestricted.add(app);
final long future = killAppIfBgRestrictedAndCachedIdleLocked(
app, nowElapsed);
- if (future > 0 && !mService.mHandler.hasMessages(IDLE_UIDS_MSG)) {
+ if (future > 0
+ && (mService.mDeterministicUidIdle
+ || !mService.mHandler.hasMessages(IDLE_UIDS_MSG))) {
mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG,
future - nowElapsed);
}
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index dccbb0accadd..50fe6d71d26e 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
import static android.app.ProcessMemoryState.HOSTING_COMPONENT_TYPE_BOUND_SERVICE;
@@ -244,6 +245,11 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
*/
long mRestartSchedulingTime;
+ /**
+ * The snapshot process state when the service is requested (either start or bind).
+ */
+ int mProcessStateOnRequest;
+
static class StartItem {
final ServiceRecord sr;
final boolean taskRemoved;
@@ -253,6 +259,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
final Intent intent;
final NeededUriGrants neededGrants;
final @Nullable String mCallingPackageName;
+ final int mCallingProcessState;
long deliveredTime;
int deliveryCount;
int doneExecutingCount;
@@ -262,7 +269,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
StartItem(ServiceRecord _sr, boolean _taskRemoved, int _id,
Intent _intent, NeededUriGrants _neededGrants, int _callingId,
- String callingProcessName, @Nullable String callingPackageName) {
+ String callingProcessName, @Nullable String callingPackageName,
+ int callingProcessState) {
sr = _sr;
taskRemoved = _taskRemoved;
id = _id;
@@ -271,6 +279,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
callingId = _callingId;
mCallingProcessName = callingProcessName;
mCallingPackageName = callingPackageName;
+ mCallingProcessState = callingProcessState;
}
UriPermissionOwner getUriPermissionsLocked() {
@@ -873,6 +882,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
app.mServices.updateHostingComonentTypeForBindingsLocked();
}
app = proc;
+ updateProcessStateOnRequest();
if (pendingConnectionGroup > 0 && proc != null) {
final ProcessServiceRecord psr = proc.mServices;
psr.setConnectionService(this);
@@ -899,6 +909,11 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
}
}
+ void updateProcessStateOnRequest() {
+ mProcessStateOnRequest = app != null && app.getThread() != null && !app.isKilled()
+ ? app.mState.getCurProcState() : PROCESS_STATE_NONEXISTENT;
+ }
+
@NonNull
ArrayMap<IBinder, ArrayList<ConnectionRecord>> getConnections() {
return connections;
@@ -1061,12 +1076,13 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
if (app == null) {
return;
}
- if (mBackgroundStartPrivilegesByStartMerged.allowsAny()
- || mIsAllowedBgActivityStartsByBinding) {
+ BackgroundStartPrivileges backgroundStartPrivileges =
+ getBackgroundStartPrivilegesWithExclusiveToken();
+ if (backgroundStartPrivileges.allowsAny()) {
// if the token is already there it's safe to "re-add it" - we're dealing with
// a set of Binder objects
app.addOrUpdateBackgroundStartPrivileges(this,
- getBackgroundStartPrivilegesWithExclusiveToken());
+ backgroundStartPrivileges);
} else {
app.removeBackgroundStartPrivileges(this);
}
diff --git a/services/core/java/com/android/server/am/StackTracesDumpHelper.java b/services/core/java/com/android/server/am/StackTracesDumpHelper.java
index 01fb0d1d8b18..cf69b535151c 100644
--- a/services/core/java/com/android/server/am/StackTracesDumpHelper.java
+++ b/services/core/java/com/android/server/am/StackTracesDumpHelper.java
@@ -229,7 +229,7 @@ public class StackTracesDumpHelper {
firstPidEnd = new File(tracesFile).length();
}
// Append the Durations/latency comma separated array after the first PID.
- if (latencyTracker != null) {
+ if (firstPidTempDumpCopied && latencyTracker != null) {
appendtoANRFile(tracesFile,
latencyTracker.dumpAsCommaSeparatedArrayWithHeader());
}
@@ -392,11 +392,9 @@ public class StackTracesDumpHelper {
if (TEMP_DUMP_TIME_LIMIT <= timeTaken) {
Slog.e(TAG, "Aborted stack trace dump (current primary pid=" + pid
+ "); deadline exceeded.");
- tmpTracesFile.delete();
if (latencyTracker != null) {
latencyTracker.dumpStackTracesTempFileTimedOut();
}
- return null;
}
if (DEBUG_ANR) {
Slog.d(TAG, "Done with primary pid " + pid + " in " + timeTaken + "ms"
diff --git a/services/core/java/com/android/server/am/UidObserverController.java b/services/core/java/com/android/server/am/UidObserverController.java
index a6677a5185ca..7eeec32cf24a 100644
--- a/services/core/java/com/android/server/am/UidObserverController.java
+++ b/services/core/java/com/android/server/am/UidObserverController.java
@@ -30,6 +30,7 @@ import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -104,40 +105,62 @@ public class UidObserverController {
}
}
- void addUidToObserver(@NonNull IBinder observerToken, int uid) {
- synchronized (mLock) {
- int i = mUidObservers.beginBroadcast();
- while (i-- > 0) {
- var reg = (UidObserverRegistration) mUidObservers.getBroadcastCookie(i);
- if (reg.getToken().equals(observerToken)) {
- reg.addUid(uid);
- break;
- }
+ final void addUidToObserver(@NonNull IBinder observerToken, int uid) {
+ Message msg = Message.obtain(mHandler, ActivityManagerService.ADD_UID_TO_OBSERVER_MSG,
+ uid, /*arg2*/ 0, observerToken);
+ mHandler.sendMessage(msg);
+ }
- if (i == 0) {
- Slog.e(TAG_UID_OBSERVERS, "Unable to find UidObserver by token");
- }
+ /**
+ * Add a uid to the list of uids an observer is interested in. Must be run on the same thread
+ * as mDispatchRunnable.
+ *
+ * @param observerToken The token identifier for a UidObserver
+ * @param uid The uid to add to the list of watched uids
+ */
+ public final void addUidToObserverImpl(@NonNull IBinder observerToken, int uid) {
+ int i = mUidObservers.beginBroadcast();
+ while (i-- > 0) {
+ var reg = (UidObserverRegistration) mUidObservers.getBroadcastCookie(i);
+ if (reg.getToken().equals(observerToken)) {
+ reg.addUid(uid);
+ break;
+ }
+
+ if (i == 0) {
+ Slog.e(TAG_UID_OBSERVERS, "Unable to find UidObserver by token");
}
- mUidObservers.finishBroadcast();
}
+ mUidObservers.finishBroadcast();
}
- void removeUidFromObserver(@NonNull IBinder observerToken, int uid) {
- synchronized (mLock) {
- int i = mUidObservers.beginBroadcast();
- while (i-- > 0) {
- var reg = (UidObserverRegistration) mUidObservers.getBroadcastCookie(i);
- if (reg.getToken().equals(observerToken)) {
- reg.removeUid(uid);
- break;
- }
+ final void removeUidFromObserver(@NonNull IBinder observerToken, int uid) {
+ Message msg = Message.obtain(mHandler, ActivityManagerService.REMOVE_UID_FROM_OBSERVER_MSG,
+ uid, /*arg2*/ 0, observerToken);
+ mHandler.sendMessage(msg);
+ }
- if (i == 0) {
- Slog.e(TAG_UID_OBSERVERS, "Unable to find UidObserver by token");
- }
+ /**
+ * Remove a uid from the list of uids an observer is interested in. Must be run on the same
+ * thread as mDispatchRunnable.
+ *
+ * @param observerToken The token identifier for a UidObserver
+ * @param uid The uid to remove from the list of watched uids
+ */
+ public final void removeUidFromObserverImpl(@NonNull IBinder observerToken, int uid) {
+ int i = mUidObservers.beginBroadcast();
+ while (i-- > 0) {
+ var reg = (UidObserverRegistration) mUidObservers.getBroadcastCookie(i);
+ if (reg.getToken().equals(observerToken)) {
+ reg.removeUid(uid);
+ break;
+ }
+
+ if (i == 0) {
+ Slog.e(TAG_UID_OBSERVERS, "Unable to find UidObserver by token");
}
- mUidObservers.finishBroadcast();
}
+ mUidObservers.finishBroadcast();
}
int enqueueUidChange(@Nullable ChangeRecord currentRecord, int uid, int change, int procState,
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 1f8ff73b2d5d..29a19417b8fd 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1018,13 +1018,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
}
}
- /*package*/ void clearA2dpSuspended() {
+ /*package*/ void clearA2dpSuspended(boolean internalOnly) {
if (AudioService.DEBUG_COMM_RTE) {
- Log.v(TAG, "clearA2dpSuspended");
+ Log.v(TAG, "clearA2dpSuspended, internalOnly: " + internalOnly);
}
synchronized (mBluetoothAudioStateLock) {
mBluetoothA2dpSuspendedInt = false;
- mBluetoothA2dpSuspendedExt = false;
+ if (!internalOnly) {
+ mBluetoothA2dpSuspendedExt = false;
+ }
updateAudioHalBluetoothState();
}
}
@@ -1046,13 +1048,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
}
}
- /*package*/ void clearLeAudioSuspended() {
+ /*package*/ void clearLeAudioSuspended(boolean internalOnly) {
if (AudioService.DEBUG_COMM_RTE) {
- Log.v(TAG, "clearLeAudioSuspended");
+ Log.v(TAG, "clearLeAudioSuspended, internalOnly: " + internalOnly);
}
synchronized (mBluetoothAudioStateLock) {
mBluetoothLeSuspendedInt = false;
- mBluetoothLeSuspendedExt = false;
+ if (!internalOnly) {
+ mBluetoothLeSuspendedExt = false;
+ }
updateAudioHalBluetoothState();
}
}
@@ -2214,6 +2218,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
mDeviceInventory.removePreferredDevicesForStrategyInt(mAccessibilityStrategyId);
}
mDeviceInventory.applyConnectedDevicesRoles();
+ mDeviceInventory.reapplyExternalDevicesRoles();
} else {
mDeviceInventory.setPreferredDevicesForStrategyInt(
mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice));
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index d1cae490a31d..ec85d577a8e7 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -361,23 +361,34 @@ public class AudioDeviceInventory {
AudioSystem.DEVICE_STATE_AVAILABLE,
di.mDeviceCodecFormat);
}
- mAppliedStrategyRoles.clear();
mAppliedStrategyRolesInt.clear();
- mAppliedPresetRoles.clear();
mAppliedPresetRolesInt.clear();
applyConnectedDevicesRoles_l();
}
+ reapplyExternalDevicesRoles();
+ }
+
+ /*package*/ void reapplyExternalDevicesRoles() {
+ synchronized (mDevicesLock) {
+ mAppliedStrategyRoles.clear();
+ mAppliedPresetRoles.clear();
+ }
synchronized (mPreferredDevices) {
mPreferredDevices.forEach((strategy, devices) -> {
- setPreferredDevicesForStrategy(strategy, devices); });
+ setPreferredDevicesForStrategy(strategy, devices);
+ });
}
synchronized (mNonDefaultDevices) {
mNonDefaultDevices.forEach((strategy, devices) -> {
addDevicesRoleForStrategy(strategy, AudioSystem.DEVICE_ROLE_DISABLED,
- devices, false /* internal */); });
+ devices, false /* internal */);
+ });
}
synchronized (mPreferredDevicesForCapturePreset) {
- // TODO: call audiosystem to restore
+ mPreferredDevicesForCapturePreset.forEach((capturePreset, devices) -> {
+ setDevicesRoleForCapturePreset(
+ capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
+ });
}
}
@@ -1163,6 +1174,7 @@ public class AudioDeviceInventory {
return mAudioSystem.removeDevicesRoleForStrategy(s, r, d); });
purgeRoles(mAppliedPresetRolesInt, (p, r, d) -> {
return mAudioSystem.removeDevicesRoleForCapturePreset(p, r, d); });
+ reapplyExternalDevicesRoles();
}
@GuardedBy("mDevicesLock")
@@ -1535,7 +1547,7 @@ public class AudioDeviceInventory {
}
// Reset A2DP suspend state each time a new sink is connected
- mDeviceBroker.clearA2dpSuspended();
+ mDeviceBroker.clearA2dpSuspended(true /* internalOnly */);
// The convention for head tracking sensors associated with A2DP devices is to
// use a UUID derived from the MAC address as follows:
@@ -1958,7 +1970,7 @@ public class AudioDeviceInventory {
"LE Audio device addr=" + address + " now available").printLog(TAG));
}
// Reset LEA suspend state each time a new sink is connected
- mDeviceBroker.clearLeAudioSuspended();
+ mDeviceBroker.clearLeAudioSuspended(true /* internalOnly */);
UUID sensorUuid = UuidUtils.uuidFromAudioDeviceAttributes(ada);
mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address),
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index ac03c82260f9..c177c4efb5ef 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -353,7 +353,6 @@ public class AudioService extends IAudioService.Stub
private static final int MSG_PLAY_SOUND_EFFECT = 5;
private static final int MSG_LOAD_SOUND_EFFECTS = 7;
private static final int MSG_SET_FORCE_USE = 8;
- private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
private static final int MSG_SET_ALL_VOLUMES = 10;
private static final int MSG_UNLOAD_SOUND_EFFECTS = 15;
private static final int MSG_SYSTEM_READY = 16;
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index e46c3cc4a285..c8a17e5eea5a 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -445,8 +445,8 @@ public class BtHelper {
/*package*/ synchronized void resetBluetoothSco() {
mScoAudioState = SCO_STATE_INACTIVE;
broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
- mDeviceBroker.clearA2dpSuspended();
- mDeviceBroker.clearLeAudioSuspended();
+ mDeviceBroker.clearA2dpSuspended(false /* internalOnly */);
+ mDeviceBroker.clearLeAudioSuspended(false /* internalOnly */);
mDeviceBroker.setBluetoothScoOn(false, "resetBluetoothSco");
}
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 9fc00382d396..50ffbcb9f4c4 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -812,8 +812,7 @@ public final class PlaybackActivityMonitor
return false;
}
final int reqUsage = requester.getAudioAttributes().getUsage();
- if ((reqUsage == AudioAttributes.USAGE_ASSISTANT)
- || (reqUsage == AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)) {
+ if (reqUsage == AudioAttributes.USAGE_ASSISTANT) {
return true;
}
return false;
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index d2dcc508d01f..41651fd5553c 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -126,6 +126,7 @@ public final class DreamManagerService extends SystemService {
private final boolean mDreamsActivatedOnChargeByDefault;
private final boolean mDreamsActivatedOnDockByDefault;
private final boolean mKeepDreamingWhenUnpluggingDefault;
+ private final boolean mDreamsDisabledByAmbientModeSuppressionConfig;
private final CopyOnWriteArrayList<DreamManagerInternal.DreamManagerStateListener>
mDreamManagerStateListeners = new CopyOnWriteArrayList<>();
@@ -239,6 +240,9 @@ public final class DreamManagerService extends SystemService {
mSettingsObserver = new SettingsObserver(mHandler);
mKeepDreamingWhenUnpluggingDefault = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_keepDreamingWhenUnplugging);
+ mDreamsDisabledByAmbientModeSuppressionConfig = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_dreamsDisabledByAmbientModeSuppressionConfig);
+
}
@Override
@@ -406,6 +410,13 @@ public final class DreamManagerService extends SystemService {
return false;
}
+ if (mDreamsDisabledByAmbientModeSuppressionConfig
+ && mPowerManagerInternal.isAmbientDisplaySuppressed()) {
+ // Don't dream if Bedtime (or something else) is suppressing ambient.
+ Slog.i(TAG, "Can't start dreaming because ambient is suppressed.");
+ return false;
+ }
+
if ((mWhenToDream & DREAM_ON_CHARGE) == DREAM_ON_CHARGE) {
return mIsCharging;
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b39e8606e189..d29d9c84501d 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -6597,7 +6597,10 @@ public class NotificationManagerService extends SystemService {
}
private PostNotificationTracker acquireWakeLockForPost(String pkg, int uid) {
- if (mFlagResolver.isEnabled(WAKE_LOCK_FOR_POSTING_NOTIFICATION)) {
+ if (mFlagResolver.isEnabled(WAKE_LOCK_FOR_POSTING_NOTIFICATION)
+ && Binder.withCleanCallingIdentity(
+ () -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, false))) {
// The package probably doesn't have WAKE_LOCK permission and should not require it.
return Binder.withCleanCallingIdentity(() -> {
WakeLock wakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index f2d1357ac1b5..aaf13ebeff2a 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3714,11 +3714,16 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile
if (parser.getName().equals(TAG_PERMISSIONS)) {
final LegacyPermissionState legacyState;
if (ps.hasSharedUser()) {
- legacyState = getSettingLPr(ps.getSharedUserAppId()).getLegacyPermissionState();
+ final SettingBase sharedUserSettings = getSettingLPr(
+ ps.getSharedUserAppId());
+ legacyState = sharedUserSettings != null
+ ? sharedUserSettings.getLegacyPermissionState() : null;
} else {
legacyState = ps.getLegacyPermissionState();
}
- readInstallPermissionsLPr(parser, legacyState, users);
+ if (legacyState != null) {
+ readInstallPermissionsLPr(parser, legacyState, users);
+ }
} else if (parser.getName().equals(TAG_USES_STATIC_LIB)) {
readUsesStaticLibLPw(parser, ps);
} else if (parser.getName().equals(TAG_USES_SDK_LIB)) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index a020728cc85e..5b3514c01f9f 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -2547,10 +2547,7 @@ public class ShortcutService extends IShortcutService.Stub {
enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APP_PREDICTIONS,
"getShareTargets");
final ComponentName chooser = injectChooserActivity();
- final String pkg = (chooser != null
- && mPackageManagerInternal.getComponentEnabledSetting(chooser,
- injectBinderCallingUid(), userId) == PackageManager.COMPONENT_ENABLED_STATE_ENABLED)
- ? chooser.getPackageName() : mContext.getPackageName();
+ final String pkg = chooser != null ? chooser.getPackageName() : mContext.getPackageName();
synchronized (mLock) {
throwIfUserLockedL(userId);
final List<ShortcutManager.ShareShortcutInfo> shortcutInfoList = new ArrayList<>();
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 3e7ae331d705..2499529f0fc0 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -141,6 +141,7 @@ import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
import com.android.server.pm.pkg.PackageStateInternal;
+import com.android.server.pm.pkg.SharedUserApi;
import com.android.server.pm.pkg.component.ComponentMutateUtils;
import com.android.server.pm.pkg.component.ParsedPermission;
import com.android.server.pm.pkg.component.ParsedPermissionGroup;
@@ -4538,8 +4539,13 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
final int appId = ps.getAppId();
final LegacyPermissionState legacyState;
if (ps.hasSharedUser()) {
- legacyState = mPackageManagerInt.getSharedUserApi(
- ps.getSharedUserAppId()).getSharedUserLegacyPermissionState();
+ final int sharedUserId = ps.getSharedUserAppId();
+ SharedUserApi sharedUserApi = mPackageManagerInt.getSharedUserApi(sharedUserId);
+ if (sharedUserApi == null) {
+ Slog.wtf(TAG, "Missing shared user Api for " + sharedUserId);
+ return;
+ }
+ legacyState = sharedUserApi.getSharedUserLegacyPermissionState();
} else {
legacyState = ps.getLegacyPermissionState();
}
@@ -4584,8 +4590,13 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
ps.setInstallPermissionsFixed(false);
final LegacyPermissionState legacyState;
if (ps.hasSharedUser()) {
- legacyState = mPackageManagerInt.getSharedUserApi(
- ps.getSharedUserAppId()).getSharedUserLegacyPermissionState();
+ final int sharedUserId = ps.getSharedUserAppId();
+ SharedUserApi sharedUserApi = mPackageManagerInt.getSharedUserApi(sharedUserId);
+ if (sharedUserApi == null) {
+ Slog.wtf(TAG, "Missing shared user Api for " + sharedUserId);
+ return;
+ }
+ legacyState = sharedUserApi.getSharedUserLegacyPermissionState();
} else {
legacyState = ps.getLegacyPermissionState();
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 695a0cf3f79d..a53b831d55c1 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -283,7 +283,7 @@ public final class PowerManagerService extends SystemService
private static final long ENHANCED_DISCHARGE_PREDICTION_BROADCAST_MIN_DELAY_MS = 60 * 1000L;
/**
- * Apps targeting Android U and above need to define
+ * Apps targeting Android V and above need to define
* {@link android.Manifest.permission#TURN_SCREEN_ON} in their manifest for
* {@link android.os.PowerManager#ACQUIRE_CAUSES_WAKEUP} to have any effect.
* Note that most applications should use {@link android.R.attr#turnScreenOn} or
@@ -291,7 +291,7 @@ public final class PowerManagerService extends SystemService
* previous foreground app from being resumed first when the screen turns on.
*/
@ChangeId
- @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT)
public static final long REQUIRE_TURN_SCREEN_ON_PERMISSION = 216114297L;
/** Reason ID for holding display suspend blocker. */
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperData.java b/services/core/java/com/android/server/wallpaper/WallpaperData.java
index 9ff6a0d7e6ee..d87fca4d3c71 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperData.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperData.java
@@ -133,16 +133,14 @@ class WallpaperData {
*/
final Rect cropHint = new Rect(0, 0, 0, 0);
- WallpaperData(int userId, File wallpaperDir, String inputFileName, String cropFileName) {
- this.userId = userId;
- wallpaperFile = new File(wallpaperDir, inputFileName);
- cropFile = new File(wallpaperDir, cropFileName);
- }
-
WallpaperData(int userId, @SetWallpaperFlags int wallpaperType) {
- this(userId, getWallpaperDir(userId),
- (wallpaperType == FLAG_LOCK) ? WALLPAPER_LOCK_ORIG : WALLPAPER,
- (wallpaperType == FLAG_LOCK) ? WALLPAPER_LOCK_CROP : WALLPAPER_CROP);
+ this.userId = userId;
+ this.mWhich = wallpaperType;
+ File wallpaperDir = getWallpaperDir(userId);
+ String wallpaperFileName = (wallpaperType == FLAG_LOCK) ? WALLPAPER_LOCK_ORIG : WALLPAPER;
+ String cropFileName = (wallpaperType == FLAG_LOCK) ? WALLPAPER_LOCK_CROP : WALLPAPER_CROP;
+ this.wallpaperFile = new File(wallpaperDir, wallpaperFileName);
+ this.cropFile = new File(wallpaperDir, cropFileName);
}
/**
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index a079875a23e4..9e9b3444006c 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1588,7 +1588,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
mShuttingDown = false;
mImageWallpaper = ComponentName.unflattenFromString(
context.getResources().getString(R.string.image_wallpaper_component));
- mDefaultWallpaperComponent = WallpaperManager.getCmfDefaultWallpaperComponent(context);
+ mDefaultWallpaperComponent = WallpaperManager.getDefaultWallpaperComponent(context);
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mIPackageManager = AppGlobals.getPackageManager();
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 9f16a8441533..788bfbcd65c9 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -223,6 +223,7 @@ import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
+import static com.android.server.wm.LetterboxConfiguration.DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW;
import static com.android.server.wm.LetterboxConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
@@ -2425,7 +2426,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
allowTaskSnapshot, activityCreated, activityAllDrawn, snapshot);
- //TODO(191787740) Remove for T+
+ //TODO(191787740) Remove for V+
final boolean useLegacy = type == STARTING_WINDOW_TYPE_SPLASH_SCREEN
&& mWmService.mStartingSurfaceController.isExceptionApp(packageName, mTargetSdk,
() -> {
@@ -4550,6 +4551,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* immediately finishes after, so we have to transfer T to M.
*/
void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
+ final WindowState mainWin = findMainWindow(false);
+ if (mainWin != null && mainWin.mWinAnimator.getShown()) {
+ // This activity already has a visible window, so doesn't need to transfer the starting
+ // window from above activity to here. The starting window will be removed with above
+ // activity.
+ return;
+ }
task.forAllActivities(fromActivity -> {
if (fromActivity == this) return true;
return !fromActivity.isVisibleRequested() && transferStartingWindow(fromActivity);
@@ -8294,6 +8302,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
mIsAspectRatioApplied = false;
+ mIsEligibleForFixedOrientationLetterbox = false;
+ mLetterboxBoundsForFixedOrientationAndAspectRatio = null;
// Can't use resolvedConfig.windowConfiguration.getWindowingMode() because it can be
// different from windowing mode of the task (PiP) during transition from fullscreen to PiP
@@ -8303,8 +8313,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final boolean isFixedOrientationLetterboxAllowed =
parentWindowingMode == WINDOWING_MODE_MULTI_WINDOW
|| parentWindowingMode == WINDOWING_MODE_FULLSCREEN
- // Switching from PiP to fullscreen.
- || (parentWindowingMode == WINDOWING_MODE_PINNED
+ // When starting to switch between PiP and fullscreen, the task is pinned
+ // and the activity is fullscreen. But only allow to apply letterbox if the
+ // activity is exiting PiP because an entered PiP should fill the task.
+ || (!mWaitForEnteringPinnedMode
+ && parentWindowingMode == WINDOWING_MODE_PINNED
&& resolvedConfig.windowConfiguration.getWindowingMode()
== WINDOWING_MODE_FULLSCREEN);
// TODO(b/181207944): Consider removing the if condition and always run
@@ -8698,8 +8711,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* in this method.
*/
private void resolveFixedOrientationConfiguration(@NonNull Configuration newParentConfig) {
- mLetterboxBoundsForFixedOrientationAndAspectRatio = null;
- mIsEligibleForFixedOrientationLetterbox = false;
final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
final Rect stableBounds = new Rect();
// If orientation is respected when insets are applied, then stableBounds will be empty.
@@ -8784,9 +8795,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final float letterboxAspectRatioOverride =
mLetterboxUiController.getFixedOrientationLetterboxAspectRatio(newParentConfig);
- final float desiredAspectRatio =
- letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO
- ? letterboxAspectRatioOverride : computeAspectRatio(parentBounds);
+
+ // Aspect ratio as suggested by the system. Apps requested mix/max aspect ratio will
+ // be respected in #applyAspectRatio.
+ final float desiredAspectRatio;
+ if (isDefaultMultiWindowLetterboxAspectRatioDesired(newParentConfig)) {
+ desiredAspectRatio = DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW;
+ } else if (letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO) {
+ desiredAspectRatio = letterboxAspectRatioOverride;
+ } else {
+ desiredAspectRatio = computeAspectRatio(parentBounds);
+ }
+
// Apply aspect ratio to resolved bounds
mIsAspectRatioApplied = applyAspectRatio(resolvedBounds, containingBoundsWithInsets,
containingBounds, desiredAspectRatio);
@@ -8812,6 +8832,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
/**
+ * Returns {@code true} if the default aspect ratio for a letterboxed app in multi-window mode
+ * should be used.
+ */
+ private boolean isDefaultMultiWindowLetterboxAspectRatioDesired(
+ @NonNull Configuration parentConfig) {
+ if (mDisplayContent == null) {
+ return false;
+ }
+ final int windowingMode = parentConfig.windowConfiguration.getWindowingMode();
+ return WindowConfiguration.inMultiWindowMode(windowingMode)
+ && !mDisplayContent.getIgnoreOrientationRequest();
+ }
+
+ /**
* Resolves aspect ratio restrictions for an activity. If the bounds are restricted by
* aspect ratio, the position will be adjusted later in {@link #updateResolvedBoundsPosition
* within parent's app bounds to balance the visual appearance. The policy of aspect ratio has
diff --git a/services/core/java/com/android/server/wm/AsyncRotationController.java b/services/core/java/com/android/server/wm/AsyncRotationController.java
index 7e783938d30a..01158779c24f 100644
--- a/services/core/java/com/android/server/wm/AsyncRotationController.java
+++ b/services/core/java/com/android/server/wm/AsyncRotationController.java
@@ -185,6 +185,8 @@ class AsyncRotationController extends FadeAnimationController implements Consume
}
} else if (navigationBarCanMove || mTransitionOp == OP_CHANGE_MAY_SEAMLESS) {
action = Operation.ACTION_SEAMLESS;
+ } else if (mDisplayContent.mTransitionController.mNavigationBarAttachedToApp) {
+ return;
}
mTargetWindowTokens.put(w.mToken, new Operation(action));
return;
diff --git a/services/core/java/com/android/server/wm/DeviceStateController.java b/services/core/java/com/android/server/wm/DeviceStateController.java
index db4762e5f877..857e03d71f3f 100644
--- a/services/core/java/com/android/server/wm/DeviceStateController.java
+++ b/services/core/java/com/android/server/wm/DeviceStateController.java
@@ -20,6 +20,7 @@ import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.content.Context;
import android.util.ArrayMap;
+import android.util.Pair;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -165,19 +166,28 @@ final class DeviceStateController {
// Make a copy here because it's possible that the consumer tries to remove a callback
// while we're still iterating through the list, which would end up in a
- // ConcurrentModificationException.
- final List<Map.Entry<Consumer<DeviceState>, Executor>> entries = new ArrayList<>();
- synchronized (mWmLock) {
- for (Map.Entry<Consumer<DeviceState>, Executor> entry
- : mDeviceStateCallbacks.entrySet()) {
- entries.add(entry);
- }
- }
+ // ConcurrentModificationException. Note that cannot use a List<Map.Entry> because the
+ // entries are tied to the backing map. So, if a client removes a callback while
+ // we are notifying clients, we will get a NPE.
+ final List<Pair<Consumer<DeviceState>, Executor>> entries = copyDeviceStateCallbacks();
for (int i = 0; i < entries.size(); i++) {
- Map.Entry<Consumer<DeviceState>, Executor> entry = entries.get(i);
- entry.getValue().execute(() -> entry.getKey().accept(mCurrentDeviceState));
+ final Pair<Consumer<DeviceState>, Executor> entry = entries.get(i);
+ entry.second.execute(() -> entry.first.accept(deviceState));
}
}
}
+
+ @VisibleForTesting
+ @NonNull
+ List<Pair<Consumer<DeviceState>, Executor>> copyDeviceStateCallbacks() {
+ final List<Pair<Consumer<DeviceState>, Executor>> entries = new ArrayList<>();
+
+ synchronized (mWmLock) {
+ mDeviceStateCallbacks.forEach((deviceStateConsumer, executor) -> {
+ entries.add(new Pair<>(deviceStateConsumer, executor));
+ });
+ }
+ return entries;
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 7fc86b0fdc01..ef19eef22794 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -244,6 +244,7 @@ import android.view.inputmethod.ImeTracker;
import android.window.DisplayWindowPolicyController;
import android.window.IDisplayAreaOrganizer;
import android.window.ScreenCapture;
+import android.window.ScreenCapture.SynchronousScreenCaptureListener;
import android.window.TransitionRequestInfo;
import com.android.internal.R;
@@ -5088,7 +5089,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return null;
}
- Pair<ScreenCapture.ScreenCaptureListener, ScreenCapture.ScreenshotSync> syncScreenCapture =
+ SynchronousScreenCaptureListener syncScreenCapture =
ScreenCapture.createSyncCaptureListener();
getBounds(mTmpRect);
@@ -5097,10 +5098,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
new ScreenCapture.LayerCaptureArgs.Builder(getSurfaceControl())
.setSourceCrop(mTmpRect).build();
- ScreenCapture.captureLayers(args, syncScreenCapture.first);
+ ScreenCapture.captureLayers(args, syncScreenCapture);
final ScreenCapture.ScreenshotHardwareBuffer screenshotBuffer =
- syncScreenCapture.second.get();
+ syncScreenCapture.getBuffer();
final Bitmap bitmap = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
if (bitmap == null) {
Slog.w(TAG_WM, "Failed to take screenshot");
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 65771d1ce373..95c953a5cf2d 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -2368,7 +2368,8 @@ public class DisplayPolicy {
// We need to force the consumption of the system bars if they are force shown or if they
// are controlled by a remote insets controller.
mForceConsumeSystemBars = mForceShowSystemBars
- || mDisplayContent.getInsetsPolicy().remoteInsetsControllerControlsSystemBars(win);
+ || getInsetsPolicy().remoteInsetsControllerControlsSystemBars(win)
+ || getInsetsPolicy().forcesShowingNavigationBars(win);
mDisplayContent.getInsetsPolicy().updateBarControlTarget(win);
final boolean topAppHidesStatusBar = topAppHidesSystemBar(Type.statusBars());
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index ddf96c53323d..daa823cf447f 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -567,8 +567,7 @@ class InsetsPolicy {
return focusedWin;
}
}
- if (mPolicy.isForceShowNavigationBarEnabled() && focusedWin != null
- && focusedWin.getActivityType() == ACTIVITY_TYPE_STANDARD) {
+ if (forcesShowingNavigationBars(focusedWin)) {
// When "force show navigation bar" is enabled, it means both force visible is true, and
// we are in 3-button navigation. In this mode, the navigation bar is forcibly shown
// when activity type is ACTIVITY_TYPE_STANDARD which means Launcher or Recent could
@@ -604,6 +603,11 @@ class InsetsPolicy {
return focusedWin;
}
+ boolean forcesShowingNavigationBars(WindowState win) {
+ return mPolicy.isForceShowNavigationBarEnabled() && win != null
+ && win.getActivityType() == ACTIVITY_TYPE_STANDARD;
+ }
+
/**
* Determines whether the remote insets controller should take control of system bars for all
* windows.
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index a93cb8ad2d97..067a18c88aaa 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -52,6 +52,9 @@ final class LetterboxConfiguration {
*/
static final float MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO = 1.0f;
+ /** The default aspect ratio for a letterboxed app in multi-window mode. */
+ static final float DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW = 1.01f;
+
/** Letterboxed app window position multiplier indicating center position. */
static final float LETTERBOX_POSITION_MULTIPLIER_CENTER = 0.5f;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 4995236da1be..54fec3e2f844 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2013,7 +2013,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// from doing work and changing the activity visuals while animating
// TODO(task-org): Figure-out more structured way to do this long term.
r.setWindowingMode(r.getWindowingMode());
- r.mWaitForEnteringPinnedMode = true;
final TaskFragment organizedTf = r.getOrganizedTaskFragment();
final boolean singleActivity = task.getNonFinishingActivityCount() == 1;
@@ -2140,6 +2139,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
rootTask.setDeferTaskAppear(false);
+ // After setting this, it is not expected to change activity configuration until the
+ // transition animation is finished. So the activity can keep consistent appearance
+ // when animating.
+ r.mWaitForEnteringPinnedMode = true;
// Reset the state that indicates it can enter PiP while pausing after we've moved it
// to the root pinned task
r.supportsEnterPipOnTaskSwitch = false;
@@ -2357,10 +2360,14 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
final Transition transition = new Transition(TRANSIT_SLEEP, 0 /* flags */,
display.mTransitionController, mWmService.mSyncEngine);
final TransitionController.OnStartCollect sendSleepTransition = (deferred) -> {
- display.mTransitionController.requestStartTransition(transition,
- null /* trigger */, null /* remote */, null /* display */);
- // Force playing immediately so that unrelated ops can't be collected.
- transition.playNow();
+ if (deferred && !display.shouldSleep()) {
+ transition.abort();
+ } else {
+ display.mTransitionController.requestStartTransition(transition,
+ null /* trigger */, null /* remote */, null /* display */);
+ // Force playing immediately so that unrelated ops can't be collected.
+ transition.playNow();
+ }
};
if (!display.mTransitionController.isCollecting()) {
// Since this bypasses sync, submit directly ignoring whether sync-engine
@@ -3306,9 +3313,14 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
if (aOptions != null) {
// Resolve the root task the task should be placed in now based on options
// and reparent if needed.
+ // TODO(b/229927851) For split-screen, setLaunchRootTask is no longer the "root"
+ // task, consider to rename methods like "parentTask" instead of "rootTask".
final Task targetRootTask =
getOrCreateRootTask(null, aOptions, task, onTop);
- if (targetRootTask != null && task.getRootTask() != targetRootTask) {
+ // When launch with ActivityOptions#getLaunchRootTask, the "root task" just mean the
+ // parent of current launch, not the "root task" in hierarchy.
+ if (targetRootTask != null && task.getRootTask() != targetRootTask
+ && task.getParent() != targetRootTask) {
final int reparentMode = onTop
? REPARENT_MOVE_ROOT_TASK_TO_FRONT : REPARENT_LEAVE_ROOT_TASK_IN_PLACE;
task.reparent(targetRootTask, onTop, reparentMode, ANIMATE, DEFER_RESUME,
diff --git a/services/core/java/com/android/server/wm/SplashScreenExceptionList.java b/services/core/java/com/android/server/wm/SplashScreenExceptionList.java
index b3cd3f0df97e..3fb897b5c0e9 100644
--- a/services/core/java/com/android/server/wm/SplashScreenExceptionList.java
+++ b/services/core/java/com/android/server/wm/SplashScreenExceptionList.java
@@ -70,7 +70,7 @@ class SplashScreenExceptionList {
}
/**
- * Returns true if the packageName is in the list and the target sdk is before or including T.
+ * Returns true if the packageName is in the list and the target sdk is before or including V.
*
* @param packageName The package name of the application to check
* @param targetSdk The target sdk of the application
@@ -82,7 +82,7 @@ class SplashScreenExceptionList {
@SuppressWarnings("AndroidFrameworkCompatChange") // Target sdk check
public boolean isException(@NonNull String packageName, int targetSdk,
@Nullable Supplier<ApplicationInfo> infoSupplier) {
- if (targetSdk > Build.VERSION_CODES.TIRAMISU) {
+ if (targetSdk > Build.VERSION_CODES.UPSIDE_DOWN_CAKE + 1) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 7104739068e4..ceb80d6a1a8b 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3443,6 +3443,7 @@ class Task extends TaskFragment {
: INVALID_TASK_ID;
info.isFocused = isFocused();
info.isVisible = hasVisibleChildren();
+ info.isVisibleRequested = isVisibleRequested();
info.isSleeping = shouldSleepActivities();
info.isLetterboxDoubleTapEnabled = top != null
&& top.mLetterboxUiController.isLetterboxDoubleTapEducationEnabled();
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 82b00866502b..aad12251502d 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -234,9 +234,6 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
private @TransitionState int mState = STATE_PENDING;
private final ReadyTracker mReadyTracker = new ReadyTracker();
- // TODO(b/188595497): remove when not needed.
- /** @see RecentsAnimationController#mNavigationBarAttachedToApp */
- private boolean mNavBarAttachedToApp = false;
private int mRecentsDisplayId = INVALID_DISPLAY;
/** The delay for light bar appearance animation. */
@@ -690,6 +687,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
if (!wc.mDisplayContent.getDisplayPolicy().isScreenOnFully()
|| wc.mDisplayContent.getDisplayInfo().state == Display.STATE_OFF) {
mFlags |= WindowManager.TRANSIT_FLAG_INVISIBLE;
+ return;
}
if (mContainerFreezer == null) {
@@ -1780,7 +1778,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
if (navWindow == null || navWindow.mToken == null) {
return;
}
- mNavBarAttachedToApp = true;
+ mController.mNavigationBarAttachedToApp = true;
navWindow.mToken.cancelAnimation();
final SurfaceControl.Transaction t = navWindow.mToken.getPendingTransaction();
final SurfaceControl navSurfaceControl = navWindow.mToken.getSurfaceControl();
@@ -1802,8 +1800,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
/** @see RecentsAnimationController#restoreNavigationBarFromApp */
void legacyRestoreNavigationBarFromApp() {
- if (!mNavBarAttachedToApp) return;
- mNavBarAttachedToApp = false;
+ if (!mController.mNavigationBarAttachedToApp) {
+ return;
+ }
+ mController.mNavigationBarAttachedToApp = false;
if (mRecentsDisplayId == INVALID_DISPLAY) {
Slog.e(TAG, "Reparented navigation bar without a valid display");
@@ -1836,6 +1836,11 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
break;
}
+ final AsyncRotationController asyncRotationController = dc.getAsyncRotationController();
+ if (asyncRotationController != null) {
+ asyncRotationController.accept(navWindow);
+ }
+
if (animate) {
final NavBarFadeAnimationController controller =
new NavBarFadeAnimationController(dc);
@@ -1844,6 +1849,9 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
// Reparent the SurfaceControl of nav bar token back.
t.reparent(navToken.getSurfaceControl(), parent.getSurfaceControl());
}
+
+ // To apply transactions.
+ dc.mWmService.scheduleAnimationLocked();
}
private void reportStartReasonsToLogger() {
@@ -2317,23 +2325,13 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
task.fillTaskInfo(tinfo);
change.setTaskInfo(tinfo);
change.setRotationAnimation(getTaskRotationAnimation(task));
- final ActivityRecord topMostActivity = task.getTopMostActivity();
- change.setAllowEnterPip(topMostActivity != null
- && topMostActivity.checkEnterPictureInPictureAppOpsState());
final ActivityRecord topRunningActivity = task.topRunningActivity();
- if (topRunningActivity != null && task.mDisplayContent != null
- // Display won't be rotated for multi window Task, so the fixed rotation
- // won't be applied. This can happen when the windowing mode is changed
- // before the previous fixed rotation is applied.
- && (!task.inMultiWindowMode() || !topRunningActivity.inMultiWindowMode())) {
- // If Activity is in fixed rotation, its will be applied with the next rotation,
- // when the Task is still in the previous rotation.
- final int taskRotation = task.getWindowConfiguration().getDisplayRotation();
- final int activityRotation = topRunningActivity.getWindowConfiguration()
- .getDisplayRotation();
- if (taskRotation != activityRotation) {
- change.setEndFixedRotation(activityRotation);
+ if (topRunningActivity != null) {
+ if (topRunningActivity.info.supportsPictureInPicture()) {
+ change.setAllowEnterPip(
+ topRunningActivity.checkEnterPictureInPictureAppOpsState());
}
+ setEndFixedRotationIfNeeded(change, task, topRunningActivity);
}
} else if ((info.mFlags & ChangeInfo.FLAG_SEAMLESS_ROTATION) != 0) {
change.setRotationAnimation(ROTATION_ANIMATION_SEAMLESS);
@@ -2441,6 +2439,48 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
}
return animOptions;
}
+
+ private static void setEndFixedRotationIfNeeded(@NonNull TransitionInfo.Change change,
+ @NonNull Task task, @NonNull ActivityRecord taskTopRunning) {
+ if (!taskTopRunning.isVisibleRequested()) {
+ // Fixed rotation only applies to opening or changing activity.
+ return;
+ }
+ if (task.inMultiWindowMode() && taskTopRunning.inMultiWindowMode()) {
+ // Display won't be rotated for multi window Task, so the fixed rotation won't be
+ // applied. This can happen when the windowing mode is changed before the previous
+ // fixed rotation is applied. Check both task and activity because the activity keeps
+ // fullscreen mode when the task is entering PiP.
+ return;
+ }
+ final int taskRotation = task.getWindowConfiguration().getDisplayRotation();
+ final int activityRotation = taskTopRunning.getWindowConfiguration()
+ .getDisplayRotation();
+ // If the Activity uses fixed rotation, its rotation will be applied to display after
+ // the current transition is done, while the Task is still in the previous rotation.
+ if (taskRotation != activityRotation) {
+ change.setEndFixedRotation(activityRotation);
+ return;
+ }
+
+ // For example, the task is entering PiP so it no longer decides orientation. If the next
+ // orientation source (it could be an activity which was behind the PiP or launching to top)
+ // will change display rotation, then set the fixed rotation hint as well so the animation
+ // can consider the rotated position.
+ if (!task.inPinnedWindowingMode() || taskTopRunning.mDisplayContent.inTransition()) {
+ return;
+ }
+ final WindowContainer<?> orientationSource =
+ taskTopRunning.mDisplayContent.getLastOrientationSource();
+ if (orientationSource == null) {
+ return;
+ }
+ final int nextRotation = orientationSource.getWindowConfiguration().getDisplayRotation();
+ if (taskRotation != nextRotation) {
+ change.setEndFixedRotation(nextRotation);
+ }
+ }
+
/**
* Finds the top-most common ancestor of app targets.
*
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 0cb6f14b38f2..359b353ba336 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -206,6 +206,11 @@ class TransitionController {
*/
boolean mBuildingFinishLayers = false;
+ /**
+ * Whether the surface of navigation bar token is reparented to an app.
+ */
+ boolean mNavigationBarAttachedToApp = false;
+
private boolean mAnimatingState = false;
final Handler mLoggerHandler = FgThread.getHandler();
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 7f41ff1a3d9b..eb7b8c2555fb 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -21,7 +21,6 @@ import static android.app.WallpaperManager.COMMAND_UNFREEZE;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
@@ -137,7 +136,8 @@ class WallpaperController {
};
private final ToBooleanFunction<WindowState> mFindWallpaperTargetFunction = w -> {
- if (!w.mTransitionController.isShellTransitionsEnabled()) {
+ final boolean useShellTransition = w.mTransitionController.isShellTransitionsEnabled();
+ if (!useShellTransition) {
if (w.mActivityRecord != null && !w.mActivityRecord.isVisible()
&& !w.mActivityRecord.isAnimating(TRANSITION | PARENTS)) {
// If this window's app token is hidden and not animating, it is of no interest.
@@ -159,32 +159,25 @@ class WallpaperController {
final WindowContainer animatingContainer = w.mActivityRecord != null
? w.mActivityRecord.getAnimatingContainer() : null;
- final boolean keyguardGoingAwayWithWallpaper = (animatingContainer != null
+ if (!useShellTransition && animatingContainer != null
&& animatingContainer.isAnimating(TRANSITION | PARENTS)
&& AppTransition.isKeyguardGoingAwayTransitOld(animatingContainer.mTransit)
&& (animatingContainer.mTransitFlags
- & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0);
-
- boolean needsShowWhenLockedWallpaper = false;
- if ((w.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && mService.mPolicy.isKeyguardLocked()) {
- final TransitionController tc = w.mTransitionController;
- final boolean isInTransition = tc.isShellTransitionsEnabled()
- && tc.inTransition(w);
- if (mService.mPolicy.isKeyguardOccluded() || mService.mPolicy.isKeyguardUnoccluding()
- || isInTransition) {
+ & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0) {
+ // Keep the wallpaper visible when Keyguard is going away.
+ mFindResults.setUseTopWallpaperAsTarget(true);
+ }
+
+ if (mService.mPolicy.isKeyguardLocked() && w.canShowWhenLocked()) {
+ if (mService.mPolicy.isKeyguardOccluded() || (useShellTransition
+ ? w.inTransition() : mService.mPolicy.isKeyguardUnoccluding())) {
// The lowest show when locked window decides whether we need to put the wallpaper
// behind.
- needsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
+ mFindResults.mNeedsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
|| (w.mActivityRecord != null && !w.mActivityRecord.fillsParent());
}
}
- if (keyguardGoingAwayWithWallpaper || needsShowWhenLockedWallpaper) {
- // Keep the wallpaper during Keyguard exit but also when it's needed for a
- // non-fullscreen show when locked activity.
- mFindResults.setUseTopWallpaperAsTarget(true);
- }
-
final boolean animationWallpaper = animatingContainer != null
&& animatingContainer.getAnimation() != null
&& animatingContainer.getAnimation().getShowWallpaper();
@@ -691,7 +684,8 @@ class WallpaperController {
private void findWallpaperTarget() {
mFindResults.reset();
- if (mDisplayContent.getDefaultTaskDisplayArea()
+ if (mService.mAtmService.mSupportsFreeformWindowManagement
+ && mDisplayContent.getDefaultTaskDisplayArea()
.isRootTaskVisible(WINDOWING_MODE_FREEFORM)) {
// In freeform mode we set the wallpaper as its own target, so we don't need an
// additional window to make it visible.
@@ -700,6 +694,10 @@ class WallpaperController {
mDisplayContent.forAllWindows(mFindWallpapers, true /* traverseTopToBottom */);
mDisplayContent.forAllWindows(mFindWallpaperTargetFunction, true /* traverseTopToBottom */);
+ if (mFindResults.mNeedsShowWhenLockedWallpaper) {
+ // Keep wallpaper visible if the show-when-locked activities doesn't fill screen.
+ mFindResults.setUseTopWallpaperAsTarget(true);
+ }
if (mFindResults.wallpaperTarget == null && mFindResults.useTopWallpaperAsTarget) {
mFindResults.setWallpaperTarget(
@@ -1084,6 +1082,7 @@ class WallpaperController {
}
TopWallpaper mTopWallpaper = new TopWallpaper();
+ boolean mNeedsShowWhenLockedWallpaper;
boolean useTopWallpaperAsTarget = false;
WindowState wallpaperTarget = null;
boolean isWallpaperTargetForLetterbox = false;
@@ -1132,6 +1131,7 @@ class WallpaperController {
void reset() {
mTopWallpaper.reset();
+ mNeedsShowWhenLockedWallpaper = false;
wallpaperTarget = null;
useTopWallpaperAsTarget = false;
isWallpaperTargetForLetterbox = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d84c85c8e823..67572bfcad18 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -88,6 +88,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
import static android.view.WindowManager.TRANSIT_NONE;
+import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.fixScale;
import static android.view.WindowManagerGlobal.ADD_OKAY;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_CANCEL_AND_REDRAW;
@@ -3591,6 +3592,7 @@ public class WindowManagerService extends IWindowManager.Stub
public void setCurrentUser(@UserIdInt int newUserId) {
synchronized (mGlobalLock) {
+ mAtmService.getTransitionController().requestTransitionIfNeeded(TRANSIT_OPEN, null);
mCurrentUserId = newUserId;
mPolicy.setCurrentUserLw(newUserId);
mKeyguardDisableHandler.setCurrentUser(newUserId);
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 3672820c13ad..d7d2b4e9dde2 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -563,7 +563,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
return;
}
- final long diff = lastLaunchTime - launchTime;
+ final long diff = launchTime - lastLaunchTime;
if (diff < RAPID_ACTIVITY_LAUNCH_MS) {
mRapidActivityLaunchCount++;
} else if (diff >= RESET_RAPID_ACTIVITY_LAUNCH_MS) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 8f49384f6101..9ffca414a04c 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2983,10 +2983,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
@Override
public boolean canShowWhenLocked() {
- final boolean showBecauseOfActivity =
- mActivityRecord != null && mActivityRecord.canShowWhenLocked();
- final boolean showBecauseOfWindow = (getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0;
- return showBecauseOfActivity || showBecauseOfWindow;
+ if (mActivityRecord != null) {
+ // It will also check if its windows contain FLAG_SHOW_WHEN_LOCKED.
+ return mActivityRecord.canShowWhenLocked();
+ }
+ return (mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0;
}
/**
@@ -3883,15 +3884,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
/**
- * @return {@code true} if activity bounds are letterboxed or letterboxed for display cutout.
- * Note that it's always {@code false} if the activity is in pip mode.
+ * Returns {@code true} if activity bounds are letterboxed or letterboxed for display cutout.
*
* <p>Note that letterbox UI may not be shown even when this returns {@code true}. See {@link
* LetterboxUiController#shouldShowLetterboxUi} for more context.
*/
boolean areAppWindowBoundsLetterboxed() {
return mActivityRecord != null
- && !mActivityRecord.inPinnedWindowingMode()
&& (mActivityRecord.areBoundsLetterboxed() || isLetterboxedForDisplayCutout());
}
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index cadee6f06aad..a1199d99f1c3 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -21,6 +21,7 @@ import static android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN;
import static android.content.Context.CREDENTIAL_SERVICE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -55,6 +56,7 @@ import android.provider.DeviceConfig;
import android.provider.Settings;
import android.service.credentials.CallingAppInfo;
import android.service.credentials.CredentialProviderInfoFactory;
+import android.service.credentials.PermissionUtils;
import android.text.TextUtils;
import android.util.Pair;
import android.util.Slog;
@@ -546,11 +548,16 @@ public final class CredentialManagerService
if (providerSessions.isEmpty()) {
try {
- // TODO: fix
prepareGetCredentialCallback.onResponse(
- new PrepareGetCredentialResponseInternal(
- false, null,
- false, false, null));
+ new PrepareGetCredentialResponseInternal(PermissionUtils.hasPermission(
+ mContext,
+ callingPackage,
+ Manifest.permission
+ .CREDENTIAL_MANAGER_QUERY_CANDIDATE_CREDENTIALS),
+ /*credentialResultTypes=*/null,
+ /*hasAuthenticationResults=*/false,
+ /*hasRemoteResults=*/false,
+ /*pendingIntent=*/null));
} catch (RemoteException e) {
Slog.e(
TAG,
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index c918fb87154f..9c1d765fe0f9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -101,7 +101,7 @@ final class DevicePolicyEngine {
private final UserManager mUserManager;
// TODO(b/256849338): add more granular locks
- private final Object mLock = new Object();
+ private final Object mLock;
/**
* Map of <userId, Map<policyKey, policyState>>
@@ -122,9 +122,11 @@ final class DevicePolicyEngine {
DevicePolicyEngine(
@NonNull Context context,
- @NonNull DeviceAdminServiceController deviceAdminServiceController) {
+ @NonNull DeviceAdminServiceController deviceAdminServiceController,
+ @NonNull Object lock) {
mContext = Objects.requireNonNull(context);
mDeviceAdminServiceController = Objects.requireNonNull(deviceAdminServiceController);
+ mLock = Objects.requireNonNull(lock);
mUserManager = mContext.getSystemService(UserManager.class);
mLocalPolicies = new SparseArray<>();
mGlobalPolicies = new HashMap<>();
@@ -152,8 +154,8 @@ final class DevicePolicyEngine {
PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
if (policyDefinition.isNonCoexistablePolicy()) {
- setNonCoexistableLocalPolicy(policyDefinition, localPolicyState, enforcingAdmin,
- value, userId, skipEnforcePolicy);
+ setNonCoexistableLocalPolicyLocked(policyDefinition, localPolicyState,
+ enforcingAdmin, value, userId, skipEnforcePolicy);
return;
}
@@ -173,7 +175,7 @@ final class DevicePolicyEngine {
// the data structures.
if (!skipEnforcePolicy) {
if (policyChanged) {
- onLocalPolicyChanged(policyDefinition, enforcingAdmin, userId);
+ onLocalPolicyChangedLocked(policyDefinition, enforcingAdmin, userId);
}
boolean policyEnforced = Objects.equals(
localPolicyState.getCurrentResolvedPolicy(), value);
@@ -211,7 +213,7 @@ final class DevicePolicyEngine {
*
* <p>Passing a {@code null} value means the policy set by this admin should be removed.
*/
- private <V> void setNonCoexistableLocalPolicy(
+ private <V> void setNonCoexistableLocalPolicyLocked(
PolicyDefinition<V> policyDefinition,
PolicyState<V> localPolicyState,
EnforcingAdmin enforcingAdmin,
@@ -266,8 +268,8 @@ final class DevicePolicyEngine {
PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
if (policyDefinition.isNonCoexistablePolicy()) {
- setNonCoexistableLocalPolicy(policyDefinition, localPolicyState, enforcingAdmin,
- /* value= */ null, userId, /* skipEnforcePolicy= */ false);
+ setNonCoexistableLocalPolicyLocked(policyDefinition, localPolicyState,
+ enforcingAdmin, /* value= */ null, userId, /* skipEnforcePolicy= */ false);
return;
}
@@ -282,7 +284,7 @@ final class DevicePolicyEngine {
}
if (policyChanged) {
- onLocalPolicyChanged(policyDefinition, enforcingAdmin, userId);
+ onLocalPolicyChangedLocked(policyDefinition, enforcingAdmin, userId);
}
// For a removePolicy to be enforced, it means no current policy exists
@@ -348,7 +350,7 @@ final class DevicePolicyEngine {
/**
* Enforces the new policy and notifies relevant admins.
*/
- private <V> void onLocalPolicyChanged(
+ private <V> void onLocalPolicyChangedLocked(
@NonNull PolicyDefinition<V> policyDefinition,
@NonNull EnforcingAdmin enforcingAdmin,
int userId) {
@@ -358,7 +360,7 @@ final class DevicePolicyEngine {
policyDefinition, localPolicyState.getCurrentResolvedPolicy(), userId);
// Send policy updates to admins who've set it locally
- sendPolicyChangedToAdmins(
+ sendPolicyChangedToAdminsLocked(
localPolicyState,
enforcingAdmin,
policyDefinition,
@@ -369,7 +371,7 @@ final class DevicePolicyEngine {
// Send policy updates to admins who've set it globally
if (hasGlobalPolicyLocked(policyDefinition)) {
PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition);
- sendPolicyChangedToAdmins(
+ sendPolicyChangedToAdminsLocked(
globalPolicyState,
enforcingAdmin,
policyDefinition,
@@ -424,7 +426,7 @@ final class DevicePolicyEngine {
// the data structures.
if (!skipEnforcePolicy) {
if (policyChanged) {
- onGlobalPolicyChanged(policyDefinition, enforcingAdmin);
+ onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin);
}
boolean policyAppliedGlobally = Objects.equals(
@@ -473,7 +475,7 @@ final class DevicePolicyEngine {
boolean policyChanged = policyState.removePolicy(enforcingAdmin);
if (policyChanged) {
- onGlobalPolicyChanged(policyDefinition, enforcingAdmin);
+ onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin);
}
applyGlobalPolicyOnUsersWithLocalPoliciesLocked(policyDefinition, enforcingAdmin,
@@ -499,7 +501,7 @@ final class DevicePolicyEngine {
/**
* Enforces the new policy globally and notifies relevant admins.
*/
- private <V> void onGlobalPolicyChanged(
+ private <V> void onGlobalPolicyChangedLocked(
@NonNull PolicyDefinition<V> policyDefinition,
@NonNull EnforcingAdmin enforcingAdmin) {
PolicyState<V> policyState = getGlobalPolicyStateLocked(policyDefinition);
@@ -507,7 +509,7 @@ final class DevicePolicyEngine {
enforcePolicy(policyDefinition, policyState.getCurrentResolvedPolicy(),
UserHandle.USER_ALL);
- sendPolicyChangedToAdmins(
+ sendPolicyChangedToAdminsLocked(
policyState,
enforcingAdmin,
policyDefinition,
@@ -552,7 +554,7 @@ final class DevicePolicyEngine {
policyDefinition,
localPolicyState.getCurrentResolvedPolicy(),
userId);
- sendPolicyChangedToAdmins(
+ sendPolicyChangedToAdminsLocked(
localPolicyState,
enforcingAdmin,
policyDefinition,
@@ -745,34 +747,35 @@ final class DevicePolicyEngine {
}
<V> void transferPolicies(EnforcingAdmin oldAdmin, EnforcingAdmin newAdmin) {
- Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet());
- for (PolicyKey policy : globalPolicies) {
- PolicyState<?> policyState = mGlobalPolicies.get(policy);
- if (policyState.getPoliciesSetByAdmins().containsKey(oldAdmin)) {
- PolicyDefinition<V> policyDefinition =
- (PolicyDefinition<V>) policyState.getPolicyDefinition();
- PolicyValue<V> policyValue =
- (PolicyValue<V>) policyState.getPoliciesSetByAdmins().get(oldAdmin);
- setGlobalPolicy(policyDefinition, newAdmin, policyValue);
- }
- }
-
- for (int i = 0; i < mLocalPolicies.size(); i++) {
- int userId = mLocalPolicies.keyAt(i);
- Set<PolicyKey> localPolicies = new HashSet<>(
- mLocalPolicies.get(userId).keySet());
- for (PolicyKey policy : localPolicies) {
- PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy);
+ synchronized (mLock) {
+ Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet());
+ for (PolicyKey policy : globalPolicies) {
+ PolicyState<?> policyState = mGlobalPolicies.get(policy);
if (policyState.getPoliciesSetByAdmins().containsKey(oldAdmin)) {
PolicyDefinition<V> policyDefinition =
(PolicyDefinition<V>) policyState.getPolicyDefinition();
PolicyValue<V> policyValue =
(PolicyValue<V>) policyState.getPoliciesSetByAdmins().get(oldAdmin);
- setLocalPolicy(policyDefinition, newAdmin, policyValue, userId);
+ setGlobalPolicy(policyDefinition, newAdmin, policyValue);
}
}
- }
+ for (int i = 0; i < mLocalPolicies.size(); i++) {
+ int userId = mLocalPolicies.keyAt(i);
+ Set<PolicyKey> localPolicies = new HashSet<>(
+ mLocalPolicies.get(userId).keySet());
+ for (PolicyKey policy : localPolicies) {
+ PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy);
+ if (policyState.getPoliciesSetByAdmins().containsKey(oldAdmin)) {
+ PolicyDefinition<V> policyDefinition =
+ (PolicyDefinition<V>) policyState.getPolicyDefinition();
+ PolicyValue<V> policyValue =
+ (PolicyValue<V>) policyState.getPoliciesSetByAdmins().get(oldAdmin);
+ setLocalPolicy(policyDefinition, newAdmin, policyValue, userId);
+ }
+ }
+ }
+ }
removePoliciesForAdmin(oldAdmin);
}
@@ -836,7 +839,7 @@ final class DevicePolicyEngine {
mLocalPolicies.get(userId).put(
policyDefinition.getPolicyKey(), new PolicyState<>(policyDefinition));
}
- return getPolicyState(mLocalPolicies.get(userId), policyDefinition);
+ return getPolicyStateLocked(mLocalPolicies.get(userId), policyDefinition);
}
private <V> void removeLocalPolicyStateLocked(
@@ -858,14 +861,14 @@ final class DevicePolicyEngine {
mGlobalPolicies.put(
policyDefinition.getPolicyKey(), new PolicyState<>(policyDefinition));
}
- return getPolicyState(mGlobalPolicies, policyDefinition);
+ return getPolicyStateLocked(mGlobalPolicies, policyDefinition);
}
private <V> void removeGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition) {
mGlobalPolicies.remove(policyDefinition.getPolicyKey());
}
- private static <V> PolicyState<V> getPolicyState(
+ private static <V> PolicyState<V> getPolicyStateLocked(
Map<PolicyKey, PolicyState<?>> policies, PolicyDefinition<V> policyDefinition) {
try {
// This will not throw an exception because policyDefinition is of type V, so unless
@@ -935,7 +938,7 @@ final class DevicePolicyEngine {
}
// TODO(b/261430877): Finalise the decision on which admins to send the updates to.
- private <V> void sendPolicyChangedToAdmins(
+ private <V> void sendPolicyChangedToAdminsLocked(
PolicyState<V> policyState,
EnforcingAdmin callingAdmin,
PolicyDefinition<V> policyDefinition,
@@ -1210,17 +1213,19 @@ final class DevicePolicyEngine {
if (parentInfo == null || parentInfo.getUserHandle().getIdentifier() == userId) {
return;
}
- if (!mLocalPolicies.contains(parentInfo.getUserHandle().getIdentifier())) {
- return;
- }
- for (Map.Entry<PolicyKey, PolicyState<?>> entry : mLocalPolicies.get(
- parentInfo.getUserHandle().getIdentifier()).entrySet()) {
- enforcePolicyOnUser(userId, entry.getValue());
+ synchronized (mLock) {
+ if (!mLocalPolicies.contains(parentInfo.getUserHandle().getIdentifier())) {
+ return;
+ }
+ for (Map.Entry<PolicyKey, PolicyState<?>> entry : mLocalPolicies.get(
+ parentInfo.getUserHandle().getIdentifier()).entrySet()) {
+ enforcePolicyOnUserLocked(userId, entry.getValue());
+ }
}
});
}
- private <V> void enforcePolicyOnUser(int userId, PolicyState<V> policyState) {
+ private <V> void enforcePolicyOnUserLocked(int userId, PolicyState<V> policyState) {
if (!policyState.getPolicyDefinition().isInheritable()) {
return;
}
@@ -1239,26 +1244,28 @@ final class DevicePolicyEngine {
*/
@NonNull
DevicePolicyState getDevicePolicyState() {
- Map<UserHandle, Map<PolicyKey, android.app.admin.PolicyState<?>>> policies =
- new HashMap<>();
- for (int i = 0; i < mLocalPolicies.size(); i++) {
- UserHandle user = UserHandle.of(mLocalPolicies.keyAt(i));
- policies.put(user, new HashMap<>());
- for (PolicyKey policyKey : mLocalPolicies.valueAt(i).keySet()) {
- policies.get(user).put(
- policyKey,
- mLocalPolicies.valueAt(i).get(policyKey).getParcelablePolicyState());
+ synchronized (mLock) {
+ Map<UserHandle, Map<PolicyKey, android.app.admin.PolicyState<?>>> policies =
+ new HashMap<>();
+ for (int i = 0; i < mLocalPolicies.size(); i++) {
+ UserHandle user = UserHandle.of(mLocalPolicies.keyAt(i));
+ policies.put(user, new HashMap<>());
+ for (PolicyKey policyKey : mLocalPolicies.valueAt(i).keySet()) {
+ policies.get(user).put(
+ policyKey,
+ mLocalPolicies.valueAt(i).get(policyKey).getParcelablePolicyState());
+ }
}
- }
- if (!mGlobalPolicies.isEmpty()) {
- policies.put(UserHandle.ALL, new HashMap<>());
- for (PolicyKey policyKey : mGlobalPolicies.keySet()) {
- policies.get(UserHandle.ALL).put(
- policyKey,
- mGlobalPolicies.get(policyKey).getParcelablePolicyState());
+ if (!mGlobalPolicies.isEmpty()) {
+ policies.put(UserHandle.ALL, new HashMap<>());
+ for (PolicyKey policyKey : mGlobalPolicies.keySet()) {
+ policies.get(UserHandle.ALL).put(
+ policyKey,
+ mGlobalPolicies.get(policyKey).getParcelablePolicyState());
+ }
}
+ return new DevicePolicyState(policies);
}
- return new DevicePolicyState(policies);
}
@@ -1266,23 +1273,25 @@ final class DevicePolicyEngine {
* Removes all local and global policies set by that admin.
*/
void removePoliciesForAdmin(EnforcingAdmin admin) {
- Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet());
- for (PolicyKey policy : globalPolicies) {
- PolicyState<?> policyState = mGlobalPolicies.get(policy);
- if (policyState.getPoliciesSetByAdmins().containsKey(admin)) {
- removeGlobalPolicy(policyState.getPolicyDefinition(), admin);
+ synchronized (mLock) {
+ Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet());
+ for (PolicyKey policy : globalPolicies) {
+ PolicyState<?> policyState = mGlobalPolicies.get(policy);
+ if (policyState.getPoliciesSetByAdmins().containsKey(admin)) {
+ removeGlobalPolicy(policyState.getPolicyDefinition(), admin);
+ }
}
- }
- for (int i = 0; i < mLocalPolicies.size(); i++) {
- Set<PolicyKey> localPolicies = new HashSet<>(
- mLocalPolicies.get(mLocalPolicies.keyAt(i)).keySet());
- for (PolicyKey policy : localPolicies) {
- PolicyState<?> policyState = mLocalPolicies.get(
- mLocalPolicies.keyAt(i)).get(policy);
- if (policyState.getPoliciesSetByAdmins().containsKey(admin)) {
- removeLocalPolicy(
- policyState.getPolicyDefinition(), admin, mLocalPolicies.keyAt(i));
+ for (int i = 0; i < mLocalPolicies.size(); i++) {
+ Set<PolicyKey> localPolicies = new HashSet<>(
+ mLocalPolicies.get(mLocalPolicies.keyAt(i)).keySet());
+ for (PolicyKey policy : localPolicies) {
+ PolicyState<?> policyState = mLocalPolicies.get(
+ mLocalPolicies.keyAt(i)).get(policy);
+ if (policyState.getPoliciesSetByAdmins().containsKey(admin)) {
+ removeLocalPolicy(
+ policyState.getPolicyDefinition(), admin, mLocalPolicies.keyAt(i));
+ }
}
}
}
@@ -1292,23 +1301,25 @@ final class DevicePolicyEngine {
* Removes all local policies for the provided {@code userId}.
*/
private void removeLocalPoliciesForUser(int userId) {
- if (!mLocalPolicies.contains(userId)) {
- // No policies on user
- return;
- }
+ synchronized (mLock) {
+ if (!mLocalPolicies.contains(userId)) {
+ // No policies on user
+ return;
+ }
- Set<PolicyKey> localPolicies = new HashSet<>(mLocalPolicies.get(userId).keySet());
- for (PolicyKey policy : localPolicies) {
- PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy);
- Set<EnforcingAdmin> admins = new HashSet<>(
- policyState.getPoliciesSetByAdmins().keySet());
- for (EnforcingAdmin admin : admins) {
- removeLocalPolicy(
- policyState.getPolicyDefinition(), admin, userId);
+ Set<PolicyKey> localPolicies = new HashSet<>(mLocalPolicies.get(userId).keySet());
+ for (PolicyKey policy : localPolicies) {
+ PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy);
+ Set<EnforcingAdmin> admins = new HashSet<>(
+ policyState.getPoliciesSetByAdmins().keySet());
+ for (EnforcingAdmin admin : admins) {
+ removeLocalPolicy(
+ policyState.getPolicyDefinition(), admin, userId);
+ }
}
- }
- mLocalPolicies.remove(userId);
+ mLocalPolicies.remove(userId);
+ }
}
/**
@@ -1376,7 +1387,7 @@ final class DevicePolicyEngine {
*/
private void updateDeviceAdminServiceOnPolicyRemoveLocked(
@NonNull EnforcingAdmin enforcingAdmin) {
- if (doesAdminHavePolicies(enforcingAdmin)) {
+ if (doesAdminHavePoliciesLocked(enforcingAdmin)) {
return;
}
int userId = enforcingAdmin.getUserId();
@@ -1399,7 +1410,7 @@ final class DevicePolicyEngine {
/* actionForLog= */ "policy-removed");
}
- private boolean doesAdminHavePolicies(@NonNull EnforcingAdmin enforcingAdmin) {
+ private boolean doesAdminHavePoliciesLocked(@NonNull EnforcingAdmin enforcingAdmin) {
for (PolicyKey policy : mGlobalPolicies.keySet()) {
PolicyState<?> policyState = mGlobalPolicies.get(policy);
if (policyState.getPoliciesSetByAdmins().containsKey(enforcingAdmin)) {
@@ -1420,13 +1431,17 @@ final class DevicePolicyEngine {
@NonNull
private Set<EnforcingAdmin> getEnforcingAdminsOnUser(int userId) {
- return mEnforcingAdmins.contains(userId)
- ? mEnforcingAdmins.get(userId) : Collections.emptySet();
+ synchronized (mLock) {
+ return mEnforcingAdmins.contains(userId)
+ ? mEnforcingAdmins.get(userId) : Collections.emptySet();
+ }
}
private void write() {
- Log.d(TAG, "Writing device policies to file.");
- new DevicePoliciesReaderWriter().writeToFileLocked();
+ synchronized (mLock) {
+ Log.d(TAG, "Writing device policies to file.");
+ new DevicePoliciesReaderWriter().writeToFileLocked();
+ }
}
// TODO(b/256852787): trigger resolving logic after loading policies as roles are recalculated
@@ -1436,11 +1451,11 @@ final class DevicePolicyEngine {
synchronized (mLock) {
clear();
new DevicePoliciesReaderWriter().readFromFileLocked();
- reapplyAllPolicies();
+ reapplyAllPoliciesLocked();
}
}
- private <V> void reapplyAllPolicies() {
+ private <V> void reapplyAllPoliciesLocked() {
for (PolicyKey policy : mGlobalPolicies.keySet()) {
PolicyState<?> policyState = mGlobalPolicies.get(policy);
// Policy definition and value will always be of the same type
@@ -1470,10 +1485,8 @@ final class DevicePolicyEngine {
* <p>Note that this doesn't clear any enforcements, it only clears the data structures.
*/
void clearAllPolicies() {
- synchronized (mLock) {
- clear();
- write();
- }
+ clear();
+ write();
}
private void clear() {
synchronized (mLock) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a5b15489f292..e44b8cdbaab0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2093,7 +2093,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mUserData = new SparseArray<>();
mOwners = makeOwners(injector, pathProvider);
- mDevicePolicyEngine = new DevicePolicyEngine(mContext, mDeviceAdminServiceController);
+ mDevicePolicyEngine = new DevicePolicyEngine(
+ mContext, mDeviceAdminServiceController, getLockObject());
if (!mHasFeature) {
// Skip the rest of the initialization
@@ -7840,27 +7841,29 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
throw new SecurityException("Cannot wipe data. " + restriction
+ " restriction is set for user " + userId);
}
+ });
- boolean isSystemUser = userId == UserHandle.USER_SYSTEM;
- boolean wipeDevice;
- if (factoryReset == null || !mInjector.isChangeEnabled(EXPLICIT_WIPE_BEHAVIOUR,
- adminPackage,
- userId)) {
- // Legacy mode
- wipeDevice = isSystemUser;
+ boolean isSystemUser = userId == UserHandle.USER_SYSTEM;
+ boolean wipeDevice;
+ if (factoryReset == null || !mInjector.isChangeEnabled(EXPLICIT_WIPE_BEHAVIOUR,
+ adminPackage,
+ userId)) {
+ // Legacy mode
+ wipeDevice = isSystemUser;
+ } else {
+ // Explicit behaviour
+ if (factoryReset) {
+ EnforcingAdmin enforcingAdmin = enforcePermissionsAndGetEnforcingAdmin(
+ /*admin=*/ null,
+ /*permission=*/ new String[]{MANAGE_DEVICE_POLICY_WIPE_DATA,
+ MASTER_CLEAR},
+ USES_POLICY_WIPE_DATA,
+ adminPackage,
+ factoryReset ? UserHandle.USER_ALL :
+ getAffectedUser(calledOnParentInstance));
+ wipeDevice = true;
} else {
- // Explicit behaviour
- if (factoryReset) {
- EnforcingAdmin enforcingAdmin = enforcePermissionsAndGetEnforcingAdmin(
- /*admin=*/ null,
- /*permission=*/ new String[]{MANAGE_DEVICE_POLICY_WIPE_DATA,
- MASTER_CLEAR},
- USES_POLICY_WIPE_DATA,
- adminPackage,
- factoryReset ? UserHandle.USER_ALL :
- getAffectedUser(calledOnParentInstance));
- wipeDevice = true;
- } else {
+ mInjector.binderWithCleanCallingIdentity(() -> {
Preconditions.checkCallAuthorization(!isSystemUser,
"User %s is a system user and cannot be removed", userId);
boolean isLastNonHeadlessUser = getUserInfo(userId).isFull()
@@ -7871,9 +7874,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
"Removing user %s would leave the device without any active users. "
+ "Consider factory resetting the device instead.",
userId);
- wipeDevice = false;
- }
+ });
+ wipeDevice = false;
}
+ }
+ mInjector.binderWithCleanCallingIdentity(() -> {
if (wipeDevice) {
forceWipeDeviceNoLock(
(flags & WIPE_EXTERNAL_STORAGE) != 0,
diff --git a/services/tests/PackageManagerServiceTests/server/res/raw/install_app1_cert5 b/services/tests/PackageManagerServiceTests/server/res/raw/install_app1_cert5
index 138b6113ea6b..3683dca64449 100644
--- a/services/tests/PackageManagerServiceTests/server/res/raw/install_app1_cert5
+++ b/services/tests/PackageManagerServiceTests/server/res/raw/install_app1_cert5
Binary files differ
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
index ca4a4048cc00..dc92376263a6 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
@@ -66,7 +66,6 @@ import android.system.StructStat;
import android.test.AndroidTestCase;
import android.util.Log;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SmallTest;
import androidx.test.filters.Suppress;
@@ -2507,7 +2506,6 @@ public class PackageManagerTests extends AndroidTestCase {
}
@LargeTest
- @FlakyTest(bugId = 283797480)
public void testCheckSignaturesRotatedAgainstRotated() throws Exception {
// checkSignatures should be successful when both apps have been signed with the same
// rotated key since the initial signature comparison between the two apps should
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index a614c4dd1d61..2bc66ace454b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -27,6 +27,7 @@ import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
+import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
import static android.util.DebugUtils.valueToString;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
@@ -742,24 +743,24 @@ public class ActivityManagerServiceTest {
broadcastIntent(intent1, null, true);
assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER),
- StickyBroadcast.create(intent1, false, Process.myUid()));
+ StickyBroadcast.create(intent1, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
assertNull(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER));
assertNull(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER));
broadcastIntent(intent2, options.toBundle(), true);
assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER),
- StickyBroadcast.create(intent1, false, Process.myUid()));
+ StickyBroadcast.create(intent1, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER),
- StickyBroadcast.create(intent2, true, Process.myUid()));
+ StickyBroadcast.create(intent2, true, Process.myUid(), PROCESS_STATE_UNKNOWN));
assertNull(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER));
broadcastIntent(intent3, null, true);
assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION1, TEST_USER),
- StickyBroadcast.create(intent1, false, Process.myUid()));
+ StickyBroadcast.create(intent1, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION2, TEST_USER),
- StickyBroadcast.create(intent2, true, Process.myUid()));
+ StickyBroadcast.create(intent2, true, Process.myUid(), PROCESS_STATE_UNKNOWN));
assertStickyBroadcasts(mAms.getStickyBroadcasts(TEST_ACTION3, TEST_USER),
- StickyBroadcast.create(intent3, false, Process.myUid()));
+ StickyBroadcast.create(intent3, false, Process.myUid(), PROCESS_STATE_UNKNOWN));
}
@SuppressWarnings("GuardedBy")
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
index 582685cf009e..f4238f678f08 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -16,6 +16,8 @@
package com.android.server.am;
+import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED;
import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD;
@@ -246,7 +248,7 @@ public final class BroadcastQueueModernImplTest {
return new BroadcastRecord(mImpl, intent, mProcess, PACKAGE_RED, null, 21, 42, false, null,
null, null, null, AppOpsManager.OP_NONE, options, receivers, null, resultTo,
Activity.RESULT_OK, null, null, ordered, false, false, UserHandle.USER_SYSTEM,
- BackgroundStartPrivileges.NONE, false, null);
+ BackgroundStartPrivileges.NONE, false, null, PROCESS_STATE_UNKNOWN);
}
private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue,
@@ -1092,6 +1094,17 @@ public final class BroadcastQueueModernImplTest {
verifyPendingRecords(greenQueue, List.of(screenOff, screenOn));
verifyPendingRecords(redQueue, List.of(screenOff));
verifyPendingRecords(blueQueue, List.of(screenOff, screenOn));
+
+ final BroadcastRecord screenOffRecord = makeBroadcastRecord(screenOff, screenOnOffOptions,
+ List.of(greenReceiver, redReceiver, blueReceiver), resultTo, false);
+ screenOffRecord.setDeliveryState(2, BroadcastRecord.DELIVERY_DEFERRED,
+ "testDeliveryGroupPolicy_resultTo_diffReceivers");
+ mImpl.enqueueBroadcastLocked(screenOffRecord);
+ mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, screenOnOffOptions,
+ List.of(greenReceiver, blueReceiver), resultTo, false));
+ verifyPendingRecords(greenQueue, List.of(screenOff, screenOn));
+ verifyPendingRecords(redQueue, List.of(screenOff));
+ verifyPendingRecords(blueQueue, List.of(screenOn));
}
@Test
@@ -1277,6 +1290,36 @@ public final class BroadcastQueueModernImplTest {
}
@Test
+ public void testDeliveryGroupPolicy_merged_multipleReceivers() {
+ final long now = SystemClock.elapsedRealtime();
+ final Pair<Intent, BroadcastOptions> dropboxEntryBroadcast1 = createDropboxBroadcast(
+ "TAG_A", now, 2);
+ final Pair<Intent, BroadcastOptions> dropboxEntryBroadcast2 = createDropboxBroadcast(
+ "TAG_A", now + 1000, 4);
+
+ mImpl.enqueueBroadcastLocked(makeBroadcastRecord(dropboxEntryBroadcast1.first,
+ dropboxEntryBroadcast1.second,
+ List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN),
+ makeManifestReceiver(PACKAGE_RED, CLASS_RED)),
+ false));
+ mImpl.enqueueBroadcastLocked(makeBroadcastRecord(dropboxEntryBroadcast2.first,
+ dropboxEntryBroadcast2.second,
+ List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN),
+ makeManifestReceiver(PACKAGE_RED, CLASS_RED)),
+ false));
+
+ final BroadcastProcessQueue greenQueue = mImpl.getProcessQueue(PACKAGE_GREEN,
+ getUidForPackage(PACKAGE_GREEN));
+ final BroadcastProcessQueue redQueue = mImpl.getProcessQueue(PACKAGE_RED,
+ getUidForPackage(PACKAGE_RED));
+
+ verifyPendingRecords(greenQueue,
+ List.of(dropboxEntryBroadcast1.first, dropboxEntryBroadcast2.first));
+ verifyPendingRecords(redQueue,
+ List.of(dropboxEntryBroadcast1.first, dropboxEntryBroadcast2.first));
+ }
+
+ @Test
public void testDeliveryGroupPolicy_sameAction_differentMatchingCriteria() {
final Intent closeSystemDialogs1 = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
final BroadcastOptions optionsCloseSystemDialog1 = BroadcastOptions.makeBasic()
@@ -1407,7 +1450,7 @@ public final class BroadcastQueueModernImplTest {
eq(BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST),
eq(BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD),
anyLong(), anyLong(), anyLong(), anyInt(), nullable(String.class),
- anyString(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt()),
+ anyString(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt()),
times(1));
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
index 03231ecfb723..e7a94c00c41c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_FINISH_RECEIVER;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_START_RECEIVER;
import static android.os.UserHandle.USER_SYSTEM;
@@ -260,6 +261,7 @@ public class BroadcastQueueTest {
// Create a different process that will be linked to the
// returned process via a predecessor/successor relationship
mActiveProcesses.remove(res);
+ res.setKilled(true);
deliverRes = makeActiveProcessRecord(ai, processName,
ProcessBehavior.NORMAL, UnaryOperator.identity());
deliverRes.mPredecessor = res;
@@ -611,7 +613,7 @@ public class BroadcastQueueTest {
callerApp.getPid(), callerApp.info.uid, false, null, null, null, null,
AppOpsManager.OP_NONE, options, receivers, callerApp, resultTo,
Activity.RESULT_OK, null, resultExtras, ordered, false, false, userId,
- BackgroundStartPrivileges.NONE, false, null);
+ BackgroundStartPrivileges.NONE, false, null, PROCESS_STATE_UNKNOWN);
}
private void assertHealth() {
@@ -1315,6 +1317,53 @@ public class BroadcastQueueTest {
verifyScheduleReceiver(times(1), receiverOrangeApp, timezone);
}
+ /**
+ * Verify that a broadcast sent to a frozen app, which gets killed as part of unfreezing
+ * process due to pending sync binder transactions, is delivered as expected.
+ */
+ @Test
+ public void testDeliveryToFrozenApp_killedWhileUnfreeze() throws Exception {
+ final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
+ final ProcessRecord receiverBlueApp = makeActiveProcessRecord(PACKAGE_BLUE);
+
+ // Mark the app as killed while unfreezing it, which can happen either when we directly
+ // try to unfreeze it or when it is done as part of OomAdjust computation.
+ doAnswer(invocation -> {
+ final ProcessRecord app = invocation.getArgument(0);
+ if (app == receiverBlueApp) {
+ app.setKilled(true);
+ mActiveProcesses.remove(app);
+ }
+ return null;
+ }).when(mAms.mOomAdjuster).unfreezeTemporarily(eq(receiverBlueApp), anyInt());
+ doAnswer(invocation -> {
+ final ProcessRecord app = invocation.getArgument(0);
+ if (app == receiverBlueApp) {
+ app.setKilled(true);
+ mActiveProcesses.remove(app);
+ }
+ return null;
+ }).when(mAms).enqueueOomAdjTargetLocked(eq(receiverBlueApp));
+
+ final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ enqueueBroadcast(makeBroadcastRecord(airplane, callerApp, List.of(
+ makeManifestReceiver(PACKAGE_BLUE, CLASS_BLUE))));
+
+ waitForIdle();
+ final ProcessRecord restartedReceiverBlueApp = mAms.getProcessRecordLocked(PACKAGE_BLUE,
+ getUidForPackage(PACKAGE_BLUE));
+ assertNotEquals(receiverBlueApp, restartedReceiverBlueApp);
+ // Legacy queue will always try delivering the broadcast even if the process
+ // has been killed.
+ if (mImpl == Impl.MODERN) {
+ verifyScheduleReceiver(never(), receiverBlueApp, airplane);
+ } else {
+ verifyScheduleReceiver(times(1), receiverBlueApp, airplane);
+ }
+ // Verify that the new process receives the broadcast.
+ verifyScheduleReceiver(times(1), restartedReceiverBlueApp, airplane);
+ }
+
@Test
public void testCold_Success() throws Exception {
doCold(ProcessStartBehavior.SUCCESS);
@@ -1599,7 +1648,7 @@ public class BroadcastQueueTest {
null, null, null, null, AppOpsManager.OP_NONE, BroadcastOptions.makeBasic(),
List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN)), null, null,
Activity.RESULT_OK, null, null, false, false, false, UserHandle.USER_SYSTEM,
- backgroundStartPrivileges, false, null);
+ backgroundStartPrivileges, false, null, PROCESS_STATE_UNKNOWN);
enqueueBroadcast(r);
waitForIdle();
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java
index 08952eab071f..f0efb795f5a1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastRecordTest.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
import static android.app.ActivityManager.RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
import static android.content.Intent.ACTION_BOOT_COMPLETED;
import static android.content.Intent.ACTION_LOCKED_BOOT_COMPLETED;
@@ -958,7 +959,8 @@ public class BroadcastRecordTest {
userId,
BackgroundStartPrivileges.NONE,
false /* timeoutExempt */,
- filterExtrasForReceiver);
+ filterExtrasForReceiver,
+ PROCESS_STATE_UNKNOWN);
}
private static int getAppId(int i) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
index 8dc0ac6515cd..170076098b7d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -646,14 +646,16 @@ public final class DisplayPowerController2Test {
@Test
public void testSetScreenOffBrightnessSensorEnabled_DisplayIsInDoze() {
+ mContext.getOrCreateTestableResources().addOverride(
+ com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, false);
+ mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
+
Settings.System.putInt(mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
DisplayPowerRequest dpr = new DisplayPowerRequest();
dpr.policy = DisplayPowerRequest.POLICY_DOZE;
- mContext.getOrCreateTestableResources().addOverride(
- com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing, true);
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
index c5ff8cc7b0d6..dd23d9f006e3 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
@@ -28,6 +28,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX;
import static com.android.server.job.JobSchedulerService.RARE_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+import static com.android.server.job.JobSchedulerService.sUptimeMillisClock;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -148,6 +149,9 @@ public class JobSchedulerServiceTest {
// Used in JobConcurrencyManager.
doReturn(mock(UserManagerInternal.class))
.when(() -> LocalServices.getService(UserManagerInternal.class));
+ // Used in JobStatus.
+ doReturn(mock(JobSchedulerInternal.class))
+ .when(() -> LocalServices.getService(JobSchedulerInternal.class));
// Called via IdleController constructor.
when(mContext.getPackageManager()).thenReturn(mock(PackageManager.class));
when(mContext.getResources()).thenReturn(mock(Resources.class));
@@ -168,6 +172,8 @@ public class JobSchedulerServiceTest {
JobSchedulerService.sSystemClock = Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(SystemClock.elapsedRealtimeClock().instant(), ZoneOffset.UTC);
+ // Make sure the uptime is at least 24 hours so that tests that rely on high uptime work.
+ sUptimeMillisClock = getAdvancedClock(sUptimeMillisClock, 24 * HOUR_IN_MILLIS);
// Called by DeviceIdlenessTracker
when(mContext.getSystemService(UiModeManager.class)).thenReturn(mock(UiModeManager.class));
@@ -313,6 +319,260 @@ public class JobSchedulerServiceTest {
}
@Test
+ public void testGetMinJobExecutionGuaranteeMs_timeoutSafeguards_disabled() {
+ JobStatus jobUij = createJobStatus("testGetMinJobExecutionGuaranteeMs_timeoutSafeguards",
+ createJobInfo(1)
+ .setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
+ JobStatus jobEj = createJobStatus("testGetMinJobExecutionGuaranteeMs_timeoutSafeguards",
+ createJobInfo(2).setExpedited(true));
+ JobStatus jobReg = createJobStatus("testGetMinJobExecutionGuaranteeMs_timeoutSafeguards",
+ createJobInfo(3));
+ spyOn(jobUij);
+ when(jobUij.shouldTreatAsUserInitiatedJob()).thenReturn(true);
+ jobUij.startedAsUserInitiatedJob = true;
+ spyOn(jobEj);
+ when(jobEj.shouldTreatAsExpeditedJob()).thenReturn(true);
+ jobEj.startedAsExpeditedJob = true;
+
+ mService.mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC = false;
+ mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT = 2;
+ mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT = 2;
+ mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT = 2;
+ mService.updateQuotaTracker();
+ mService.resetScheduleQuota();
+
+ // Safeguards disabled -> no penalties.
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+ // 1 UIJ timeout. No max execution penalty yet.
+ mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+ // 2 UIJ timeouts. Safeguards disabled -> no penalties.
+ jobUij.madeActive =
+ sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS;
+ mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+ // 1 EJ timeout. No max execution penalty yet.
+ mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+ // 2 EJ timeouts. Safeguards disabled -> no penalties.
+ jobEj.madeActive =
+ sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS;
+ mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+ // 1 reg timeout. No max execution penalty yet.
+ mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+ // 2 Reg timeouts. Safeguards disabled -> no penalties.
+ jobReg.madeActive =
+ sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_GUARANTEE_MS;
+ mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobReg));
+ }
+
+ @Test
+ public void testGetMinJobExecutionGuaranteeMs_timeoutSafeguards_enabled() {
+ JobStatus jobUij = createJobStatus("testGetMinJobExecutionGuaranteeMs_timeoutSafeguards",
+ createJobInfo(1)
+ .setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
+ JobStatus jobEj = createJobStatus("testGetMinJobExecutionGuaranteeMs_timeoutSafeguards",
+ createJobInfo(2).setExpedited(true));
+ JobStatus jobReg = createJobStatus("testGetMinJobExecutionGuaranteeMs_timeoutSafeguards",
+ createJobInfo(3));
+ spyOn(jobUij);
+ when(jobUij.shouldTreatAsUserInitiatedJob()).thenReturn(true);
+ jobUij.startedAsUserInitiatedJob = true;
+ spyOn(jobEj);
+ when(jobEj.shouldTreatAsExpeditedJob()).thenReturn(true);
+ jobEj.startedAsExpeditedJob = true;
+
+ mService.mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC = true;
+ mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT = 2;
+ mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT = 2;
+ mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT = 2;
+ mService.updateQuotaTracker();
+ mService.resetScheduleQuota();
+
+ // No timeouts -> no penalties.
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+ // 1 UIJ timeout. No execution penalty yet.
+ mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+ // Not a timeout -> 1 UIJ timeout. No execution penalty yet.
+ jobUij.madeActive = sUptimeMillisClock.millis() - 1;
+ mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+ // 2 UIJ timeouts. Min execution penalty only for UIJs.
+ jobUij.madeActive =
+ sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS;
+ mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+ // 1 EJ timeout. No max execution penalty yet.
+ mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+ // 2 EJ timeouts. Max execution penalty for EJs.
+ jobEj.madeActive =
+ sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS;
+ mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+ // 1 reg timeout. No max execution penalty yet.
+ mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobReg));
+
+ // 2 Reg timeouts. Max execution penalty for regular jobs.
+ jobReg.madeActive =
+ sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_GUARANTEE_MS;
+ mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobReg));
+ }
+
+ @Test
public void testGetMaxJobExecutionTimeMs() {
JobStatus jobUIDT = createJobStatus("testGetMaxJobExecutionTimeMs",
createJobInfo(10)
@@ -327,7 +587,7 @@ public class JobSchedulerServiceTest {
doReturn(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
.when(quotaController).getMaxJobExecutionTimeMsLocked(any());
doReturn(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
- .when(quotaController).getMaxJobExecutionTimeMsLocked(any());
+ .when(tareController).getMaxJobExecutionTimeMsLocked(any());
grantRunUserInitiatedJobsPermission(true);
assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
@@ -337,6 +597,306 @@ public class JobSchedulerServiceTest {
mService.getMaxJobExecutionTimeMs(jobUIDT));
}
+ @Test
+ public void testGetMaxJobExecutionTimeMs_timeoutSafeguards_disabled() {
+ JobStatus jobUij = createJobStatus("testGetMaxJobExecutionTimeMs_timeoutSafeguards",
+ createJobInfo(1)
+ .setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
+ JobStatus jobEj = createJobStatus("testGetMaxJobExecutionTimeMs_timeoutSafeguards",
+ createJobInfo(2).setExpedited(true));
+ JobStatus jobReg = createJobStatus("testGetMaxJobExecutionTimeMs_timeoutSafeguards",
+ createJobInfo(3));
+ spyOn(jobUij);
+ when(jobUij.shouldTreatAsUserInitiatedJob()).thenReturn(true);
+ jobUij.startedAsUserInitiatedJob = true;
+ spyOn(jobEj);
+ when(jobEj.shouldTreatAsExpeditedJob()).thenReturn(true);
+ jobEj.startedAsExpeditedJob = true;
+
+ QuotaController quotaController = mService.getQuotaController();
+ spyOn(quotaController);
+ TareController tareController = mService.getTareController();
+ spyOn(tareController);
+ doReturn(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
+ .when(quotaController).getMaxJobExecutionTimeMsLocked(any());
+ doReturn(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
+ .when(tareController).getMaxJobExecutionTimeMsLocked(any());
+
+ mService.mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC = false;
+ mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT = 2;
+ mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT = 2;
+ mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT = 2;
+ mService.updateQuotaTracker();
+ mService.resetScheduleQuota();
+
+ // Safeguards disabled -> no penalties.
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+
+ // 1 UIJ timeout. No max execution penalty yet.
+ mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+
+ // 2 UIJ timeouts. Safeguards disabled -> no penalties.
+ jobUij.madeActive =
+ sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS;
+ mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+
+ // 1 EJ timeout. No max execution penalty yet.
+ mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+
+ // 2 EJ timeouts. Safeguards disabled -> no penalties.
+ jobEj.madeActive =
+ sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS;
+ mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+
+ // 1 reg timeout. No max execution penalty yet.
+ mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+
+ // 2 Reg timeouts. Safeguards disabled -> no penalties.
+ jobReg.madeActive =
+ sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_GUARANTEE_MS;
+ mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+ }
+
+ @Test
+ public void testGetMaxJobExecutionTimeMs_timeoutSafeguards_enabled() {
+ JobStatus jobUij = createJobStatus("testGetMaxJobExecutionTimeMs_timeoutSafeguards",
+ createJobInfo(1)
+ .setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
+ JobStatus jobEj = createJobStatus("testGetMaxJobExecutionTimeMs_timeoutSafeguards",
+ createJobInfo(2).setExpedited(true));
+ JobStatus jobReg = createJobStatus("testGetMaxJobExecutionTimeMs_timeoutSafeguards",
+ createJobInfo(3));
+ spyOn(jobUij);
+ when(jobUij.shouldTreatAsUserInitiatedJob()).thenReturn(true);
+ jobUij.startedAsUserInitiatedJob = true;
+ spyOn(jobEj);
+ when(jobEj.shouldTreatAsExpeditedJob()).thenReturn(true);
+ jobEj.startedAsExpeditedJob = true;
+
+ QuotaController quotaController = mService.getQuotaController();
+ spyOn(quotaController);
+ TareController tareController = mService.getTareController();
+ spyOn(tareController);
+ doReturn(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
+ .when(quotaController).getMaxJobExecutionTimeMsLocked(any());
+ doReturn(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
+ .when(tareController).getMaxJobExecutionTimeMsLocked(any());
+
+ mService.mConstants.ENABLE_EXECUTION_SAFEGUARDS_UDC = true;
+ mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_UIJ_COUNT = 2;
+ mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_EJ_COUNT = 2;
+ mService.mConstants.EXECUTION_SAFEGUARDS_UDC_TIMEOUT_REG_COUNT = 2;
+ mService.updateQuotaTracker();
+ mService.resetScheduleQuota();
+
+ // No timeouts -> no penalties.
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+
+ // 1 UIJ timeout. No max execution penalty yet.
+ mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+
+ // Not a timeout -> 1 UIJ timeout. No max execution penalty yet.
+ jobUij.madeActive = sUptimeMillisClock.millis() - 1;
+ mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_UI_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+
+ // 2 UIJ timeouts. Max execution penalty only for UIJs.
+ jobUij.madeActive =
+ sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_UI_GUARANTEE_MS;
+ mService.maybeProcessBuggyJob(jobUij, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+
+ // 1 EJ timeout. No max execution penalty yet.
+ mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+
+ // Not a timeout -> 1 EJ timeout. No max execution penalty yet.
+ jobEj.madeActive = sUptimeMillisClock.millis() - 1;
+ mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+
+ // 2 EJ timeouts. Max execution penalty for EJs.
+ jobEj.madeActive =
+ sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS;
+ mService.maybeProcessBuggyJob(jobEj, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+
+ // 1 reg timeout. No max execution penalty yet.
+ mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+
+ // Not a timeout -> 1 reg timeout. No max execution penalty yet.
+ jobReg.madeActive = sUptimeMillisClock.millis() - 1;
+ mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+
+ // 2 Reg timeouts. Max execution penalty for regular jobs.
+ jobReg.madeActive =
+ sUptimeMillisClock.millis() - mService.mConstants.RUNTIME_MIN_GUARANTEE_MS;
+ mService.maybeProcessBuggyJob(jobReg, JobParameters.INTERNAL_STOP_REASON_UNKNOWN);
+ grantRunUserInitiatedJobsPermission(true);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ grantRunUserInitiatedJobsPermission(false);
+ assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+ mService.getMaxJobExecutionTimeMs(jobUij));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMaxJobExecutionTimeMs(jobEj));
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+ mService.getMaxJobExecutionTimeMs(jobReg));
+ }
+
/**
* Confirm that
* {@link JobSchedulerService#getRescheduleJobForFailureLocked(JobStatus, int, int)}
@@ -1226,6 +1786,7 @@ public class JobSchedulerServiceTest {
mService.mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION = false;
mService.mConstants.API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = true;
mService.updateQuotaTracker();
+ mService.resetScheduleQuota();
final JobInfo job = createJobInfo().setPersisted(true).build();
for (int i = 0; i < 500; ++i) {
@@ -1249,6 +1810,7 @@ public class JobSchedulerServiceTest {
mService.mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION = false;
mService.mConstants.API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = false;
mService.updateQuotaTracker();
+ mService.resetScheduleQuota();
final JobInfo job = createJobInfo().setPersisted(true).build();
for (int i = 0; i < 500; ++i) {
@@ -1270,6 +1832,7 @@ public class JobSchedulerServiceTest {
mService.mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION = false;
mService.mConstants.API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = true;
mService.updateQuotaTracker();
+ mService.resetScheduleQuota();
final JobInfo job = createJobInfo().setPersisted(true).build();
for (int i = 0; i < 500; ++i) {
@@ -1292,6 +1855,7 @@ public class JobSchedulerServiceTest {
mService.mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION = false;
mService.mConstants.API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = true;
mService.updateQuotaTracker();
+ mService.resetScheduleQuota();
final JobInfo job = createJobInfo().setPersisted(true).build();
for (int i = 0; i < 500; ++i) {
@@ -1315,6 +1879,7 @@ public class JobSchedulerServiceTest {
mService.mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION = false;
mService.mConstants.API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = false;
mService.updateQuotaTracker();
+ mService.resetScheduleQuota();
final JobInfo job = createJobInfo().setPersisted(false).build();
final JobWorkItem item = new JobWorkItem.Builder().build();
@@ -1337,6 +1902,7 @@ public class JobSchedulerServiceTest {
mService.mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION = false;
mService.mConstants.API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = false;
mService.updateQuotaTracker();
+ mService.resetScheduleQuota();
final JobInfo job = createJobInfo().setPersisted(true).build();
final JobWorkItem item = new JobWorkItem.Builder().build();
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
index 2180a781e437..2b56ea8bba33 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -73,6 +73,7 @@ import android.telephony.TelephonyManager;
import android.util.DataUnit;
import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerInternal;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.JobSchedulerService.Constants;
import com.android.server.net.NetworkPolicyManagerInternal;
@@ -124,6 +125,10 @@ public class ConnectivityControllerTest {
LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
LocalServices.addService(NetworkPolicyManagerInternal.class, mNetPolicyManagerInternal);
+ // Used in JobStatus.
+ LocalServices.removeServiceForTest(JobSchedulerInternal.class);
+ LocalServices.addService(JobSchedulerInternal.class, mock(JobSchedulerInternal.class));
+
// Freeze the clocks at this moment in time
JobSchedulerService.sSystemClock =
Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
index 05780ebe6c4b..1de7e3719112 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -21,6 +21,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX;
+import static com.android.server.job.JobSchedulerService.EXEMPTED_INDEX;
import static com.android.server.job.JobSchedulerService.FREQUENT_INDEX;
import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
import static com.android.server.job.JobSchedulerService.RARE_INDEX;
@@ -45,6 +46,8 @@ import static com.android.server.job.controllers.JobStatus.NO_LATEST_RUNTIME;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.when;
@@ -582,6 +585,40 @@ public class JobStatusTest {
}
@Test
+ public void testGetEffectiveStandbyBucket_buggyApp() {
+ when(mJobSchedulerInternal.isAppConsideredBuggy(
+ anyInt(), anyString(), anyInt(), anyString()))
+ .thenReturn(true);
+
+ final JobInfo jobInfo = new JobInfo.Builder(1234, TEST_JOB_COMPONENT).build();
+ JobStatus job = createJobStatus(jobInfo);
+
+ // Exempt apps be exempting.
+ job.setStandbyBucket(EXEMPTED_INDEX);
+ assertEquals(EXEMPTED_INDEX, job.getEffectiveStandbyBucket());
+
+ // Actual bucket is higher than the buggy cap, so the cap comes into effect.
+ job.setStandbyBucket(ACTIVE_INDEX);
+ assertEquals(WORKING_INDEX, job.getEffectiveStandbyBucket());
+
+ // Buckets at the cap or below shouldn't be affected.
+ job.setStandbyBucket(WORKING_INDEX);
+ assertEquals(WORKING_INDEX, job.getEffectiveStandbyBucket());
+
+ job.setStandbyBucket(FREQUENT_INDEX);
+ assertEquals(FREQUENT_INDEX, job.getEffectiveStandbyBucket());
+
+ job.setStandbyBucket(RARE_INDEX);
+ assertEquals(RARE_INDEX, job.getEffectiveStandbyBucket());
+
+ job.setStandbyBucket(RESTRICTED_INDEX);
+ assertEquals(RESTRICTED_INDEX, job.getEffectiveStandbyBucket());
+
+ job.setStandbyBucket(NEVER_INDEX);
+ assertEquals(NEVER_INDEX, job.getEffectiveStandbyBucket());
+ }
+
+ @Test
public void testModifyingInternalFlags() {
final JobInfo jobInfo =
new JobInfo.Builder(101, new ComponentName("foo", "bar"))
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java
index fb59ea2bb63b..7cc01e1b4292 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java
@@ -58,6 +58,7 @@ import android.util.SparseArray;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerInternal;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.controllers.PrefetchController.PcConstants;
@@ -135,6 +136,9 @@ public class PrefetchControllerTest {
when(mJobSchedulerService.getPackagesForUidLocked(anyInt()))
.thenAnswer(invocationOnMock
-> mPackagesForUid.get(invocationOnMock.getArgument(0)));
+ // Used in JobStatus.
+ doReturn(mock(JobSchedulerInternal.class))
+ .when(() -> LocalServices.getService(JobSchedulerInternal.class));
// Freeze the clocks at 24 hours after this moment in time. Several tests create sessions
// in the past, and PrefetchController sometimes floors values at 0, so if the test time
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index 6f713e0fad64..dce162c58d0b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -85,6 +85,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.ArrayUtils;
import com.android.server.LocalServices;
import com.android.server.PowerAllowlistInternal;
+import com.android.server.job.JobSchedulerInternal;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.JobStore;
import com.android.server.job.controllers.QuotaController.ExecutionStats;
@@ -190,6 +191,8 @@ public class QuotaControllerTest {
doReturn(mPowerAllowlistInternal)
.when(() -> LocalServices.getService(PowerAllowlistInternal.class));
// Used in JobStatus.
+ doReturn(mock(JobSchedulerInternal.class))
+ .when(() -> LocalServices.getService(JobSchedulerInternal.class));
doReturn(mPackageManagerInternal)
.when(() -> LocalServices.getService(PackageManagerInternal.class));
// Used in QuotaController.Handler.
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
index 51e521d8ffe4..206af5b6aea6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
@@ -17,8 +17,10 @@
package com.android.server.wallpaper;
import static android.app.WallpaperManager.COMMAND_REAPPLY;
+import static android.app.WallpaperManager.FLAG_LOCK;
import static android.app.WallpaperManager.FLAG_SYSTEM;
import static android.os.FileObserver.CLOSE_WRITE;
+import static android.os.UserHandle.MIN_SECONDARY_USER_ID;
import static android.os.UserHandle.USER_SYSTEM;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -106,6 +108,7 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.util.List;
/**
* Tests for the {@link WallpaperManagerService} class.
@@ -172,12 +175,12 @@ public class WallpaperManagerServiceTests {
sImageWallpaperComponentName = ComponentName.unflattenFromString(
sContext.getResources().getString(R.string.image_wallpaper_component));
// Mock default wallpaper as image wallpaper if there is no pre-defined default wallpaper.
- sDefaultWallpaperComponent = WallpaperManager.getCmfDefaultWallpaperComponent(sContext);
+ sDefaultWallpaperComponent = WallpaperManager.getDefaultWallpaperComponent(sContext);
if (sDefaultWallpaperComponent == null) {
sDefaultWallpaperComponent = sImageWallpaperComponentName;
doReturn(sImageWallpaperComponentName).when(() ->
- WallpaperManager.getCmfDefaultWallpaperComponent(any()));
+ WallpaperManager.getDefaultWallpaperComponent(any()));
} else {
sContext.addMockService(sDefaultWallpaperComponent, sWallpaperService);
}
@@ -262,6 +265,25 @@ public class WallpaperManagerServiceTests {
}
/**
+ * Tests that the fundamental fields are set by the main WallpaperData constructor
+ */
+ @Test
+ public void testWallpaperDataConstructor() {
+ final int testUserId = MIN_SECONDARY_USER_ID;
+ for (int which: List.of(FLAG_LOCK, FLAG_SYSTEM)) {
+ WallpaperData newWallpaperData = new WallpaperData(testUserId, which);
+ assertEquals(which, newWallpaperData.mWhich);
+ assertEquals(testUserId, newWallpaperData.userId);
+
+ WallpaperData wallpaperData = mService.getWallpaperSafeLocked(testUserId, which);
+ assertEquals(wallpaperData.cropFile.getAbsolutePath(),
+ newWallpaperData.cropFile.getAbsolutePath());
+ assertEquals(wallpaperData.wallpaperFile.getAbsolutePath(),
+ newWallpaperData.wallpaperFile.getAbsolutePath());
+ }
+ }
+
+ /**
* Tests that internal basic data should be correct after boot up.
*/
@Test
@@ -405,10 +427,7 @@ public class WallpaperManagerServiceTests {
fail("exception occurred while writing system wallpaper attributes");
}
- WallpaperData shouldMatchSystem = new WallpaperData(systemWallpaperData.userId,
- systemWallpaperData.wallpaperFile.getParentFile(),
- systemWallpaperData.wallpaperFile.getAbsolutePath(),
- systemWallpaperData.cropFile.getAbsolutePath());
+ WallpaperData shouldMatchSystem = new WallpaperData(0, FLAG_SYSTEM);
try {
TypedXmlPullParser parser = Xml.newBinaryPullParser();
mService.mWallpaperDataParser.parseWallpaperAttributes(parser, shouldMatchSystem, true);
diff --git a/services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java b/services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java
index 851d8f94d2c0..f05fa65a43ea 100644
--- a/services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java
@@ -101,12 +101,6 @@ public class DreamOverlayServiceTest {
mMonitor.onEndDream();
super.onEndDream();
}
-
- @Override
- public void onWakeUp(@NonNull Runnable onCompleteCallback) {
- mMonitor.onWakeUp();
- super.onWakeUp(onCompleteCallback);
- }
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index aad373fdaf95..aca96ad20385 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -445,14 +445,14 @@ public class SystemConfigTest {
+ " <library \n"
+ " name=\"foo\"\n"
+ " file=\"" + mFooJar + "\"\n"
- + " on-bootclasspath-before=\"A\"\n"
+ + " on-bootclasspath-before=\"Q\"\n"
+ " on-bootclasspath-since=\"W\"\n"
+ " />\n\n"
+ " </permissions>";
parseSharedLibraries(contents);
assertFooIsOnlySharedLibrary();
SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
- assertThat(entry.onBootclasspathBefore).isEqualTo("A");
+ assertThat(entry.onBootclasspathBefore).isEqualTo("Q");
assertThat(entry.onBootclasspathSince).isEqualTo("W");
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 2a0c745a0ffc..cebc5409c795 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -587,6 +587,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
return wl;
});
mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, true);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, "true", false);
// apps allowed as convos
mService.setStringArrayResourceValue(PKG_O);
@@ -1929,8 +1931,24 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
- public void enqueueNotification_wakeLockFlagOff_noWakeLock() throws Exception {
+ public void enqueueNotification_wakeLockSystemPropertyOff_noWakeLock() throws Exception {
mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, "true", false);
+
+ mBinderService.enqueueNotificationWithTag(PKG, PKG,
+ "enqueueNotification_setsWakeLockWorkSource", 0,
+ generateNotificationRecord(null).getNotification(), 0);
+ waitForIdle();
+
+ verifyZeroInteractions(mPowerManager);
+ }
+
+ @Test
+ public void enqueueNotification_wakeLockDeviceConfigOff_noWakeLock() throws Exception {
+ mTestFlagResolver.setFlagOverride(WAKE_LOCK_FOR_POSTING_NOTIFICATION, true);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.NOTIFY_WAKELOCK, "false", false);
mBinderService.enqueueNotificationWithTag(PKG, PKG,
"enqueueNotification_setsWakeLockWorkSource", 0,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 3ff433e546d8..e881039db1df 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2784,8 +2784,12 @@ public class ActivityRecordTests extends WindowTestsBase {
testLegacySplashScreen(Build.VERSION_CODES.S, TYPE_PARAMETER_LEGACY_SPLASH_SCREEN);
testLegacySplashScreen(Build.VERSION_CODES.TIRAMISU,
TYPE_PARAMETER_LEGACY_SPLASH_SCREEN);
- // Above T
- testLegacySplashScreen(Build.VERSION_CODES.TIRAMISU + 1, 0);
+ testLegacySplashScreen(Build.VERSION_CODES.UPSIDE_DOWN_CAKE,
+ TYPE_PARAMETER_LEGACY_SPLASH_SCREEN);
+ testLegacySplashScreen(Build.VERSION_CODES.UPSIDE_DOWN_CAKE + 1,
+ TYPE_PARAMETER_LEGACY_SPLASH_SCREEN);
+ // Above V
+ testLegacySplashScreen(Build.VERSION_CODES.UPSIDE_DOWN_CAKE + 2, 0);
} finally {
try {
DeviceConfig.setProperties(properties);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DeviceStateControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DeviceStateControllerTests.java
index 07d8b8a0c8df..51255948ed4a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DeviceStateControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DeviceStateControllerTests.java
@@ -17,17 +17,16 @@
package com.android.server.wm;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
import android.content.Context;
import android.content.res.Resources;
import android.hardware.devicestate.DeviceStateManager;
import android.platform.test.annotations.Presubmit;
+import android.util.Pair;
import androidx.test.filters.SmallTest;
@@ -38,6 +37,8 @@ import com.google.common.util.concurrent.MoreExecutors;
import org.junit.Before;
import org.junit.Test;
+import java.util.List;
+import java.util.concurrent.Executor;
import java.util.function.Consumer;
/**
@@ -58,6 +59,7 @@ public class DeviceStateControllerTests {
private DeviceStateController.DeviceState mCurrentState =
DeviceStateController.DeviceState.UNKNOWN;
private Consumer<DeviceStateController.DeviceState> mDelegate;
+ private Executor mExecutor = MoreExecutors.directExecutor();
@Before
public void setUp() {
@@ -124,13 +126,31 @@ public class DeviceStateControllerTests {
mTarget.onDeviceStateReceivedByDisplayManager(mFoldedStates[0]);
assertEquals(DeviceStateController.DeviceState.FOLDED, mCurrentState);
- // The callback should not receive state change when the it is unregistered.
+ // The callback should not receive state change when it is unregistered.
mTarget.unregisterDeviceStateCallback(mDelegate);
assertTrue(mTarget.mDeviceStateCallbacks.isEmpty());
mTarget.onDeviceStateReceivedByDisplayManager(mOpenDeviceStates[0]);
assertEquals(DeviceStateController.DeviceState.FOLDED /* unchanged */, mCurrentState);
}
+ @Test
+ public void testCopyDeviceStateCallbacks() {
+ initialize(true /* supportFold */, true /* supportHalfFolded */);
+ assertEquals(1, mTarget.mDeviceStateCallbacks.size());
+ assertTrue(mTarget.mDeviceStateCallbacks.containsKey(mDelegate));
+
+ List<Pair<Consumer<DeviceStateController.DeviceState>, Executor>> entries =
+ mTarget.copyDeviceStateCallbacks();
+ mTarget.unregisterDeviceStateCallback(mDelegate);
+
+ // In contrast to List<Map.Entry> where the entries are tied to changes in the backing map,
+ // List<Pair> should still contain non-null callbacks and executors even though they were
+ // removed from the backing map via the unregister method above.
+ assertEquals(1, entries.size());
+ assertEquals(mDelegate, entries.get(0).first);
+ assertEquals(mExecutor, entries.get(0).second);
+ }
+
private final int[] mFoldedStates = {0};
private final int[] mOpenDeviceStates = {1};
private final int[] mHalfFoldedStates = {2};
@@ -194,7 +214,7 @@ public class DeviceStateControllerTests {
when(mMockContext.getResources()).thenReturn((mockRes));
mockFold(mSupportFold, mSupportHalfFold);
mTarget = new DeviceStateController(mMockContext, new WindowManagerGlobalLock());
- mTarget.registerDeviceStateCallback(mDelegate, MoreExecutors.directExecutor());
+ mTarget.registerDeviceStateCallback(mDelegate, mExecutor);
}
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index d173ce9d522a..3bc6450ae591 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -337,6 +337,17 @@ public class RootWindowContainerTests extends WindowTestsBase {
// Ensure a task has moved over.
ensureTaskPlacement(task, activity);
assertTrue(task.inPinnedWindowingMode());
+
+ // The activity with fixed orientation should not apply letterbox when entering PiP.
+ final int requestedOrientation = task.getConfiguration().orientation
+ == Configuration.ORIENTATION_PORTRAIT
+ ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT;
+ doReturn(requestedOrientation).when(activity).getRequestedConfigurationOrientation();
+ doReturn(false).when(activity).handlesOrientationChangeFromDescendant(anyInt());
+ final Rect bounds = new Rect(task.getBounds());
+ bounds.scale(0.5f);
+ task.setBounds(bounds);
+ assertFalse(activity.isLetterboxedForFixedOrientationAndAspectRatio());
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java b/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java
index 1ee0959447a6..b181213df003 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java
@@ -43,16 +43,14 @@ import android.os.Handler;
import android.os.Looper;
import android.os.ServiceManager;
import android.platform.test.annotations.Presubmit;
-import android.util.Pair;
import android.view.IWindowManager;
import android.view.PointerIcon;
import android.view.SurfaceControl;
import android.view.cts.surfacevalidator.BitmapPixelChecker;
import android.view.cts.surfacevalidator.SaveBitmapHelper;
import android.window.ScreenCapture;
-import android.window.ScreenCapture.ScreenCaptureListener;
import android.window.ScreenCapture.ScreenshotHardwareBuffer;
-import android.window.ScreenCapture.ScreenshotSync;
+import android.window.ScreenCapture.SynchronousScreenCaptureListener;
import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
@@ -169,10 +167,10 @@ public class ScreenshotTests {
.setPosition(sc, point.x, point.y)
.apply(true);
- Pair<ScreenCaptureListener, ScreenshotSync> syncScreenCapture =
+ SynchronousScreenCaptureListener syncScreenCapture =
ScreenCapture.createSyncCaptureListener();
- windowManager.captureDisplay(DEFAULT_DISPLAY, null, syncScreenCapture.first);
- ScreenshotHardwareBuffer hardwareBuffer = syncScreenCapture.second.get();
+ windowManager.captureDisplay(DEFAULT_DISPLAY, null, syncScreenCapture);
+ ScreenshotHardwareBuffer hardwareBuffer = syncScreenCapture.getBuffer();
assertNotNull(hardwareBuffer);
Bitmap screenshot = hardwareBuffer.asBitmap();
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 082122e33175..6a89b55b80cc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -2046,6 +2046,72 @@ public class SizeCompatTests extends WindowTestsBase {
}
@Test
+ public void testDefaultLetterboxAspectRatioForMultiWindowMode_fixedOrientationApp() {
+ // Set-up display in portrait.
+ mAtm.mDevEnableNonResizableMultiWindow = true;
+ final int screenWidth = 1100;
+ final int screenHeight = 2100;
+ setUpDisplaySizeWithApp(screenWidth, screenHeight);
+
+ mActivity.mDisplayContent.getWindowConfiguration()
+ .setAppBounds(/* left */ 0, /* top */ 0, screenWidth, screenHeight);
+
+ final TestSplitOrganizer organizer =
+ new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
+ // Move activity to multi-window which takes half of the screen.
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ organizer.mPrimary.setBounds(0, 0, screenWidth, getExpectedSplitSize(screenHeight));
+ assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
+ assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
+
+ // Unresizable portrait-only activity.
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+
+ // Activity should be letterboxed with an aspect ratio of 1.01.
+ final Rect afterBounds = mActivity.getBounds();
+ final float actualAspectRatio = 1f * afterBounds.height() / afterBounds.width();
+ assertEquals(LetterboxConfiguration.DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW,
+ actualAspectRatio, 0.001f);
+ assertTrue(mActivity.areBoundsLetterboxed());
+ }
+
+ @Test
+ public void
+ testDefaultLetterboxAspectRatioForMultiWindowMode_fixedOrientationAppWithMinRatio() {
+ // Set-up display in portrait.
+ mAtm.mDevEnableNonResizableMultiWindow = true;
+ final int screenWidth = 1100;
+ final int screenHeight = 2100;
+ setUpDisplaySizeWithApp(screenWidth, screenHeight);
+
+ mActivity.mDisplayContent.getWindowConfiguration()
+ .setAppBounds(/* left */ 0, /* top */ 0, screenWidth, screenHeight);
+
+ // Set min aspect ratio to value greater than the default letterbox aspect ratio for
+ // multi-window mode.
+ final float minAspectRatio = 1.2f;
+ mActivity.info.setMinAspectRatio(minAspectRatio);
+
+ final TestSplitOrganizer organizer =
+ new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
+ // Move activity to multi-window which takes half of the screen.
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ organizer.mPrimary.setBounds(0, 0, screenWidth, getExpectedSplitSize(screenHeight));
+ assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
+ assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
+
+ // Unresizable portrait-only activity.
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+
+ // Activity should be letterboxed with the min aspect ratio requested by the app NOT the
+ // default letterbox aspect ratio for multi-window.
+ final Rect afterBounds = mActivity.getBounds();
+ final float actualAspectRatio = 1f * afterBounds.height() / afterBounds.width();
+ assertEquals(minAspectRatio, actualAspectRatio, 0.001f);
+ assertTrue(mActivity.areBoundsLetterboxed());
+ }
+
+ @Test
public void testDisplayIgnoreOrientationRequest_unresizableWithCorrespondingMinAspectRatio() {
// Set up a display in landscape and ignoring orientation request.
setUpDisplaySizeWithApp(2800, 1400);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SplashScreenExceptionListTest.java b/services/tests/wmtests/src/com/android/server/wm/SplashScreenExceptionListTest.java
index 8425844d8042..8bd54731c7c2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SplashScreenExceptionListTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SplashScreenExceptionListTest.java
@@ -90,19 +90,23 @@ public class SplashScreenExceptionListTest {
public void packageFromDeviceConfigIgnored() {
setExceptionListAndWaitForCallback("com.test.nosplashscreen1,com.test.nosplashscreen2");
- // In list, up to T included
+ // In list, up to V included
assertIsException("com.test.nosplashscreen1", VERSION_CODES.R);
assertIsException("com.test.nosplashscreen1", VERSION_CODES.S);
assertIsException("com.test.nosplashscreen1", VERSION_CODES.TIRAMISU);
+ assertIsException("com.test.nosplashscreen1", VERSION_CODES.UPSIDE_DOWN_CAKE);
+ assertIsException("com.test.nosplashscreen1", VERSION_CODES.UPSIDE_DOWN_CAKE + 1);
- // In list, after T
- assertIsNotException("com.test.nosplashscreen2", VERSION_CODES.TIRAMISU + 1);
+ // In list, after V
+ assertIsNotException("com.test.nosplashscreen2", VERSION_CODES.UPSIDE_DOWN_CAKE + 2);
assertIsNotException("com.test.nosplashscreen2", VERSION_CODES.CUR_DEVELOPMENT);
- // Not in list, up to T included
+ // Not in list, up to V included
assertIsNotException("com.test.splashscreen", VERSION_CODES.S);
assertIsNotException("com.test.splashscreen", VERSION_CODES.R);
assertIsNotException("com.test.splashscreen", VERSION_CODES.TIRAMISU);
+ assertIsNotException("com.test.splashscreen", VERSION_CODES.UPSIDE_DOWN_CAKE);
+ assertIsNotException("com.test.splashscreen", VERSION_CODES.UPSIDE_DOWN_CAKE + 1);
}
@Test
@@ -119,15 +123,19 @@ public class SplashScreenExceptionListTest {
assertIsNotException(packageName, VERSION_CODES.R, activityInfo);
assertIsNotException(packageName, VERSION_CODES.S, activityInfo);
assertIsNotException(packageName, VERSION_CODES.TIRAMISU, activityInfo);
+ assertIsNotException(packageName, VERSION_CODES.UPSIDE_DOWN_CAKE, activityInfo);
+ assertIsNotException(packageName, VERSION_CODES.UPSIDE_DOWN_CAKE + 1, activityInfo);
- // Exception up to T
+ // Exception up to V
metaData.putBoolean("android.splashscreen.exception_opt_out", false);
assertIsException(packageName, VERSION_CODES.R, activityInfo);
assertIsException(packageName, VERSION_CODES.S, activityInfo);
assertIsException(packageName, VERSION_CODES.TIRAMISU, activityInfo);
+ assertIsException(packageName, VERSION_CODES.UPSIDE_DOWN_CAKE, activityInfo);
+ assertIsException(packageName, VERSION_CODES.UPSIDE_DOWN_CAKE + 1, activityInfo);
- // No Exception after T
- assertIsNotException(packageName, VERSION_CODES.TIRAMISU + 1, activityInfo);
+ // No Exception after V
+ assertIsNotException(packageName, VERSION_CODES.UPSIDE_DOWN_CAKE + 2, activityInfo);
assertIsNotException(packageName, VERSION_CODES.CUR_DEVELOPMENT, activityInfo);
// Edge Cases
diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index f3d8114b9e94..4afcd0539b94 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -288,6 +288,32 @@ public class WallpaperControllerTests extends WindowTestsBase {
assertEquals(homeWin, dc.mWallpaperController.getWallpaperTarget());
}
+ @Test
+ public void testShowWhenLockedWallpaperTarget() {
+ final WindowState wallpaperWindow = createWallpaperWindow(mDisplayContent);
+ wallpaperWindow.mToken.asWallpaperToken().setShowWhenLocked(true);
+ final WindowState behind = createWindow(null, TYPE_BASE_APPLICATION, "behind");
+ final WindowState topTranslucent = createWindow(null, TYPE_BASE_APPLICATION,
+ "topTranslucent");
+ behind.mAttrs.width = behind.mAttrs.height = topTranslucent.mAttrs.width =
+ topTranslucent.mAttrs.height = WindowManager.LayoutParams.MATCH_PARENT;
+ topTranslucent.mAttrs.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
+ doReturn(true).when(behind.mActivityRecord).fillsParent();
+ doReturn(false).when(topTranslucent.mActivityRecord).fillsParent();
+
+ spyOn(mWm.mPolicy);
+ doReturn(true).when(mWm.mPolicy).isKeyguardLocked();
+ doReturn(true).when(mWm.mPolicy).isKeyguardOccluded();
+ mDisplayContent.mWallpaperController.adjustWallpaperWindows();
+ // Wallpaper is visible because the show-when-locked activity is translucent.
+ assertTrue(mDisplayContent.mWallpaperController.isWallpaperTarget(wallpaperWindow));
+
+ behind.mActivityRecord.setShowWhenLocked(true);
+ mDisplayContent.mWallpaperController.adjustWallpaperWindows();
+ // Wallpaper is invisible because the lowest show-when-locked activity is opaque.
+ assertTrue(mDisplayContent.mWallpaperController.isWallpaperTarget(null));
+ }
+
/**
* Tests that the windowing mode of the wallpaper window must always be fullscreen.
*/
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 188894339f6a..5b1c6b1c88b8 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -10318,7 +10318,7 @@ public class CarrierConfigManager {
sDefaults.putInt(KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT,
CellSignalStrengthLte.USE_RSRP);
sDefaults.putInt(KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT, 300);
- sDefaults.putInt(KEY_PREFERRED_IKE_PROTOCOL_INT, 0);
+ sDefaults.putInt(KEY_PREFERRED_IKE_PROTOCOL_INT, -1);
// Default wifi configurations.
sDefaults.putAll(Wifi.getDefaults());
sDefaults.putBoolean(ENABLE_EAP_METHOD_PREFIX_BOOL, false);
diff --git a/tests/SilkFX/res/layout/gainmap_transform_test.xml b/tests/SilkFX/res/layout/gainmap_transform_test.xml
new file mode 100644
index 000000000000..5aeb53661cbc
--- /dev/null
+++ b/tests/SilkFX/res/layout/gainmap_transform_test.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<com.android.test.silkfx.hdr.GainmapTransformsTest xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <Button
+ android:id="@+id/original"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Original" />
+
+ <Button
+ android:id="@+id/scaled"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Scaled (1/3)" />
+
+ <Button
+ android:id="@+id/rotate_90"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Rotate 90" />
+
+ <Button
+ android:id="@+id/rotate_90_scaled"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Rot90+Scale" />
+
+ <Button
+ android:id="@+id/crop"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Crop" />
+
+ <Button
+ android:id="@+id/crop_200"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="Crop 200" />
+
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/source_info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:layout_weight="1">
+
+ <TextView
+ android:id="@+id/sdr_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <ImageView
+ android:id="@+id/sdr_source"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="8dp"
+ android:scaleType="fitStart" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:layout_weight="1">
+
+ <TextView
+ android:id="@+id/gainmap_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <ImageView
+ android:id="@+id/gainmap"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="8dp"
+ android:scaleType="fitStart" />
+ </LinearLayout>
+
+ </LinearLayout>
+
+</com.android.test.silkfx.hdr.GainmapTransformsTest> \ No newline at end of file
diff --git a/tests/SilkFX/src/com/android/test/silkfx/Main.kt b/tests/SilkFX/src/com/android/test/silkfx/Main.kt
index a6cdbb9865bc..59a6078376cf 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/Main.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/Main.kt
@@ -55,7 +55,9 @@ private val AllDemos = listOf(
Demo("Color Grid", R.layout.color_grid),
Demo("Gradient Sweep", R.layout.gradient_sweep),
Demo("Gainmap Image", R.layout.gainmap_image),
- Demo("Gainmap Decode Test", R.layout.gainmap_decode_test, commonControls = false)
+ Demo("Gainmap Decode Test", R.layout.gainmap_decode_test, commonControls = false),
+ Demo("Gainmap Transform Test", R.layout.gainmap_transform_test,
+ commonControls = false)
)),
DemoGroup("Materials", listOf(
Demo("Glass", GlassActivity::class),
diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt
index a004fb5a4305..585320aee615 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt
@@ -17,7 +17,12 @@
package com.android.test.silkfx.hdr
import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.ColorMatrixColorFilter
+import android.graphics.Gainmap
import android.graphics.ImageDecoder
+import android.graphics.Paint
import android.graphics.Rect
import android.util.AttributeSet
import android.widget.Button
@@ -34,6 +39,25 @@ enum class DecodeMode {
CropedSquaredScaled33
}
+fun gainmapVisualizer(gainmap: Gainmap): Bitmap {
+ val map = gainmap.gainmapContents
+ val gainmapVisualizer = Bitmap.createBitmap(map.width, map.height,
+ Bitmap.Config.ARGB_8888)
+ val canvas = Canvas(gainmapVisualizer!!)
+ val paint = Paint()
+ paint.colorFilter = ColorMatrixColorFilter(
+ floatArrayOf(
+ 0f, 0f, 0f, 1f, 0f,
+ 0f, 0f, 0f, 1f, 0f,
+ 0f, 0f, 0f, 1f, 0f,
+ 0f, 0f, 0f, 0f, 255f
+ )
+ )
+ canvas.drawBitmap(map, 0f, 0f, paint)
+ canvas.setBitmap(null)
+ return gainmapVisualizer
+}
+
class GainmapDecodeTest(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) {
private fun decode(mode: DecodeMode) {
@@ -71,7 +95,7 @@ class GainmapDecodeTest(context: Context, attrs: AttributeSet?) : LinearLayout(c
}
}
- val gainmapContents = gainmapImage.gainmap!!.gainmapContents!!
+ val gainmapContents = gainmapImage.gainmap?.let { gainmapVisualizer(it) }
val sdrBitmap = gainmapImage.also { it.gainmap = null }
findViewById<ImageView>(R.id.sdr_source)!!.setImageBitmap(sdrBitmap)
@@ -80,7 +104,7 @@ class GainmapDecodeTest(context: Context, attrs: AttributeSet?) : LinearLayout(c
findViewById<ImageView>(R.id.gainmap)!!.setImageBitmap(gainmapContents)
findViewById<TextView>(R.id.gainmap_label)!!.text =
- "Gainmap Size: ${gainmapContents.width}x${gainmapContents.height}"
+ "Gainmap Size: ${gainmapContents?.width ?: 0}x${gainmapContents?.height ?: 0}"
}
override fun onFinishInflate() {
diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapTransformsTest.kt b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapTransformsTest.kt
new file mode 100644
index 000000000000..20984fae2133
--- /dev/null
+++ b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapTransformsTest.kt
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.silkfx.hdr
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.ImageDecoder
+import android.graphics.Matrix
+import android.util.AttributeSet
+import android.widget.Button
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.TextView
+import com.android.test.silkfx.R
+
+class GainmapTransformsTest(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) {
+
+ private val sourceImage = loadSample()
+
+ private fun loadSample(): Bitmap {
+ val source = ImageDecoder.createSource(resources.assets,
+ "gainmaps/${context.assets.list("gainmaps")!![0]}")
+
+ return ImageDecoder.decodeBitmap(source) { decoder, info, source ->
+ decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE
+ }
+ }
+
+ private fun process(transform: (Bitmap) -> Bitmap) {
+ val result = transform(sourceImage)
+
+ val gainmapContents = result.gainmap?.let { gainmapVisualizer(it) }
+ val sdrBitmap = result.also { it.gainmap = null }
+
+ findViewById<ImageView>(R.id.sdr_source)!!.setImageBitmap(sdrBitmap)
+ findViewById<TextView>(R.id.sdr_label)!!.text =
+ "SDR Size: ${sdrBitmap.width}x${sdrBitmap.height}"
+
+ findViewById<ImageView>(R.id.gainmap)!!.setImageBitmap(gainmapContents)
+ findViewById<TextView>(R.id.gainmap_label)!!.text =
+ "Gainmap Size: ${gainmapContents?.width ?: 0}x${gainmapContents?.height ?: 0}"
+ }
+
+ override fun onFinishInflate() {
+ super.onFinishInflate()
+ val sourceInfo = findViewById<TextView>(R.id.source_info)!!
+ sourceInfo.text = "Original size ${sourceImage.width}x${sourceImage.height}"
+ process { it.copy(Bitmap.Config.ARGB_8888, false) }
+
+ findViewById<Button>(R.id.original)!!.setOnClickListener {
+ process { it.copy(Bitmap.Config.ARGB_8888, false) }
+ }
+
+ findViewById<Button>(R.id.scaled)!!.setOnClickListener {
+ process { Bitmap.createScaledBitmap(it, it.width / 3, it.height / 3, true) }
+ }
+
+ findViewById<Button>(R.id.rotate_90)!!.setOnClickListener {
+ process {
+ val width: Int = it.width
+ val height: Int = it.height
+
+ val m = Matrix()
+ m.setRotate(90.0f, (width / 2).toFloat(), (height / 2).toFloat())
+ Bitmap.createBitmap(it, 0, 0, width, height, m, false)
+ }
+ }
+
+ findViewById<Button>(R.id.rotate_90_scaled)!!.setOnClickListener {
+ process {
+ val width: Int = it.width
+ val height: Int = it.height
+
+ val m = Matrix()
+ m.setRotate(90.0f, (width / 2).toFloat(), (height / 2).toFloat())
+ m.preScale(.3f, .3f)
+ Bitmap.createBitmap(it, 0, 0, width, height, m, false)
+ }
+ }
+
+ findViewById<Button>(R.id.crop)!!.setOnClickListener {
+ process {
+ val width: Int = it.width
+ val height: Int = it.height
+ Bitmap.createBitmap(it, width / 2, height / 2,
+ width / 4, height / 4, null, false)
+ }
+ }
+
+ findViewById<Button>(R.id.crop_200)!!.setOnClickListener {
+ process {
+ val width: Int = it.width
+ val height: Int = it.height
+
+ val m = Matrix()
+ m.setRotate(200.0f, (width / 2).toFloat(), (height / 2).toFloat())
+ Bitmap.createBitmap(it, width / 2, height / 2,
+ width / 4, height / 4, m, false)
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 4123f8070e36..960b57cb632a 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -118,6 +118,7 @@ import java.util.UUID;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class VcnManagementServiceTest {
+ private static final String CONTEXT_ATTRIBUTION_TAG = "VCN";
private static final String TEST_PACKAGE_NAME =
VcnManagementServiceTest.class.getPackage().getName();
private static final String TEST_PACKAGE_NAME_2 = "TEST_PKG_2";
@@ -177,6 +178,7 @@ public class VcnManagementServiceTest {
0 /* carrierId */,
0 /* profileClass */);
+ private final Context mMockContextWithoutAttributionTag = mock(Context.class);
private final Context mMockContext = mock(Context.class);
private final VcnManagementService.Dependencies mMockDeps =
mock(VcnManagementService.Dependencies.class);
@@ -202,6 +204,10 @@ public class VcnManagementServiceTest {
private final IBinder mMockIBinder = mock(IBinder.class);
public VcnManagementServiceTest() throws Exception {
+ doReturn(mMockContext)
+ .when(mMockContextWithoutAttributionTag)
+ .createAttributionContext(CONTEXT_ATTRIBUTION_TAG);
+
setupSystemService(
mMockContext, mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
setupSystemService(
@@ -249,7 +255,7 @@ public class VcnManagementServiceTest {
doReturn(bundle).when(mConfigReadWriteHelper).readFromDisk();
setupMockedCarrierPrivilege(true);
- mVcnMgmtSvc = new VcnManagementService(mMockContext, mMockDeps);
+ mVcnMgmtSvc = new VcnManagementService(mMockContextWithoutAttributionTag, mMockDeps);
setupActiveSubscription(TEST_UUID_1);
doReturn(mMockIBinder).when(mMockPolicyListener).asBinder();